[PATCH 1/1] omap3: Save and restore CM_AUTOIDLE_PLL across off mode

Sanjeev Premi premi at ti.com
Thu Feb 10 11:02:04 EST 2011


As per commit "bb33cc58", ROM code is expected to restore
context related to CORE domain. As part of this change,
CM_AUTOIDLE_PLL is neither saved nor restored.

This results in loosing the value of AUTO_PERIPH_DPLL.

The concern of setting the AUTOIDLE flag before the DPLL
is locked seems valid. Hence, the restoration of this
register is delayed until after the context of PER
domain is restored.

The patch has been verified on OMAP3EVM by checking value
of CM_AUTOIDLE_PLL register across the suspend/resume
sequence (using devmem) with flags sleep_while_idle and
enable_off_mode set to 1.

Signed-off-by: Sanjeev Premi <premi at ti.com>
---
 arch/arm/mach-omap2/cm2xxx_3xxx.c |   13 +++++++++++++
 arch/arm/mach-omap2/pm34xx.c      |   25 ++++++++++++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
index 96954aa..a775d8a 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c
@@ -178,6 +178,7 @@ struct omap3_cm_regs {
 	u32 per_cm_clksel;
 	u32 emu_cm_clksel;
 	u32 emu_cm_clkstctrl;
+	u32 pll_cm_autoidle;
 	u32 pll_cm_autoidle2;
 	u32 pll_cm_clksel4;
 	u32 pll_cm_clksel5;
@@ -250,6 +251,8 @@ void omap3_cm_save_context(void)
 		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
 	cm_context.emu_cm_clkstctrl =
 		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.pll_cm_autoidle =
+		 omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
 	cm_context.pll_cm_autoidle2 =
 		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
 	cm_context.pll_cm_clksel4 =
@@ -468,4 +471,14 @@ void omap3_cm_restore_context(void)
 	omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
 			       OMAP3_CM_CLKOUT_CTRL_OFFSET);
 }
+
+
+/**
+ * Returns the value corresponding to CM_AUTOIDLE_PLL from the most recent
+ * context saved before entering the OFF mode.
+ */
+u32 stored_cm_autoidle_pll(void)
+{
+	return cm_context.pll_cm_autoidle;
+}
 #endif
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 8bb85fb..25bd230 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -91,6 +91,8 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
 static struct powerdomain *cam_pwrdm;
 
+extern u32 stored_cm_autoidle_pll(void);
+
 static inline void omap3_per_save_context(void)
 {
 	omap_gpio_save_context();
@@ -163,6 +165,25 @@ static void omap3_core_restore_context(void)
 	omap_dma_global_context_restore();
 }
 
+/**
+ * Restore the contents of CM_AUTOIDLE_PLL register.
+ *
+ * The implementation below restores AUTO_CORE_DPLL as 'good' redundancy.
+ */
+static void pll_mod_restore_autoidle(void)
+{
+	u32 ctx = stored_cm_autoidle_pll();
+	u32 val = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+
+	if (ctx & OMAP3430_AUTO_CORE_DPLL_MASK)
+		val |= ctx & OMAP3430_AUTO_CORE_DPLL_MASK;
+
+	if (ctx & OMAP3430_AUTO_PERIPH_DPLL_MASK)
+		val |= ctx & OMAP3430_AUTO_PERIPH_DPLL_MASK;
+
+	omap2_cm_write_mod_reg(val, PLL_MOD, CM_AUTOIDLE);
+}
+
 /*
  * FIXME: This function should be called before entering off-mode after
  * OMAP3 secure services have been accessed. Currently it is only called
@@ -488,8 +509,10 @@ void omap_sram_idle(void)
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
 		omap2_gpio_resume_after_idle();
-		if (per_prev_state == PWRDM_POWER_OFF)
+		if (per_prev_state == PWRDM_POWER_OFF) {
 			omap3_per_restore_context();
+			pll_mod_restore_autoidle();
+		}
 		omap_uart_resume_idle(2);
 		omap_uart_resume_idle(3);
 	}
-- 
1.7.2.2




More information about the linux-arm-kernel mailing list