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