]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/mach-omap2/clock34xx.c
OMAP2/3 clock: don't tinker with hardirqs when they are supposed to be disabled
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / clock34xx.c
index cc43f4f2a547e7e6d965df4cb1d37d821f8c5991..f7ac5c1c7c09d2474c187e03fae6bc1660ea8d37 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/limits.h>
+#include <linux/bitops.h>
 
 #include <mach/clock.h>
 #include <mach/sram.h>
 #include <asm/div64.h>
-#include <asm/bitops.h>
 
 #include <mach/sdrc.h>
 #include "clock.h"
 /**
  * omap3_dpll_recalc - recalculate DPLL rate
  * @clk: DPLL struct clk
+ * @parent_rate: rate of the DPLL's parent clock
+ * @rate_storage: flag indicating whether current or temporary rate is changing
  *
  * Recalculate and propagate the DPLL rate.
  */
-static void omap3_dpll_recalc(struct clk *clk)
+static void omap3_dpll_recalc(struct clk *clk, unsigned long parent_rate,
+                             u8 rate_storage)
 {
-       clk->rate = omap2_get_dpll_rate(clk);
+       unsigned long rate;
 
-       propagate_rate(clk);
+       rate = omap2_get_dpll_rate(clk, parent_rate);
+
+       if (rate_storage == CURRENT_RATE)
+               clk->rate = rate;
+       else if (rate_storage == TEMP_RATE)
+               clk->temp_rate = rate;
 }
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -163,19 +171,14 @@ static int _omap3_noncore_dpll_lock(struct clk *clk)
 
        ai = omap3_dpll_autoidle_read(clk);
 
+       omap3_dpll_deny_idle(clk);
+
        _omap3_dpll_write_clken(clk, DPLL_LOCKED);
 
-       if (ai) {
-               /*
-                * If no downstream clocks are enabled, CM_IDLEST bit
-                * may never become active, so don't wait for DPLL to lock.
-                */
-               r = 0;
+       r = _omap3_wait_dpll_status(clk, 1);
+
+       if (ai)
                omap3_dpll_allow_idle(clk);
-       } else {
-               r = _omap3_wait_dpll_status(clk, 1);
-               omap3_dpll_deny_idle(clk);
-       };
 
        return r;
 }
@@ -285,9 +288,6 @@ static int omap3_noncore_dpll_enable(struct clk *clk)
        else
                r = _omap3_noncore_dpll_lock(clk);
 
-       if (!r)
-               clk->rate = omap2_get_dpll_rate(clk);
-
        return r;
 }
 
@@ -343,7 +343,7 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
         * on 3430ES1 prevents us from changing DPLL multipliers or dividers
         * on DPLL4.
         */
-       if (system_rev == OMAP3430_REV_ES1_0 &&
+       if (omap_rev() == OMAP3430_REV_ES1_0 &&
            !strcmp("dpll4_ck", clk->name)) {
                printk(KERN_ERR "clock: DPLL4 cannot change rate due to "
                       "silicon 'Limitation 2.5' on 3430ES1.\n");
@@ -399,7 +399,7 @@ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
        if (!dd)
                return -EINVAL;
 
-       if (rate == omap2_get_dpll_rate(clk))
+       if (rate == omap2_get_dpll_rate(clk, clk->parent->rate))
                return 0;
 
        if (dd->bypass_clk->rate == rate &&
@@ -434,8 +434,6 @@ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 
        }
 
-       omap3_dpll_recalc(clk);
-
        return 0;
 }
 
@@ -493,12 +491,8 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        WARN_ON(new_div != 1 && new_div != 2);
 
        /* REVISIT: Add SDRC_MR changing to this code also */
-       local_irq_disable();
        omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
                                  sp->actim_ctrlb, new_div);
-       local_irq_enable();
-
-       omap2_clksel_recalc(clk);
 
        return 0;
 }
@@ -589,14 +583,18 @@ static void omap3_dpll_deny_idle(struct clk *clk)
 /**
  * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
  * @clk: DPLL output struct clk
+ * @parent_rate: rate of the parent clock of @clk
+ * @rate_storage: flag indicating whether current or temporary rate is changing
  *
  * Using parent clock DPLL data, look up DPLL state.  If locked, set our
  * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
  */
-static void omap3_clkoutx2_recalc(struct clk *clk)
+static void omap3_clkoutx2_recalc(struct clk *clk, unsigned long parent_rate,
+                                 u8 rate_storage)
 {
        const struct dpll_data *dd;
        u32 v;
+       unsigned long rate;
        struct clk *pclk;
 
        /* Walk up the parents of clk, looking for a DPLL */
@@ -609,16 +607,19 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
 
        dd = pclk->dpll_data;
 
-       WARN_ON(!dd->idlest_reg || !dd->idlest_mask);
+       WARN_ON(!dd->enable_mask);
 
-       v = cm_read_mod_reg(pclk->prcm_mod, dd->idlest_reg) & dd->idlest_mask;
-       if (!v)
-               clk->rate = clk->parent->rate;
-       else
-               clk->rate = clk->parent->rate * 2;
+       rate = parent_rate;
+
+       v = cm_read_mod_reg(pclk->prcm_mod, dd->control_reg) & dd->enable_mask;
+       v >>= __ffs(dd->enable_mask);
+       if (v == OMAP3XXX_EN_DPLL_LOCKED)
+               rate *= 2;
 
-       if (clk->flags & RATE_PROPAGATES)
-               propagate_rate(clk);
+       if (rate_storage == CURRENT_RATE)
+               clk->rate = rate;
+       else if (rate_storage == TEMP_RATE)
+               clk->temp_rate = rate;
 }
 
 /* Common clock code */
@@ -630,11 +631,13 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
 #if defined(CONFIG_ARCH_OMAP3)
 
 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,
        .clk_set_rate           = omap2_clk_set_rate,
        .clk_set_parent         = omap2_clk_set_parent,
+       .clk_get_parent         = omap2_clk_get_parent,
        .clk_disable_unused     = omap2_clk_disable_unused,
 };
 
@@ -668,7 +671,7 @@ static int __init omap2_clk_arch_init(void)
 
        /* REVISIT: not yet ready for 343x */
 #if 0
-       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");
 #endif
 
@@ -711,7 +714,7 @@ int __init omap2_clk_init(void)
                 * Update this if there are further clock changes between ES2
                 * and production parts
                 */
-               if (system_rev == OMAP3430_REV_ES1_0) {
+               if (omap_rev() == OMAP3430_REV_ES1_0) {
                        /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */
                        cpu_clkflg |= CLOCK_IN_OMAP3430ES1;
                } else {
@@ -725,10 +728,8 @@ int __init omap2_clk_init(void)
        for (clkp = onchip_34xx_clks;
             clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
             clkp++) {
-               if ((*clkp)->flags & cpu_clkflg) {
+               if ((*clkp)->flags & cpu_clkflg)
                        clk_register(*clkp);
-                       omap2_init_clk_clkdm(*clkp);
-               }
        }
 
        /* REVISIT: Not yet ready for OMAP3 */