diff options
Diffstat (limited to 'arch/arm/mach-prima2/clock.c')
-rw-r--r-- | arch/arm/mach-prima2/clock.c | 1189 |
1 files changed, 925 insertions, 264 deletions
diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c index aebad7e565cf..517874fa6858 100644 --- a/arch/arm/mach-prima2/clock.c +++ b/arch/arm/mach-prima2/clock.c | |||
@@ -8,16 +8,12 @@ | |||
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
11 | #include <linux/err.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/io.h> | 11 | #include <linux/io.h> |
14 | #include <linux/clkdev.h> | ||
15 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
16 | #include <linux/spinlock.h> | 13 | #include <linux/clkdev.h> |
17 | #include <linux/of.h> | 14 | #include <linux/clk-provider.h> |
18 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
19 | #include <asm/mach/map.h> | 16 | #include <linux/syscore_ops.h> |
20 | #include <mach/map.h> | ||
21 | 17 | ||
22 | #define SIRFSOC_CLKC_CLK_EN0 0x0000 | 18 | #define SIRFSOC_CLKC_CLK_EN0 0x0000 |
23 | #define SIRFSOC_CLKC_CLK_EN1 0x0004 | 19 | #define SIRFSOC_CLKC_CLK_EN1 0x0004 |
@@ -29,7 +25,7 @@ | |||
29 | #define SIRFSOC_CLKC_DSP_CFG 0x0028 | 25 | #define SIRFSOC_CLKC_DSP_CFG 0x0028 |
30 | #define SIRFSOC_CLKC_GFX_CFG 0x002c | 26 | #define SIRFSOC_CLKC_GFX_CFG 0x002c |
31 | #define SIRFSOC_CLKC_MM_CFG 0x0030 | 27 | #define SIRFSOC_CLKC_MM_CFG 0x0030 |
32 | #define SIRFSOC_LKC_LCD_CFG 0x0034 | 28 | #define SIRFSOC_CLKC_LCD_CFG 0x0034 |
33 | #define SIRFSOC_CLKC_MMC_CFG 0x0038 | 29 | #define SIRFSOC_CLKC_MMC_CFG 0x0038 |
34 | #define SIRFSOC_CLKC_PLL1_CFG0 0x0040 | 30 | #define SIRFSOC_CLKC_PLL1_CFG0 0x0040 |
35 | #define SIRFSOC_CLKC_PLL2_CFG0 0x0044 | 31 | #define SIRFSOC_CLKC_PLL2_CFG0 0x0044 |
@@ -40,68 +36,82 @@ | |||
40 | #define SIRFSOC_CLKC_PLL1_CFG2 0x0058 | 36 | #define SIRFSOC_CLKC_PLL1_CFG2 0x0058 |
41 | #define SIRFSOC_CLKC_PLL2_CFG2 0x005c | 37 | #define SIRFSOC_CLKC_PLL2_CFG2 0x005c |
42 | #define SIRFSOC_CLKC_PLL3_CFG2 0x0060 | 38 | #define SIRFSOC_CLKC_PLL3_CFG2 0x0060 |
39 | #define SIRFSOC_USBPHY_PLL_CTRL 0x0008 | ||
40 | #define SIRFSOC_USBPHY_PLL_POWERDOWN BIT(1) | ||
41 | #define SIRFSOC_USBPHY_PLL_BYPASS BIT(2) | ||
42 | #define SIRFSOC_USBPHY_PLL_LOCK BIT(3) | ||
43 | 43 | ||
44 | #define SIRFSOC_CLOCK_VA_BASE SIRFSOC_VA(0x005000) | 44 | static void *sirfsoc_clk_vbase, *sirfsoc_rsc_vbase; |
45 | 45 | ||
46 | #define KHZ 1000 | 46 | #define KHZ 1000 |
47 | #define MHZ (KHZ * KHZ) | 47 | #define MHZ (KHZ * KHZ) |
48 | 48 | ||
49 | struct clk_ops { | 49 | /* |
50 | unsigned long (*get_rate)(struct clk *clk); | 50 | * SiRFprimaII clock controller |
51 | long (*round_rate)(struct clk *clk, unsigned long rate); | 51 | * - 2 oscillators: osc-26MHz, rtc-32.768KHz |
52 | int (*set_rate)(struct clk *clk, unsigned long rate); | 52 | * - 3 standard configurable plls: pll1, pll2 & pll3 |
53 | int (*enable)(struct clk *clk); | 53 | * - 2 exclusive plls: usb phy pll and sata phy pll |
54 | int (*disable)(struct clk *clk); | 54 | * - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia, |
55 | struct clk *(*get_parent)(struct clk *clk); | 55 | * display and sdphy. |
56 | int (*set_parent)(struct clk *clk, struct clk *parent); | 56 | * Each clock domain can select its own clock source from five clock sources, |
57 | * X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source | ||
58 | * clock of the group clock. | ||
59 | * - dsp domain: gps, mf | ||
60 | * - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse | ||
61 | * - sys domain: security | ||
62 | */ | ||
63 | |||
64 | struct clk_pll { | ||
65 | struct clk_hw hw; | ||
66 | unsigned short regofs; /* register offset */ | ||
57 | }; | 67 | }; |
58 | 68 | ||
59 | struct clk { | 69 | #define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw) |
60 | struct clk *parent; /* parent clk */ | 70 | |
61 | unsigned long rate; /* clock rate in Hz */ | 71 | struct clk_dmn { |
62 | signed char usage; /* clock enable count */ | 72 | struct clk_hw hw; |
63 | signed char enable_bit; /* enable bit: 0 ~ 63 */ | 73 | signed char enable_bit; /* enable bit: 0 ~ 63 */ |
64 | unsigned short regofs; /* register offset */ | 74 | unsigned short regofs; /* register offset */ |
65 | struct clk_ops *ops; /* clock operation */ | ||
66 | }; | 75 | }; |
67 | 76 | ||
68 | static DEFINE_SPINLOCK(clocks_lock); | 77 | #define to_dmnclk(_hw) container_of(_hw, struct clk_dmn, hw) |
78 | |||
79 | struct clk_std { | ||
80 | struct clk_hw hw; | ||
81 | signed char enable_bit; /* enable bit: 0 ~ 63 */ | ||
82 | }; | ||
83 | |||
84 | #define to_stdclk(_hw) container_of(_hw, struct clk_std, hw) | ||
85 | |||
86 | static int std_clk_is_enabled(struct clk_hw *hw); | ||
87 | static int std_clk_enable(struct clk_hw *hw); | ||
88 | static void std_clk_disable(struct clk_hw *hw); | ||
69 | 89 | ||
70 | static inline unsigned long clkc_readl(unsigned reg) | 90 | static inline unsigned long clkc_readl(unsigned reg) |
71 | { | 91 | { |
72 | return readl(SIRFSOC_CLOCK_VA_BASE + reg); | 92 | return readl(sirfsoc_clk_vbase + reg); |
73 | } | 93 | } |
74 | 94 | ||
75 | static inline void clkc_writel(u32 val, unsigned reg) | 95 | static inline void clkc_writel(u32 val, unsigned reg) |
76 | { | 96 | { |
77 | writel(val, SIRFSOC_CLOCK_VA_BASE + reg); | 97 | writel(val, sirfsoc_clk_vbase + reg); |
78 | } | 98 | } |
79 | 99 | ||
80 | /* | 100 | /* |
81 | * osc_rtc - real time oscillator - 32.768KHz | ||
82 | * osc_sys - high speed oscillator - 26MHz | ||
83 | */ | ||
84 | |||
85 | static struct clk clk_rtc = { | ||
86 | .rate = 32768, | ||
87 | }; | ||
88 | |||
89 | static struct clk clk_osc = { | ||
90 | .rate = 26 * MHZ, | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * std pll | 101 | * std pll |
95 | */ | 102 | */ |
96 | static unsigned long std_pll_get_rate(struct clk *clk) | 103 | |
104 | static unsigned long pll_clk_recalc_rate(struct clk_hw *hw, | ||
105 | unsigned long parent_rate) | ||
97 | { | 106 | { |
98 | unsigned long fin = clk_get_rate(clk->parent); | 107 | unsigned long fin = parent_rate; |
108 | struct clk_pll *clk = to_pllclk(hw); | ||
99 | u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - | 109 | u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - |
100 | SIRFSOC_CLKC_PLL1_CFG0; | 110 | SIRFSOC_CLKC_PLL1_CFG0; |
101 | 111 | ||
102 | if (clkc_readl(regcfg2) & BIT(2)) { | 112 | if (clkc_readl(regcfg2) & BIT(2)) { |
103 | /* pll bypass mode */ | 113 | /* pll bypass mode */ |
104 | clk->rate = fin; | 114 | return fin; |
105 | } else { | 115 | } else { |
106 | /* fout = fin * nf / nr / od */ | 116 | /* fout = fin * nf / nr / od */ |
107 | u32 cfg0 = clkc_readl(clk->regofs); | 117 | u32 cfg0 = clkc_readl(clk->regofs); |
@@ -109,14 +119,41 @@ static unsigned long std_pll_get_rate(struct clk *clk) | |||
109 | u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; | 119 | u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; |
110 | u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; | 120 | u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; |
111 | WARN_ON(fin % MHZ); | 121 | WARN_ON(fin % MHZ); |
112 | clk->rate = fin / MHZ * nf / nr / od * MHZ; | 122 | return fin / MHZ * nf / nr / od * MHZ; |
113 | } | 123 | } |
124 | } | ||
125 | |||
126 | static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
127 | unsigned long *parent_rate) | ||
128 | { | ||
129 | unsigned long fin, nf, nr, od; | ||
130 | |||
131 | /* | ||
132 | * fout = fin * nf / (nr * od); | ||
133 | * set od = 1, nr = fin/MHz, so fout = nf * MHz | ||
134 | */ | ||
135 | rate = rate - rate % MHZ; | ||
136 | |||
137 | nf = rate / MHZ; | ||
138 | if (nf > BIT(13)) | ||
139 | nf = BIT(13); | ||
140 | if (nf < 1) | ||
141 | nf = 1; | ||
114 | 142 | ||
115 | return clk->rate; | 143 | fin = *parent_rate; |
144 | |||
145 | nr = fin / MHZ; | ||
146 | if (nr > BIT(6)) | ||
147 | nr = BIT(6); | ||
148 | od = 1; | ||
149 | |||
150 | return fin * nf / (nr * od); | ||
116 | } | 151 | } |
117 | 152 | ||
118 | static int std_pll_set_rate(struct clk *clk, unsigned long rate) | 153 | static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
154 | unsigned long parent_rate) | ||
119 | { | 155 | { |
156 | struct clk_pll *clk = to_pllclk(hw); | ||
120 | unsigned long fin, nf, nr, od, reg; | 157 | unsigned long fin, nf, nr, od, reg; |
121 | 158 | ||
122 | /* | 159 | /* |
@@ -128,7 +165,7 @@ static int std_pll_set_rate(struct clk *clk, unsigned long rate) | |||
128 | if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) | 165 | if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) |
129 | return -EINVAL; | 166 | return -EINVAL; |
130 | 167 | ||
131 | fin = clk_get_rate(clk->parent); | 168 | fin = parent_rate; |
132 | BUG_ON(fin < MHZ); | 169 | BUG_ON(fin < MHZ); |
133 | 170 | ||
134 | nr = fin / MHZ; | 171 | nr = fin / MHZ; |
@@ -146,76 +183,163 @@ static int std_pll_set_rate(struct clk *clk, unsigned long rate) | |||
146 | while (!(clkc_readl(reg) & BIT(6))) | 183 | while (!(clkc_readl(reg) & BIT(6))) |
147 | cpu_relax(); | 184 | cpu_relax(); |
148 | 185 | ||
149 | clk->rate = 0; /* set to zero will force recalculation */ | ||
150 | return 0; | 186 | return 0; |
151 | } | 187 | } |
152 | 188 | ||
153 | static struct clk_ops std_pll_ops = { | 189 | static struct clk_ops std_pll_ops = { |
154 | .get_rate = std_pll_get_rate, | 190 | .recalc_rate = pll_clk_recalc_rate, |
155 | .set_rate = std_pll_set_rate, | 191 | .round_rate = pll_clk_round_rate, |
192 | .set_rate = pll_clk_set_rate, | ||
156 | }; | 193 | }; |
157 | 194 | ||
158 | static struct clk clk_pll1 = { | 195 | static const char *pll_clk_parents[] = { |
159 | .parent = &clk_osc, | 196 | "osc", |
160 | .regofs = SIRFSOC_CLKC_PLL1_CFG0, | 197 | }; |
198 | |||
199 | static struct clk_init_data clk_pll1_init = { | ||
200 | .name = "pll1", | ||
161 | .ops = &std_pll_ops, | 201 | .ops = &std_pll_ops, |
202 | .parent_names = pll_clk_parents, | ||
203 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
162 | }; | 204 | }; |
163 | 205 | ||
164 | static struct clk clk_pll2 = { | 206 | static struct clk_init_data clk_pll2_init = { |
165 | .parent = &clk_osc, | 207 | .name = "pll2", |
166 | .regofs = SIRFSOC_CLKC_PLL2_CFG0, | ||
167 | .ops = &std_pll_ops, | 208 | .ops = &std_pll_ops, |
209 | .parent_names = pll_clk_parents, | ||
210 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
168 | }; | 211 | }; |
169 | 212 | ||
170 | static struct clk clk_pll3 = { | 213 | static struct clk_init_data clk_pll3_init = { |
171 | .parent = &clk_osc, | 214 | .name = "pll3", |
172 | .regofs = SIRFSOC_CLKC_PLL3_CFG0, | ||
173 | .ops = &std_pll_ops, | 215 | .ops = &std_pll_ops, |
216 | .parent_names = pll_clk_parents, | ||
217 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
218 | }; | ||
219 | |||
220 | static struct clk_pll clk_pll1 = { | ||
221 | .regofs = SIRFSOC_CLKC_PLL1_CFG0, | ||
222 | .hw = { | ||
223 | .init = &clk_pll1_init, | ||
224 | }, | ||
225 | }; | ||
226 | |||
227 | static struct clk_pll clk_pll2 = { | ||
228 | .regofs = SIRFSOC_CLKC_PLL2_CFG0, | ||
229 | .hw = { | ||
230 | .init = &clk_pll2_init, | ||
231 | }, | ||
232 | }; | ||
233 | |||
234 | static struct clk_pll clk_pll3 = { | ||
235 | .regofs = SIRFSOC_CLKC_PLL3_CFG0, | ||
236 | .hw = { | ||
237 | .init = &clk_pll3_init, | ||
238 | }, | ||
174 | }; | 239 | }; |
175 | 240 | ||
176 | /* | 241 | /* |
177 | * clock domains - cpu, mem, sys/io | 242 | * usb uses specified pll |
178 | */ | 243 | */ |
179 | 244 | ||
180 | static struct clk clk_mem; | 245 | static int usb_pll_clk_enable(struct clk_hw *hw) |
246 | { | ||
247 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
248 | reg &= ~(SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); | ||
249 | writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
250 | while (!(readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL) & | ||
251 | SIRFSOC_USBPHY_PLL_LOCK)) | ||
252 | cpu_relax(); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static void usb_pll_clk_disable(struct clk_hw *clk) | ||
258 | { | ||
259 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
260 | reg |= (SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); | ||
261 | writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
262 | } | ||
181 | 263 | ||
182 | static struct clk *dmn_get_parent(struct clk *clk) | 264 | static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
183 | { | 265 | { |
184 | struct clk *clks[] = { | 266 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); |
185 | &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 | 267 | return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ; |
186 | }; | 268 | } |
269 | |||
270 | static struct clk_ops usb_pll_ops = { | ||
271 | .enable = usb_pll_clk_enable, | ||
272 | .disable = usb_pll_clk_disable, | ||
273 | .recalc_rate = usb_pll_clk_recalc_rate, | ||
274 | }; | ||
275 | |||
276 | static struct clk_init_data clk_usb_pll_init = { | ||
277 | .name = "usb_pll", | ||
278 | .ops = &usb_pll_ops, | ||
279 | .parent_names = pll_clk_parents, | ||
280 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
281 | }; | ||
282 | |||
283 | static struct clk_hw usb_pll_clk_hw = { | ||
284 | .init = &clk_usb_pll_init, | ||
285 | }; | ||
286 | |||
287 | /* | ||
288 | * clock domains - cpu, mem, sys/io, dsp, gfx | ||
289 | */ | ||
290 | |||
291 | static const char *dmn_clk_parents[] = { | ||
292 | "rtc", | ||
293 | "osc", | ||
294 | "pll1", | ||
295 | "pll2", | ||
296 | "pll3", | ||
297 | }; | ||
298 | |||
299 | static u8 dmn_clk_get_parent(struct clk_hw *hw) | ||
300 | { | ||
301 | struct clk_dmn *clk = to_dmnclk(hw); | ||
187 | u32 cfg = clkc_readl(clk->regofs); | 302 | u32 cfg = clkc_readl(clk->regofs); |
303 | |||
304 | /* parent of io domain can only be pll3 */ | ||
305 | if (strcmp(hw->init->name, "io") == 0) | ||
306 | return 4; | ||
307 | |||
188 | WARN_ON((cfg & (BIT(3) - 1)) > 4); | 308 | WARN_ON((cfg & (BIT(3) - 1)) > 4); |
189 | return clks[cfg & (BIT(3) - 1)]; | 309 | |
310 | return cfg & (BIT(3) - 1); | ||
190 | } | 311 | } |
191 | 312 | ||
192 | static int dmn_set_parent(struct clk *clk, struct clk *parent) | 313 | static int dmn_clk_set_parent(struct clk_hw *hw, u8 parent) |
193 | { | 314 | { |
194 | const struct clk *clks[] = { | 315 | struct clk_dmn *clk = to_dmnclk(hw); |
195 | &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 | ||
196 | }; | ||
197 | u32 cfg = clkc_readl(clk->regofs); | 316 | u32 cfg = clkc_readl(clk->regofs); |
198 | int i; | 317 | |
199 | for (i = 0; i < ARRAY_SIZE(clks); i++) { | 318 | /* parent of io domain can only be pll3 */ |
200 | if (clks[i] == parent) { | 319 | if (strcmp(hw->init->name, "io") == 0) |
201 | cfg &= ~(BIT(3) - 1); | 320 | return -EINVAL; |
202 | clkc_writel(cfg | i, clk->regofs); | 321 | |
203 | /* BIT(3) - switching status: 1 - busy, 0 - done */ | 322 | cfg &= ~(BIT(3) - 1); |
204 | while (clkc_readl(clk->regofs) & BIT(3)) | 323 | clkc_writel(cfg | parent, clk->regofs); |
205 | cpu_relax(); | 324 | /* BIT(3) - switching status: 1 - busy, 0 - done */ |
206 | return 0; | 325 | while (clkc_readl(clk->regofs) & BIT(3)) |
207 | } | 326 | cpu_relax(); |
208 | } | 327 | |
209 | return -EINVAL; | 328 | return 0; |
210 | } | 329 | } |
211 | 330 | ||
212 | static unsigned long dmn_get_rate(struct clk *clk) | 331 | static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw, |
332 | unsigned long parent_rate) | ||
333 | |||
213 | { | 334 | { |
214 | unsigned long fin = clk_get_rate(clk->parent); | 335 | unsigned long fin = parent_rate; |
336 | struct clk_dmn *clk = to_dmnclk(hw); | ||
337 | |||
215 | u32 cfg = clkc_readl(clk->regofs); | 338 | u32 cfg = clkc_readl(clk->regofs); |
339 | |||
216 | if (cfg & BIT(24)) { | 340 | if (cfg & BIT(24)) { |
217 | /* fcd bypass mode */ | 341 | /* fcd bypass mode */ |
218 | clk->rate = fin; | 342 | return fin; |
219 | } else { | 343 | } else { |
220 | /* | 344 | /* |
221 | * wait count: bit[19:16], hold count: bit[23:20] | 345 | * wait count: bit[19:16], hold count: bit[23:20] |
@@ -223,19 +347,40 @@ static unsigned long dmn_get_rate(struct clk *clk) | |||
223 | u32 wait = (cfg >> 16) & (BIT(4) - 1); | 347 | u32 wait = (cfg >> 16) & (BIT(4) - 1); |
224 | u32 hold = (cfg >> 20) & (BIT(4) - 1); | 348 | u32 hold = (cfg >> 20) & (BIT(4) - 1); |
225 | 349 | ||
226 | clk->rate = fin / (wait + hold + 2); | 350 | return fin / (wait + hold + 2); |
227 | } | 351 | } |
352 | } | ||
353 | |||
354 | static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
355 | unsigned long *parent_rate) | ||
356 | { | ||
357 | unsigned long fin; | ||
358 | unsigned ratio, wait, hold; | ||
359 | unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; | ||
360 | |||
361 | fin = *parent_rate; | ||
362 | ratio = fin / rate; | ||
363 | |||
364 | if (ratio < 2) | ||
365 | ratio = 2; | ||
366 | if (ratio > BIT(bits + 1)) | ||
367 | ratio = BIT(bits + 1); | ||
228 | 368 | ||
229 | return clk->rate; | 369 | wait = (ratio >> 1) - 1; |
370 | hold = ratio - wait - 2; | ||
371 | |||
372 | return fin / (wait + hold + 2); | ||
230 | } | 373 | } |
231 | 374 | ||
232 | static int dmn_set_rate(struct clk *clk, unsigned long rate) | 375 | static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
376 | unsigned long parent_rate) | ||
233 | { | 377 | { |
378 | struct clk_dmn *clk = to_dmnclk(hw); | ||
234 | unsigned long fin; | 379 | unsigned long fin; |
235 | unsigned ratio, wait, hold, reg; | 380 | unsigned ratio, wait, hold, reg; |
236 | unsigned bits = (clk == &clk_mem) ? 3 : 4; | 381 | unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; |
237 | 382 | ||
238 | fin = clk_get_rate(clk->parent); | 383 | fin = parent_rate; |
239 | ratio = fin / rate; | 384 | ratio = fin / rate; |
240 | 385 | ||
241 | if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) | 386 | if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) |
@@ -255,256 +400,772 @@ static int dmn_set_rate(struct clk *clk, unsigned long rate) | |||
255 | while (clkc_readl(clk->regofs) & BIT(25)) | 400 | while (clkc_readl(clk->regofs) & BIT(25)) |
256 | cpu_relax(); | 401 | cpu_relax(); |
257 | 402 | ||
258 | clk->rate = 0; /* set to zero will force recalculation */ | ||
259 | |||
260 | return 0; | 403 | return 0; |
261 | } | 404 | } |
262 | 405 | ||
263 | /* | 406 | static struct clk_ops msi_ops = { |
264 | * cpu clock has no FCD register in Prima2, can only change pll | 407 | .set_rate = dmn_clk_set_rate, |
265 | */ | 408 | .round_rate = dmn_clk_round_rate, |
266 | static int cpu_set_rate(struct clk *clk, unsigned long rate) | 409 | .recalc_rate = dmn_clk_recalc_rate, |
267 | { | 410 | .set_parent = dmn_clk_set_parent, |
268 | int ret1, ret2; | 411 | .get_parent = dmn_clk_get_parent, |
269 | struct clk *cur_parent, *tmp_parent; | 412 | }; |
270 | 413 | ||
271 | cur_parent = dmn_get_parent(clk); | 414 | static struct clk_init_data clk_mem_init = { |
272 | BUG_ON(cur_parent == NULL || cur_parent->usage > 1); | 415 | .name = "mem", |
416 | .ops = &msi_ops, | ||
417 | .parent_names = dmn_clk_parents, | ||
418 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
419 | }; | ||
273 | 420 | ||
274 | /* switch to tmp pll before setting parent clock's rate */ | 421 | static struct clk_dmn clk_mem = { |
275 | tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1; | 422 | .regofs = SIRFSOC_CLKC_MEM_CFG, |
276 | ret1 = dmn_set_parent(clk, tmp_parent); | 423 | .hw = { |
277 | BUG_ON(ret1); | 424 | .init = &clk_mem_init, |
425 | }, | ||
426 | }; | ||
278 | 427 | ||
279 | ret2 = clk_set_rate(cur_parent, rate); | 428 | static struct clk_init_data clk_sys_init = { |
429 | .name = "sys", | ||
430 | .ops = &msi_ops, | ||
431 | .parent_names = dmn_clk_parents, | ||
432 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
433 | .flags = CLK_SET_RATE_GATE, | ||
434 | }; | ||
280 | 435 | ||
281 | ret1 = dmn_set_parent(clk, cur_parent); | 436 | static struct clk_dmn clk_sys = { |
437 | .regofs = SIRFSOC_CLKC_SYS_CFG, | ||
438 | .hw = { | ||
439 | .init = &clk_sys_init, | ||
440 | }, | ||
441 | }; | ||
282 | 442 | ||
283 | clk->rate = 0; /* set to zero will force recalculation */ | 443 | static struct clk_init_data clk_io_init = { |
444 | .name = "io", | ||
445 | .ops = &msi_ops, | ||
446 | .parent_names = dmn_clk_parents, | ||
447 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
448 | }; | ||
284 | 449 | ||
285 | return ret2 ? ret2 : ret1; | 450 | static struct clk_dmn clk_io = { |
286 | } | 451 | .regofs = SIRFSOC_CLKC_IO_CFG, |
452 | .hw = { | ||
453 | .init = &clk_io_init, | ||
454 | }, | ||
455 | }; | ||
287 | 456 | ||
288 | static struct clk_ops cpu_ops = { | 457 | static struct clk_ops cpu_ops = { |
289 | .get_parent = dmn_get_parent, | 458 | .set_parent = dmn_clk_set_parent, |
290 | .set_parent = dmn_set_parent, | 459 | .get_parent = dmn_clk_get_parent, |
291 | .set_rate = cpu_set_rate, | ||
292 | }; | 460 | }; |
293 | 461 | ||
294 | static struct clk clk_cpu = { | 462 | static struct clk_init_data clk_cpu_init = { |
295 | .parent = &clk_pll1, | 463 | .name = "cpu", |
296 | .regofs = SIRFSOC_CLKC_CPU_CFG, | ||
297 | .ops = &cpu_ops, | 464 | .ops = &cpu_ops, |
465 | .parent_names = dmn_clk_parents, | ||
466 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
467 | .flags = CLK_SET_RATE_PARENT, | ||
298 | }; | 468 | }; |
299 | 469 | ||
470 | static struct clk_dmn clk_cpu = { | ||
471 | .regofs = SIRFSOC_CLKC_CPU_CFG, | ||
472 | .hw = { | ||
473 | .init = &clk_cpu_init, | ||
474 | }, | ||
475 | }; | ||
300 | 476 | ||
301 | static struct clk_ops msi_ops = { | 477 | static struct clk_ops dmn_ops = { |
302 | .set_rate = dmn_set_rate, | 478 | .is_enabled = std_clk_is_enabled, |
303 | .get_rate = dmn_get_rate, | 479 | .enable = std_clk_enable, |
304 | .set_parent = dmn_set_parent, | 480 | .disable = std_clk_disable, |
305 | .get_parent = dmn_get_parent, | 481 | .set_rate = dmn_clk_set_rate, |
482 | .round_rate = dmn_clk_round_rate, | ||
483 | .recalc_rate = dmn_clk_recalc_rate, | ||
484 | .set_parent = dmn_clk_set_parent, | ||
485 | .get_parent = dmn_clk_get_parent, | ||
306 | }; | 486 | }; |
307 | 487 | ||
308 | static struct clk clk_mem = { | 488 | /* dsp, gfx, mm, lcd and vpp domain */ |
309 | .parent = &clk_pll2, | 489 | |
310 | .regofs = SIRFSOC_CLKC_MEM_CFG, | 490 | static struct clk_init_data clk_dsp_init = { |
311 | .ops = &msi_ops, | 491 | .name = "dsp", |
492 | .ops = &dmn_ops, | ||
493 | .parent_names = dmn_clk_parents, | ||
494 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
312 | }; | 495 | }; |
313 | 496 | ||
314 | static struct clk clk_sys = { | 497 | static struct clk_dmn clk_dsp = { |
315 | .parent = &clk_pll3, | 498 | .regofs = SIRFSOC_CLKC_DSP_CFG, |
316 | .regofs = SIRFSOC_CLKC_SYS_CFG, | 499 | .enable_bit = 0, |
317 | .ops = &msi_ops, | 500 | .hw = { |
501 | .init = &clk_dsp_init, | ||
502 | }, | ||
318 | }; | 503 | }; |
319 | 504 | ||
320 | static struct clk clk_io = { | 505 | static struct clk_init_data clk_gfx_init = { |
321 | .parent = &clk_pll3, | 506 | .name = "gfx", |
322 | .regofs = SIRFSOC_CLKC_IO_CFG, | 507 | .ops = &dmn_ops, |
323 | .ops = &msi_ops, | 508 | .parent_names = dmn_clk_parents, |
509 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
324 | }; | 510 | }; |
325 | 511 | ||
326 | /* | 512 | static struct clk_dmn clk_gfx = { |
327 | * on-chip clock sets | 513 | .regofs = SIRFSOC_CLKC_GFX_CFG, |
328 | */ | 514 | .enable_bit = 8, |
329 | static struct clk_lookup onchip_clks[] = { | 515 | .hw = { |
330 | { | 516 | .init = &clk_gfx_init, |
331 | .dev_id = "rtc", | 517 | }, |
332 | .clk = &clk_rtc, | 518 | }; |
333 | }, { | ||
334 | .dev_id = "osc", | ||
335 | .clk = &clk_osc, | ||
336 | }, { | ||
337 | .dev_id = "pll1", | ||
338 | .clk = &clk_pll1, | ||
339 | }, { | ||
340 | .dev_id = "pll2", | ||
341 | .clk = &clk_pll2, | ||
342 | }, { | ||
343 | .dev_id = "pll3", | ||
344 | .clk = &clk_pll3, | ||
345 | }, { | ||
346 | .dev_id = "cpu", | ||
347 | .clk = &clk_cpu, | ||
348 | }, { | ||
349 | .dev_id = "mem", | ||
350 | .clk = &clk_mem, | ||
351 | }, { | ||
352 | .dev_id = "sys", | ||
353 | .clk = &clk_sys, | ||
354 | }, { | ||
355 | .dev_id = "io", | ||
356 | .clk = &clk_io, | ||
357 | }, | ||
358 | }; | ||
359 | |||
360 | int clk_enable(struct clk *clk) | ||
361 | { | ||
362 | unsigned long flags; | ||
363 | 519 | ||
364 | if (unlikely(IS_ERR_OR_NULL(clk))) | 520 | static struct clk_init_data clk_mm_init = { |
365 | return -EINVAL; | 521 | .name = "mm", |
522 | .ops = &dmn_ops, | ||
523 | .parent_names = dmn_clk_parents, | ||
524 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
525 | }; | ||
366 | 526 | ||
367 | if (clk->parent) | 527 | static struct clk_dmn clk_mm = { |
368 | clk_enable(clk->parent); | 528 | .regofs = SIRFSOC_CLKC_MM_CFG, |
529 | .enable_bit = 9, | ||
530 | .hw = { | ||
531 | .init = &clk_mm_init, | ||
532 | }, | ||
533 | }; | ||
369 | 534 | ||
370 | spin_lock_irqsave(&clocks_lock, flags); | 535 | static struct clk_init_data clk_lcd_init = { |
371 | if (!clk->usage++ && clk->ops && clk->ops->enable) | 536 | .name = "lcd", |
372 | clk->ops->enable(clk); | 537 | .ops = &dmn_ops, |
373 | spin_unlock_irqrestore(&clocks_lock, flags); | 538 | .parent_names = dmn_clk_parents, |
374 | return 0; | 539 | .num_parents = ARRAY_SIZE(dmn_clk_parents), |
375 | } | 540 | }; |
376 | EXPORT_SYMBOL(clk_enable); | ||
377 | 541 | ||
378 | void clk_disable(struct clk *clk) | 542 | static struct clk_dmn clk_lcd = { |
379 | { | 543 | .regofs = SIRFSOC_CLKC_LCD_CFG, |
380 | unsigned long flags; | 544 | .enable_bit = 10, |
545 | .hw = { | ||
546 | .init = &clk_lcd_init, | ||
547 | }, | ||
548 | }; | ||
381 | 549 | ||
382 | if (unlikely(IS_ERR_OR_NULL(clk))) | 550 | static struct clk_init_data clk_vpp_init = { |
383 | return; | 551 | .name = "vpp", |
552 | .ops = &dmn_ops, | ||
553 | .parent_names = dmn_clk_parents, | ||
554 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
555 | }; | ||
384 | 556 | ||
385 | WARN_ON(!clk->usage); | 557 | static struct clk_dmn clk_vpp = { |
558 | .regofs = SIRFSOC_CLKC_LCD_CFG, | ||
559 | .enable_bit = 11, | ||
560 | .hw = { | ||
561 | .init = &clk_vpp_init, | ||
562 | }, | ||
563 | }; | ||
386 | 564 | ||
387 | spin_lock_irqsave(&clocks_lock, flags); | 565 | static struct clk_init_data clk_mmc01_init = { |
388 | if (--clk->usage == 0 && clk->ops && clk->ops->disable) | 566 | .name = "mmc01", |
389 | clk->ops->disable(clk); | 567 | .ops = &dmn_ops, |
390 | spin_unlock_irqrestore(&clocks_lock, flags); | 568 | .parent_names = dmn_clk_parents, |
569 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
570 | }; | ||
391 | 571 | ||
392 | if (clk->parent) | 572 | static struct clk_dmn clk_mmc01 = { |
393 | clk_disable(clk->parent); | 573 | .regofs = SIRFSOC_CLKC_MMC_CFG, |
394 | } | 574 | .enable_bit = 59, |
395 | EXPORT_SYMBOL(clk_disable); | 575 | .hw = { |
576 | .init = &clk_mmc01_init, | ||
577 | }, | ||
578 | }; | ||
396 | 579 | ||
397 | unsigned long clk_get_rate(struct clk *clk) | 580 | static struct clk_init_data clk_mmc23_init = { |
398 | { | 581 | .name = "mmc23", |
399 | if (unlikely(IS_ERR_OR_NULL(clk))) | 582 | .ops = &dmn_ops, |
400 | return 0; | 583 | .parent_names = dmn_clk_parents, |
584 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
585 | }; | ||
401 | 586 | ||
402 | if (clk->rate) | 587 | static struct clk_dmn clk_mmc23 = { |
403 | return clk->rate; | 588 | .regofs = SIRFSOC_CLKC_MMC_CFG, |
589 | .enable_bit = 60, | ||
590 | .hw = { | ||
591 | .init = &clk_mmc23_init, | ||
592 | }, | ||
593 | }; | ||
404 | 594 | ||
405 | if (clk->ops && clk->ops->get_rate) | 595 | static struct clk_init_data clk_mmc45_init = { |
406 | return clk->ops->get_rate(clk); | 596 | .name = "mmc45", |
597 | .ops = &dmn_ops, | ||
598 | .parent_names = dmn_clk_parents, | ||
599 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
600 | }; | ||
407 | 601 | ||
408 | return clk_get_rate(clk->parent); | 602 | static struct clk_dmn clk_mmc45 = { |
409 | } | 603 | .regofs = SIRFSOC_CLKC_MMC_CFG, |
410 | EXPORT_SYMBOL(clk_get_rate); | 604 | .enable_bit = 61, |
605 | .hw = { | ||
606 | .init = &clk_mmc45_init, | ||
607 | }, | ||
608 | }; | ||
411 | 609 | ||
412 | long clk_round_rate(struct clk *clk, unsigned long rate) | 610 | /* |
611 | * peripheral controllers in io domain | ||
612 | */ | ||
613 | |||
614 | static int std_clk_is_enabled(struct clk_hw *hw) | ||
413 | { | 615 | { |
414 | if (unlikely(IS_ERR_OR_NULL(clk))) | 616 | u32 reg; |
415 | return 0; | 617 | int bit; |
618 | struct clk_std *clk = to_stdclk(hw); | ||
416 | 619 | ||
417 | if (clk->ops && clk->ops->round_rate) | 620 | bit = clk->enable_bit % 32; |
418 | return clk->ops->round_rate(clk, rate); | 621 | reg = clk->enable_bit / 32; |
622 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | ||
419 | 623 | ||
420 | return 0; | 624 | return !!(clkc_readl(reg) & BIT(bit)); |
421 | } | 625 | } |
422 | EXPORT_SYMBOL(clk_round_rate); | ||
423 | 626 | ||
424 | int clk_set_rate(struct clk *clk, unsigned long rate) | 627 | static int std_clk_enable(struct clk_hw *hw) |
425 | { | 628 | { |
426 | if (unlikely(IS_ERR_OR_NULL(clk))) | 629 | u32 val, reg; |
427 | return -EINVAL; | 630 | int bit; |
631 | struct clk_std *clk = to_stdclk(hw); | ||
428 | 632 | ||
429 | if (!clk->ops || !clk->ops->set_rate) | 633 | BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); |
430 | return -EINVAL; | 634 | |
635 | bit = clk->enable_bit % 32; | ||
636 | reg = clk->enable_bit / 32; | ||
637 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | ||
431 | 638 | ||
432 | return clk->ops->set_rate(clk, rate); | 639 | val = clkc_readl(reg) | BIT(bit); |
640 | clkc_writel(val, reg); | ||
641 | return 0; | ||
433 | } | 642 | } |
434 | EXPORT_SYMBOL(clk_set_rate); | ||
435 | 643 | ||
436 | int clk_set_parent(struct clk *clk, struct clk *parent) | 644 | static void std_clk_disable(struct clk_hw *hw) |
437 | { | 645 | { |
438 | int ret; | 646 | u32 val, reg; |
439 | unsigned long flags; | 647 | int bit; |
648 | struct clk_std *clk = to_stdclk(hw); | ||
440 | 649 | ||
441 | if (unlikely(IS_ERR_OR_NULL(clk))) | 650 | BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); |
442 | return -EINVAL; | ||
443 | 651 | ||
444 | if (!clk->ops || !clk->ops->set_parent) | 652 | bit = clk->enable_bit % 32; |
445 | return -EINVAL; | 653 | reg = clk->enable_bit / 32; |
654 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | ||
446 | 655 | ||
447 | spin_lock_irqsave(&clocks_lock, flags); | 656 | val = clkc_readl(reg) & ~BIT(bit); |
448 | ret = clk->ops->set_parent(clk, parent); | 657 | clkc_writel(val, reg); |
449 | if (!ret) { | ||
450 | parent->usage += clk->usage; | ||
451 | clk->parent->usage -= clk->usage; | ||
452 | BUG_ON(clk->parent->usage < 0); | ||
453 | clk->parent = parent; | ||
454 | } | ||
455 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
456 | return ret; | ||
457 | } | 658 | } |
458 | EXPORT_SYMBOL(clk_set_parent); | ||
459 | 659 | ||
460 | struct clk *clk_get_parent(struct clk *clk) | 660 | static const char *std_clk_io_parents[] = { |
461 | { | 661 | "io", |
462 | unsigned long flags; | 662 | }; |
463 | 663 | ||
464 | if (unlikely(IS_ERR_OR_NULL(clk))) | 664 | static struct clk_ops ios_ops = { |
465 | return NULL; | 665 | .is_enabled = std_clk_is_enabled, |
666 | .enable = std_clk_enable, | ||
667 | .disable = std_clk_disable, | ||
668 | }; | ||
466 | 669 | ||
467 | if (!clk->ops || !clk->ops->get_parent) | 670 | static struct clk_init_data clk_dmac0_init = { |
468 | return clk->parent; | 671 | .name = "dmac0", |
672 | .ops = &ios_ops, | ||
673 | .parent_names = std_clk_io_parents, | ||
674 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
675 | }; | ||
469 | 676 | ||
470 | spin_lock_irqsave(&clocks_lock, flags); | 677 | static struct clk_std clk_dmac0 = { |
471 | clk->parent = clk->ops->get_parent(clk); | 678 | .enable_bit = 32, |
472 | spin_unlock_irqrestore(&clocks_lock, flags); | 679 | .hw = { |
473 | return clk->parent; | 680 | .init = &clk_dmac0_init, |
474 | } | 681 | }, |
475 | EXPORT_SYMBOL(clk_get_parent); | 682 | }; |
476 | 683 | ||
477 | static void __init sirfsoc_clk_init(void) | 684 | static struct clk_init_data clk_dmac1_init = { |
478 | { | 685 | .name = "dmac1", |
479 | clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks)); | 686 | .ops = &ios_ops, |
480 | } | 687 | .parent_names = std_clk_io_parents, |
688 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
689 | }; | ||
690 | |||
691 | static struct clk_std clk_dmac1 = { | ||
692 | .enable_bit = 33, | ||
693 | .hw = { | ||
694 | .init = &clk_dmac1_init, | ||
695 | }, | ||
696 | }; | ||
697 | |||
698 | static struct clk_init_data clk_nand_init = { | ||
699 | .name = "nand", | ||
700 | .ops = &ios_ops, | ||
701 | .parent_names = std_clk_io_parents, | ||
702 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
703 | }; | ||
704 | |||
705 | static struct clk_std clk_nand = { | ||
706 | .enable_bit = 34, | ||
707 | .hw = { | ||
708 | .init = &clk_nand_init, | ||
709 | }, | ||
710 | }; | ||
711 | |||
712 | static struct clk_init_data clk_audio_init = { | ||
713 | .name = "audio", | ||
714 | .ops = &ios_ops, | ||
715 | .parent_names = std_clk_io_parents, | ||
716 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
717 | }; | ||
718 | |||
719 | static struct clk_std clk_audio = { | ||
720 | .enable_bit = 35, | ||
721 | .hw = { | ||
722 | .init = &clk_audio_init, | ||
723 | }, | ||
724 | }; | ||
725 | |||
726 | static struct clk_init_data clk_uart0_init = { | ||
727 | .name = "uart0", | ||
728 | .ops = &ios_ops, | ||
729 | .parent_names = std_clk_io_parents, | ||
730 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
731 | }; | ||
732 | |||
733 | static struct clk_std clk_uart0 = { | ||
734 | .enable_bit = 36, | ||
735 | .hw = { | ||
736 | .init = &clk_uart0_init, | ||
737 | }, | ||
738 | }; | ||
739 | |||
740 | static struct clk_init_data clk_uart1_init = { | ||
741 | .name = "uart1", | ||
742 | .ops = &ios_ops, | ||
743 | .parent_names = std_clk_io_parents, | ||
744 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
745 | }; | ||
746 | |||
747 | static struct clk_std clk_uart1 = { | ||
748 | .enable_bit = 37, | ||
749 | .hw = { | ||
750 | .init = &clk_uart1_init, | ||
751 | }, | ||
752 | }; | ||
753 | |||
754 | static struct clk_init_data clk_uart2_init = { | ||
755 | .name = "uart2", | ||
756 | .ops = &ios_ops, | ||
757 | .parent_names = std_clk_io_parents, | ||
758 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
759 | }; | ||
760 | |||
761 | static struct clk_std clk_uart2 = { | ||
762 | .enable_bit = 38, | ||
763 | .hw = { | ||
764 | .init = &clk_uart2_init, | ||
765 | }, | ||
766 | }; | ||
767 | |||
768 | static struct clk_init_data clk_usp0_init = { | ||
769 | .name = "usp0", | ||
770 | .ops = &ios_ops, | ||
771 | .parent_names = std_clk_io_parents, | ||
772 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
773 | }; | ||
774 | |||
775 | static struct clk_std clk_usp0 = { | ||
776 | .enable_bit = 39, | ||
777 | .hw = { | ||
778 | .init = &clk_usp0_init, | ||
779 | }, | ||
780 | }; | ||
781 | |||
782 | static struct clk_init_data clk_usp1_init = { | ||
783 | .name = "usp1", | ||
784 | .ops = &ios_ops, | ||
785 | .parent_names = std_clk_io_parents, | ||
786 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
787 | }; | ||
788 | |||
789 | static struct clk_std clk_usp1 = { | ||
790 | .enable_bit = 40, | ||
791 | .hw = { | ||
792 | .init = &clk_usp1_init, | ||
793 | }, | ||
794 | }; | ||
795 | |||
796 | static struct clk_init_data clk_usp2_init = { | ||
797 | .name = "usp2", | ||
798 | .ops = &ios_ops, | ||
799 | .parent_names = std_clk_io_parents, | ||
800 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
801 | }; | ||
802 | |||
803 | static struct clk_std clk_usp2 = { | ||
804 | .enable_bit = 41, | ||
805 | .hw = { | ||
806 | .init = &clk_usp2_init, | ||
807 | }, | ||
808 | }; | ||
809 | |||
810 | static struct clk_init_data clk_vip_init = { | ||
811 | .name = "vip", | ||
812 | .ops = &ios_ops, | ||
813 | .parent_names = std_clk_io_parents, | ||
814 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
815 | }; | ||
816 | |||
817 | static struct clk_std clk_vip = { | ||
818 | .enable_bit = 42, | ||
819 | .hw = { | ||
820 | .init = &clk_vip_init, | ||
821 | }, | ||
822 | }; | ||
823 | |||
824 | static struct clk_init_data clk_spi0_init = { | ||
825 | .name = "spi0", | ||
826 | .ops = &ios_ops, | ||
827 | .parent_names = std_clk_io_parents, | ||
828 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
829 | }; | ||
830 | |||
831 | static struct clk_std clk_spi0 = { | ||
832 | .enable_bit = 43, | ||
833 | .hw = { | ||
834 | .init = &clk_spi0_init, | ||
835 | }, | ||
836 | }; | ||
837 | |||
838 | static struct clk_init_data clk_spi1_init = { | ||
839 | .name = "spi1", | ||
840 | .ops = &ios_ops, | ||
841 | .parent_names = std_clk_io_parents, | ||
842 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
843 | }; | ||
844 | |||
845 | static struct clk_std clk_spi1 = { | ||
846 | .enable_bit = 44, | ||
847 | .hw = { | ||
848 | .init = &clk_spi1_init, | ||
849 | }, | ||
850 | }; | ||
851 | |||
852 | static struct clk_init_data clk_tsc_init = { | ||
853 | .name = "tsc", | ||
854 | .ops = &ios_ops, | ||
855 | .parent_names = std_clk_io_parents, | ||
856 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
857 | }; | ||
858 | |||
859 | static struct clk_std clk_tsc = { | ||
860 | .enable_bit = 45, | ||
861 | .hw = { | ||
862 | .init = &clk_tsc_init, | ||
863 | }, | ||
864 | }; | ||
865 | |||
866 | static struct clk_init_data clk_i2c0_init = { | ||
867 | .name = "i2c0", | ||
868 | .ops = &ios_ops, | ||
869 | .parent_names = std_clk_io_parents, | ||
870 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
871 | }; | ||
872 | |||
873 | static struct clk_std clk_i2c0 = { | ||
874 | .enable_bit = 46, | ||
875 | .hw = { | ||
876 | .init = &clk_i2c0_init, | ||
877 | }, | ||
878 | }; | ||
879 | |||
880 | static struct clk_init_data clk_i2c1_init = { | ||
881 | .name = "i2c1", | ||
882 | .ops = &ios_ops, | ||
883 | .parent_names = std_clk_io_parents, | ||
884 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
885 | }; | ||
886 | |||
887 | static struct clk_std clk_i2c1 = { | ||
888 | .enable_bit = 47, | ||
889 | .hw = { | ||
890 | .init = &clk_i2c1_init, | ||
891 | }, | ||
892 | }; | ||
893 | |||
894 | static struct clk_init_data clk_pwmc_init = { | ||
895 | .name = "pwmc", | ||
896 | .ops = &ios_ops, | ||
897 | .parent_names = std_clk_io_parents, | ||
898 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
899 | }; | ||
900 | |||
901 | static struct clk_std clk_pwmc = { | ||
902 | .enable_bit = 48, | ||
903 | .hw = { | ||
904 | .init = &clk_pwmc_init, | ||
905 | }, | ||
906 | }; | ||
907 | |||
908 | static struct clk_init_data clk_efuse_init = { | ||
909 | .name = "efuse", | ||
910 | .ops = &ios_ops, | ||
911 | .parent_names = std_clk_io_parents, | ||
912 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
913 | }; | ||
914 | |||
915 | static struct clk_std clk_efuse = { | ||
916 | .enable_bit = 49, | ||
917 | .hw = { | ||
918 | .init = &clk_efuse_init, | ||
919 | }, | ||
920 | }; | ||
921 | |||
922 | static struct clk_init_data clk_pulse_init = { | ||
923 | .name = "pulse", | ||
924 | .ops = &ios_ops, | ||
925 | .parent_names = std_clk_io_parents, | ||
926 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
927 | }; | ||
928 | |||
929 | static struct clk_std clk_pulse = { | ||
930 | .enable_bit = 50, | ||
931 | .hw = { | ||
932 | .init = &clk_pulse_init, | ||
933 | }, | ||
934 | }; | ||
935 | |||
936 | static const char *std_clk_dsp_parents[] = { | ||
937 | "dsp", | ||
938 | }; | ||
939 | |||
940 | static struct clk_init_data clk_gps_init = { | ||
941 | .name = "gps", | ||
942 | .ops = &ios_ops, | ||
943 | .parent_names = std_clk_dsp_parents, | ||
944 | .num_parents = ARRAY_SIZE(std_clk_dsp_parents), | ||
945 | }; | ||
946 | |||
947 | static struct clk_std clk_gps = { | ||
948 | .enable_bit = 1, | ||
949 | .hw = { | ||
950 | .init = &clk_gps_init, | ||
951 | }, | ||
952 | }; | ||
953 | |||
954 | static struct clk_init_data clk_mf_init = { | ||
955 | .name = "mf", | ||
956 | .ops = &ios_ops, | ||
957 | .parent_names = std_clk_io_parents, | ||
958 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
959 | }; | ||
960 | |||
961 | static struct clk_std clk_mf = { | ||
962 | .enable_bit = 2, | ||
963 | .hw = { | ||
964 | .init = &clk_mf_init, | ||
965 | }, | ||
966 | }; | ||
967 | |||
968 | static const char *std_clk_sys_parents[] = { | ||
969 | "sys", | ||
970 | }; | ||
971 | |||
972 | static struct clk_init_data clk_security_init = { | ||
973 | .name = "mf", | ||
974 | .ops = &ios_ops, | ||
975 | .parent_names = std_clk_sys_parents, | ||
976 | .num_parents = ARRAY_SIZE(std_clk_sys_parents), | ||
977 | }; | ||
978 | |||
979 | static struct clk_std clk_security = { | ||
980 | .enable_bit = 19, | ||
981 | .hw = { | ||
982 | .init = &clk_security_init, | ||
983 | }, | ||
984 | }; | ||
985 | |||
986 | static const char *std_clk_usb_parents[] = { | ||
987 | "usb_pll", | ||
988 | }; | ||
989 | |||
990 | static struct clk_init_data clk_usb0_init = { | ||
991 | .name = "usb0", | ||
992 | .ops = &ios_ops, | ||
993 | .parent_names = std_clk_usb_parents, | ||
994 | .num_parents = ARRAY_SIZE(std_clk_usb_parents), | ||
995 | }; | ||
996 | |||
997 | static struct clk_std clk_usb0 = { | ||
998 | .enable_bit = 16, | ||
999 | .hw = { | ||
1000 | .init = &clk_usb0_init, | ||
1001 | }, | ||
1002 | }; | ||
1003 | |||
1004 | static struct clk_init_data clk_usb1_init = { | ||
1005 | .name = "usb1", | ||
1006 | .ops = &ios_ops, | ||
1007 | .parent_names = std_clk_usb_parents, | ||
1008 | .num_parents = ARRAY_SIZE(std_clk_usb_parents), | ||
1009 | }; | ||
1010 | |||
1011 | static struct clk_std clk_usb1 = { | ||
1012 | .enable_bit = 17, | ||
1013 | .hw = { | ||
1014 | .init = &clk_usb1_init, | ||
1015 | }, | ||
1016 | }; | ||
481 | 1017 | ||
482 | static struct of_device_id clkc_ids[] = { | 1018 | static struct of_device_id clkc_ids[] = { |
483 | { .compatible = "sirf,prima2-clkc" }, | 1019 | { .compatible = "sirf,prima2-clkc" }, |
484 | {}, | 1020 | {}, |
485 | }; | 1021 | }; |
486 | 1022 | ||
1023 | static struct of_device_id rsc_ids[] = { | ||
1024 | { .compatible = "sirf,prima2-rsc" }, | ||
1025 | {}, | ||
1026 | }; | ||
1027 | |||
487 | void __init sirfsoc_of_clk_init(void) | 1028 | void __init sirfsoc_of_clk_init(void) |
488 | { | 1029 | { |
1030 | struct clk *clk; | ||
489 | struct device_node *np; | 1031 | struct device_node *np; |
490 | struct resource res; | ||
491 | struct map_desc sirfsoc_clkc_iodesc = { | ||
492 | .virtual = SIRFSOC_CLOCK_VA_BASE, | ||
493 | .type = MT_DEVICE, | ||
494 | }; | ||
495 | 1032 | ||
496 | np = of_find_matching_node(NULL, clkc_ids); | 1033 | np = of_find_matching_node(NULL, clkc_ids); |
497 | if (!np) | 1034 | if (!np) |
498 | panic("unable to find compatible clkc node in dtb\n"); | 1035 | panic("unable to find compatible clkc node in dtb\n"); |
499 | 1036 | ||
500 | if (of_address_to_resource(np, 0, &res)) | 1037 | sirfsoc_clk_vbase = of_iomap(np, 0); |
501 | panic("unable to find clkc range in dtb"); | 1038 | if (!sirfsoc_clk_vbase) |
1039 | panic("unable to map clkc registers\n"); | ||
1040 | |||
502 | of_node_put(np); | 1041 | of_node_put(np); |
503 | 1042 | ||
504 | sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start); | 1043 | np = of_find_matching_node(NULL, rsc_ids); |
505 | sirfsoc_clkc_iodesc.length = 1 + res.end - res.start; | 1044 | if (!np) |
1045 | panic("unable to find compatible rsc node in dtb\n"); | ||
1046 | |||
1047 | sirfsoc_rsc_vbase = of_iomap(np, 0); | ||
1048 | if (!sirfsoc_rsc_vbase) | ||
1049 | panic("unable to map rsc registers\n"); | ||
1050 | |||
1051 | of_node_put(np); | ||
506 | 1052 | ||
507 | iotable_init(&sirfsoc_clkc_iodesc, 1); | ||
508 | 1053 | ||
509 | sirfsoc_clk_init(); | 1054 | /* These are always available (RTC and 26MHz OSC)*/ |
1055 | clk = clk_register_fixed_rate(NULL, "rtc", NULL, | ||
1056 | CLK_IS_ROOT, 32768); | ||
1057 | BUG_ON(!clk); | ||
1058 | clk = clk_register_fixed_rate(NULL, "osc", NULL, | ||
1059 | CLK_IS_ROOT, 26000000); | ||
1060 | BUG_ON(!clk); | ||
1061 | |||
1062 | clk = clk_register(NULL, &clk_pll1.hw); | ||
1063 | BUG_ON(!clk); | ||
1064 | clk = clk_register(NULL, &clk_pll2.hw); | ||
1065 | BUG_ON(!clk); | ||
1066 | clk = clk_register(NULL, &clk_pll3.hw); | ||
1067 | BUG_ON(!clk); | ||
1068 | clk = clk_register(NULL, &clk_mem.hw); | ||
1069 | BUG_ON(!clk); | ||
1070 | clk = clk_register(NULL, &clk_sys.hw); | ||
1071 | BUG_ON(!clk); | ||
1072 | clk = clk_register(NULL, &clk_security.hw); | ||
1073 | BUG_ON(!clk); | ||
1074 | clk_register_clkdev(clk, NULL, "b8030000.security"); | ||
1075 | clk = clk_register(NULL, &clk_dsp.hw); | ||
1076 | BUG_ON(!clk); | ||
1077 | clk = clk_register(NULL, &clk_gps.hw); | ||
1078 | BUG_ON(!clk); | ||
1079 | clk_register_clkdev(clk, NULL, "a8010000.gps"); | ||
1080 | clk = clk_register(NULL, &clk_mf.hw); | ||
1081 | BUG_ON(!clk); | ||
1082 | clk = clk_register(NULL, &clk_io.hw); | ||
1083 | BUG_ON(!clk); | ||
1084 | clk_register_clkdev(clk, NULL, "io"); | ||
1085 | clk = clk_register(NULL, &clk_cpu.hw); | ||
1086 | BUG_ON(!clk); | ||
1087 | clk_register_clkdev(clk, NULL, "cpu"); | ||
1088 | clk = clk_register(NULL, &clk_uart0.hw); | ||
1089 | BUG_ON(!clk); | ||
1090 | clk_register_clkdev(clk, NULL, "b0050000.uart"); | ||
1091 | clk = clk_register(NULL, &clk_uart1.hw); | ||
1092 | BUG_ON(!clk); | ||
1093 | clk_register_clkdev(clk, NULL, "b0060000.uart"); | ||
1094 | clk = clk_register(NULL, &clk_uart2.hw); | ||
1095 | BUG_ON(!clk); | ||
1096 | clk_register_clkdev(clk, NULL, "b0070000.uart"); | ||
1097 | clk = clk_register(NULL, &clk_tsc.hw); | ||
1098 | BUG_ON(!clk); | ||
1099 | clk_register_clkdev(clk, NULL, "b0110000.tsc"); | ||
1100 | clk = clk_register(NULL, &clk_i2c0.hw); | ||
1101 | BUG_ON(!clk); | ||
1102 | clk_register_clkdev(clk, NULL, "b00e0000.i2c"); | ||
1103 | clk = clk_register(NULL, &clk_i2c1.hw); | ||
1104 | BUG_ON(!clk); | ||
1105 | clk_register_clkdev(clk, NULL, "b00f0000.i2c"); | ||
1106 | clk = clk_register(NULL, &clk_spi0.hw); | ||
1107 | BUG_ON(!clk); | ||
1108 | clk_register_clkdev(clk, NULL, "b00d0000.spi"); | ||
1109 | clk = clk_register(NULL, &clk_spi1.hw); | ||
1110 | BUG_ON(!clk); | ||
1111 | clk_register_clkdev(clk, NULL, "b0170000.spi"); | ||
1112 | clk = clk_register(NULL, &clk_pwmc.hw); | ||
1113 | BUG_ON(!clk); | ||
1114 | clk_register_clkdev(clk, NULL, "b0130000.pwm"); | ||
1115 | clk = clk_register(NULL, &clk_efuse.hw); | ||
1116 | BUG_ON(!clk); | ||
1117 | clk_register_clkdev(clk, NULL, "b0140000.efusesys"); | ||
1118 | clk = clk_register(NULL, &clk_pulse.hw); | ||
1119 | BUG_ON(!clk); | ||
1120 | clk_register_clkdev(clk, NULL, "b0150000.pulsec"); | ||
1121 | clk = clk_register(NULL, &clk_dmac0.hw); | ||
1122 | BUG_ON(!clk); | ||
1123 | clk_register_clkdev(clk, NULL, "b00b0000.dma-controller"); | ||
1124 | clk = clk_register(NULL, &clk_dmac1.hw); | ||
1125 | BUG_ON(!clk); | ||
1126 | clk_register_clkdev(clk, NULL, "b0160000.dma-controller"); | ||
1127 | clk = clk_register(NULL, &clk_nand.hw); | ||
1128 | BUG_ON(!clk); | ||
1129 | clk_register_clkdev(clk, NULL, "b0030000.nand"); | ||
1130 | clk = clk_register(NULL, &clk_audio.hw); | ||
1131 | BUG_ON(!clk); | ||
1132 | clk_register_clkdev(clk, NULL, "b0040000.audio"); | ||
1133 | clk = clk_register(NULL, &clk_usp0.hw); | ||
1134 | BUG_ON(!clk); | ||
1135 | clk_register_clkdev(clk, NULL, "b0080000.usp"); | ||
1136 | clk = clk_register(NULL, &clk_usp1.hw); | ||
1137 | BUG_ON(!clk); | ||
1138 | clk_register_clkdev(clk, NULL, "b0090000.usp"); | ||
1139 | clk = clk_register(NULL, &clk_usp2.hw); | ||
1140 | BUG_ON(!clk); | ||
1141 | clk_register_clkdev(clk, NULL, "b00a0000.usp"); | ||
1142 | clk = clk_register(NULL, &clk_vip.hw); | ||
1143 | BUG_ON(!clk); | ||
1144 | clk_register_clkdev(clk, NULL, "b00c0000.vip"); | ||
1145 | clk = clk_register(NULL, &clk_gfx.hw); | ||
1146 | BUG_ON(!clk); | ||
1147 | clk_register_clkdev(clk, NULL, "98000000.graphics"); | ||
1148 | clk = clk_register(NULL, &clk_mm.hw); | ||
1149 | BUG_ON(!clk); | ||
1150 | clk_register_clkdev(clk, NULL, "a0000000.multimedia"); | ||
1151 | clk = clk_register(NULL, &clk_lcd.hw); | ||
1152 | BUG_ON(!clk); | ||
1153 | clk_register_clkdev(clk, NULL, "90010000.display"); | ||
1154 | clk = clk_register(NULL, &clk_vpp.hw); | ||
1155 | BUG_ON(!clk); | ||
1156 | clk_register_clkdev(clk, NULL, "90020000.vpp"); | ||
1157 | clk = clk_register(NULL, &clk_mmc01.hw); | ||
1158 | BUG_ON(!clk); | ||
1159 | clk = clk_register(NULL, &clk_mmc23.hw); | ||
1160 | BUG_ON(!clk); | ||
1161 | clk = clk_register(NULL, &clk_mmc45.hw); | ||
1162 | BUG_ON(!clk); | ||
1163 | clk = clk_register(NULL, &usb_pll_clk_hw); | ||
1164 | BUG_ON(!clk); | ||
1165 | clk = clk_register(NULL, &clk_usb0.hw); | ||
1166 | BUG_ON(!clk); | ||
1167 | clk_register_clkdev(clk, NULL, "b00e0000.usb"); | ||
1168 | clk = clk_register(NULL, &clk_usb1.hw); | ||
1169 | BUG_ON(!clk); | ||
1170 | clk_register_clkdev(clk, NULL, "b00f0000.usb"); | ||
510 | } | 1171 | } |