2 * linux/arch/arm/mach-omap2/clock.c
4 * Copyright (C) 2005-2008 Texas Instruments, Inc.
5 * Copyright (C) 2004-2008 Nokia Corporation
8 * Richard Woodruff <r-woodruff2@ti.com>
11 * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
12 * Gordon McNutt and RidgeRun, Inc.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/device.h>
23 #include <linux/list.h>
24 #include <linux/errno.h>
25 #include <linux/delay.h>
26 #include <linux/clk.h>
29 #include <linux/cpufreq.h>
31 #include <mach/clock.h>
32 #include <mach/sram.h>
33 #include <asm/div64.h>
34 #include <asm/bitops.h>
38 #include "clock24xx.h"
40 #include "prm-regbits-24xx.h"
42 #include "cm-regbits-24xx.h"
44 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
45 #define EN_APLL_STOPPED 0
46 #define EN_APLL_LOCKED 3
48 /* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
49 #define APLLS_CLKIN_19_2MHZ 0
50 #define APLLS_CLKIN_13MHZ 2
51 #define APLLS_CLKIN_12MHZ 3
53 /* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */
55 static struct prcm_config
*curr_prcm_set
;
56 static struct clk
*vclk
;
57 static struct clk
*sclk
;
59 /*-------------------------------------------------------------------------
60 * Omap24xx specific clock functions
61 *-------------------------------------------------------------------------*/
63 /* This actually returns the rate of core_ck, not dpll_ck. */
64 static u32
omap2_get_dpll_rate_24xx(struct clk
*tclk
)
69 dpll_clk
= omap2_get_dpll_rate(tclk
);
71 amult
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
72 amult
&= OMAP24XX_CORE_CLK_SRC_MASK
;
78 static int omap2_enable_osc_ck(struct clk
*clk
)
82 pcc
= __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL
);
84 __raw_writel(pcc
& ~OMAP_AUTOEXTCLKMODE_MASK
,
85 OMAP24XX_PRCM_CLKSRC_CTRL
);
90 static void omap2_disable_osc_ck(struct clk
*clk
)
94 pcc
= __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL
);
96 __raw_writel(pcc
| OMAP_AUTOEXTCLKMODE_MASK
,
97 OMAP24XX_PRCM_CLKSRC_CTRL
);
101 /* Recalculate SYST_CLK */
102 static void omap2_sys_clk_recalc(struct clk
* clk
)
104 u32 div
= PRCM_CLKSRC_CTRL
;
105 div
&= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */
106 div
>>= clk
->rate_offset
;
107 clk
->rate
= (clk
->parent
->rate
/ div
);
112 /* Enable an APLL if off */
113 static int omap2_clk_fixed_enable(struct clk
*clk
)
117 apll_mask
= EN_APLL_LOCKED
<< clk
->enable_bit
;
119 cval
= cm_read_mod_reg(PLL_MOD
, CM_CLKEN
);
121 if ((cval
& apll_mask
) == apll_mask
)
122 return 0; /* apll already enabled */
126 cm_write_mod_reg(cval
, PLL_MOD
, CM_CLKEN
);
128 if (clk
== &apll96_ck
)
129 cval
= OMAP24XX_ST_96M_APLL
;
130 else if (clk
== &apll54_ck
)
131 cval
= OMAP24XX_ST_54M_APLL
;
133 omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD
, CM_IDLEST
), cval
,
137 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
144 static void omap2_clk_fixed_disable(struct clk
*clk
)
148 cval
= cm_read_mod_reg(PLL_MOD
, CM_CLKEN
);
149 cval
&= ~(EN_APLL_LOCKED
<< clk
->enable_bit
);
150 cm_write_mod_reg(cval
, PLL_MOD
, CM_CLKEN
);
154 * Uses the current prcm set to tell if a rate is valid.
155 * You can go slower, but not faster within a given rate set.
157 long omap2_dpllcore_round_rate(unsigned long target_rate
)
159 u32 high
, low
, core_clk_src
;
161 core_clk_src
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
162 core_clk_src
&= OMAP24XX_CORE_CLK_SRC_MASK
;
164 if (core_clk_src
== CORE_CLK_SRC_DPLL
) { /* DPLL clockout */
165 high
= curr_prcm_set
->dpll_speed
* 2;
166 low
= curr_prcm_set
->dpll_speed
;
167 } else { /* DPLL clockout x 2 */
168 high
= curr_prcm_set
->dpll_speed
;
169 low
= curr_prcm_set
->dpll_speed
/ 2;
172 #ifdef DOWN_VARIABLE_DPLL
173 if (target_rate
> high
)
178 if (target_rate
> low
)
186 static void omap2_dpllcore_recalc(struct clk
*clk
)
188 clk
->rate
= omap2_get_dpll_rate_24xx(clk
);
193 static int omap2_reprogram_dpllcore(struct clk
*clk
, unsigned long rate
)
195 u32 cur_rate
, low
, mult
, div
, valid_rate
, done_rate
;
197 struct prcm_config tmpset
;
198 const struct dpll_data
*dd
;
202 local_irq_save(flags
);
203 cur_rate
= omap2_get_dpll_rate_24xx(&dpll_ck
);
204 mult
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
205 mult
&= OMAP24XX_CORE_CLK_SRC_MASK
;
207 if ((rate
== (cur_rate
/ 2)) && (mult
== 2)) {
208 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL
, 1);
209 } else if ((rate
== (cur_rate
* 2)) && (mult
== 1)) {
210 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1);
211 } else if (rate
!= cur_rate
) {
212 valid_rate
= omap2_dpllcore_round_rate(rate
);
213 if (valid_rate
!= rate
)
217 low
= curr_prcm_set
->dpll_speed
;
219 low
= curr_prcm_set
->dpll_speed
/ 2;
225 tmpset
.cm_clksel1_pll
= __raw_readl(dd
->mult_div1_reg
);
226 tmpset
.cm_clksel1_pll
&= ~(dd
->mult_mask
|
228 div
= ((curr_prcm_set
->xtal_speed
/ 1000000) - 1);
229 tmpset
.cm_clksel2_pll
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
230 tmpset
.cm_clksel2_pll
&= ~OMAP24XX_CORE_CLK_SRC_MASK
;
232 tmpset
.cm_clksel2_pll
|= CORE_CLK_SRC_DPLL_X2
;
233 mult
= ((rate
/ 2) / 1000000);
234 done_rate
= CORE_CLK_SRC_DPLL_X2
;
236 tmpset
.cm_clksel2_pll
|= CORE_CLK_SRC_DPLL
;
237 mult
= (rate
/ 1000000);
238 done_rate
= CORE_CLK_SRC_DPLL
;
240 tmpset
.cm_clksel1_pll
|= (div
<< __ffs(dd
->mult_mask
));
241 tmpset
.cm_clksel1_pll
|= (mult
<< __ffs(dd
->div1_mask
));
244 tmpset
.base_sdrc_rfr
= SDRC_RFR_CTRL_BYPASS
;
246 if (rate
== curr_prcm_set
->xtal_speed
) /* If asking for 1-1 */
249 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1); /* For init_mem */
251 /* Force dll lock mode */
252 omap2_set_prcm(tmpset
.cm_clksel1_pll
, tmpset
.base_sdrc_rfr
,
255 /* Errata: ret dll entry state */
256 omap2_init_memory_params(omap2_dll_force_needed());
257 omap2_reprogram_sdrc(done_rate
, 0);
259 omap2_dpllcore_recalc(&dpll_ck
);
263 local_irq_restore(flags
);
268 * omap2_table_mpu_recalc - just return the MPU speed
269 * @clk: virt_prcm_set struct clk
271 * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
273 static void omap2_table_mpu_recalc(struct clk
*clk
)
275 clk
->rate
= curr_prcm_set
->mpu_speed
;
279 * Look for a rate equal or less than the target rate given a configuration set.
281 * What's not entirely clear is "which" field represents the key field.
282 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
283 * just uses the ARM rates.
285 static long omap2_round_to_table_rate(struct clk
*clk
, unsigned long rate
)
287 struct prcm_config
*ptr
;
290 if (clk
!= &virt_prcm_set
)
293 highest_rate
= -EINVAL
;
295 for (ptr
= rate_table
; ptr
->mpu_speed
; ptr
++) {
296 if (!(ptr
->flags
& cpu_mask
))
298 if (ptr
->xtal_speed
!= sys_ck
.rate
)
301 highest_rate
= ptr
->mpu_speed
;
303 /* Can check only after xtal frequency check */
304 if (ptr
->mpu_speed
<= rate
)
310 /* Sets basic clocks based on the specified rate */
311 static int omap2_select_table_rate(struct clk
*clk
, unsigned long rate
)
313 u32 cur_rate
, done_rate
, bypass
= 0, tmp
;
314 struct prcm_config
*prcm
;
315 unsigned long found_speed
= 0;
318 if (clk
!= &virt_prcm_set
)
321 for (prcm
= rate_table
; prcm
->mpu_speed
; prcm
++) {
322 if (!(prcm
->flags
& cpu_mask
))
325 if (prcm
->xtal_speed
!= sys_ck
.rate
)
328 if (prcm
->mpu_speed
<= rate
) {
329 found_speed
= prcm
->mpu_speed
;
335 printk(KERN_INFO
"Could not set MPU rate to %luMHz\n",
340 curr_prcm_set
= prcm
;
341 cur_rate
= omap2_get_dpll_rate_24xx(&dpll_ck
);
343 if (prcm
->dpll_speed
== cur_rate
/ 2) {
344 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL
, 1);
345 } else if (prcm
->dpll_speed
== cur_rate
* 2) {
346 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1);
347 } else if (prcm
->dpll_speed
!= cur_rate
) {
348 local_irq_save(flags
);
350 if (prcm
->dpll_speed
== prcm
->xtal_speed
)
353 if ((prcm
->cm_clksel2_pll
& OMAP24XX_CORE_CLK_SRC_MASK
) ==
354 CORE_CLK_SRC_DPLL_X2
)
355 done_rate
= CORE_CLK_SRC_DPLL_X2
;
357 done_rate
= CORE_CLK_SRC_DPLL
;
360 cm_write_mod_reg(prcm
->cm_clksel_mpu
, MPU_MOD
, CM_CLKSEL
);
362 /* dsp + iva1 div(2420), iva2.1(2430) */
363 cm_write_mod_reg(prcm
->cm_clksel_dsp
,
364 OMAP24XX_DSP_MOD
, CM_CLKSEL
);
366 cm_write_mod_reg(prcm
->cm_clksel_gfx
, GFX_MOD
, CM_CLKSEL
);
368 /* Major subsystem dividers */
369 tmp
= cm_read_mod_reg(CORE_MOD
, CM_CLKSEL1
) & OMAP24XX_CLKSEL_DSS2_MASK
;
370 cm_write_mod_reg(prcm
->cm_clksel1_core
| tmp
, CORE_MOD
, CM_CLKSEL1
);
371 if (cpu_is_omap2430())
372 cm_write_mod_reg(prcm
->cm_clksel_mdm
,
373 OMAP2430_MDM_MOD
, CM_CLKSEL
);
375 /* x2 to enter init_mem */
376 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1);
378 omap2_set_prcm(prcm
->cm_clksel1_pll
, prcm
->base_sdrc_rfr
,
381 omap2_init_memory_params(omap2_dll_force_needed());
382 omap2_reprogram_sdrc(done_rate
, 0);
384 local_irq_restore(flags
);
386 omap2_dpllcore_recalc(&dpll_ck
);
391 static struct clk_functions omap2_clk_functions
= {
392 .clk_enable
= omap2_clk_enable
,
393 .clk_disable
= omap2_clk_disable
,
394 .clk_round_rate
= omap2_clk_round_rate
,
395 .clk_set_rate
= omap2_clk_set_rate
,
396 .clk_set_parent
= omap2_clk_set_parent
,
397 .clk_disable_unused
= omap2_clk_disable_unused
,
400 static u32
omap2_get_apll_clkin(void)
404 aplls
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL1
);
405 aplls
&= OMAP24XX_APLLS_CLKIN_MASK
;
406 aplls
>>= OMAP24XX_APLLS_CLKIN_SHIFT
;
408 if (aplls
== APLLS_CLKIN_19_2MHZ
)
410 else if (aplls
== APLLS_CLKIN_13MHZ
)
412 else if (aplls
== APLLS_CLKIN_12MHZ
)
418 static u32
omap2_get_sysclkdiv(void)
422 div
= __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL
);
423 div
&= OMAP_SYSCLKDIV_MASK
;
424 div
>>= OMAP_SYSCLKDIV_SHIFT
;
429 static void omap2_osc_clk_recalc(struct clk
*clk
)
431 clk
->rate
= omap2_get_apll_clkin() * omap2_get_sysclkdiv();
435 static void omap2_sys_clk_recalc(struct clk
*clk
)
437 clk
->rate
= clk
->parent
->rate
/ omap2_get_sysclkdiv();
442 * Set clocks for bypass mode for reboot to work.
444 void omap2_clk_prepare_for_reboot(void)
448 if (vclk
== NULL
|| sclk
== NULL
)
451 rate
= clk_get_rate(sclk
);
452 clk_set_rate(vclk
, rate
);
456 * Switch the MPU rate if specified on cmdline.
457 * We cannot do this early until cmdline is parsed.
459 static int __init
omap2_clk_arch_init(void)
464 if (omap2_select_table_rate(&virt_prcm_set
, mpurate
))
465 printk(KERN_ERR
"Could not find matching MPU rate\n");
467 recalculate_root_clocks();
469 printk(KERN_INFO
"Switched to new clocking rate (Crystal/DPLL/MPU): "
470 "%ld.%01ld/%ld/%ld MHz\n",
471 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
472 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
476 arch_initcall(omap2_clk_arch_init
);
478 int __init
omap2_clk_init(void)
480 struct prcm_config
*prcm
;
484 if (cpu_is_omap242x())
485 cpu_mask
= RATE_IN_242X
;
486 else if (cpu_is_omap2430())
487 cpu_mask
= RATE_IN_243X
;
489 clk_init(&omap2_clk_functions
);
491 omap2_osc_clk_recalc(&osc_ck
);
492 omap2_sys_clk_recalc(&sys_ck
);
494 for (clkp
= onchip_24xx_clks
;
495 clkp
< onchip_24xx_clks
+ ARRAY_SIZE(onchip_24xx_clks
);
498 if ((*clkp
)->flags
& CLOCK_IN_OMAP242X
&& cpu_is_omap2420()) {
503 if ((*clkp
)->flags
& CLOCK_IN_OMAP243X
&& cpu_is_omap2430()) {
509 /* Check the MPU rate set by bootloader */
510 clkrate
= omap2_get_dpll_rate_24xx(&dpll_ck
);
511 for (prcm
= rate_table
; prcm
->mpu_speed
; prcm
++) {
512 if (!(prcm
->flags
& cpu_mask
))
514 if (prcm
->xtal_speed
!= sys_ck
.rate
)
516 if (prcm
->dpll_speed
<= clkrate
)
519 curr_prcm_set
= prcm
;
521 recalculate_root_clocks();
523 printk(KERN_INFO
"Clocking rate (Crystal/DPLL/MPU): "
524 "%ld.%01ld/%ld/%ld MHz\n",
525 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
526 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
529 * Only enable those clocks we will need, let the drivers
530 * enable other clocks as necessary
532 clk_enable_init_clocks();
534 /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
535 vclk
= clk_get(NULL
, "virt_prcm_set");
536 sclk
= clk_get(NULL
, "sys_ck");