]> err.no Git - linux-2.6/commitdiff
ARM: OMAP2: Clock: Add OMAP3 DPLL autoidle functions
authorPaul Walmsley <paul@pwsan.com>
Thu, 3 Jul 2008 09:24:45 +0000 (12:24 +0300)
committerTony Lindgren <tony@atomide.com>
Thu, 3 Jul 2008 09:24:45 +0000 (12:24 +0300)
This patch adds support for DPLL autoidle control to the OMAP3 clock
framework.  These functions will be used by the noncore DPLL enable
and disable code - this is because, according to the CDP code, the
DPLL autoidle status must be saved and restored across DPLL
lock/bypass/off transitions.

N.B.: the CORE DPLL (DPLL3) has three autoidle mode options, rather
than just two.  This code currently does not support the third option,
low-power bypass autoidle.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock34xx.h
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm.h
include/asm-arm/arch-omap/clock.h

index b42bdd6079a554eeb62156efe4eb26427c7fe74d..4263099b1ad3defa11c4f077a5e9d33f9c2c5655 100644 (file)
@@ -1,10 +1,11 @@
 /*
  * OMAP3-specific clock framework functions
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Copyright (C) 2007 Nokia Corporation
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
  *
  * Written by Paul Walmsley
+ * Testing and integration fixes by Jouni Högander
  *
  * Parts of this code are based on code written by
  * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
@@ -23,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/limits.h>
 
 #include <asm/arch/clock.h>
 #include <asm/arch/sram.h>
 #include "cm.h"
 #include "cm-regbits-34xx.h"
 
-/* CM_CLKEN_PLL*.EN* bit values */
-#define DPLL_LOCKED            0x7
+/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
+#define DPLL_AUTOIDLE_DISABLE                  0x0
+#define DPLL_AUTOIDLE_LOW_POWER_STOP           0x1
+
+#define MAX_DPLL_WAIT_TRIES            1000000
 
 /**
  * omap3_dpll_recalc - recalculate DPLL rate
@@ -53,6 +58,290 @@ static void omap3_dpll_recalc(struct clk *clk)
        propagate_rate(clk);
 }
 
+/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
+static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
+{
+       const struct dpll_data *dd;
+
+       dd = clk->dpll_data;
+
+       cm_rmw_reg_bits(dd->enable_mask, clken_bits << __ffs(dd->enable_mask),
+                       dd->control_reg);
+}
+
+/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
+static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
+{
+       const struct dpll_data *dd;
+       int i = 0;
+       int ret = -EINVAL;
+       u32 idlest_mask;
+
+       dd = clk->dpll_data;
+
+       state <<= dd->idlest_bit;
+       idlest_mask = 1 << dd->idlest_bit;
+
+       while (((cm_read_reg(dd->idlest_reg) & idlest_mask) != state) &&
+              i < MAX_DPLL_WAIT_TRIES) {
+               i++;
+               udelay(1);
+       }
+
+       if (i == MAX_DPLL_WAIT_TRIES) {
+               printk(KERN_ERR "clock: %s failed transition to '%s'\n",
+                      clk->name, (state) ? "locked" : "bypassed");
+       } else {
+               pr_debug("clock: %s transition to '%s' in %d loops\n",
+                        clk->name, (state) ? "locked" : "bypassed", i);
+
+               ret = 0;
+       }
+
+       return ret;
+}
+
+/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
+
+/*
+ * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to lock.  Waits for the DPLL to report
+ * readiness before returning.  Will save and restore the DPLL's
+ * autoidle state across the enable, per the CDP code.  If the DPLL
+ * locked successfully, return 0; if the DPLL did not lock in the time
+ * allotted, or DPLL3 was passed in, return -EINVAL.
+ */
+static int _omap3_noncore_dpll_lock(struct clk *clk)
+{
+       u8 ai;
+       int r;
+
+       if (clk == &dpll3_ck)
+               return -EINVAL;
+
+       pr_debug("clock: locking DPLL %s\n", clk->name);
+
+       ai = omap3_dpll_autoidle_read(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;
+               omap3_dpll_allow_idle(clk);
+       } else {
+               r = _omap3_wait_dpll_status(clk, 1);
+               omap3_dpll_deny_idle(clk);
+       };
+
+       return r;
+}
+
+/*
+ * omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enter low-power bypass mode.  In
+ * bypass mode, the DPLL's rate is set equal to its parent clock's
+ * rate.  Waits for the DPLL to report readiness before returning.
+ * Will save and restore the DPLL's autoidle state across the enable,
+ * per the CDP code.  If the DPLL entered bypass mode successfully,
+ * return 0; if the DPLL did not enter bypass in the time allotted, or
+ * DPLL3 was passed in, or the DPLL does not support low-power bypass,
+ * return -EINVAL.
+ */
+static int _omap3_noncore_dpll_bypass(struct clk *clk)
+{
+       int r;
+       u8 ai;
+
+       if (clk == &dpll3_ck)
+               return -EINVAL;
+
+       if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
+               return -EINVAL;
+
+       pr_debug("clock: configuring DPLL %s for low-power bypass\n",
+                clk->name);
+
+       ai = omap3_dpll_autoidle_read(clk);
+
+       _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
+
+       r = _omap3_wait_dpll_status(clk, 0);
+
+       if (ai)
+               omap3_dpll_allow_idle(clk);
+       else
+               omap3_dpll_deny_idle(clk);
+
+       return r;
+}
+
+/*
+ * _omap3_noncore_dpll_stop - instruct a DPLL to stop
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enter low-power stop. Will save and
+ * restore the DPLL's autoidle state across the stop, per the CDP
+ * code.  If DPLL3 was passed in, or the DPLL does not support
+ * low-power stop, return -EINVAL; otherwise, return 0.
+ */
+static int _omap3_noncore_dpll_stop(struct clk *clk)
+{
+       u8 ai;
+
+       if (clk == &dpll3_ck)
+               return -EINVAL;
+
+       if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
+               return -EINVAL;
+
+       pr_debug("clock: stopping DPLL %s\n", clk->name);
+
+       ai = omap3_dpll_autoidle_read(clk);
+
+       _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
+
+       if (ai)
+               omap3_dpll_allow_idle(clk);
+       else
+               omap3_dpll_deny_idle(clk);
+
+       return 0;
+}
+
+/**
+ * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
+ * The choice of modes depends on the DPLL's programmed rate: if it is
+ * the same as the DPLL's parent clock, it will enter bypass;
+ * otherwise, it will enter lock.  This code will wait for the DPLL to
+ * indicate readiness before returning, unless the DPLL takes too long
+ * to enter the target state.  Intended to be used as the struct clk's
+ * enable function.  If DPLL3 was passed in, or the DPLL does not
+ * support low-power stop, or if the DPLL took too long to enter
+ * bypass or lock, return -EINVAL; otherwise, return 0.
+ */
+static int omap3_noncore_dpll_enable(struct clk *clk)
+{
+       int r;
+
+       if (clk == &dpll3_ck)
+               return -EINVAL;
+
+       if (clk->parent->rate == clk_get_rate(clk))
+               r = _omap3_noncore_dpll_bypass(clk);
+       else
+               r = _omap3_noncore_dpll_lock(clk);
+
+       return r;
+}
+
+/**
+ * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
+ * @clk: pointer to a DPLL struct clk
+ *
+ * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
+ * The choice of modes depends on the DPLL's programmed rate: if it is
+ * the same as the DPLL's parent clock, it will enter bypass;
+ * otherwise, it will enter lock.  This code will wait for the DPLL to
+ * indicate readiness before returning, unless the DPLL takes too long
+ * to enter the target state.  Intended to be used as the struct clk's
+ * enable function.  If DPLL3 was passed in, or the DPLL does not
+ * support low-power stop, or if the DPLL took too long to enter
+ * bypass or lock, return -EINVAL; otherwise, return 0.
+ */
+static void omap3_noncore_dpll_disable(struct clk *clk)
+{
+       if (clk == &dpll3_ck)
+               return;
+
+       _omap3_noncore_dpll_stop(clk);
+}
+
+/**
+ * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
+ * @clk: struct clk * of the DPLL to read
+ *
+ * Return the DPLL's autoidle bits, shifted down to bit 0.  Returns
+ * -EINVAL if passed a null pointer or if the struct clk does not
+ * appear to refer to a DPLL.
+ */
+static u32 omap3_dpll_autoidle_read(struct clk *clk)
+{
+       const struct dpll_data *dd;
+       u32 v;
+
+       if (!clk || !clk->dpll_data)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+
+       v = cm_read_reg(dd->autoidle_reg);
+       v &= dd->autoidle_mask;
+       v >>= __ffs(dd->autoidle_mask);
+
+       return v;
+}
+
+/**
+ * omap3_dpll_allow_idle - enable DPLL autoidle bits
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Enable DPLL automatic idle control.  This automatic idle mode
+ * switching takes effect only when the DPLL is locked, at least on
+ * OMAP3430.  The DPLL will enter low-power stop when its downstream
+ * clocks are gated.  No return value.
+ */
+static void omap3_dpll_allow_idle(struct clk *clk)
+{
+       const struct dpll_data *dd;
+
+       if (!clk || !clk->dpll_data)
+               return;
+
+       dd = clk->dpll_data;
+
+       /*
+        * REVISIT: CORE DPLL can optionally enter low-power bypass
+        * by writing 0x5 instead of 0x1.  Add some mechanism to
+        * optionally enter this mode.
+        */
+       cm_rmw_reg_bits(dd->autoidle_mask,
+                       DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask),
+                       dd->autoidle_reg);
+}
+
+/**
+ * omap3_dpll_deny_idle - prevent DPLL from automatically idling
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Disable DPLL automatic idle control.  No return value.
+ */
+static void omap3_dpll_deny_idle(struct clk *clk)
+{
+       const struct dpll_data *dd;
+
+       if (!clk || !clk->dpll_data)
+               return;
+
+       dd = clk->dpll_data;
+
+       cm_rmw_reg_bits(dd->autoidle_mask,
+                       DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask),
+                       dd->autoidle_reg);
+}
+
+/* Clock control for DPLL outputs */
+
 /**
  * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
  * @clk: DPLL output struct clk
@@ -89,6 +378,8 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
                propagate_rate(clk);
 }
 
+/* Common clock code */
+
 /*
  * As it is structured now, this will prevent an OMAP2/3 multiboot
  * kernel from compiling.  This will need further attention.
index 73624dc04c97fb28f3c3aacf434b47fffa2d48e3..e349d48ee80732c92b22d721456320699cf73be0 100644 (file)
@@ -1,14 +1,19 @@
 /*
  * OMAP3 clock framework
  *
- * Virtual clocks are introduced as a convenient tools.
- * They are sources for other clocks and not supposed
- * to be requested from drivers directly.
- *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
  * Copyright (C) 2007-2008 Nokia Corporation
  *
  * Written by Paul Walmsley
+ * With many device clock fixes by Kevin Hilman and Jouni Högander
+ * DPLL bypass clock support added by Roman Tereshonkov
+ *
+ */
+
+/*
+ * Virtual clocks are introduced as convenient tools.
+ * They are sources for other clocks and not supposed
+ * to be requested from drivers directly.
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
 
 static void omap3_dpll_recalc(struct clk *clk);
 static void omap3_clkoutx2_recalc(struct clk *clk);
+static void omap3_dpll_allow_idle(struct clk *clk);
+static void omap3_dpll_deny_idle(struct clk *clk);
+static u32 omap3_dpll_autoidle_read(struct clk *clk);
+static int omap3_noncore_dpll_enable(struct clk *clk);
+static void omap3_noncore_dpll_disable(struct clk *clk);
 
 /*
  * DPLL1 supplies clock to the MPU.
@@ -33,6 +43,11 @@ static void omap3_clkoutx2_recalc(struct clk *clk);
  * DPLL5 supplies other peripheral clocks (USBHOST, USIM).
  */
 
+/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
+#define DPLL_LOW_POWER_STOP            0x1
+#define DPLL_LOW_POWER_BYPASS          0x5
+#define DPLL_LOCKED                    0x7
+
 /* PRM CLOCKS */
 
 /* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
@@ -246,9 +261,14 @@ static const struct dpll_data dpll1_dd = {
        .div1_mask      = OMAP3430_MPU_DPLL_DIV_MASK,
        .control_reg    = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
        .enable_mask    = OMAP3430_EN_MPU_DPLL_MASK,
+       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
        .recal_en_bit   = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
        .recal_st_bit   = OMAP3430_MPU_DPLL_ST_SHIFT,
+       .autoidle_reg   = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
+       .autoidle_mask  = OMAP3430_AUTO_MPU_DPLL_MASK,
+       .idlest_reg     = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
+       .idlest_bit     = OMAP3430_ST_MPU_CLK_SHIFT,
 };
 
 static struct clk dpll1_ck = {
@@ -303,16 +323,24 @@ static const struct dpll_data dpll2_dd = {
        .div1_mask      = OMAP3430_IVA2_DPLL_DIV_MASK,
        .control_reg    = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
        .enable_mask    = OMAP3430_EN_IVA2_DPLL_MASK,
+       .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
+                               (1 << DPLL_LOW_POWER_BYPASS),
        .auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
        .recal_en_bit   = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
        .recal_st_bit   = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
+       .autoidle_reg   = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
+       .autoidle_mask  = OMAP3430_AUTO_IVA2_DPLL_MASK,
+       .idlest_reg     = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
+       .idlest_bit     = OMAP3430_ST_IVA2_CLK_SHIFT
 };
 
 static struct clk dpll2_ck = {
        .name           = "dpll2_ck",
        .parent         = &sys_ck,
        .dpll_data      = &dpll2_dd,
-       .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
        .recalc         = &omap3_dpll_recalc,
 };
 
@@ -338,9 +366,11 @@ static struct clk dpll2_m2_ck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
-/* DPLL3 */
-/* Source clock for all interfaces and for some device fclks */
-/* Type: DPLL */
+/*
+ * DPLL3
+ * Source clock for all interfaces and for some device fclks
+ * REVISIT: Also supports fast relock bypass - not included below
+ */
 static const struct dpll_data dpll3_dd = {
        .mult_div1_reg  = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
        .mult_mask      = OMAP3430_CORE_DPLL_MULT_MASK,
@@ -350,6 +380,8 @@ static const struct dpll_data dpll3_dd = {
        .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
        .recal_en_bit   = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
        .recal_st_bit   = OMAP3430_CORE_DPLL_ST_SHIFT,
+       .autoidle_reg   = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+       .autoidle_mask  = OMAP3430_AUTO_CORE_DPLL_MASK,
 };
 
 static struct clk dpll3_ck = {
@@ -439,7 +471,7 @@ static struct clk core_ck = {
        .name           = "core_ck",
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_CORE_CLK,
+       .clksel_mask    = OMAP3430_ST_CORE_CLK_MASK,
        .clksel         = core_ck_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
@@ -456,7 +488,7 @@ static struct clk dpll3_m2x2_ck = {
        .name           = "dpll3_m2x2_ck",
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_CORE_CLK,
+       .clksel_mask    = OMAP3430_ST_CORE_CLK_MASK,
        .clksel         = dpll3_m2x2_ck_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
@@ -503,7 +535,7 @@ static struct clk emu_core_alwon_ck = {
        .parent         = &dpll3_m3x2_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_CORE_CLK,
+       .clksel_mask    = OMAP3430_ST_CORE_CLK_MASK,
        .clksel         = emu_core_alwon_ck_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
@@ -519,16 +551,23 @@ static const struct dpll_data dpll4_dd = {
        .div1_mask      = OMAP3430_PERIPH_DPLL_DIV_MASK,
        .control_reg    = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
        .enable_mask    = OMAP3430_EN_PERIPH_DPLL_MASK,
+       .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
        .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
        .recal_en_bit   = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
        .recal_st_bit   = OMAP3430_PERIPH_DPLL_ST_SHIFT,
+       .autoidle_reg   = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+       .autoidle_mask  = OMAP3430_AUTO_PERIPH_DPLL_MASK,
+       .idlest_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+       .idlest_bit     = OMAP3430_ST_PERIPH_CLK_SHIFT,
 };
 
 static struct clk dpll4_ck = {
        .name           = "dpll4_ck",
        .parent         = &sys_ck,
        .dpll_data      = &dpll4_dd,
-       .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
        .recalc         = &omap3_dpll_recalc,
 };
 
@@ -584,7 +623,7 @@ static struct clk omap_96m_alwon_fck = {
        .parent         = &dpll4_m2x2_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK,
+       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
        .clksel         = omap_96m_alwon_fck_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                 PARENT_CONTROLS_CLOCK,
@@ -610,7 +649,7 @@ static struct clk cm_96m_fck = {
        .parent         = &dpll4_m2x2_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK,
+       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
        .clksel         = cm_96m_fck_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
@@ -652,7 +691,7 @@ static struct clk virt_omap_54m_fck = {
        .parent         = &dpll4_m3x2_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK,
+       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
        .clksel         = virt_omap_54m_fck_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
@@ -810,17 +849,23 @@ static const struct dpll_data dpll5_dd = {
        .div1_mask      = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
        .control_reg    = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
        .enable_mask    = OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
+       .modes          = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
        .auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
        .recal_en_bit   = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
        .recal_st_bit   = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
+       .autoidle_reg   = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
+       .autoidle_mask  = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
+       .idlest_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
+       .idlest_bit     = OMAP3430ES2_ST_PERIPH2_CLK_SHIFT,
 };
 
 static struct clk dpll5_ck = {
        .name           = "dpll5_ck",
        .parent         = &sys_ck,
        .dpll_data      = &dpll5_dd,
-       .flags          = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
-                               ALWAYS_ENABLED,
+       .flags          = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES,
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
        .recalc         = &omap3_dpll_recalc,
 };
 
@@ -1939,7 +1984,7 @@ static struct clk dss1_alwon_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_DSS1_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK,
+       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
        .clksel         = dss1_alwon_fck_clksel,
        .flags          = CLOCK_IN_OMAP343X,
        .recalc         = &omap2_clksel_recalc,
@@ -1995,7 +2040,7 @@ static struct clk cam_mclk = {
        .parent         = &dpll4_m5x2_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK,
+       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
        .clksel         = cam_mclk_clksel,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_CAM_SHIFT,
index 3c38395f6442cff0e4b425303737aad9eb59d45e..ee4c0ca1a7087af06ad8bb45498accbeb67f2cea 100644 (file)
@@ -72,7 +72,8 @@
 #define OMAP3430_ST_IVA2                               (1 << 0)
 
 /* CM_IDLEST_PLL_IVA2 */
-#define OMAP3430_ST_IVA2_CLK                           (1 << 0)
+#define OMAP3430_ST_IVA2_CLK_SHIFT                     0
+#define OMAP3430_ST_IVA2_CLK_MASK                      (1 << 0)
 
 /* CM_AUTOIDLE_PLL_IVA2 */
 #define OMAP3430_AUTO_IVA2_DPLL_SHIFT                  0
 #define OMAP3430_ST_MPU                                        (1 << 0)
 
 /* CM_IDLEST_PLL_MPU */
-#define OMAP3430_ST_MPU_CLK                            (1 << 0)
-#define OMAP3430_ST_IVA2_CLK_MASK                      (1 << 0)
-
-/* CM_IDLEST_PLL_MPU */
+#define OMAP3430_ST_MPU_CLK_SHIFT                      0
 #define OMAP3430_ST_MPU_CLK_MASK                       (1 << 0)
 
 /* CM_AUTOIDLE_PLL_MPU */
 #define OMAP3430_ST_12M_CLK                            (1 << 4)
 #define OMAP3430_ST_48M_CLK                            (1 << 3)
 #define OMAP3430_ST_96M_CLK                            (1 << 2)
-#define OMAP3430_ST_PERIPH_CLK                         (1 << 1)
-#define OMAP3430_ST_CORE_CLK                           (1 << 0)
+#define OMAP3430_ST_PERIPH_CLK_SHIFT                   1
+#define OMAP3430_ST_PERIPH_CLK_MASK                    (1 << 1)
+#define OMAP3430_ST_CORE_CLK_SHIFT                     0
+#define OMAP3430_ST_CORE_CLK_MASK                      (1 << 0)
 
 /* CM_IDLEST2_CKGEN */
 #define OMAP3430ES2_ST_120M_CLK_SHIFT                  1
 #define OMAP3430_AUTO_CORE_DPLL_SHIFT                  0
 #define OMAP3430_AUTO_CORE_DPLL_MASK                   (0x7 << 0)
 
+/* CM_AUTOIDLE2_PLL */
+#define OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT            0
+#define OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK             (0x7 << 0)
+
 /* CM_CLKSEL1_PLL */
 /* Note that OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK was (0x3 << 27) on 3430ES1 */
 #define OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT            27
index 1dd873fcc2bd3ded4fab33f7527ad2bee359ba46..87a44c715aa4dd1b0604f4f81874c15df9de5d7b 100644 (file)
@@ -81,6 +81,7 @@
 #define OMAP3430ES2_CM_FCLKEN3                         0x0008
 #define OMAP3430_CM_IDLEST_PLL                         CM_IDLEST2
 #define OMAP3430_CM_AUTOIDLE_PLL                       CM_AUTOIDLE2
+#define OMAP3430ES2_CM_AUTOIDLE2_PLL                   CM_AUTOIDLE2
 #define OMAP3430_CM_CLKSEL1                            CM_CLKSEL
 #define OMAP3430_CM_CLKSEL1_PLL                                CM_CLKSEL
 #define OMAP3430_CM_CLKSEL2_PLL                                CM_CLKSEL2
index 8490fbba39d1506ae2915cecf5c43acca51f6a40..22daa5d64d35a5aac91f8604b843d32e150db7ac 100644 (file)
@@ -34,11 +34,16 @@ struct dpll_data {
        u32                     mult_mask;
        u32                     div1_mask;
 #  if defined(CONFIG_ARCH_OMAP3)
+       u8                      modes;
        void __iomem            *control_reg;
        u32                     enable_mask;
        u8                      auto_recal_bit;
        u8                      recal_en_bit;
        u8                      recal_st_bit;
+       void __iomem            *autoidle_reg;
+       u32                     autoidle_mask;
+       void __iomem            *idlest_reg;
+       u8                      idlest_bit;
 #  endif
 };