diff options
Diffstat (limited to 'drivers/clk/sirf/clk-common.c')
-rw-r--r-- | drivers/clk/sirf/clk-common.c | 1031 |
1 files changed, 1031 insertions, 0 deletions
diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c new file mode 100644 index 000000000000..7dde6a82f514 --- /dev/null +++ b/drivers/clk/sirf/clk-common.c | |||
@@ -0,0 +1,1031 @@ | |||
1 | /* | ||
2 | * common clks module for all SiRF SoCs | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #define KHZ 1000 | ||
10 | #define MHZ (KHZ * KHZ) | ||
11 | |||
12 | static void *sirfsoc_clk_vbase; | ||
13 | static void *sirfsoc_rsc_vbase; | ||
14 | static struct clk_onecell_data clk_data; | ||
15 | |||
16 | /* | ||
17 | * SiRFprimaII clock controller | ||
18 | * - 2 oscillators: osc-26MHz, rtc-32.768KHz | ||
19 | * - 3 standard configurable plls: pll1, pll2 & pll3 | ||
20 | * - 2 exclusive plls: usb phy pll and sata phy pll | ||
21 | * - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia, | ||
22 | * display and sdphy. | ||
23 | * Each clock domain can select its own clock source from five clock sources, | ||
24 | * X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source | ||
25 | * clock of the group clock. | ||
26 | * - dsp domain: gps, mf | ||
27 | * - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse | ||
28 | * - sys domain: security | ||
29 | */ | ||
30 | |||
31 | struct clk_pll { | ||
32 | struct clk_hw hw; | ||
33 | unsigned short regofs; /* register offset */ | ||
34 | }; | ||
35 | |||
36 | #define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw) | ||
37 | |||
38 | struct clk_dmn { | ||
39 | struct clk_hw hw; | ||
40 | signed char enable_bit; /* enable bit: 0 ~ 63 */ | ||
41 | unsigned short regofs; /* register offset */ | ||
42 | }; | ||
43 | |||
44 | #define to_dmnclk(_hw) container_of(_hw, struct clk_dmn, hw) | ||
45 | |||
46 | struct clk_std { | ||
47 | struct clk_hw hw; | ||
48 | signed char enable_bit; /* enable bit: 0 ~ 63 */ | ||
49 | }; | ||
50 | |||
51 | #define to_stdclk(_hw) container_of(_hw, struct clk_std, hw) | ||
52 | |||
53 | static int std_clk_is_enabled(struct clk_hw *hw); | ||
54 | static int std_clk_enable(struct clk_hw *hw); | ||
55 | static void std_clk_disable(struct clk_hw *hw); | ||
56 | |||
57 | static inline unsigned long clkc_readl(unsigned reg) | ||
58 | { | ||
59 | return readl(sirfsoc_clk_vbase + reg); | ||
60 | } | ||
61 | |||
62 | static inline void clkc_writel(u32 val, unsigned reg) | ||
63 | { | ||
64 | writel(val, sirfsoc_clk_vbase + reg); | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * std pll | ||
69 | */ | ||
70 | |||
71 | static unsigned long pll_clk_recalc_rate(struct clk_hw *hw, | ||
72 | unsigned long parent_rate) | ||
73 | { | ||
74 | unsigned long fin = parent_rate; | ||
75 | struct clk_pll *clk = to_pllclk(hw); | ||
76 | u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - | ||
77 | SIRFSOC_CLKC_PLL1_CFG0; | ||
78 | |||
79 | if (clkc_readl(regcfg2) & BIT(2)) { | ||
80 | /* pll bypass mode */ | ||
81 | return fin; | ||
82 | } else { | ||
83 | /* fout = fin * nf / nr / od */ | ||
84 | u32 cfg0 = clkc_readl(clk->regofs); | ||
85 | u32 nf = (cfg0 & (BIT(13) - 1)) + 1; | ||
86 | u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; | ||
87 | u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; | ||
88 | WARN_ON(fin % MHZ); | ||
89 | return fin / MHZ * nf / nr / od * MHZ; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
94 | unsigned long *parent_rate) | ||
95 | { | ||
96 | unsigned long fin, nf, nr, od; | ||
97 | u64 dividend; | ||
98 | |||
99 | /* | ||
100 | * fout = fin * nf / (nr * od); | ||
101 | * set od = 1, nr = fin/MHz, so fout = nf * MHz | ||
102 | */ | ||
103 | rate = rate - rate % MHZ; | ||
104 | |||
105 | nf = rate / MHZ; | ||
106 | if (nf > BIT(13)) | ||
107 | nf = BIT(13); | ||
108 | if (nf < 1) | ||
109 | nf = 1; | ||
110 | |||
111 | fin = *parent_rate; | ||
112 | |||
113 | nr = fin / MHZ; | ||
114 | if (nr > BIT(6)) | ||
115 | nr = BIT(6); | ||
116 | od = 1; | ||
117 | |||
118 | dividend = (u64)fin * nf; | ||
119 | do_div(dividend, nr * od); | ||
120 | |||
121 | return (long)dividend; | ||
122 | } | ||
123 | |||
124 | static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
125 | unsigned long parent_rate) | ||
126 | { | ||
127 | struct clk_pll *clk = to_pllclk(hw); | ||
128 | unsigned long fin, nf, nr, od, reg; | ||
129 | |||
130 | /* | ||
131 | * fout = fin * nf / (nr * od); | ||
132 | * set od = 1, nr = fin/MHz, so fout = nf * MHz | ||
133 | */ | ||
134 | |||
135 | nf = rate / MHZ; | ||
136 | if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) | ||
137 | return -EINVAL; | ||
138 | |||
139 | fin = parent_rate; | ||
140 | BUG_ON(fin < MHZ); | ||
141 | |||
142 | nr = fin / MHZ; | ||
143 | BUG_ON((fin % MHZ) || nr > BIT(6)); | ||
144 | |||
145 | od = 1; | ||
146 | |||
147 | reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19); | ||
148 | clkc_writel(reg, clk->regofs); | ||
149 | |||
150 | reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0; | ||
151 | clkc_writel((nf >> 1) - 1, reg); | ||
152 | |||
153 | reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0; | ||
154 | while (!(clkc_readl(reg) & BIT(6))) | ||
155 | cpu_relax(); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static long cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
161 | unsigned long *parent_rate) | ||
162 | { | ||
163 | /* | ||
164 | * SiRF SoC has not cpu clock control, | ||
165 | * So bypass to it's parent pll. | ||
166 | */ | ||
167 | struct clk *parent_clk = clk_get_parent(hw->clk); | ||
168 | struct clk *pll_parent_clk = clk_get_parent(parent_clk); | ||
169 | unsigned long pll_parent_rate = clk_get_rate(pll_parent_clk); | ||
170 | return pll_clk_round_rate(__clk_get_hw(parent_clk), rate, &pll_parent_rate); | ||
171 | } | ||
172 | |||
173 | static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw, | ||
174 | unsigned long parent_rate) | ||
175 | { | ||
176 | /* | ||
177 | * SiRF SoC has not cpu clock control, | ||
178 | * So return the parent pll rate. | ||
179 | */ | ||
180 | struct clk *parent_clk = clk_get_parent(hw->clk); | ||
181 | return __clk_get_rate(parent_clk); | ||
182 | } | ||
183 | |||
184 | static struct clk_ops std_pll_ops = { | ||
185 | .recalc_rate = pll_clk_recalc_rate, | ||
186 | .round_rate = pll_clk_round_rate, | ||
187 | .set_rate = pll_clk_set_rate, | ||
188 | }; | ||
189 | |||
190 | static const char *pll_clk_parents[] = { | ||
191 | "osc", | ||
192 | }; | ||
193 | |||
194 | static struct clk_init_data clk_pll1_init = { | ||
195 | .name = "pll1", | ||
196 | .ops = &std_pll_ops, | ||
197 | .parent_names = pll_clk_parents, | ||
198 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
199 | }; | ||
200 | |||
201 | static struct clk_init_data clk_pll2_init = { | ||
202 | .name = "pll2", | ||
203 | .ops = &std_pll_ops, | ||
204 | .parent_names = pll_clk_parents, | ||
205 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
206 | }; | ||
207 | |||
208 | static struct clk_init_data clk_pll3_init = { | ||
209 | .name = "pll3", | ||
210 | .ops = &std_pll_ops, | ||
211 | .parent_names = pll_clk_parents, | ||
212 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
213 | }; | ||
214 | |||
215 | static struct clk_pll clk_pll1 = { | ||
216 | .regofs = SIRFSOC_CLKC_PLL1_CFG0, | ||
217 | .hw = { | ||
218 | .init = &clk_pll1_init, | ||
219 | }, | ||
220 | }; | ||
221 | |||
222 | static struct clk_pll clk_pll2 = { | ||
223 | .regofs = SIRFSOC_CLKC_PLL2_CFG0, | ||
224 | .hw = { | ||
225 | .init = &clk_pll2_init, | ||
226 | }, | ||
227 | }; | ||
228 | |||
229 | static struct clk_pll clk_pll3 = { | ||
230 | .regofs = SIRFSOC_CLKC_PLL3_CFG0, | ||
231 | .hw = { | ||
232 | .init = &clk_pll3_init, | ||
233 | }, | ||
234 | }; | ||
235 | |||
236 | /* | ||
237 | * usb uses specified pll | ||
238 | */ | ||
239 | |||
240 | static int usb_pll_clk_enable(struct clk_hw *hw) | ||
241 | { | ||
242 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
243 | reg &= ~(SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); | ||
244 | writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
245 | while (!(readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL) & | ||
246 | SIRFSOC_USBPHY_PLL_LOCK)) | ||
247 | cpu_relax(); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static void usb_pll_clk_disable(struct clk_hw *clk) | ||
253 | { | ||
254 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
255 | reg |= (SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); | ||
256 | writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
257 | } | ||
258 | |||
259 | static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | ||
260 | { | ||
261 | u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); | ||
262 | return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ; | ||
263 | } | ||
264 | |||
265 | static struct clk_ops usb_pll_ops = { | ||
266 | .enable = usb_pll_clk_enable, | ||
267 | .disable = usb_pll_clk_disable, | ||
268 | .recalc_rate = usb_pll_clk_recalc_rate, | ||
269 | }; | ||
270 | |||
271 | static struct clk_init_data clk_usb_pll_init = { | ||
272 | .name = "usb_pll", | ||
273 | .ops = &usb_pll_ops, | ||
274 | .parent_names = pll_clk_parents, | ||
275 | .num_parents = ARRAY_SIZE(pll_clk_parents), | ||
276 | }; | ||
277 | |||
278 | static struct clk_hw usb_pll_clk_hw = { | ||
279 | .init = &clk_usb_pll_init, | ||
280 | }; | ||
281 | |||
282 | /* | ||
283 | * clock domains - cpu, mem, sys/io, dsp, gfx | ||
284 | */ | ||
285 | |||
286 | static const char *dmn_clk_parents[] = { | ||
287 | "rtc", | ||
288 | "osc", | ||
289 | "pll1", | ||
290 | "pll2", | ||
291 | "pll3", | ||
292 | }; | ||
293 | |||
294 | static u8 dmn_clk_get_parent(struct clk_hw *hw) | ||
295 | { | ||
296 | struct clk_dmn *clk = to_dmnclk(hw); | ||
297 | u32 cfg = clkc_readl(clk->regofs); | ||
298 | |||
299 | /* parent of io domain can only be pll3 */ | ||
300 | if (strcmp(hw->init->name, "io") == 0) | ||
301 | return 4; | ||
302 | |||
303 | WARN_ON((cfg & (BIT(3) - 1)) > 4); | ||
304 | |||
305 | return cfg & (BIT(3) - 1); | ||
306 | } | ||
307 | |||
308 | static int dmn_clk_set_parent(struct clk_hw *hw, u8 parent) | ||
309 | { | ||
310 | struct clk_dmn *clk = to_dmnclk(hw); | ||
311 | u32 cfg = clkc_readl(clk->regofs); | ||
312 | |||
313 | /* parent of io domain can only be pll3 */ | ||
314 | if (strcmp(hw->init->name, "io") == 0) | ||
315 | return -EINVAL; | ||
316 | |||
317 | cfg &= ~(BIT(3) - 1); | ||
318 | clkc_writel(cfg | parent, clk->regofs); | ||
319 | /* BIT(3) - switching status: 1 - busy, 0 - done */ | ||
320 | while (clkc_readl(clk->regofs) & BIT(3)) | ||
321 | cpu_relax(); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw, | ||
327 | unsigned long parent_rate) | ||
328 | |||
329 | { | ||
330 | unsigned long fin = parent_rate; | ||
331 | struct clk_dmn *clk = to_dmnclk(hw); | ||
332 | |||
333 | u32 cfg = clkc_readl(clk->regofs); | ||
334 | |||
335 | if (cfg & BIT(24)) { | ||
336 | /* fcd bypass mode */ | ||
337 | return fin; | ||
338 | } else { | ||
339 | /* | ||
340 | * wait count: bit[19:16], hold count: bit[23:20] | ||
341 | */ | ||
342 | u32 wait = (cfg >> 16) & (BIT(4) - 1); | ||
343 | u32 hold = (cfg >> 20) & (BIT(4) - 1); | ||
344 | |||
345 | return fin / (wait + hold + 2); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
350 | unsigned long *parent_rate) | ||
351 | { | ||
352 | unsigned long fin; | ||
353 | unsigned ratio, wait, hold; | ||
354 | unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; | ||
355 | |||
356 | fin = *parent_rate; | ||
357 | ratio = fin / rate; | ||
358 | |||
359 | if (ratio < 2) | ||
360 | ratio = 2; | ||
361 | if (ratio > BIT(bits + 1)) | ||
362 | ratio = BIT(bits + 1); | ||
363 | |||
364 | wait = (ratio >> 1) - 1; | ||
365 | hold = ratio - wait - 2; | ||
366 | |||
367 | return fin / (wait + hold + 2); | ||
368 | } | ||
369 | |||
370 | static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
371 | unsigned long parent_rate) | ||
372 | { | ||
373 | struct clk_dmn *clk = to_dmnclk(hw); | ||
374 | unsigned long fin; | ||
375 | unsigned ratio, wait, hold, reg; | ||
376 | unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4; | ||
377 | |||
378 | fin = parent_rate; | ||
379 | ratio = fin / rate; | ||
380 | |||
381 | if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) | ||
382 | return -EINVAL; | ||
383 | |||
384 | WARN_ON(fin % rate); | ||
385 | |||
386 | wait = (ratio >> 1) - 1; | ||
387 | hold = ratio - wait - 2; | ||
388 | |||
389 | reg = clkc_readl(clk->regofs); | ||
390 | reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20)); | ||
391 | reg |= (wait << 16) | (hold << 20) | BIT(25); | ||
392 | clkc_writel(reg, clk->regofs); | ||
393 | |||
394 | /* waiting FCD been effective */ | ||
395 | while (clkc_readl(clk->regofs) & BIT(25)) | ||
396 | cpu_relax(); | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
402 | unsigned long parent_rate) | ||
403 | { | ||
404 | int ret1, ret2; | ||
405 | struct clk *cur_parent; | ||
406 | |||
407 | if (rate == clk_get_rate(clk_pll1.hw.clk)) { | ||
408 | ret1 = clk_set_parent(hw->clk, clk_pll1.hw.clk); | ||
409 | return ret1; | ||
410 | } | ||
411 | |||
412 | if (rate == clk_get_rate(clk_pll2.hw.clk)) { | ||
413 | ret1 = clk_set_parent(hw->clk, clk_pll2.hw.clk); | ||
414 | return ret1; | ||
415 | } | ||
416 | |||
417 | if (rate == clk_get_rate(clk_pll3.hw.clk)) { | ||
418 | ret1 = clk_set_parent(hw->clk, clk_pll3.hw.clk); | ||
419 | return ret1; | ||
420 | } | ||
421 | |||
422 | cur_parent = clk_get_parent(hw->clk); | ||
423 | |||
424 | /* switch to tmp pll before setting parent clock's rate */ | ||
425 | if (cur_parent == clk_pll1.hw.clk) { | ||
426 | ret1 = clk_set_parent(hw->clk, clk_pll2.hw.clk); | ||
427 | BUG_ON(ret1); | ||
428 | } | ||
429 | |||
430 | ret2 = clk_set_rate(clk_pll1.hw.clk, rate); | ||
431 | |||
432 | ret1 = clk_set_parent(hw->clk, clk_pll1.hw.clk); | ||
433 | |||
434 | return ret2 ? ret2 : ret1; | ||
435 | } | ||
436 | |||
437 | static struct clk_ops msi_ops = { | ||
438 | .set_rate = dmn_clk_set_rate, | ||
439 | .round_rate = dmn_clk_round_rate, | ||
440 | .recalc_rate = dmn_clk_recalc_rate, | ||
441 | .set_parent = dmn_clk_set_parent, | ||
442 | .get_parent = dmn_clk_get_parent, | ||
443 | }; | ||
444 | |||
445 | static struct clk_init_data clk_mem_init = { | ||
446 | .name = "mem", | ||
447 | .ops = &msi_ops, | ||
448 | .parent_names = dmn_clk_parents, | ||
449 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
450 | }; | ||
451 | |||
452 | static struct clk_dmn clk_mem = { | ||
453 | .regofs = SIRFSOC_CLKC_MEM_CFG, | ||
454 | .hw = { | ||
455 | .init = &clk_mem_init, | ||
456 | }, | ||
457 | }; | ||
458 | |||
459 | static struct clk_init_data clk_sys_init = { | ||
460 | .name = "sys", | ||
461 | .ops = &msi_ops, | ||
462 | .parent_names = dmn_clk_parents, | ||
463 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
464 | .flags = CLK_SET_RATE_GATE, | ||
465 | }; | ||
466 | |||
467 | static struct clk_dmn clk_sys = { | ||
468 | .regofs = SIRFSOC_CLKC_SYS_CFG, | ||
469 | .hw = { | ||
470 | .init = &clk_sys_init, | ||
471 | }, | ||
472 | }; | ||
473 | |||
474 | static struct clk_init_data clk_io_init = { | ||
475 | .name = "io", | ||
476 | .ops = &msi_ops, | ||
477 | .parent_names = dmn_clk_parents, | ||
478 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
479 | }; | ||
480 | |||
481 | static struct clk_dmn clk_io = { | ||
482 | .regofs = SIRFSOC_CLKC_IO_CFG, | ||
483 | .hw = { | ||
484 | .init = &clk_io_init, | ||
485 | }, | ||
486 | }; | ||
487 | |||
488 | static struct clk_ops cpu_ops = { | ||
489 | .set_parent = dmn_clk_set_parent, | ||
490 | .get_parent = dmn_clk_get_parent, | ||
491 | .set_rate = cpu_clk_set_rate, | ||
492 | .round_rate = cpu_clk_round_rate, | ||
493 | .recalc_rate = cpu_clk_recalc_rate, | ||
494 | }; | ||
495 | |||
496 | static struct clk_init_data clk_cpu_init = { | ||
497 | .name = "cpu", | ||
498 | .ops = &cpu_ops, | ||
499 | .parent_names = dmn_clk_parents, | ||
500 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
501 | .flags = CLK_SET_RATE_PARENT, | ||
502 | }; | ||
503 | |||
504 | static struct clk_dmn clk_cpu = { | ||
505 | .regofs = SIRFSOC_CLKC_CPU_CFG, | ||
506 | .hw = { | ||
507 | .init = &clk_cpu_init, | ||
508 | }, | ||
509 | }; | ||
510 | |||
511 | static struct clk_ops dmn_ops = { | ||
512 | .is_enabled = std_clk_is_enabled, | ||
513 | .enable = std_clk_enable, | ||
514 | .disable = std_clk_disable, | ||
515 | .set_rate = dmn_clk_set_rate, | ||
516 | .round_rate = dmn_clk_round_rate, | ||
517 | .recalc_rate = dmn_clk_recalc_rate, | ||
518 | .set_parent = dmn_clk_set_parent, | ||
519 | .get_parent = dmn_clk_get_parent, | ||
520 | }; | ||
521 | |||
522 | /* dsp, gfx, mm, lcd and vpp domain */ | ||
523 | |||
524 | static struct clk_init_data clk_dsp_init = { | ||
525 | .name = "dsp", | ||
526 | .ops = &dmn_ops, | ||
527 | .parent_names = dmn_clk_parents, | ||
528 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
529 | }; | ||
530 | |||
531 | static struct clk_dmn clk_dsp = { | ||
532 | .regofs = SIRFSOC_CLKC_DSP_CFG, | ||
533 | .enable_bit = 0, | ||
534 | .hw = { | ||
535 | .init = &clk_dsp_init, | ||
536 | }, | ||
537 | }; | ||
538 | |||
539 | static struct clk_init_data clk_gfx_init = { | ||
540 | .name = "gfx", | ||
541 | .ops = &dmn_ops, | ||
542 | .parent_names = dmn_clk_parents, | ||
543 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
544 | }; | ||
545 | |||
546 | static struct clk_dmn clk_gfx = { | ||
547 | .regofs = SIRFSOC_CLKC_GFX_CFG, | ||
548 | .enable_bit = 8, | ||
549 | .hw = { | ||
550 | .init = &clk_gfx_init, | ||
551 | }, | ||
552 | }; | ||
553 | |||
554 | static struct clk_init_data clk_mm_init = { | ||
555 | .name = "mm", | ||
556 | .ops = &dmn_ops, | ||
557 | .parent_names = dmn_clk_parents, | ||
558 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
559 | }; | ||
560 | |||
561 | static struct clk_dmn clk_mm = { | ||
562 | .regofs = SIRFSOC_CLKC_MM_CFG, | ||
563 | .enable_bit = 9, | ||
564 | .hw = { | ||
565 | .init = &clk_mm_init, | ||
566 | }, | ||
567 | }; | ||
568 | |||
569 | /* | ||
570 | * for atlas6, gfx2d holds the bit of prima2's clk_mm | ||
571 | */ | ||
572 | #define clk_gfx2d clk_mm | ||
573 | |||
574 | static struct clk_init_data clk_lcd_init = { | ||
575 | .name = "lcd", | ||
576 | .ops = &dmn_ops, | ||
577 | .parent_names = dmn_clk_parents, | ||
578 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
579 | }; | ||
580 | |||
581 | static struct clk_dmn clk_lcd = { | ||
582 | .regofs = SIRFSOC_CLKC_LCD_CFG, | ||
583 | .enable_bit = 10, | ||
584 | .hw = { | ||
585 | .init = &clk_lcd_init, | ||
586 | }, | ||
587 | }; | ||
588 | |||
589 | static struct clk_init_data clk_vpp_init = { | ||
590 | .name = "vpp", | ||
591 | .ops = &dmn_ops, | ||
592 | .parent_names = dmn_clk_parents, | ||
593 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
594 | }; | ||
595 | |||
596 | static struct clk_dmn clk_vpp = { | ||
597 | .regofs = SIRFSOC_CLKC_LCD_CFG, | ||
598 | .enable_bit = 11, | ||
599 | .hw = { | ||
600 | .init = &clk_vpp_init, | ||
601 | }, | ||
602 | }; | ||
603 | |||
604 | static struct clk_init_data clk_mmc01_init = { | ||
605 | .name = "mmc01", | ||
606 | .ops = &dmn_ops, | ||
607 | .parent_names = dmn_clk_parents, | ||
608 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
609 | }; | ||
610 | |||
611 | static struct clk_init_data clk_mmc23_init = { | ||
612 | .name = "mmc23", | ||
613 | .ops = &dmn_ops, | ||
614 | .parent_names = dmn_clk_parents, | ||
615 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
616 | }; | ||
617 | |||
618 | static struct clk_init_data clk_mmc45_init = { | ||
619 | .name = "mmc45", | ||
620 | .ops = &dmn_ops, | ||
621 | .parent_names = dmn_clk_parents, | ||
622 | .num_parents = ARRAY_SIZE(dmn_clk_parents), | ||
623 | }; | ||
624 | |||
625 | /* | ||
626 | * peripheral controllers in io domain | ||
627 | */ | ||
628 | |||
629 | static int std_clk_is_enabled(struct clk_hw *hw) | ||
630 | { | ||
631 | u32 reg; | ||
632 | int bit; | ||
633 | struct clk_std *clk = to_stdclk(hw); | ||
634 | |||
635 | bit = clk->enable_bit % 32; | ||
636 | reg = clk->enable_bit / 32; | ||
637 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | ||
638 | |||
639 | return !!(clkc_readl(reg) & BIT(bit)); | ||
640 | } | ||
641 | |||
642 | static int std_clk_enable(struct clk_hw *hw) | ||
643 | { | ||
644 | u32 val, reg; | ||
645 | int bit; | ||
646 | struct clk_std *clk = to_stdclk(hw); | ||
647 | |||
648 | BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); | ||
649 | |||
650 | bit = clk->enable_bit % 32; | ||
651 | reg = clk->enable_bit / 32; | ||
652 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | ||
653 | |||
654 | val = clkc_readl(reg) | BIT(bit); | ||
655 | clkc_writel(val, reg); | ||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static void std_clk_disable(struct clk_hw *hw) | ||
660 | { | ||
661 | u32 val, reg; | ||
662 | int bit; | ||
663 | struct clk_std *clk = to_stdclk(hw); | ||
664 | |||
665 | BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); | ||
666 | |||
667 | bit = clk->enable_bit % 32; | ||
668 | reg = clk->enable_bit / 32; | ||
669 | reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); | ||
670 | |||
671 | val = clkc_readl(reg) & ~BIT(bit); | ||
672 | clkc_writel(val, reg); | ||
673 | } | ||
674 | |||
675 | static const char *std_clk_io_parents[] = { | ||
676 | "io", | ||
677 | }; | ||
678 | |||
679 | static struct clk_ops ios_ops = { | ||
680 | .is_enabled = std_clk_is_enabled, | ||
681 | .enable = std_clk_enable, | ||
682 | .disable = std_clk_disable, | ||
683 | }; | ||
684 | |||
685 | static struct clk_init_data clk_cphif_init = { | ||
686 | .name = "cphif", | ||
687 | .ops = &ios_ops, | ||
688 | .parent_names = std_clk_io_parents, | ||
689 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
690 | }; | ||
691 | |||
692 | static struct clk_std clk_cphif = { | ||
693 | .enable_bit = 20, | ||
694 | .hw = { | ||
695 | .init = &clk_cphif_init, | ||
696 | }, | ||
697 | }; | ||
698 | |||
699 | static struct clk_init_data clk_dmac0_init = { | ||
700 | .name = "dmac0", | ||
701 | .ops = &ios_ops, | ||
702 | .parent_names = std_clk_io_parents, | ||
703 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
704 | }; | ||
705 | |||
706 | static struct clk_std clk_dmac0 = { | ||
707 | .enable_bit = 32, | ||
708 | .hw = { | ||
709 | .init = &clk_dmac0_init, | ||
710 | }, | ||
711 | }; | ||
712 | |||
713 | static struct clk_init_data clk_dmac1_init = { | ||
714 | .name = "dmac1", | ||
715 | .ops = &ios_ops, | ||
716 | .parent_names = std_clk_io_parents, | ||
717 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
718 | }; | ||
719 | |||
720 | static struct clk_std clk_dmac1 = { | ||
721 | .enable_bit = 33, | ||
722 | .hw = { | ||
723 | .init = &clk_dmac1_init, | ||
724 | }, | ||
725 | }; | ||
726 | |||
727 | static struct clk_init_data clk_audio_init = { | ||
728 | .name = "audio", | ||
729 | .ops = &ios_ops, | ||
730 | .parent_names = std_clk_io_parents, | ||
731 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
732 | }; | ||
733 | |||
734 | static struct clk_std clk_audio = { | ||
735 | .enable_bit = 35, | ||
736 | .hw = { | ||
737 | .init = &clk_audio_init, | ||
738 | }, | ||
739 | }; | ||
740 | |||
741 | static struct clk_init_data clk_uart0_init = { | ||
742 | .name = "uart0", | ||
743 | .ops = &ios_ops, | ||
744 | .parent_names = std_clk_io_parents, | ||
745 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
746 | }; | ||
747 | |||
748 | static struct clk_std clk_uart0 = { | ||
749 | .enable_bit = 36, | ||
750 | .hw = { | ||
751 | .init = &clk_uart0_init, | ||
752 | }, | ||
753 | }; | ||
754 | |||
755 | static struct clk_init_data clk_uart1_init = { | ||
756 | .name = "uart1", | ||
757 | .ops = &ios_ops, | ||
758 | .parent_names = std_clk_io_parents, | ||
759 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
760 | }; | ||
761 | |||
762 | static struct clk_std clk_uart1 = { | ||
763 | .enable_bit = 37, | ||
764 | .hw = { | ||
765 | .init = &clk_uart1_init, | ||
766 | }, | ||
767 | }; | ||
768 | |||
769 | static struct clk_init_data clk_uart2_init = { | ||
770 | .name = "uart2", | ||
771 | .ops = &ios_ops, | ||
772 | .parent_names = std_clk_io_parents, | ||
773 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
774 | }; | ||
775 | |||
776 | static struct clk_std clk_uart2 = { | ||
777 | .enable_bit = 38, | ||
778 | .hw = { | ||
779 | .init = &clk_uart2_init, | ||
780 | }, | ||
781 | }; | ||
782 | |||
783 | static struct clk_init_data clk_usp0_init = { | ||
784 | .name = "usp0", | ||
785 | .ops = &ios_ops, | ||
786 | .parent_names = std_clk_io_parents, | ||
787 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
788 | }; | ||
789 | |||
790 | static struct clk_std clk_usp0 = { | ||
791 | .enable_bit = 39, | ||
792 | .hw = { | ||
793 | .init = &clk_usp0_init, | ||
794 | }, | ||
795 | }; | ||
796 | |||
797 | static struct clk_init_data clk_usp1_init = { | ||
798 | .name = "usp1", | ||
799 | .ops = &ios_ops, | ||
800 | .parent_names = std_clk_io_parents, | ||
801 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
802 | }; | ||
803 | |||
804 | static struct clk_std clk_usp1 = { | ||
805 | .enable_bit = 40, | ||
806 | .hw = { | ||
807 | .init = &clk_usp1_init, | ||
808 | }, | ||
809 | }; | ||
810 | |||
811 | static struct clk_init_data clk_usp2_init = { | ||
812 | .name = "usp2", | ||
813 | .ops = &ios_ops, | ||
814 | .parent_names = std_clk_io_parents, | ||
815 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
816 | }; | ||
817 | |||
818 | static struct clk_std clk_usp2 = { | ||
819 | .enable_bit = 41, | ||
820 | .hw = { | ||
821 | .init = &clk_usp2_init, | ||
822 | }, | ||
823 | }; | ||
824 | |||
825 | static struct clk_init_data clk_vip_init = { | ||
826 | .name = "vip", | ||
827 | .ops = &ios_ops, | ||
828 | .parent_names = std_clk_io_parents, | ||
829 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
830 | }; | ||
831 | |||
832 | static struct clk_std clk_vip = { | ||
833 | .enable_bit = 42, | ||
834 | .hw = { | ||
835 | .init = &clk_vip_init, | ||
836 | }, | ||
837 | }; | ||
838 | |||
839 | static struct clk_init_data clk_spi0_init = { | ||
840 | .name = "spi0", | ||
841 | .ops = &ios_ops, | ||
842 | .parent_names = std_clk_io_parents, | ||
843 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
844 | }; | ||
845 | |||
846 | static struct clk_std clk_spi0 = { | ||
847 | .enable_bit = 43, | ||
848 | .hw = { | ||
849 | .init = &clk_spi0_init, | ||
850 | }, | ||
851 | }; | ||
852 | |||
853 | static struct clk_init_data clk_spi1_init = { | ||
854 | .name = "spi1", | ||
855 | .ops = &ios_ops, | ||
856 | .parent_names = std_clk_io_parents, | ||
857 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
858 | }; | ||
859 | |||
860 | static struct clk_std clk_spi1 = { | ||
861 | .enable_bit = 44, | ||
862 | .hw = { | ||
863 | .init = &clk_spi1_init, | ||
864 | }, | ||
865 | }; | ||
866 | |||
867 | static struct clk_init_data clk_tsc_init = { | ||
868 | .name = "tsc", | ||
869 | .ops = &ios_ops, | ||
870 | .parent_names = std_clk_io_parents, | ||
871 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
872 | }; | ||
873 | |||
874 | static struct clk_std clk_tsc = { | ||
875 | .enable_bit = 45, | ||
876 | .hw = { | ||
877 | .init = &clk_tsc_init, | ||
878 | }, | ||
879 | }; | ||
880 | |||
881 | static struct clk_init_data clk_i2c0_init = { | ||
882 | .name = "i2c0", | ||
883 | .ops = &ios_ops, | ||
884 | .parent_names = std_clk_io_parents, | ||
885 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
886 | }; | ||
887 | |||
888 | static struct clk_std clk_i2c0 = { | ||
889 | .enable_bit = 46, | ||
890 | .hw = { | ||
891 | .init = &clk_i2c0_init, | ||
892 | }, | ||
893 | }; | ||
894 | |||
895 | static struct clk_init_data clk_i2c1_init = { | ||
896 | .name = "i2c1", | ||
897 | .ops = &ios_ops, | ||
898 | .parent_names = std_clk_io_parents, | ||
899 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
900 | }; | ||
901 | |||
902 | static struct clk_std clk_i2c1 = { | ||
903 | .enable_bit = 47, | ||
904 | .hw = { | ||
905 | .init = &clk_i2c1_init, | ||
906 | }, | ||
907 | }; | ||
908 | |||
909 | static struct clk_init_data clk_pwmc_init = { | ||
910 | .name = "pwmc", | ||
911 | .ops = &ios_ops, | ||
912 | .parent_names = std_clk_io_parents, | ||
913 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
914 | }; | ||
915 | |||
916 | static struct clk_std clk_pwmc = { | ||
917 | .enable_bit = 48, | ||
918 | .hw = { | ||
919 | .init = &clk_pwmc_init, | ||
920 | }, | ||
921 | }; | ||
922 | |||
923 | static struct clk_init_data clk_efuse_init = { | ||
924 | .name = "efuse", | ||
925 | .ops = &ios_ops, | ||
926 | .parent_names = std_clk_io_parents, | ||
927 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
928 | }; | ||
929 | |||
930 | static struct clk_std clk_efuse = { | ||
931 | .enable_bit = 49, | ||
932 | .hw = { | ||
933 | .init = &clk_efuse_init, | ||
934 | }, | ||
935 | }; | ||
936 | |||
937 | static struct clk_init_data clk_pulse_init = { | ||
938 | .name = "pulse", | ||
939 | .ops = &ios_ops, | ||
940 | .parent_names = std_clk_io_parents, | ||
941 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
942 | }; | ||
943 | |||
944 | static struct clk_std clk_pulse = { | ||
945 | .enable_bit = 50, | ||
946 | .hw = { | ||
947 | .init = &clk_pulse_init, | ||
948 | }, | ||
949 | }; | ||
950 | |||
951 | static const char *std_clk_dsp_parents[] = { | ||
952 | "dsp", | ||
953 | }; | ||
954 | |||
955 | static struct clk_init_data clk_gps_init = { | ||
956 | .name = "gps", | ||
957 | .ops = &ios_ops, | ||
958 | .parent_names = std_clk_dsp_parents, | ||
959 | .num_parents = ARRAY_SIZE(std_clk_dsp_parents), | ||
960 | }; | ||
961 | |||
962 | static struct clk_std clk_gps = { | ||
963 | .enable_bit = 1, | ||
964 | .hw = { | ||
965 | .init = &clk_gps_init, | ||
966 | }, | ||
967 | }; | ||
968 | |||
969 | static struct clk_init_data clk_mf_init = { | ||
970 | .name = "mf", | ||
971 | .ops = &ios_ops, | ||
972 | .parent_names = std_clk_io_parents, | ||
973 | .num_parents = ARRAY_SIZE(std_clk_io_parents), | ||
974 | }; | ||
975 | |||
976 | static struct clk_std clk_mf = { | ||
977 | .enable_bit = 2, | ||
978 | .hw = { | ||
979 | .init = &clk_mf_init, | ||
980 | }, | ||
981 | }; | ||
982 | |||
983 | static const char *std_clk_sys_parents[] = { | ||
984 | "sys", | ||
985 | }; | ||
986 | |||
987 | static struct clk_init_data clk_security_init = { | ||
988 | .name = "security", | ||
989 | .ops = &ios_ops, | ||
990 | .parent_names = std_clk_sys_parents, | ||
991 | .num_parents = ARRAY_SIZE(std_clk_sys_parents), | ||
992 | }; | ||
993 | |||
994 | static struct clk_std clk_security = { | ||
995 | .enable_bit = 19, | ||
996 | .hw = { | ||
997 | .init = &clk_security_init, | ||
998 | }, | ||
999 | }; | ||
1000 | |||
1001 | static const char *std_clk_usb_parents[] = { | ||
1002 | "usb_pll", | ||
1003 | }; | ||
1004 | |||
1005 | static struct clk_init_data clk_usb0_init = { | ||
1006 | .name = "usb0", | ||
1007 | .ops = &ios_ops, | ||
1008 | .parent_names = std_clk_usb_parents, | ||
1009 | .num_parents = ARRAY_SIZE(std_clk_usb_parents), | ||
1010 | }; | ||
1011 | |||
1012 | static struct clk_std clk_usb0 = { | ||
1013 | .enable_bit = 16, | ||
1014 | .hw = { | ||
1015 | .init = &clk_usb0_init, | ||
1016 | }, | ||
1017 | }; | ||
1018 | |||
1019 | static struct clk_init_data clk_usb1_init = { | ||
1020 | .name = "usb1", | ||
1021 | .ops = &ios_ops, | ||
1022 | .parent_names = std_clk_usb_parents, | ||
1023 | .num_parents = ARRAY_SIZE(std_clk_usb_parents), | ||
1024 | }; | ||
1025 | |||
1026 | static struct clk_std clk_usb1 = { | ||
1027 | .enable_bit = 17, | ||
1028 | .hw = { | ||
1029 | .init = &clk_usb1_init, | ||
1030 | }, | ||
1031 | }; | ||