2 * linux/arch/arm/mach-omap2/clock.c
4 * Copyright (C) 2005 Texas Instruments Inc.
5 * Richard Woodruff <r-woodruff2@ti.com>
8 * Cleaned up and modified to use omap shared clock framework by
9 * Tony Lindgren <tony@atomide.com>
11 * Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
12 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
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.
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/device.h>
21 #include <linux/list.h>
22 #include <linux/errno.h>
23 #include <linux/delay.h>
24 #include <linux/clk.h>
28 #include <asm/arch/clock.h>
29 #include <asm/arch/sram.h>
30 #include <asm/div64.h>
35 #include "prm_regbits_24xx.h"
37 #include "cm_regbits_24xx.h"
41 /* CM_CLKSEL1_CORE.CLKSEL_VLYNQ options (2420) */
42 #define CLKSEL_VLYNQ_96MHZ 0
43 #define CLKSEL_VLYNQ_CORECLK_16 0x10
45 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
46 #define EN_APLL_STOPPED 0
47 #define EN_APLL_LOCKED 3
49 /* CM_{CLKSEL2_CORE,CLKSEL_WKUP}.CLKSEL_GPT* options (24XX) */
50 #define CLKSEL_GPT_32K 0
51 #define CLKSEL_GPT_SYSCLK 1
52 #define CLKSEL_GPT_EXTALTCLK 2
54 /* CM_CLKSEL1_CORE.CLKSEL_DSS1 options (24XX) */
55 #define CLKSEL_DSS1_SYSCLK 0
56 #define CLKSEL_DSS1_CORECLK_16 0x10
58 /* CM_CLKSEL1_CORE.CLKSEL_DSS2 options (24XX) */
59 #define CLKSEL_DSS2_SYSCLK 0
60 #define CLKSEL_DSS2_48MHZ 1
62 /* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
63 #define APLLS_CLKIN_19_2MHZ 0
64 #define APLLS_CLKIN_13MHZ 2
65 #define APLLS_CLKIN_12MHZ 3
67 /* CM_CLKSEL1_PLL.54M_SOURCE options (24XX) */
68 #define CLK_54M_SOURCE_APLL 0
69 #define CLK_54M_SOURCE_EXTALTCLK 1
71 /* CM_CLKSEL1_PLL.48M_SOURCE options (24XX) */
72 #define CLK_48M_SOURCE_APLL 0
73 #define CLK_48M_SOURCE_EXTALTCLK 1
75 /* PRCM_CLKOUT_CTRL.CLKOUT_SOURCE options (2420) */
76 #define CLKOUT_SOURCE_CORE_CLK 0
77 #define CLKOUT_SOURCE_SYS_CLK 1
78 #define CLKOUT_SOURCE_96M_CLK 2
79 #define CLKOUT_SOURCE_54M_CLK 3
81 #define MAX_PLL_LOCK_WAIT 100000
83 //#define DOWN_VARIABLE_DPLL 1 /* Experimental */
85 static struct prcm_config *curr_prcm_set;
86 static struct clk *vclk;
87 static struct clk *sclk;
90 static u32 sysclkout_div[] = {1, 2, 4, 8, 16};
92 /*-------------------------------------------------------------------------
93 * Omap2 specific clock functions
94 *-------------------------------------------------------------------------*/
96 /* Recalculate SYST_CLK */
97 static void omap2_sys_clk_recalc(struct clk * clk)
101 if (!cpu_is_omap34xx()) {
102 div = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
103 /* Test if ext clk divided by 1 or 2 */
104 div &= OMAP_SYSCLKDIV_MASK;
105 div >>= clk->rate_offset;
106 clk->rate = (clk->parent->rate / div);
111 static u32 omap2_get_dpll_rate(struct clk * tclk)
114 int dpll_mult, dpll_div, amult;
117 dpll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
119 dpll_mult = dpll & OMAP24XX_DPLL_MULT_MASK;
120 dpll_mult >>= OMAP24XX_DPLL_MULT_SHIFT; /* 10 bits */
121 dpll_div = dpll & OMAP24XX_DPLL_DIV_MASK;
122 dpll_div >>= OMAP24XX_DPLL_DIV_SHIFT; /* 4 bits */
123 dpll_clk = (long long)tclk->parent->rate * dpll_mult;
124 do_div(dpll_clk, dpll_div + 1);
125 amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
126 amult &= OMAP24XX_CORE_CLK_SRC_MASK;
133 * Used for clocks that have the same value as the parent clock,
134 * divided by some factor
136 static void omap2_fixed_divisor_recalc(struct clk *clk)
138 WARN_ON(!clk->fixed_div);
140 clk->rate = clk->parent->rate / clk->fixed_div;
142 if (clk->flags & RATE_PROPAGATES)
146 static void omap2_set_osc_ck(int enable)
150 pcc = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
153 prm_write_reg(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
154 OMAP24XX_PRCM_CLKSRC_CTRL);
156 prm_write_reg(pcc | OMAP_AUTOEXTCLKMODE_MASK,
157 OMAP24XX_PRCM_CLKSRC_CTRL);
161 * omap2_wait_clock_ready - wait for PLL to lock
163 * Returns 1 if the PLL locked, 0 if it failed to lock.
165 static int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name)
170 while (!(cm_read_reg(reg) & cval)) {
173 if (i == MAX_PLL_LOCK_WAIT) {
174 printk(KERN_ERR "Clock %s didn't lock in %d tries\n",
175 name, MAX_PLL_LOCK_WAIT);
181 pr_debug("Clock %s stable after %d loops\n", name, i);
183 return (i < MAX_PLL_LOCK_WAIT) ? 1 : 0;
187 /* Enable an APLL if off */
188 static void omap2_clk_fixed_enable(struct clk *clk)
192 apll_mask = EN_APLL_LOCKED << clk->enable_bit;
194 cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
196 if ((cval & apll_mask) == apll_mask)
197 return; /* apll already enabled */
201 cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
203 if (clk == &apll96_ck)
204 cval = OMAP24XX_ST_96M_APLL;
205 else if (clk == &apll54_ck)
206 cval = OMAP24XX_ST_54M_CLK;
208 omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
212 static void omap2_clk_wait_ready(struct clk *clk)
214 void __iomem *reg, *other_reg, *st_reg;
217 reg = clk->enable_reg;
218 if (reg == OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1) ||
219 reg == OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2))
220 other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x10); /* CM_ICLKEN* */
221 else if (reg == OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1) ||
222 reg == OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2))
223 other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x00); /* CM_FCLKEN* */
227 /* No check for DSS or cam clocks */
228 if (((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */
229 if (clk->enable_bit == OMAP24XX_EN_DSS2_SHIFT ||
230 clk->enable_bit == OMAP24XX_EN_DSS1_SHIFT ||
231 clk->enable_bit == OMAP24XX_EN_CAM_SHIFT)
235 /* Check if both functional and interface clocks
237 bit = 1 << clk->enable_bit;
238 if (!(cm_read_reg(other_reg) & bit))
240 st_reg = (void __iomem *)(((u32)other_reg & ~0xf0) | 0x20); /* CM_IDLEST* */
242 omap2_wait_clock_ready(st_reg, bit, clk->name);
245 /* Enables clock without considering parent dependencies or use count
246 * REVISIT: Maybe change this to use clk->enable like on omap1?
248 static int _omap2_clk_enable(struct clk * clk)
252 if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
255 if (unlikely(clk == &osc_ck)) {
260 if (unlikely(clk->enable_reg == 0)) {
261 printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
266 if (clk->enable_reg == OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN)) {
267 omap2_clk_fixed_enable(clk);
271 regval32 = cm_read_reg(clk->enable_reg);
272 regval32 |= (1 << clk->enable_bit);
273 cm_write_reg(regval32, clk->enable_reg);
276 omap2_clk_wait_ready(clk);
282 static void omap2_clk_fixed_disable(struct clk *clk)
286 cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
287 cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
288 cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
291 /* Disables clock without considering parent dependencies or use count */
292 static void _omap2_clk_disable(struct clk *clk)
296 if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
299 if (unlikely(clk == &osc_ck)) {
304 if (clk->enable_reg == 0) {
306 * 'Independent' here refers to a clock which is not
307 * controlled by its parent.
309 printk(KERN_ERR "clock: clk_disable called on independent "
310 "clock %s which has no enable_reg\n", clk->name);
314 if (clk->enable_reg == OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN)) {
315 omap2_clk_fixed_disable(clk);
319 regval32 = cm_read_reg(clk->enable_reg);
320 regval32 &= ~(1 << clk->enable_bit);
321 cm_write_reg(regval32, clk->enable_reg);
325 static int omap2_clk_enable(struct clk *clk)
329 if (clk->usecount++ == 0) {
330 if (likely((u32)clk->parent))
331 ret = omap2_clk_enable(clk->parent);
333 if (unlikely(ret != 0)) {
338 ret = _omap2_clk_enable(clk);
340 if (unlikely(ret != 0) && clk->parent) {
341 omap2_clk_disable(clk->parent);
349 static void omap2_clk_disable(struct clk *clk)
351 if (clk->usecount > 0 && !(--clk->usecount)) {
352 _omap2_clk_disable(clk);
353 if (likely((u32)clk->parent))
354 omap2_clk_disable(clk->parent);
359 * Uses the current prcm set to tell if a rate is valid.
360 * You can go slower, but not faster within a given rate set.
362 static u32 omap2_dpll_round_rate(unsigned long target_rate)
364 u32 high, low, core_clk_src;
366 core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
367 core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
369 if (core_clk_src == CORE_CLK_SRC_DPLL) { /* DPLL clockout */
370 high = curr_prcm_set->dpll_speed * 2;
371 low = curr_prcm_set->dpll_speed;
372 } else { /* DPLL clockout x 2 */
373 high = curr_prcm_set->dpll_speed;
374 low = curr_prcm_set->dpll_speed / 2;
377 #ifdef DOWN_VARIABLE_DPLL
378 if (target_rate > high)
383 if (target_rate > low)
391 static void omap2_dpll_recalc(struct clk *clk)
393 clk->rate = omap2_get_dpll_rate(clk);
399 * Used for clocks that are part of CLKSEL_xyz governed clocks.
400 * REVISIT: Maybe change to use clk->enable() functions like on omap1?
402 static void omap2_clksel_recalc(struct clk * clk)
404 u32 clksel1_core, div = 0;
406 clksel1_core = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1);
408 if ((clk == &dss1_fck) &&
409 (clksel1_core & OMAP24XX_CLKSEL_DSS1_MASK) == 0) {
413 if ((clk == &vlynq_fck) && cpu_is_omap2420() &&
414 (clksel1_core & OMAP2420_CLKSEL_VLYNQ_MASK) == CLKSEL_VLYNQ_96MHZ) {
418 div = omap2_clksel_get_divisor(clk);
422 if (unlikely(clk->rate == clk->parent->rate / div))
424 clk->rate = clk->parent->rate / div;
426 if (unlikely(clk->flags & RATE_PROPAGATES))
431 * Finds best divider value in an array based on the source and target
432 * rates. The divider array must be sorted with smallest divider first.
434 static inline u32 omap2_divider_from_table(u32 size, u32 *div_array,
435 u32 src_rate, u32 tgt_rate)
439 if (div_array == NULL)
442 for (i = 0; i < size; i++) {
443 test_rate = src_rate / *div_array;
444 if (test_rate <= tgt_rate)
449 return ~0; /* No acceptable divider */
453 * Find divisor for the given clock and target rate.
455 * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
456 * they are only settable as part of virtual_prcm set.
458 static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate,
461 u32 gfx_div[] = {2, 3, 4};
462 u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
463 u32 vlynq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
464 u32 best_div = ~0, asize = 0;
465 u32 *div_array = NULL;
467 switch (tclk->flags & SRC_RATE_SEL_MASK) {
469 asize = ARRAY_SIZE(gfx_div);
473 return omap2_dpll_round_rate(target_rate);
474 case CM_SYSCLKOUT_SEL1:
475 asize = ARRAY_SIZE(sysclkout_div);
476 div_array = sysclkout_div;
479 if (tclk == &dss1_fck) {
480 if (tclk->parent == &core_ck) {
481 asize = ARRAY_SIZE(dss1_div);
482 div_array = dss1_div;
484 *new_div = 0; /* fixed clk */
485 return(tclk->parent->rate);
487 } else if ((tclk == &vlynq_fck) && cpu_is_omap2420()) {
488 if (tclk->parent == &core_ck) {
489 asize = ARRAY_SIZE(vlynq_div);
490 div_array = vlynq_div;
492 *new_div = 0; /* fixed clk */
493 return (tclk->parent->rate);
499 best_div = omap2_divider_from_table(asize, div_array,
500 tclk->parent->rate, target_rate);
501 if (best_div == ~0) {
503 return best_div; /* signal error */
507 return (tclk->parent->rate / best_div);
510 /* Given a clock and a rate apply a clock specific rounding function */
511 static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
515 if (clk->flags & RATE_FIXED)
518 if (clk->flags & RATE_CKCTL)
519 return omap2_clksel_round_rate(clk, rate, &new_div);
521 if (clk->round_rate != 0)
522 return clk->round_rate(clk, rate);
527 static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
529 u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
531 struct prcm_config tmpset;
534 local_irq_save(flags);
535 cur_rate = omap2_get_dpll_rate(&dpll_ck);
536 mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
537 mult &= OMAP24XX_CORE_CLK_SRC_MASK;
539 if ((rate == (cur_rate / 2)) && (mult == 2)) {
540 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
541 } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
542 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
543 } else if (rate != cur_rate) {
544 valid_rate = omap2_dpll_round_rate(rate);
545 if (valid_rate != rate)
549 low = curr_prcm_set->dpll_speed;
551 low = curr_prcm_set->dpll_speed / 2;
553 tmpset.cm_clksel1_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
554 tmpset.cm_clksel1_pll &= ~(OMAP24XX_DPLL_MULT_MASK |
555 OMAP24XX_DPLL_DIV_MASK);
556 div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
557 tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
558 tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
560 tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
561 mult = ((rate / 2) / 1000000);
562 done_rate = CORE_CLK_SRC_DPLL_X2;
564 tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
565 mult = (rate / 1000000);
566 done_rate = CORE_CLK_SRC_DPLL;
568 tmpset.cm_clksel1_pll |= (div << OMAP24XX_DPLL_DIV_SHIFT);
569 tmpset.cm_clksel1_pll |= (mult << OMAP24XX_DPLL_MULT_SHIFT);
572 tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
574 if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */
577 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
579 /* Force dll lock mode */
580 omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
583 /* Errata: ret dll entry state */
584 omap2_init_memory_params(omap2_dll_force_needed());
585 omap2_reprogram_sdrc(done_rate, 0);
587 omap2_dpll_recalc(&dpll_ck);
591 local_irq_restore(flags);
596 * omap2_table_mpu_recalc - just return the MPU speed
597 * @clk: virt_prcm_set struct clk
599 * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
601 static void omap2_table_mpu_recalc(struct clk *clk)
603 clk->rate = curr_prcm_set->mpu_speed;
607 * Look for a rate equal or less than the target rate given a configuration set.
609 * What's not entirely clear is "which" field represents the key field.
610 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
611 * just uses the ARM rates.
613 static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
615 struct prcm_config * ptr;
618 if (clk != &virt_prcm_set)
621 highest_rate = -EINVAL;
623 for (ptr = rate_table; ptr->mpu_speed; ptr++) {
624 if (!(ptr->flags & cpu_mask))
626 if (ptr->xtal_speed != sys_ck.rate)
629 highest_rate = ptr->mpu_speed;
631 /* Can check only after xtal frequency check */
632 if (ptr->mpu_speed <= rate)
639 * omap2_clksel_to_divisor() - turn field value into integer divider
641 static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
645 if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
646 for (i = 0; i < ARRAY_SIZE(sysclkout_div); i++) {
648 return sysclkout_div[i];
656 * omap2_divisor_to_clksel() - turn integer divider into field value
658 static u32 omap2_divisor_to_clksel(u32 div_sel, u32 div)
662 if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
663 for (i = 0; i < ARRAY_SIZE(sysclkout_div); i++) {
664 if (div == sysclkout_div[i])
673 * Returns the CLKSEL divider register value
675 static void __iomem *omap2_get_clksel(u32 *field_mask, struct clk *clk)
677 u32 div_off, mask = ~0;
678 void __iomem *div_addr = 0;
680 div_off = clk->rate_offset;
682 switch (clk->flags & SRC_RATE_SEL_MASK) {
684 div_addr = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL);
685 mask = OMAP24XX_CLKSEL_MPU_MASK;
688 div_addr = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL);
689 if (cpu_is_omap2420()) {
690 if (div_off == OMAP24XX_CLKSEL_DSP_SHIFT)
691 mask = OMAP24XX_CLKSEL_DSP_MASK;
692 else if (div_off == OMAP2420_CLKSEL_IVA_SHIFT)
693 mask = OMAP2420_CLKSEL_IVA_MASK;
694 else if (div_off == OMAP24XX_CLKSEL_DSP_IF_SHIFT)
695 mask = OMAP24XX_CLKSEL_DSP_IF_MASK;
696 } else if (cpu_is_omap2430()) {
697 if (div_off == OMAP24XX_CLKSEL_DSP_SHIFT)
698 mask = OMAP24XX_CLKSEL_DSP_MASK;
699 else if (div_off == OMAP24XX_CLKSEL_DSP_IF_SHIFT)
700 mask = OMAP24XX_CLKSEL_DSP_IF_MASK;
703 div_addr = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL);
704 if (div_off == OMAP_CLKSEL_GFX_SHIFT)
705 mask = OMAP_CLKSEL_GFX_MASK;
708 div_addr = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL);
709 if (div_off == OMAP2430_CLKSEL_MDM_SHIFT)
710 mask = OMAP2430_CLKSEL_MDM_MASK;
712 case CM_SYSCLKOUT_SEL1:
713 div_addr = OMAP24XX_PRCM_CLKOUT_CTRL;
714 if (div_off == OMAP24XX_CLKOUT_DIV_SHIFT)
715 mask = OMAP24XX_CLKOUT_DIV_MASK;
716 else if (div_off == OMAP2420_CLKOUT2_DIV_SHIFT)
717 mask = OMAP2420_CLKOUT2_DIV_MASK;
720 div_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1);
722 case OMAP24XX_CLKSEL_L3_SHIFT:
723 mask = OMAP24XX_CLKSEL_L3_MASK;
725 case OMAP24XX_CLKSEL_L4_SHIFT:
726 mask = OMAP24XX_CLKSEL_L4_MASK;
728 case OMAP24XX_CLKSEL_DSS1_SHIFT:
729 mask = OMAP24XX_CLKSEL_DSS1_MASK;
731 case OMAP24XX_CLKSEL_DSS2_SHIFT:
732 mask = OMAP24XX_CLKSEL_DSS2_MASK;
734 case OMAP2420_CLKSEL_VLYNQ_SHIFT:
735 mask = OMAP2420_CLKSEL_VLYNQ_MASK;
737 case OMAP24XX_CLKSEL_SSI_SHIFT:
738 mask = OMAP24XX_CLKSEL_SSI_MASK;
740 case OMAP24XX_CLKSEL_USB_SHIFT:
741 mask = OMAP24XX_CLKSEL_USB_MASK;
746 if (unlikely((mask == ~0) || (div_addr == 0)))
756 * Return divider to be applied to parent clock.
759 static u32 omap2_clksel_get_divisor(struct clk *clk)
761 u32 div, field_mask, field_val;
762 void __iomem *div_addr;
764 div_addr = omap2_get_clksel(&field_mask, clk);
768 field_val = cm_read_reg(div_addr) & field_mask;
769 field_val >>= clk->rate_offset;
771 div = omap2_clksel_to_divisor(clk->flags, field_val);
776 /* Set the clock rate for a clock source */
777 static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
780 u32 div_off, field_mask, field_val, reg_val, validrate;
782 void __iomem *div_addr;
784 if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
786 return omap2_reprogram_dpll(clk, rate);
788 /* Isolate control register */
789 div_off = clk->rate_offset;
791 validrate = omap2_clksel_round_rate(clk, rate, &new_div);
792 if (validrate != rate)
795 div_addr = omap2_get_clksel(&field_mask, clk);
799 field_val = omap2_divisor_to_clksel(clk->flags, new_div);
803 reg_val = cm_read_reg(div_addr);
804 reg_val &= ~field_mask;
805 reg_val |= (field_val << div_off);
806 cm_write_reg(reg_val, div_addr);
808 clk->rate = clk->parent->rate / new_div;
810 if (clk->flags & DELAYED_APP) {
811 prm_write_reg(OMAP24XX_VALID_CONFIG,
812 OMAP24XX_PRCM_CLKCFG_CTRL);
816 } else if (clk->set_rate != 0) {
817 ret = clk->set_rate(clk, rate);
820 if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
826 /* Converts encoded control register address into a full address */
827 static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
828 struct clk *src_clk, u32 *field_mask,
829 struct clk *clk, u32 *parent_div)
831 u32 val = ~0, mask = 0;
832 void __iomem *src_reg_addr = 0;
836 reg_offset = clk->src_offset;
838 /* Find target control register.*/
839 switch (clk->flags & SRC_RATE_SEL_MASK) {
841 src_reg_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1);
842 if (reg_offset == OMAP24XX_CLKSEL_DSS2_SHIFT) {
843 mask = OMAP24XX_CLKSEL_DSS2_MASK;
844 if (src_clk == &sys_ck)
845 val = CLKSEL_DSS2_SYSCLK;
846 else if (src_clk == &func_48m_ck)
847 val = CLKSEL_DSS2_48MHZ;
849 WARN_ON(1); /* unknown src_clk */
850 } else if (reg_offset == OMAP24XX_CLKSEL_DSS1_SHIFT) {
851 mask = OMAP24XX_CLKSEL_DSS1_MASK;
852 if (src_clk == &sys_ck) {
853 val = CLKSEL_DSS1_SYSCLK;
854 } else if (src_clk == &core_ck) {
855 val = CLKSEL_DSS1_CORECLK_16;
858 WARN_ON(1); /* unknown src clk */
860 } else if ((reg_offset == OMAP2420_CLKSEL_VLYNQ_SHIFT) &&
862 mask = OMAP2420_CLKSEL_VLYNQ_MASK;
863 if (src_clk == &func_96m_ck) {
864 val = CLKSEL_VLYNQ_96MHZ;
865 } else if (src_clk == &core_ck) {
866 val = CLKSEL_VLYNQ_CORECLK_16;
869 WARN_ON(1); /* unknown src_clk */
872 WARN_ON(1); /* unknown reg_offset */
876 WARN_ON(reg_offset < OMAP24XX_CLKSEL_GPT2_SHIFT ||
877 reg_offset > OMAP24XX_CLKSEL_GPT12_SHIFT);
878 src_reg_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2);
879 mask = OMAP24XX_CLKSEL_GPT2_MASK;
880 mask <<= (reg_offset - OMAP24XX_CLKSEL_GPT2_SHIFT);
881 if (src_clk == &func_32k_ck)
882 val = CLKSEL_GPT_32K;
883 else if (src_clk == &sys_ck)
884 val = CLKSEL_GPT_SYSCLK;
885 else if (src_clk == &alt_ck)
886 val = CLKSEL_GPT_EXTALTCLK;
888 WARN_ON(1); /* unknown src_clk */
891 WARN_ON(reg_offset != 0); /* unknown reg_offset */
892 src_reg_addr = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL);
893 mask = OMAP24XX_CLKSEL_GPT1_MASK;
894 if (src_clk == &func_32k_ck)
895 val = CLKSEL_GPT_32K;
896 else if (src_clk == &sys_ck)
897 val = CLKSEL_GPT_SYSCLK;
898 else if (src_clk == &alt_ck)
899 val = CLKSEL_GPT_EXTALTCLK;
901 WARN_ON(1); /* unknown src_clk */
904 src_reg_addr = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1);
905 if (reg_offset == 0x3) {
906 mask = OMAP24XX_48M_SOURCE;
907 if (src_clk == &apll96_ck)
908 val = CLK_48M_SOURCE_APLL;
909 else if (src_clk == &alt_ck)
910 val = CLK_48M_SOURCE_EXTALTCLK;
912 WARN_ON(1); /* unknown src_clk */
914 else if (reg_offset == 0x5) {
915 mask = OMAP24XX_54M_SOURCE;
916 if (src_clk == &apll54_ck)
917 val = CLK_54M_SOURCE_APLL;
918 else if (src_clk == &alt_ck)
919 val = CLK_54M_SOURCE_EXTALTCLK;
921 WARN_ON(1); /* unknown src_clk */
923 WARN_ON(1); /* unknown reg_offset */
927 WARN_ON(reg_offset != 0);
928 src_reg_addr = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2);
929 mask = OMAP24XX_CORE_CLK_SRC_MASK;
930 if (src_clk == &func_32k_ck)
931 val = CORE_CLK_SRC_32K;
932 else if (src_clk == &dpll_ck)
933 val = CORE_CLK_SRC_DPLL_X2;
935 WARN_ON(1); /* unknown src_clk */
937 case CM_SYSCLKOUT_SEL1:
938 src_reg_addr = OMAP24XX_PRCM_CLKOUT_CTRL;
940 if (reg_offset == OMAP24XX_CLKOUT_SOURCE_SHIFT) {
941 mask = OMAP24XX_CLKOUT_SOURCE_MASK;
942 } else if (reg_offset == OMAP2420_CLKOUT2_SOURCE_SHIFT) {
943 mask = OMAP2420_CLKOUT2_SOURCE_MASK;
945 WARN_ON(1); /* unknown reg_offset */
948 if (src_clk == &dpll_ck)
950 else if (src_clk == &sys_ck)
952 else if (src_clk == &func_96m_ck)
954 else if (src_clk == &func_54m_ck)
957 WARN_ON(1); /* unknown src_clk */
961 if (val == ~0) /* Catch errors in offset */
964 *src_addr = src_reg_addr;
973 static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
975 void __iomem *src_addr;
976 u32 field_val, field_mask, reg_val, parent_div;
978 if (unlikely(clk->flags & CONFIG_PARTICIPANT))
981 if (unlikely(!(clk->flags & SRC_SEL_MASK)))
984 field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
985 &field_mask, clk, &parent_div);
989 if (clk->usecount > 0)
990 _omap2_clk_disable(clk);
992 /* Set new source value (previous dividers if any in effect) */
993 reg_val = __raw_readl(src_addr) & ~field_mask;
994 reg_val |= (field_val << clk->src_offset);
995 __raw_writel(reg_val, src_addr);
998 if (clk->flags & DELAYED_APP) {
999 prm_write_reg(OMAP24XX_VALID_CONFIG,
1000 OMAP24XX_PRCM_CLKCFG_CTRL);
1004 if (clk->usecount > 0)
1005 _omap2_clk_enable(clk);
1007 clk->parent = new_parent;
1009 /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
1010 clk->rate = new_parent->rate;
1013 clk->rate /= parent_div;
1015 if (unlikely(clk->flags & RATE_PROPAGATES))
1016 propagate_rate(clk);
1021 /* Sets basic clocks based on the specified rate */
1022 static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
1024 u32 flags, cur_rate, done_rate, bypass = 0, tmp;
1025 struct prcm_config *prcm;
1026 unsigned long found_speed = 0;
1028 if (clk != &virt_prcm_set)
1031 for (prcm = rate_table; prcm->mpu_speed; prcm++) {
1032 if (!(prcm->flags & cpu_mask))
1035 if (prcm->xtal_speed != sys_ck.rate)
1038 if (prcm->mpu_speed <= rate) {
1039 found_speed = prcm->mpu_speed;
1045 printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
1050 curr_prcm_set = prcm;
1051 cur_rate = omap2_get_dpll_rate(&dpll_ck);
1053 if (prcm->dpll_speed == cur_rate / 2) {
1054 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
1055 } else if (prcm->dpll_speed == cur_rate * 2) {
1056 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
1057 } else if (prcm->dpll_speed != cur_rate) {
1058 local_irq_save(flags);
1060 if (prcm->dpll_speed == prcm->xtal_speed)
1063 if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
1064 CORE_CLK_SRC_DPLL_X2)
1065 done_rate = CORE_CLK_SRC_DPLL_X2;
1067 done_rate = CORE_CLK_SRC_DPLL;
1070 cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
1072 /* dsp + iva1 div(2420), iva2.1(2430) */
1073 cm_write_mod_reg(prcm->cm_clksel_dsp,
1074 OMAP24XX_DSP_MOD, CM_CLKSEL);
1076 cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
1078 /* Major subsystem dividers */
1079 tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
1080 cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1);
1081 if (cpu_is_omap2430())
1082 cm_write_mod_reg(prcm->cm_clksel_mdm,
1083 OMAP2430_MDM_MOD, CM_CLKSEL);
1085 /* x2 to enter init_mem */
1086 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
1088 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
1091 omap2_init_memory_params(omap2_dll_force_needed());
1092 omap2_reprogram_sdrc(done_rate, 0);
1094 local_irq_restore(flags);
1096 omap2_dpll_recalc(&dpll_ck);
1101 /*-------------------------------------------------------------------------
1102 * Omap2 clock reset and init functions
1103 *-------------------------------------------------------------------------*/
1105 #ifdef CONFIG_OMAP_RESET_CLOCKS
1106 static void __init omap2_clk_disable_unused(struct clk *clk)
1110 regval32 = cm_read_reg(clk->enable_reg);
1111 if ((regval32 & (1 << clk->enable_bit)) == 0)
1114 printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
1115 _omap2_clk_disable(clk);
1118 #define omap2_clk_disable_unused NULL
1121 static struct clk_functions omap2_clk_functions = {
1122 .clk_enable = omap2_clk_enable,
1123 .clk_disable = omap2_clk_disable,
1124 .clk_round_rate = omap2_clk_round_rate,
1125 .clk_set_rate = omap2_clk_set_rate,
1126 .clk_set_parent = omap2_clk_set_parent,
1127 .clk_disable_unused = omap2_clk_disable_unused,
1130 static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
1132 u32 div, aplls, sclk = 13000000;
1134 aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
1135 aplls &= OMAP24XX_APLLS_CLKIN_MASK;
1136 aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
1138 if (aplls == APLLS_CLKIN_19_2MHZ)
1140 else if (aplls == APLLS_CLKIN_13MHZ)
1142 else if (aplls == APLLS_CLKIN_12MHZ)
1145 div = prm_read_reg(OMAP24XX_PRCM_CLKSRC_CTRL);
1146 div &= OMAP_SYSCLKDIV_MASK;
1147 div >>= sys->rate_offset;
1149 osc->rate = sclk * div;
1154 * Set clocks for bypass mode for reboot to work.
1156 void omap2_clk_prepare_for_reboot(void)
1160 if (vclk == NULL || sclk == NULL)
1163 rate = clk_get_rate(sclk);
1164 clk_set_rate(vclk, rate);
1168 * Switch the MPU rate if specified on cmdline.
1169 * We cannot do this early until cmdline is parsed.
1171 static int __init omap2_clk_arch_init(void)
1176 if (omap2_select_table_rate(&virt_prcm_set, mpurate))
1177 printk(KERN_ERR "Could not find matching MPU rate\n");
1179 recalculate_root_clocks();
1181 printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
1182 "%ld.%01ld/%ld/%ld MHz\n",
1183 (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1184 (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1188 arch_initcall(omap2_clk_arch_init);
1190 int __init omap2_clk_init(void)
1192 struct prcm_config *prcm;
1196 clk_init(&omap2_clk_functions);
1197 omap2_get_crystal_rate(&osc_ck, &sys_ck);
1199 for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
1202 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
1203 clk_register(*clkp);
1207 if ((*clkp)->flags & CLOCK_IN_OMAP243X && (cpu_is_omap2430() || cpu_is_omap34xx())) {
1208 clk_register(*clkp);
1213 if (cpu_is_omap242x())
1214 cpu_mask = RATE_IN_242X;
1215 else if (cpu_is_omap2430())
1216 cpu_mask = RATE_IN_243X;
1218 /* Check the MPU rate set by bootloader */
1219 clkrate = omap2_get_dpll_rate(&dpll_ck);
1220 for (prcm = rate_table; prcm->mpu_speed; prcm++) {
1221 if (!(prcm->flags & cpu_mask))
1223 if (prcm->xtal_speed != sys_ck.rate)
1225 if (prcm->dpll_speed <= clkrate)
1228 curr_prcm_set = prcm;
1230 recalculate_root_clocks();
1232 printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
1233 "%ld.%01ld/%ld/%ld MHz\n",
1234 (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
1235 (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
1238 * Only enable those clocks we will need, let the drivers
1239 * enable other clocks as necessary
1241 clk_enable(&sync_32k_ick);
1242 clk_enable(&omapctrl_ick);
1244 /* Force the APLLs always active. The clocks are idled
1245 * automatically by hardware. */
1246 clk_enable(&apll96_ck);
1247 clk_enable(&apll54_ck);
1249 if (cpu_is_omap2430())
1250 clk_enable(&sdrc_ick);
1252 /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
1253 vclk = clk_get(NULL, "virt_prcm_set");
1254 sclk = clk_get(NULL, "sys_ck");