OMAP2xxx: clock: add clockfw autoidle support for APLLs
authorPaul Walmsley <paul@pwsan.com>
Fri, 25 Feb 2011 22:39:27 +0000 (15:39 -0700)
committerPaul Walmsley <paul@pwsan.com>
Tue, 8 Mar 2011 03:02:13 +0000 (20:02 -0700)
OMAP2xxx devices have two on-chip APLLs.  These APLLs can
automatically enter idle when not in use.  Connect the APLL autoidle
code to the clock code, so that the clock framework can handle this
process.  As part of this patch, remove the code in mach-omap2/pm24xx.c
that previously handled APLL autoidle control.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
Tested-by: Rajendra Nayak <rnayak@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
arch/arm/mach-omap2/clkt2xxx_apll.c
arch/arm/mach-omap2/cm2xxx_3xxx.c
arch/arm/mach-omap2/cm2xxx_3xxx.h
arch/arm/mach-omap2/pm24xx.c

index f51cffd1fc53518479baf02ead3e2c9d8cfa32be..b19a1f7234ae9446786e3d370ceeeec7889428e9 100644 (file)
@@ -78,6 +78,26 @@ static int omap2_clk_apll54_enable(struct clk *clk)
        return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL_MASK);
 }
 
+static void _apll96_allow_idle(struct clk *clk)
+{
+       omap2xxx_cm_set_apll96_auto_low_power_stop();
+}
+
+static void _apll96_deny_idle(struct clk *clk)
+{
+       omap2xxx_cm_set_apll96_disable_autoidle();
+}
+
+static void _apll54_allow_idle(struct clk *clk)
+{
+       omap2xxx_cm_set_apll54_auto_low_power_stop();
+}
+
+static void _apll54_deny_idle(struct clk *clk)
+{
+       omap2xxx_cm_set_apll54_disable_autoidle();
+}
+
 /* Stop APLL */
 static void omap2_clk_apll_disable(struct clk *clk)
 {
@@ -93,11 +113,15 @@ static void omap2_clk_apll_disable(struct clk *clk)
 const struct clkops clkops_apll96 = {
        .enable         = omap2_clk_apll96_enable,
        .disable        = omap2_clk_apll_disable,
+       .allow_idle     = _apll96_allow_idle,
+       .deny_idle      = _apll96_deny_idle,
 };
 
 const struct clkops clkops_apll54 = {
        .enable         = omap2_clk_apll54_enable,
        .disable        = omap2_clk_apll_disable,
+       .allow_idle     = _apll54_allow_idle,
+       .deny_idle      = _apll54_deny_idle,
 };
 
 /* Public functions */
index 6b0c7c85ef530269d50e9f4578ca7cbf3b0ea2de..9d0dec806e9294e721294149550a8746960e4d4f 100644 (file)
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
-/* CM_AUTOIDLE_PLL.AUTO_* bit values */
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
 #define DPLL_AUTOIDLE_DISABLE                          0x0
 #define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP          0x3
 
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
+#define OMAP2XXX_APLL_AUTOIDLE_DISABLE                 0x0
+#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP          0x3
+
 static const u8 cm_idlest_offs[] = {
        CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
 };
@@ -153,6 +157,44 @@ void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
        _omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
 }
 
+/*
+ * APLL autoidle control
+ */
+
+static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
+{
+       u32 v;
+
+       v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+       v &= ~mask;
+       v |= m << __ffs(mask);
+       omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_apll54_disable_autoidle(void)
+{
+       _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+                                   OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
+{
+       _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+                                   OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_disable_autoidle(void)
+{
+       _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+                                   OMAP24XX_AUTO_96M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
+{
+       _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+                                   OMAP24XX_AUTO_96M_MASK);
+}
+
 /*
  *
  */
index 5f4df1ceafad7280dc3d7ff54d9ca3e8fc0c0a7f..088bbad73db541fcbceed4850e78369736bfc853 100644 (file)
@@ -125,6 +125,11 @@ extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
 extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
 extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
 
+extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
+extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
+
 #endif
 
 /* CM register bits shared between 24XX and 3430 */
index 297bb21061b8890ccaf235b481091789f48dfc86..abe08f49b2ecf94fd4514d0d874e8f819f4a7324 100644 (file)
@@ -378,7 +378,6 @@ static void __init prcm_setup_regs(void)
 {
        int i, num_mem_banks;
        struct powerdomain *pwrdm;
-       u32 v;
 
        /* Enable autoidle */
        omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
@@ -469,13 +468,6 @@ static void __init prcm_setup_regs(void)
        omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD,
                               CM_AUTOIDLE);
 
-       /* Put both APLLs into autoidle mode */
-       v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
-       v &= ~(OMAP24XX_AUTO_96M_MASK | OMAP24XX_AUTO_54M_SHIFT);
-       v |= (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
-               (0x03 << OMAP24XX_AUTO_54M_SHIFT);
-       omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
-
        omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK |
                               OMAP24XX_AUTO_WDT1_MASK |
                               OMAP24XX_AUTO_MPU_WDT_MASK |