]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
OMAP2/3 clock: fix DPLL rate calculation
authorTero Kristo <tero.kristo@nokia.com>
Mon, 1 Dec 2008 07:43:58 +0000 (00:43 -0700)
committerTony Lindgren <tony@atomide.com>
Sat, 6 Dec 2008 00:19:37 +0000 (16:19 -0800)
Noncore dpll can enter autoidle state, in which case the rate calculation
fails.  Fixed by checking dpll mode instead of idle status.

Also, previously, the OMAP2xxx code returned the wrong value for the
DPLL rate under some conditions.  Move the CORE_CLK rate recalculation
to clock24xx.c:omap2xxx_clk_get_core_rate().

This patch is a collaboration between Tero Kristo <tero.kristo@nokia.com>
and Paul Walmsley <paul@pwsan.com>.  Thanks to Peter de Schrijver
<peter.de-schrijver@nokia.com> for help debugging and Kevin Hilman
<khilman@deeprootsystems.com> for reporting the OMAP2 build problems with
an earlier version of this patch.

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Peter de Schrijver <peter.de-schrijver@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock24xx.c
arch/arm/mach-omap2/clock24xx.h
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/sdrc2xxx.c
arch/arm/plat-omap/include/mach/clock.h

index 93a692fe05ba4a1ac5393e06f5f3bd1587374756..8a064b3d1d93211afa9f13e91029800c05c18543 100644 (file)
 #define DPLL_FINT_UNDERFLOW            -1
 #define DPLL_FINT_INVALID              -2
 
-/* Some OMAP2xxx CM_CLKSEL_PLL.ST_CORE_CLK bits - for omap2_get_dpll_rate() */
-#define ST_CORE_CLK_REF                        0x1
-#define ST_CORE_CLK_32K                        0x3
-
 /* Bitmask to isolate the register type of clk.enable_reg */
 #define PRCM_REGTYPE_MASK              0xf0
 /* various CM register type options */
@@ -267,19 +263,20 @@ u32 omap2_get_dpll_rate(struct clk *clk)
                return 0;
 
        /* Return bypass rate if DPLL is bypassed */
-       v = cm_read_mod_reg(clk->prcm_mod, dd->idlest_reg);
-       v &= dd->idlest_mask;
-       v >>= __ffs(dd->idlest_mask);
+       v = cm_read_mod_reg(clk->prcm_mod, dd->control_reg);
+       v &= dd->enable_mask;
+       v >>= __ffs(dd->enable_mask);
+
        if (cpu_is_omap24xx()) {
 
-               if (v == ST_CORE_CLK_REF)
-                       return clk->parent->rate; /* sys_clk */
-               else if (v == ST_CORE_CLK_32K)
-                       return 32768;
+               if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
+                   v == OMAP2XXX_EN_DPLL_FRBYPASS)
+                       return clk->parent->rate;
 
        } else if (cpu_is_omap34xx()) {
 
-               if (!v)
+               if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
+                   v == OMAP3XXX_EN_DPLL_FRBYPASS)
                        return dd->bypass_clk->rate;
 
        }
index a5183d0f971e9fa3512d3de4961bd2d122b7cd94..faff95e16e7a1415485e30bb24794839e7b2fe9c 100644 (file)
 /* The maximum error between a target DPLL rate and the rounded rate in Hz */
 #define DEFAULT_DPLL_RATE_TOLERANCE    50000
 
+/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
+#define CORE_CLK_SRC_32K               0x0
+#define CORE_CLK_SRC_DPLL              0x1
+#define CORE_CLK_SRC_DPLL_X2           0x2
+
+/* OMAP2xxx CM_CLKEN_PLL.EN_DPLL bits - for omap2_get_dpll_rate() */
+#define OMAP2XXX_EN_DPLL_LPBYPASS              0x1
+#define OMAP2XXX_EN_DPLL_FRBYPASS              0x2
+#define OMAP2XXX_EN_DPLL_LOCKED                        0x3
+
+/* OMAP3xxx CM_CLKEN_PLL*.EN_*_DPLL bits - for omap2_get_dpll_rate() */
+#define OMAP3XXX_EN_DPLL_LPBYPASS              0x5
+#define OMAP3XXX_EN_DPLL_FRBYPASS              0x6
+#define OMAP3XXX_EN_DPLL_LOCKED                        0x7
+
 int omap2_clk_init(void);
 int omap2_clk_enable(struct clk *clk);
 void omap2_clk_disable(struct clk *clk);
index d9a3cb3a1595529ceaf481912eff7bb53ddf2b56..ff14d12426526a9920c41a320f200d562f46999a 100644 (file)
@@ -60,19 +60,32 @@ 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")
+ *
+ * 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)
 {
-       long long dpll_clk;
-       u8 amult;
+       long long core_clk;
+       u32 v;
 
-       dpll_clk = omap2_get_dpll_rate(tclk);
+       core_clk = omap2_get_dpll_rate(clk);
 
-       amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
-       amult &= OMAP24XX_CORE_CLK_SRC_MASK;
-       dpll_clk *= amult;
+       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 dpll_clk;
+       return core_clk;
 }
 
 static int omap2_enable_osc_ck(struct clk *clk)
@@ -164,7 +177,7 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
 
 static void omap2_dpllcore_recalc(struct clk *clk)
 {
-       clk->rate = omap2_get_dpll_rate_24xx(clk);
+       clk->rate = omap2xxx_clk_get_core_rate(clk);
 
        propagate_rate(clk);
 }
@@ -179,7 +192,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);
        mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
        mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
@@ -319,7 +332,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);
 
        if (prcm->dpll_speed == cur_rate / 2) {
                omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
@@ -536,7 +549,7 @@ int __init omap2_clk_init(void)
        }
 
        /* Check the MPU rate set by bootloader */
-       clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
+       clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
        for (prcm = rate_table; prcm->mpu_speed; prcm++) {
                if (!(prcm->flags & cpu_mask))
                        continue;
index 724bcb02dcb186fcfdef687132dc7110b224bb88..929a257e92af6433a16f4cd28b57032c2c7be8ff 100644 (file)
@@ -673,8 +673,8 @@ static struct dpll_data dpll_dd = {
        .mult_div1_reg          = CM_CLKSEL1,
        .mult_mask              = OMAP24XX_DPLL_MULT_MASK,
        .div1_mask              = OMAP24XX_DPLL_DIV_MASK,
-       .idlest_reg             = CM_IDLEST,
-       .idlest_mask            = OMAP24XX_ST_CORE_CLK_MASK,
+       .control_reg            = CM_CLKEN,
+       .enable_mask            = OMAP24XX_EN_DPLL_MASK,
        .max_multiplier         = 1024,
        .min_divider            = 1,
        .max_divider            = 16,
index e15b60d1f951fb2ac9f31086f0cf0e104106c2ee..2c655bef0b6feb668227d01389508dc8225e548a 100644 (file)
@@ -604,10 +604,11 @@ 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)
+       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)
                clk->rate = clk->parent->rate;
        else
                clk->rate = clk->parent->rate * 2;
index 0723e59b587f95eddb4aebeceb7925504ae4e18e..479dc8c8837332e7f55d9926457e104465668962 100644 (file)
@@ -28,6 +28,8 @@
 #include <mach/clock.h>
 #include <mach/sram.h>
 
+#include "clock.h"
+
 #include "prm.h"
 
 #include <mach/sdrc.h>
index 4eef580df527d60fce8a3331da9c5d5cd35abd3b..e79361660231bda6460ccefc3bc3174316bf5f23 100644 (file)
@@ -42,14 +42,14 @@ struct dpll_data {
        u8                      min_divider;
        u8                      max_divider;
        u32                     max_tolerance;
-       u16                     idlest_reg;
-       u32                     idlest_mask;
        struct clk              *bypass_clk;
+       u16                     control_reg;
+       u32                     enable_mask;
 #  if defined(CONFIG_ARCH_OMAP3)
+       u16                     idlest_reg;
+       u32                     idlest_mask;
        u32                     freqsel_mask;
        u8                      modes;
-       u16                     control_reg;
-       u32                     enable_mask;
        u8                      auto_recal_bit;
        u8                      recal_en_bit;
        u8                      recal_st_bit;
@@ -175,9 +175,4 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
 #define CLK_REG_IN_PRM         (1 << 0)
 #define CLK_REG_IN_SCM         (1 << 1)
 
-/* CM_CLKSEL2_PLL.CORE_CLK_SRC options (24XX) */
-#define CORE_CLK_SRC_32K               0
-#define CORE_CLK_SRC_DPLL              1
-#define CORE_CLK_SRC_DPLL_X2           2
-
 #endif