summaryrefslogtreecommitdiff
path: root/arch/arm/plat-spear/include/plat/clock.h
blob: 863d9e98392792f95810bc99b5961e6b65541dca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * arch/arm/plat-spear/include/plat/clock.h
 *
 * Clock framework definitions for SPEAr platform
 *
 * Copyright (C) 2009 ST Microelectronics
 * Viresh Kumar<viresh.kumar@st.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#ifndef __PLAT_CLOCK_H
#define __PLAT_CLOCK_H

#include <linux/list.h>
#include <linux/clkdev.h>
#include <linux/types.h>

/* clk structure flags */
#define	ALWAYS_ENABLED		(1 << 0) /* clock always enabled */
#define	RESET_TO_ENABLE		(1 << 1) /* reset register bit to enable clk */

/**
 * struct clkops - clock operations
 * @enable: pointer to clock enable function
 * @disable: pointer to clock disable function
 */
struct clkops {
	int (*enable) (struct clk *);
	void (*disable) (struct clk *);
};

/**
 * struct pclk_info - parents info
 * @pclk: pointer to parent clk
 * @pclk_mask: value to be written for selecting this parent
 * @scalable: Is parent scalable (1 - YES, 0 - NO)
 */
struct pclk_info {
	struct clk *pclk;
	u8 pclk_mask;
	u8 scalable;
};

/**
 * struct pclk_sel - parents selection configuration
 * @pclk_info: pointer to array of parent clock info
 * @pclk_count: number of parents
 * @pclk_sel_reg: register for selecting a parent
 * @pclk_sel_mask: mask for selecting parent (can be used to clear bits also)
 */
struct pclk_sel {
	struct pclk_info *pclk_info;
	u8 pclk_count;
	void __iomem *pclk_sel_reg;
	unsigned int pclk_sel_mask;
};

/**
 * struct clk - clock structure
 * @usage_count: num of users who enabled this clock
 * @flags: flags for clock properties
 * @rate: programmed clock rate in Hz
 * @en_reg: clk enable/disable reg
 * @en_reg_bit: clk enable/disable bit
 * @ops: clk enable/disable ops - generic_clkops selected if NULL
 * @recalc: pointer to clock rate recalculate function
 * @div_factor: division factor to parent clock. Only for recalc = follow_parent
 * @pclk: current parent clk
 * @pclk_sel: pointer to parent selection structure
 * @pclk_sel_shift: register shift for selecting parent of this clock
 * @children: list for childrens or this clock
 * @sibling: node for list of clocks having same parents
 * @private_data: clock specific private data
 */
struct clk {
	unsigned int usage_count;
	unsigned int flags;
	unsigned long rate;
	void __iomem *en_reg;
	u8 en_reg_bit;
	const struct clkops *ops;
	void (*recalc) (struct clk *);
	unsigned int div_factor;

	struct clk *pclk;
	struct pclk_sel *pclk_sel;
	unsigned int pclk_sel_shift;

	struct list_head children;
	struct list_head sibling;
	void *private_data;
};

/* pll configuration structure */
struct pll_clk_masks {
	u32 mode_mask;
	u32 mode_shift;

	u32 norm_fdbk_m_mask;
	u32 norm_fdbk_m_shift;
	u32 dith_fdbk_m_mask;
	u32 dith_fdbk_m_shift;
	u32 div_p_mask;
	u32 div_p_shift;
	u32 div_n_mask;
	u32 div_n_shift;
};

struct pll_clk_config {
	void __iomem *mode_reg;
	void __iomem *cfg_reg;
	struct pll_clk_masks *masks;
};

/* ahb and apb bus configuration structure */
struct bus_clk_masks {
	u32 mask;
	u32 shift;
};

struct bus_clk_config {
	void __iomem *reg;
	struct bus_clk_masks *masks;
};

/* Aux clk configuration structure: applicable to UART and FIRDA */
struct aux_clk_masks {
	u32 eq_sel_mask;
	u32 eq_sel_shift;
	u32 eq1_mask;
	u32 eq2_mask;
	u32 xscale_sel_mask;
	u32 xscale_sel_shift;
	u32 yscale_sel_mask;
	u32 yscale_sel_shift;
};

struct aux_clk_config {
	void __iomem *synth_reg;
	struct aux_clk_masks *masks;
};

/* GPT clk configuration structure */
struct gpt_clk_masks {
	u32 mscale_sel_mask;
	u32 mscale_sel_shift;
	u32 nscale_sel_mask;
	u32 nscale_sel_shift;
};

struct gpt_clk_config {
	void __iomem *synth_reg;
	struct gpt_clk_masks *masks;
};

/* platform specific clock functions */
void clk_register(struct clk_lookup *cl);
void recalc_root_clocks(void);

/* clock recalc functions */
void follow_parent(struct clk *clk);
void pll_clk_recalc(struct clk *clk);
void bus_clk_recalc(struct clk *clk);
void gpt_clk_recalc(struct clk *clk);
void aux_clk_recalc(struct clk *clk);

#endif /* __PLAT_CLOCK_H */