Commit | Line | Data |
---|---|---|
02e19a96 PW |
1 | /* |
2 | * OMAP3-specific clock framework functions | |
3 | * | |
542313cc PW |
4 | * Copyright (C) 2007-2008 Texas Instruments, Inc. |
5 | * Copyright (C) 2007-2008 Nokia Corporation | |
02e19a96 PW |
6 | * |
7 | * Written by Paul Walmsley | |
542313cc | 8 | * Testing and integration fixes by Jouni Högander |
02e19a96 PW |
9 | * |
10 | * Parts of this code are based on code written by | |
11 | * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu | |
12 | * | |
13 | * This program is free software; you can redistribute it and/or modify | |
14 | * it under the terms of the GNU General Public License version 2 as | |
15 | * published by the Free Software Foundation. | |
16 | */ | |
17 | #undef DEBUG | |
18 | ||
19 | #include <linux/module.h> | |
20 | #include <linux/kernel.h> | |
21 | #include <linux/device.h> | |
22 | #include <linux/list.h> | |
23 | #include <linux/errno.h> | |
24 | #include <linux/delay.h> | |
25 | #include <linux/clk.h> | |
26 | #include <linux/io.h> | |
542313cc | 27 | #include <linux/limits.h> |
02e19a96 | 28 | |
a09e64fb RK |
29 | #include <mach/clock.h> |
30 | #include <mach/sram.h> | |
02e19a96 PW |
31 | #include <asm/div64.h> |
32 | #include <asm/bitops.h> | |
33 | ||
34 | #include "memory.h" | |
35 | #include "clock.h" | |
36 | #include "clock34xx.h" | |
37 | #include "prm.h" | |
38 | #include "prm-regbits-34xx.h" | |
39 | #include "cm.h" | |
40 | #include "cm-regbits-34xx.h" | |
41 | ||
542313cc PW |
42 | /* CM_AUTOIDLE_PLL*.AUTO_* bit values */ |
43 | #define DPLL_AUTOIDLE_DISABLE 0x0 | |
44 | #define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1 | |
45 | ||
46 | #define MAX_DPLL_WAIT_TRIES 1000000 | |
02e19a96 PW |
47 | |
48 | /** | |
49 | * omap3_dpll_recalc - recalculate DPLL rate | |
50 | * @clk: DPLL struct clk | |
51 | * | |
52 | * Recalculate and propagate the DPLL rate. | |
53 | */ | |
54 | static void omap3_dpll_recalc(struct clk *clk) | |
55 | { | |
56 | clk->rate = omap2_get_dpll_rate(clk); | |
57 | ||
58 | propagate_rate(clk); | |
59 | } | |
60 | ||
542313cc PW |
61 | /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */ |
62 | static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits) | |
63 | { | |
64 | const struct dpll_data *dd; | |
ad67ef68 | 65 | u32 v; |
542313cc PW |
66 | |
67 | dd = clk->dpll_data; | |
68 | ||
ad67ef68 PW |
69 | v = __raw_readl(dd->control_reg); |
70 | v &= ~dd->enable_mask; | |
71 | v |= clken_bits << __ffs(dd->enable_mask); | |
72 | __raw_writel(v, dd->control_reg); | |
542313cc PW |
73 | } |
74 | ||
75 | /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ | |
76 | static int _omap3_wait_dpll_status(struct clk *clk, u8 state) | |
77 | { | |
78 | const struct dpll_data *dd; | |
79 | int i = 0; | |
80 | int ret = -EINVAL; | |
81 | u32 idlest_mask; | |
82 | ||
83 | dd = clk->dpll_data; | |
84 | ||
85 | state <<= dd->idlest_bit; | |
86 | idlest_mask = 1 << dd->idlest_bit; | |
87 | ||
ad67ef68 | 88 | while (((__raw_readl(dd->idlest_reg) & idlest_mask) != state) && |
542313cc PW |
89 | i < MAX_DPLL_WAIT_TRIES) { |
90 | i++; | |
91 | udelay(1); | |
92 | } | |
93 | ||
94 | if (i == MAX_DPLL_WAIT_TRIES) { | |
95 | printk(KERN_ERR "clock: %s failed transition to '%s'\n", | |
96 | clk->name, (state) ? "locked" : "bypassed"); | |
97 | } else { | |
98 | pr_debug("clock: %s transition to '%s' in %d loops\n", | |
99 | clk->name, (state) ? "locked" : "bypassed", i); | |
100 | ||
101 | ret = 0; | |
102 | } | |
103 | ||
104 | return ret; | |
105 | } | |
106 | ||
107 | /* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */ | |
108 | ||
109 | /* | |
110 | * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness | |
111 | * @clk: pointer to a DPLL struct clk | |
112 | * | |
113 | * Instructs a non-CORE DPLL to lock. Waits for the DPLL to report | |
114 | * readiness before returning. Will save and restore the DPLL's | |
115 | * autoidle state across the enable, per the CDP code. If the DPLL | |
116 | * locked successfully, return 0; if the DPLL did not lock in the time | |
117 | * allotted, or DPLL3 was passed in, return -EINVAL. | |
118 | */ | |
119 | static int _omap3_noncore_dpll_lock(struct clk *clk) | |
120 | { | |
121 | u8 ai; | |
122 | int r; | |
123 | ||
124 | if (clk == &dpll3_ck) | |
125 | return -EINVAL; | |
126 | ||
127 | pr_debug("clock: locking DPLL %s\n", clk->name); | |
128 | ||
129 | ai = omap3_dpll_autoidle_read(clk); | |
130 | ||
131 | _omap3_dpll_write_clken(clk, DPLL_LOCKED); | |
132 | ||
133 | if (ai) { | |
134 | /* | |
135 | * If no downstream clocks are enabled, CM_IDLEST bit | |
136 | * may never become active, so don't wait for DPLL to lock. | |
137 | */ | |
138 | r = 0; | |
139 | omap3_dpll_allow_idle(clk); | |
140 | } else { | |
141 | r = _omap3_wait_dpll_status(clk, 1); | |
142 | omap3_dpll_deny_idle(clk); | |
143 | }; | |
144 | ||
145 | return r; | |
146 | } | |
147 | ||
148 | /* | |
149 | * omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness | |
150 | * @clk: pointer to a DPLL struct clk | |
151 | * | |
152 | * Instructs a non-CORE DPLL to enter low-power bypass mode. In | |
153 | * bypass mode, the DPLL's rate is set equal to its parent clock's | |
154 | * rate. Waits for the DPLL to report readiness before returning. | |
155 | * Will save and restore the DPLL's autoidle state across the enable, | |
156 | * per the CDP code. If the DPLL entered bypass mode successfully, | |
157 | * return 0; if the DPLL did not enter bypass in the time allotted, or | |
158 | * DPLL3 was passed in, or the DPLL does not support low-power bypass, | |
159 | * return -EINVAL. | |
160 | */ | |
161 | static int _omap3_noncore_dpll_bypass(struct clk *clk) | |
162 | { | |
163 | int r; | |
164 | u8 ai; | |
165 | ||
166 | if (clk == &dpll3_ck) | |
167 | return -EINVAL; | |
168 | ||
169 | if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) | |
170 | return -EINVAL; | |
171 | ||
172 | pr_debug("clock: configuring DPLL %s for low-power bypass\n", | |
173 | clk->name); | |
174 | ||
175 | ai = omap3_dpll_autoidle_read(clk); | |
176 | ||
177 | _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS); | |
178 | ||
179 | r = _omap3_wait_dpll_status(clk, 0); | |
180 | ||
181 | if (ai) | |
182 | omap3_dpll_allow_idle(clk); | |
183 | else | |
184 | omap3_dpll_deny_idle(clk); | |
185 | ||
186 | return r; | |
187 | } | |
188 | ||
189 | /* | |
190 | * _omap3_noncore_dpll_stop - instruct a DPLL to stop | |
191 | * @clk: pointer to a DPLL struct clk | |
192 | * | |
193 | * Instructs a non-CORE DPLL to enter low-power stop. Will save and | |
194 | * restore the DPLL's autoidle state across the stop, per the CDP | |
195 | * code. If DPLL3 was passed in, or the DPLL does not support | |
196 | * low-power stop, return -EINVAL; otherwise, return 0. | |
197 | */ | |
198 | static int _omap3_noncore_dpll_stop(struct clk *clk) | |
199 | { | |
200 | u8 ai; | |
201 | ||
202 | if (clk == &dpll3_ck) | |
203 | return -EINVAL; | |
204 | ||
205 | if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP))) | |
206 | return -EINVAL; | |
207 | ||
208 | pr_debug("clock: stopping DPLL %s\n", clk->name); | |
209 | ||
210 | ai = omap3_dpll_autoidle_read(clk); | |
211 | ||
212 | _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP); | |
213 | ||
214 | if (ai) | |
215 | omap3_dpll_allow_idle(clk); | |
216 | else | |
217 | omap3_dpll_deny_idle(clk); | |
218 | ||
219 | return 0; | |
220 | } | |
221 | ||
222 | /** | |
223 | * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode | |
224 | * @clk: pointer to a DPLL struct clk | |
225 | * | |
226 | * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. | |
227 | * The choice of modes depends on the DPLL's programmed rate: if it is | |
228 | * the same as the DPLL's parent clock, it will enter bypass; | |
229 | * otherwise, it will enter lock. This code will wait for the DPLL to | |
230 | * indicate readiness before returning, unless the DPLL takes too long | |
231 | * to enter the target state. Intended to be used as the struct clk's | |
232 | * enable function. If DPLL3 was passed in, or the DPLL does not | |
233 | * support low-power stop, or if the DPLL took too long to enter | |
234 | * bypass or lock, return -EINVAL; otherwise, return 0. | |
235 | */ | |
236 | static int omap3_noncore_dpll_enable(struct clk *clk) | |
237 | { | |
238 | int r; | |
239 | ||
240 | if (clk == &dpll3_ck) | |
241 | return -EINVAL; | |
242 | ||
243 | if (clk->parent->rate == clk_get_rate(clk)) | |
244 | r = _omap3_noncore_dpll_bypass(clk); | |
245 | else | |
246 | r = _omap3_noncore_dpll_lock(clk); | |
247 | ||
248 | return r; | |
249 | } | |
250 | ||
251 | /** | |
252 | * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode | |
253 | * @clk: pointer to a DPLL struct clk | |
254 | * | |
255 | * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. | |
256 | * The choice of modes depends on the DPLL's programmed rate: if it is | |
257 | * the same as the DPLL's parent clock, it will enter bypass; | |
258 | * otherwise, it will enter lock. This code will wait for the DPLL to | |
259 | * indicate readiness before returning, unless the DPLL takes too long | |
260 | * to enter the target state. Intended to be used as the struct clk's | |
261 | * enable function. If DPLL3 was passed in, or the DPLL does not | |
262 | * support low-power stop, or if the DPLL took too long to enter | |
263 | * bypass or lock, return -EINVAL; otherwise, return 0. | |
264 | */ | |
265 | static void omap3_noncore_dpll_disable(struct clk *clk) | |
266 | { | |
267 | if (clk == &dpll3_ck) | |
268 | return; | |
269 | ||
270 | _omap3_noncore_dpll_stop(clk); | |
271 | } | |
272 | ||
273 | /** | |
274 | * omap3_dpll_autoidle_read - read a DPLL's autoidle bits | |
275 | * @clk: struct clk * of the DPLL to read | |
276 | * | |
277 | * Return the DPLL's autoidle bits, shifted down to bit 0. Returns | |
278 | * -EINVAL if passed a null pointer or if the struct clk does not | |
279 | * appear to refer to a DPLL. | |
280 | */ | |
281 | static u32 omap3_dpll_autoidle_read(struct clk *clk) | |
282 | { | |
283 | const struct dpll_data *dd; | |
284 | u32 v; | |
285 | ||
286 | if (!clk || !clk->dpll_data) | |
287 | return -EINVAL; | |
288 | ||
289 | dd = clk->dpll_data; | |
290 | ||
ad67ef68 | 291 | v = __raw_readl(dd->autoidle_reg); |
542313cc PW |
292 | v &= dd->autoidle_mask; |
293 | v >>= __ffs(dd->autoidle_mask); | |
294 | ||
295 | return v; | |
296 | } | |
297 | ||
298 | /** | |
299 | * omap3_dpll_allow_idle - enable DPLL autoidle bits | |
300 | * @clk: struct clk * of the DPLL to operate on | |
301 | * | |
302 | * Enable DPLL automatic idle control. This automatic idle mode | |
303 | * switching takes effect only when the DPLL is locked, at least on | |
304 | * OMAP3430. The DPLL will enter low-power stop when its downstream | |
305 | * clocks are gated. No return value. | |
306 | */ | |
307 | static void omap3_dpll_allow_idle(struct clk *clk) | |
308 | { | |
309 | const struct dpll_data *dd; | |
ad67ef68 | 310 | u32 v; |
542313cc PW |
311 | |
312 | if (!clk || !clk->dpll_data) | |
313 | return; | |
314 | ||
315 | dd = clk->dpll_data; | |
316 | ||
317 | /* | |
318 | * REVISIT: CORE DPLL can optionally enter low-power bypass | |
319 | * by writing 0x5 instead of 0x1. Add some mechanism to | |
320 | * optionally enter this mode. | |
321 | */ | |
ad67ef68 PW |
322 | v = __raw_readl(dd->autoidle_reg); |
323 | v &= ~dd->autoidle_mask; | |
324 | v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); | |
325 | __raw_writel(v, dd->autoidle_reg); | |
542313cc PW |
326 | } |
327 | ||
328 | /** | |
329 | * omap3_dpll_deny_idle - prevent DPLL from automatically idling | |
330 | * @clk: struct clk * of the DPLL to operate on | |
331 | * | |
332 | * Disable DPLL automatic idle control. No return value. | |
333 | */ | |
334 | static void omap3_dpll_deny_idle(struct clk *clk) | |
335 | { | |
336 | const struct dpll_data *dd; | |
ad67ef68 | 337 | u32 v; |
542313cc PW |
338 | |
339 | if (!clk || !clk->dpll_data) | |
340 | return; | |
341 | ||
342 | dd = clk->dpll_data; | |
343 | ||
ad67ef68 PW |
344 | v = __raw_readl(dd->autoidle_reg); |
345 | v &= ~dd->autoidle_mask; | |
346 | v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); | |
347 | __raw_writel(v, dd->autoidle_reg); | |
542313cc PW |
348 | } |
349 | ||
350 | /* Clock control for DPLL outputs */ | |
351 | ||
02e19a96 PW |
352 | /** |
353 | * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate | |
354 | * @clk: DPLL output struct clk | |
355 | * | |
356 | * Using parent clock DPLL data, look up DPLL state. If locked, set our | |
357 | * rate to the dpll_clk * 2; otherwise, just use dpll_clk. | |
358 | */ | |
359 | static void omap3_clkoutx2_recalc(struct clk *clk) | |
360 | { | |
361 | const struct dpll_data *dd; | |
362 | u32 v; | |
363 | struct clk *pclk; | |
364 | ||
365 | /* Walk up the parents of clk, looking for a DPLL */ | |
366 | pclk = clk->parent; | |
367 | while (pclk && !pclk->dpll_data) | |
368 | pclk = pclk->parent; | |
369 | ||
370 | /* clk does not have a DPLL as a parent? */ | |
371 | WARN_ON(!pclk); | |
372 | ||
373 | dd = pclk->dpll_data; | |
374 | ||
375 | WARN_ON(!dd->control_reg || !dd->enable_mask); | |
376 | ||
377 | v = __raw_readl(dd->control_reg) & dd->enable_mask; | |
378 | v >>= __ffs(dd->enable_mask); | |
379 | if (v != DPLL_LOCKED) | |
380 | clk->rate = clk->parent->rate; | |
381 | else | |
382 | clk->rate = clk->parent->rate * 2; | |
383 | ||
384 | if (clk->flags & RATE_PROPAGATES) | |
385 | propagate_rate(clk); | |
386 | } | |
387 | ||
542313cc PW |
388 | /* Common clock code */ |
389 | ||
02e19a96 PW |
390 | /* |
391 | * As it is structured now, this will prevent an OMAP2/3 multiboot | |
392 | * kernel from compiling. This will need further attention. | |
393 | */ | |
394 | #if defined(CONFIG_ARCH_OMAP3) | |
395 | ||
396 | static struct clk_functions omap2_clk_functions = { | |
397 | .clk_enable = omap2_clk_enable, | |
398 | .clk_disable = omap2_clk_disable, | |
399 | .clk_round_rate = omap2_clk_round_rate, | |
400 | .clk_set_rate = omap2_clk_set_rate, | |
401 | .clk_set_parent = omap2_clk_set_parent, | |
402 | .clk_disable_unused = omap2_clk_disable_unused, | |
403 | }; | |
404 | ||
405 | /* | |
406 | * Set clocks for bypass mode for reboot to work. | |
407 | */ | |
408 | void omap2_clk_prepare_for_reboot(void) | |
409 | { | |
410 | /* REVISIT: Not ready for 343x */ | |
411 | #if 0 | |
412 | u32 rate; | |
413 | ||
414 | if (vclk == NULL || sclk == NULL) | |
415 | return; | |
416 | ||
417 | rate = clk_get_rate(sclk); | |
418 | clk_set_rate(vclk, rate); | |
419 | #endif | |
420 | } | |
421 | ||
422 | /* REVISIT: Move this init stuff out into clock.c */ | |
423 | ||
424 | /* | |
425 | * Switch the MPU rate if specified on cmdline. | |
426 | * We cannot do this early until cmdline is parsed. | |
427 | */ | |
428 | static int __init omap2_clk_arch_init(void) | |
429 | { | |
430 | if (!mpurate) | |
431 | return -EINVAL; | |
432 | ||
433 | /* REVISIT: not yet ready for 343x */ | |
434 | #if 0 | |
435 | if (omap2_select_table_rate(&virt_prcm_set, mpurate)) | |
436 | printk(KERN_ERR "Could not find matching MPU rate\n"); | |
437 | #endif | |
438 | ||
439 | recalculate_root_clocks(); | |
440 | ||
441 | printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): " | |
442 | "%ld.%01ld/%ld/%ld MHz\n", | |
443 | (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10, | |
444 | (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ; | |
445 | ||
446 | return 0; | |
447 | } | |
448 | arch_initcall(omap2_clk_arch_init); | |
449 | ||
450 | int __init omap2_clk_init(void) | |
451 | { | |
452 | /* struct prcm_config *prcm; */ | |
453 | struct clk **clkp; | |
454 | /* u32 clkrate; */ | |
455 | u32 cpu_clkflg; | |
456 | ||
457 | /* REVISIT: Ultimately this will be used for multiboot */ | |
458 | #if 0 | |
459 | if (cpu_is_omap242x()) { | |
460 | cpu_mask = RATE_IN_242X; | |
461 | cpu_clkflg = CLOCK_IN_OMAP242X; | |
462 | clkp = onchip_24xx_clks; | |
463 | } else if (cpu_is_omap2430()) { | |
464 | cpu_mask = RATE_IN_243X; | |
465 | cpu_clkflg = CLOCK_IN_OMAP243X; | |
466 | clkp = onchip_24xx_clks; | |
467 | } | |
468 | #endif | |
469 | if (cpu_is_omap34xx()) { | |
470 | cpu_mask = RATE_IN_343X; | |
471 | cpu_clkflg = CLOCK_IN_OMAP343X; | |
472 | clkp = onchip_34xx_clks; | |
473 | ||
474 | /* | |
475 | * Update this if there are further clock changes between ES2 | |
476 | * and production parts | |
477 | */ | |
478 | if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) { | |
479 | /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */ | |
480 | cpu_clkflg |= CLOCK_IN_OMAP3430ES1; | |
481 | } else { | |
482 | cpu_mask |= RATE_IN_3430ES2; | |
483 | cpu_clkflg |= CLOCK_IN_OMAP3430ES2; | |
484 | } | |
485 | } | |
486 | ||
487 | clk_init(&omap2_clk_functions); | |
488 | ||
489 | for (clkp = onchip_34xx_clks; | |
490 | clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks); | |
491 | clkp++) { | |
492 | if ((*clkp)->flags & cpu_clkflg) | |
493 | clk_register(*clkp); | |
494 | } | |
495 | ||
496 | /* REVISIT: Not yet ready for OMAP3 */ | |
497 | #if 0 | |
498 | /* Check the MPU rate set by bootloader */ | |
499 | clkrate = omap2_get_dpll_rate_24xx(&dpll_ck); | |
500 | for (prcm = rate_table; prcm->mpu_speed; prcm++) { | |
501 | if (!(prcm->flags & cpu_mask)) | |
502 | continue; | |
503 | if (prcm->xtal_speed != sys_ck.rate) | |
504 | continue; | |
505 | if (prcm->dpll_speed <= clkrate) | |
506 | break; | |
507 | } | |
508 | curr_prcm_set = prcm; | |
509 | #endif | |
510 | ||
511 | recalculate_root_clocks(); | |
512 | ||
3760d31f | 513 | printk(KERN_INFO "Clocking rate (Crystal/DPLL/ARM core): " |
02e19a96 PW |
514 | "%ld.%01ld/%ld/%ld MHz\n", |
515 | (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10, | |
3760d31f | 516 | (core_ck.rate / 1000000), (arm_fck.rate / 1000000)); |
02e19a96 PW |
517 | |
518 | /* | |
519 | * Only enable those clocks we will need, let the drivers | |
520 | * enable other clocks as necessary | |
521 | */ | |
522 | clk_enable_init_clocks(); | |
523 | ||
524 | /* Avoid sleeping during omap2_clk_prepare_for_reboot() */ | |
525 | /* REVISIT: not yet ready for 343x */ | |
526 | #if 0 | |
527 | vclk = clk_get(NULL, "virt_prcm_set"); | |
528 | sclk = clk_get(NULL, "sys_ck"); | |
529 | #endif | |
530 | return 0; | |
531 | } | |
532 | ||
533 | #endif |