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>
28 #include <linux/cpufreq.h>
29 #include <linux/bitops.h>
31 #include <mach/clock.h>
32 #include <mach/sram.h>
33 #include <asm/div64.h>
37 #include "clock24xx.h"
39 #include "prm-regbits-24xx.h"
41 #include "cm-regbits-24xx.h"
43 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
44 #define EN_APLL_STOPPED 0
45 #define EN_APLL_LOCKED 3
47 /* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
48 #define APLLS_CLKIN_19_2MHZ 0
49 #define APLLS_CLKIN_13MHZ 2
50 #define APLLS_CLKIN_12MHZ 3
52 /* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */
54 static struct prcm_config
*curr_prcm_set
;
55 static struct clk
*vclk
;
56 static struct clk
*sclk
;
58 /*-------------------------------------------------------------------------
59 * Omap24xx specific clock functions
60 *-------------------------------------------------------------------------*/
62 /* This actually returns the rate of core_ck, not dpll_ck. */
63 static u32
omap2_get_dpll_rate_24xx(struct clk
*tclk
)
68 dpll_clk
= omap2_get_dpll_rate(tclk
);
70 amult
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
71 amult
&= OMAP24XX_CORE_CLK_SRC_MASK
;
77 static int omap2_enable_osc_ck(struct clk
*clk
)
81 pcc
= __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL
);
83 __raw_writel(pcc
& ~OMAP_AUTOEXTCLKMODE_MASK
,
84 OMAP24XX_PRCM_CLKSRC_CTRL
);
89 static void omap2_disable_osc_ck(struct clk
*clk
)
93 pcc
= __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL
);
95 __raw_writel(pcc
| OMAP_AUTOEXTCLKMODE_MASK
,
96 OMAP24XX_PRCM_CLKSRC_CTRL
);
100 /* Recalculate SYST_CLK */
101 static void omap2_sys_clk_recalc(struct clk
* clk
)
103 u32 div
= PRCM_CLKSRC_CTRL
;
104 div
&= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */
105 div
>>= clk
->rate_offset
;
106 clk
->rate
= (clk
->parent
->rate
/ div
);
111 /* Enable an APLL if off */
112 static int omap2_clk_fixed_enable(struct clk
*clk
)
116 apll_mask
= EN_APLL_LOCKED
<< clk
->enable_bit
;
118 cval
= cm_read_mod_reg(PLL_MOD
, CM_CLKEN
);
120 if ((cval
& apll_mask
) == apll_mask
)
121 return 0; /* apll already enabled */
125 cm_write_mod_reg(cval
, PLL_MOD
, CM_CLKEN
);
127 if (clk
== &apll96_ck
)
128 cval
= OMAP24XX_ST_96M_APLL
;
129 else if (clk
== &apll54_ck
)
130 cval
= OMAP24XX_ST_54M_APLL
;
132 omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD
, CM_IDLEST
), cval
,
136 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
143 static void omap2_clk_fixed_disable(struct clk
*clk
)
147 cval
= cm_read_mod_reg(PLL_MOD
, CM_CLKEN
);
148 cval
&= ~(EN_APLL_LOCKED
<< clk
->enable_bit
);
149 cm_write_mod_reg(cval
, PLL_MOD
, CM_CLKEN
);
153 * Uses the current prcm set to tell if a rate is valid.
154 * You can go slower, but not faster within a given rate set.
156 long omap2_dpllcore_round_rate(unsigned long target_rate
)
158 u32 high
, low
, core_clk_src
;
160 core_clk_src
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
161 core_clk_src
&= OMAP24XX_CORE_CLK_SRC_MASK
;
163 if (core_clk_src
== CORE_CLK_SRC_DPLL
) { /* DPLL clockout */
164 high
= curr_prcm_set
->dpll_speed
* 2;
165 low
= curr_prcm_set
->dpll_speed
;
166 } else { /* DPLL clockout x 2 */
167 high
= curr_prcm_set
->dpll_speed
;
168 low
= curr_prcm_set
->dpll_speed
/ 2;
171 #ifdef DOWN_VARIABLE_DPLL
172 if (target_rate
> high
)
177 if (target_rate
> low
)
185 static void omap2_dpllcore_recalc(struct clk
*clk
)
187 clk
->rate
= omap2_get_dpll_rate_24xx(clk
);
192 static int omap2_reprogram_dpllcore(struct clk
*clk
, unsigned long rate
)
194 u32 cur_rate
, low
, mult
, div
, valid_rate
, done_rate
;
196 struct prcm_config tmpset
;
197 const struct dpll_data
*dd
;
201 local_irq_save(flags
);
202 cur_rate
= omap2_get_dpll_rate_24xx(&dpll_ck
);
203 mult
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
204 mult
&= OMAP24XX_CORE_CLK_SRC_MASK
;
206 if ((rate
== (cur_rate
/ 2)) && (mult
== 2)) {
207 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL
, 1);
208 } else if ((rate
== (cur_rate
* 2)) && (mult
== 1)) {
209 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1);
210 } else if (rate
!= cur_rate
) {
211 valid_rate
= omap2_dpllcore_round_rate(rate
);
212 if (valid_rate
!= rate
)
216 low
= curr_prcm_set
->dpll_speed
;
218 low
= curr_prcm_set
->dpll_speed
/ 2;
224 tmpset
.cm_clksel1_pll
= __raw_readl(dd
->mult_div1_reg
);
225 tmpset
.cm_clksel1_pll
&= ~(dd
->mult_mask
|
227 div
= ((curr_prcm_set
->xtal_speed
/ 1000000) - 1);
228 tmpset
.cm_clksel2_pll
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
229 tmpset
.cm_clksel2_pll
&= ~OMAP24XX_CORE_CLK_SRC_MASK
;
231 tmpset
.cm_clksel2_pll
|= CORE_CLK_SRC_DPLL_X2
;
232 mult
= ((rate
/ 2) / 1000000);
233 done_rate
= CORE_CLK_SRC_DPLL_X2
;
235 tmpset
.cm_clksel2_pll
|= CORE_CLK_SRC_DPLL
;
236 mult
= (rate
/ 1000000);
237 done_rate
= CORE_CLK_SRC_DPLL
;
239 tmpset
.cm_clksel1_pll
|= (div
<< __ffs(dd
->mult_mask
));
240 tmpset
.cm_clksel1_pll
|= (mult
<< __ffs(dd
->div1_mask
));
243 tmpset
.base_sdrc_rfr
= SDRC_RFR_CTRL_BYPASS
;
245 if (rate
== curr_prcm_set
->xtal_speed
) /* If asking for 1-1 */
248 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1); /* For init_mem */
250 /* Force dll lock mode */
251 omap2_set_prcm(tmpset
.cm_clksel1_pll
, tmpset
.base_sdrc_rfr
,
254 /* Errata: ret dll entry state */
255 omap2_init_memory_params(omap2_dll_force_needed());
256 omap2_reprogram_sdrc(done_rate
, 0);
258 omap2_dpllcore_recalc(&dpll_ck
);
262 local_irq_restore(flags
);
267 * omap2_table_mpu_recalc - just return the MPU speed
268 * @clk: virt_prcm_set struct clk
270 * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
272 static void omap2_table_mpu_recalc(struct clk
*clk
)
274 clk
->rate
= curr_prcm_set
->mpu_speed
;
278 * Look for a rate equal or less than the target rate given a configuration set.
280 * What's not entirely clear is "which" field represents the key field.
281 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
282 * just uses the ARM rates.
284 static long omap2_round_to_table_rate(struct clk
*clk
, unsigned long rate
)
286 struct prcm_config
*ptr
;
289 if (clk
!= &virt_prcm_set
)
292 highest_rate
= -EINVAL
;
294 for (ptr
= rate_table
; ptr
->mpu_speed
; ptr
++) {
295 if (!(ptr
->flags
& cpu_mask
))
297 if (ptr
->xtal_speed
!= sys_ck
.rate
)
300 highest_rate
= ptr
->mpu_speed
;
302 /* Can check only after xtal frequency check */
303 if (ptr
->mpu_speed
<= rate
)
309 /* Sets basic clocks based on the specified rate */
310 static int omap2_select_table_rate(struct clk
*clk
, unsigned long rate
)
312 u32 cur_rate
, done_rate
, bypass
= 0, tmp
;
313 struct prcm_config
*prcm
;
314 unsigned long found_speed
= 0;
317 if (clk
!= &virt_prcm_set
)
320 for (prcm
= rate_table
; prcm
->mpu_speed
; prcm
++) {
321 if (!(prcm
->flags
& cpu_mask
))
324 if (prcm
->xtal_speed
!= sys_ck
.rate
)
327 if (prcm
->mpu_speed
<= rate
) {
328 found_speed
= prcm
->mpu_speed
;
334 printk(KERN_INFO
"Could not set MPU rate to %luMHz\n",
339 curr_prcm_set
= prcm
;
340 cur_rate
= omap2_get_dpll_rate_24xx(&dpll_ck
);
342 if (prcm
->dpll_speed
== cur_rate
/ 2) {
343 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL
, 1);
344 } else if (prcm
->dpll_speed
== cur_rate
* 2) {
345 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1);
346 } else if (prcm
->dpll_speed
!= cur_rate
) {
347 local_irq_save(flags
);
349 if (prcm
->dpll_speed
== prcm
->xtal_speed
)
352 if ((prcm
->cm_clksel2_pll
& OMAP24XX_CORE_CLK_SRC_MASK
) ==
353 CORE_CLK_SRC_DPLL_X2
)
354 done_rate
= CORE_CLK_SRC_DPLL_X2
;
356 done_rate
= CORE_CLK_SRC_DPLL
;
359 cm_write_mod_reg(prcm
->cm_clksel_mpu
, MPU_MOD
, CM_CLKSEL
);
361 /* dsp + iva1 div(2420), iva2.1(2430) */
362 cm_write_mod_reg(prcm
->cm_clksel_dsp
,
363 OMAP24XX_DSP_MOD
, CM_CLKSEL
);
365 cm_write_mod_reg(prcm
->cm_clksel_gfx
, GFX_MOD
, CM_CLKSEL
);
367 /* Major subsystem dividers */
368 tmp
= cm_read_mod_reg(CORE_MOD
, CM_CLKSEL1
) & OMAP24XX_CLKSEL_DSS2_MASK
;
369 cm_write_mod_reg(prcm
->cm_clksel1_core
| tmp
, CORE_MOD
, CM_CLKSEL1
);
370 if (cpu_is_omap2430())
371 cm_write_mod_reg(prcm
->cm_clksel_mdm
,
372 OMAP2430_MDM_MOD
, CM_CLKSEL
);
374 /* x2 to enter init_mem */
375 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2
, 1);
377 omap2_set_prcm(prcm
->cm_clksel1_pll
, prcm
->base_sdrc_rfr
,
380 omap2_init_memory_params(omap2_dll_force_needed());
381 omap2_reprogram_sdrc(done_rate
, 0);
383 local_irq_restore(flags
);
385 omap2_dpllcore_recalc(&dpll_ck
);
390 static struct clk_functions omap2_clk_functions
= {
391 .clk_enable
= omap2_clk_enable
,
392 .clk_disable
= omap2_clk_disable
,
393 .clk_round_rate
= omap2_clk_round_rate
,
394 .clk_set_rate
= omap2_clk_set_rate
,
395 .clk_set_parent
= omap2_clk_set_parent
,
396 .clk_disable_unused
= omap2_clk_disable_unused
,
399 static u32
omap2_get_apll_clkin(void)
403 aplls
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL1
);
404 aplls
&= OMAP24XX_APLLS_CLKIN_MASK
;
405 aplls
>>= OMAP24XX_APLLS_CLKIN_SHIFT
;
407 if (aplls
== APLLS_CLKIN_19_2MHZ
)
409 else if (aplls
== APLLS_CLKIN_13MHZ
)
411 else if (aplls
== APLLS_CLKIN_12MHZ
)
417 static u32
omap2_get_sysclkdiv(void)
421 div
= __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL
);
422 div
&= OMAP_SYSCLKDIV_MASK
;
423 div
>>= OMAP_SYSCLKDIV_SHIFT
;
428 static void omap2_osc_clk_recalc(struct clk
*clk
)
430 clk
->rate
= omap2_get_apll_clkin() * omap2_get_sysclkdiv();
434 static void omap2_sys_clk_recalc(struct clk
*clk
)
436 clk
->rate
= clk
->parent
->rate
/ omap2_get_sysclkdiv();
441 * Set clocks for bypass mode for reboot to work.
443 void omap2_clk_prepare_for_reboot(void)
447 if (vclk
== NULL
|| sclk
== NULL
)
450 rate
= clk_get_rate(sclk
);
451 clk_set_rate(vclk
, rate
);
455 * Switch the MPU rate if specified on cmdline.
456 * We cannot do this early until cmdline is parsed.
458 static int __init
omap2_clk_arch_init(void)
463 if (omap2_select_table_rate(&virt_prcm_set
, mpurate
))
464 printk(KERN_ERR
"Could not find matching MPU rate\n");
466 recalculate_root_clocks();
468 printk(KERN_INFO
"Switched to new clocking rate (Crystal/DPLL/MPU): "
469 "%ld.%01ld/%ld/%ld MHz\n",
470 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
471 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
475 arch_initcall(omap2_clk_arch_init
);
477 int __init
omap2_clk_init(void)
479 struct prcm_config
*prcm
;
483 if (cpu_is_omap242x())
484 cpu_mask
= RATE_IN_242X
;
485 else if (cpu_is_omap2430())
486 cpu_mask
= RATE_IN_243X
;
488 clk_init(&omap2_clk_functions
);
490 omap2_osc_clk_recalc(&osc_ck
);
491 omap2_sys_clk_recalc(&sys_ck
);
493 for (clkp
= onchip_24xx_clks
;
494 clkp
< onchip_24xx_clks
+ ARRAY_SIZE(onchip_24xx_clks
);
497 if ((*clkp
)->flags
& CLOCK_IN_OMAP242X
&& cpu_is_omap2420()) {
502 if ((*clkp
)->flags
& CLOCK_IN_OMAP243X
&& cpu_is_omap2430()) {
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
))
513 if (prcm
->xtal_speed
!= sys_ck
.rate
)
515 if (prcm
->dpll_speed
<= clkrate
)
518 curr_prcm_set
= prcm
;
520 recalculate_root_clocks();
522 printk(KERN_INFO
"Clocking rate (Crystal/DPLL/MPU): "
523 "%ld.%01ld/%ld/%ld MHz\n",
524 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
525 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
528 * Only enable those clocks we will need, let the drivers
529 * enable other clocks as necessary
531 clk_enable_init_clocks();
533 /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
534 vclk
= clk_get(NULL
, "virt_prcm_set");
535 sclk
= clk_get(NULL
, "sys_ck");