@@ -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
@@ -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);
}