]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/mach-omap2/clock24xx.c
OMAP clock: add OMAP chip family-specific clk_register() option
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / clock24xx.c
index d9a3cb3a1595529ceaf481912eff7bb53ddf2b56..9e311aa0cb5fab71f7977a69085d3c9283ff2d80 100644 (file)
@@ -60,19 +60,58 @@ static struct clk *sclk;
  * Omap24xx specific clock functions
  *-------------------------------------------------------------------------*/
 
-/* This actually returns the rate of core_ck, not dpll_ck. */
-static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
+/**
+ * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
+ * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
+ * @parent_rate: rate of the parent of the dpll_ck
+ *
+ * Returns the CORE_CLK rate.  CORE_CLK can have one of three rate
+ * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
+ * (the latter is unusual).  This currently should be called with
+ * struct clk *dpll_ck, which is a composite clock of dpll_ck and
+ * core_ck.
+ */
+static u32 omap2xxx_clk_get_core_rate(struct clk *clk,
+                                     unsigned long parent_rate)
+{
+       long long core_clk;
+       u32 v;
+
+       core_clk = omap2_get_dpll_rate(clk, parent_rate);
+
+       v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+       v &= OMAP24XX_CORE_CLK_SRC_MASK;
+
+       if (v == CORE_CLK_SRC_32K)
+               core_clk = 32768;
+       else
+               core_clk *= v;
+
+       return core_clk;
+}
+
+static unsigned long omap2xxx_clk_find_oppset_by_mpurate(unsigned long mpu_speed,
+                                                        struct prcm_config **prcm)
 {
-       long long dpll_clk;
-       u8 amult;
+       unsigned long found_speed = 0;
+       struct prcm_config *p;
+
+       p = *prcm;
+
+       for (p = rate_table; p->mpu_speed; p++) {
+               if (!(p->flags & cpu_mask))
+                       continue;
 
-       dpll_clk = omap2_get_dpll_rate(tclk);
+               if (p->xtal_speed != sys_ck.rate)
+                       continue;
 
-       amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
-       amult &= OMAP24XX_CORE_CLK_SRC_MASK;
-       dpll_clk *= amult;
+               if (p->mpu_speed <= mpu_speed) {
+                       found_speed = p->mpu_speed;
+                       break;
+               }
+       }
 
-       return dpll_clk;
+       return found_speed;
 }
 
 static int omap2_enable_osc_ck(struct clk *clk)
@@ -162,11 +201,17 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
 
 }
 
-static void omap2_dpllcore_recalc(struct clk *clk)
+static void omap2_dpllcore_recalc(struct clk *clk, unsigned long parent_rate,
+                                 u8 rate_storage)
 {
-       clk->rate = omap2_get_dpll_rate_24xx(clk);
+       unsigned long rate;
+
+       rate = omap2xxx_clk_get_core_rate(clk, parent_rate);
 
-       propagate_rate(clk);
+       if (rate_storage == CURRENT_RATE)
+               clk->rate = rate;
+       else if (rate_storage == TEMP_RATE)
+               clk->temp_rate = rate;
 }
 
 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
@@ -179,7 +224,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
        int ret = -EINVAL;
 
        local_irq_save(flags);
-       cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
+       cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
        mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
        mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
@@ -237,7 +282,6 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
                omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
                omap2xxx_sdrc_reprogram(done_rate, 0);
        }
-       omap2_dpllcore_recalc(&dpll_ck);
        ret = 0;
 
 dpll_exit:
@@ -251,9 +295,18 @@ dpll_exit:
  *
  * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
  */
-static void omap2_table_mpu_recalc(struct clk *clk)
+static void omap2_table_mpu_recalc(struct clk *clk, unsigned long parent_rate,
+                                  u8 rate_storage)
 {
-       clk->rate = curr_prcm_set->mpu_speed;
+       struct prcm_config *prcm;
+       unsigned long mpurate;
+
+       mpurate = omap2xxx_clk_find_oppset_by_mpurate(parent_rate, &prcm);
+
+       if (rate_storage == CURRENT_RATE)
+               clk->rate = mpurate;
+       else if (rate_storage == TEMP_RATE)
+               clk->temp_rate = mpurate;
 }
 
 /*
@@ -293,25 +346,12 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 {
        u32 cur_rate, done_rate, bypass = 0, tmp;
        struct prcm_config *prcm;
-       unsigned long found_speed = 0;
-       unsigned long flags;
+       unsigned long flags, found_speed;
 
        if (clk != &virt_prcm_set)
                return -EINVAL;
 
-       for (prcm = rate_table; prcm->mpu_speed; prcm++) {
-               if (!(prcm->flags & cpu_mask))
-                       continue;
-
-               if (prcm->xtal_speed != sys_ck.rate)
-                       continue;
-
-               if (prcm->mpu_speed <= rate) {
-                       found_speed = prcm->mpu_speed;
-                       break;
-               }
-       }
-
+       found_speed = omap2xxx_clk_find_oppset_by_mpurate(rate, &prcm);
        if (!found_speed) {
                printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
                       rate / 1000000);
@@ -319,7 +359,7 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
        }
 
        curr_prcm_set = prcm;
-       cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
+       cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
 
        if (prcm->dpll_speed == cur_rate / 2) {
                omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
@@ -366,7 +406,6 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 
                local_irq_restore(flags);
        }
-       omap2_dpllcore_recalc(&dpll_ck);
 
        return 0;
 }
@@ -411,6 +450,7 @@ void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
 #endif
 
 static struct clk_functions omap2_clk_functions = {
+       .clk_register           = omap2_clk_register,
        .clk_enable             = omap2_clk_enable,
        .clk_disable            = omap2_clk_disable,
        .clk_round_rate         = omap2_clk_round_rate,
@@ -453,16 +493,31 @@ static u32 omap2_get_sysclkdiv(void)
        return div;
 }
 
-static void omap2_osc_clk_recalc(struct clk *clk)
+static void omap2_osc_clk_recalc(struct clk *clk, unsigned long parent_rate,
+                                u8 rate_storage)
 {
-       clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
-       propagate_rate(clk);
+       unsigned long rate;
+
+       /* XXX osc_ck on 2xxx currently is parentless */
+       rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
+
+       if (rate_storage == CURRENT_RATE)
+               clk->rate = rate;
+       else if (rate_storage == TEMP_RATE)
+               clk->temp_rate = rate;
 }
 
-static void omap2_sys_clk_recalc(struct clk *clk)
+static void omap2_sys_clk_recalc(struct clk *clk, unsigned long parent_rate,
+                                u8 rate_storage)
 {
-       clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
-       propagate_rate(clk);
+       unsigned long rate;
+
+       rate = parent_rate / omap2_get_sysclkdiv();
+
+       if (rate_storage == CURRENT_RATE)
+               clk->rate = rate;
+       else if (rate_storage == TEMP_RATE)
+               clk->temp_rate = rate;
 }
 
 /*
@@ -488,7 +543,7 @@ static int __init omap2_clk_arch_init(void)
        if (!mpurate)
                return -EINVAL;
 
-       if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+       if (clk_set_rate(&virt_prcm_set, mpurate))
                printk(KERN_ERR "Could not find matching MPU rate\n");
 
        recalculate_root_clocks();
@@ -515,8 +570,8 @@ int __init omap2_clk_init(void)
 
        clk_init(&omap2_clk_functions);
 
-       omap2_osc_clk_recalc(&osc_ck);
-       omap2_sys_clk_recalc(&sys_ck);
+       omap2_osc_clk_recalc(&osc_ck, 0, CURRENT_RATE);
+       omap2_sys_clk_recalc(&sys_ck, sys_ck.parent->rate, CURRENT_RATE);
 
        for (clkp = onchip_24xx_clks;
             clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
@@ -524,19 +579,17 @@ int __init omap2_clk_init(void)
 
                if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
                        clk_register(*clkp);
-                       omap2_init_clk_clkdm(*clkp);
                        continue;
                }
 
                if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
                        clk_register(*clkp);
-                       omap2_init_clk_clkdm(*clkp);
                        continue;
                }
        }
 
        /* Check the MPU rate set by bootloader */
-       clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
+       clkrate = omap2xxx_clk_get_core_rate(&dpll_ck, dpll_ck.parent->rate);
        for (prcm = rate_table; prcm->mpu_speed; prcm++) {
                if (!(prcm->flags & cpu_mask))
                        continue;