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