|
@@ -183,3 +183,101 @@ static void omap2_enter_mpu_retention(void)
|
|
|
/* REVISIT: These write to reserved bits? */
|
|
|
omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
|
|
|
omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
|
|
|
+ omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
|
|
|
+
|
|
|
+ /* Try to enter MPU retention */
|
|
|
+ omap2_prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
|
|
|
+ OMAP_LOGICRETSTATE_MASK,
|
|
|
+ MPU_MOD, OMAP2_PM_PWSTCTRL);
|
|
|
+ } else {
|
|
|
+ /* Block MPU retention */
|
|
|
+
|
|
|
+ omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
|
|
|
+ OMAP2_PM_PWSTCTRL);
|
|
|
+ }
|
|
|
+
|
|
|
+ omap2_sram_idle();
|
|
|
+}
|
|
|
+
|
|
|
+static int omap2_can_sleep(void)
|
|
|
+{
|
|
|
+ if (omap2_fclks_active())
|
|
|
+ return 0;
|
|
|
+ if (__clk_is_enabled(osc_ck))
|
|
|
+ return 0;
|
|
|
+ if (omap_dma_running())
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static void omap2_pm_idle(void)
|
|
|
+{
|
|
|
+ local_fiq_disable();
|
|
|
+
|
|
|
+ if (!omap2_can_sleep()) {
|
|
|
+ if (omap_irq_pending())
|
|
|
+ goto out;
|
|
|
+ omap2_enter_mpu_retention();
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (omap_irq_pending())
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ omap2_enter_full_retention();
|
|
|
+
|
|
|
+out:
|
|
|
+ local_fiq_enable();
|
|
|
+}
|
|
|
+
|
|
|
+static void __init prcm_setup_regs(void)
|
|
|
+{
|
|
|
+ int i, num_mem_banks;
|
|
|
+ struct powerdomain *pwrdm;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Enable autoidle
|
|
|
+ * XXX This should be handled by hwmod code or PRCM init code
|
|
|
+ */
|
|
|
+ omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
|
|
|
+ OMAP2_PRCM_SYSCONFIG_OFFSET);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set CORE powerdomain memory banks to retain their contents
|
|
|
+ * during RETENTION
|
|
|
+ */
|
|
|
+ num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
|
|
|
+ for (i = 0; i < num_mem_banks; i++)
|
|
|
+ pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
|
|
|
+
|
|
|
+ /* Set CORE powerdomain's next power state to RETENTION */
|
|
|
+ pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Set MPU powerdomain's next power state to RETENTION;
|
|
|
+ * preserve logic state during retention
|
|
|
+ */
|
|
|
+ pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
|
|
|
+ pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
|
|
|
+
|
|
|
+ /* Force-power down DSP, GFX powerdomains */
|
|
|
+
|
|
|
+ pwrdm = clkdm_get_pwrdm(dsp_clkdm);
|
|
|
+ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
|
|
|
+ clkdm_sleep(dsp_clkdm);
|
|
|
+
|
|
|
+ pwrdm = clkdm_get_pwrdm(gfx_clkdm);
|
|
|
+ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
|
|
|
+ clkdm_sleep(gfx_clkdm);
|
|
|
+
|
|
|
+ /* Enable hardware-supervised idle for all clkdms */
|
|
|
+ clkdm_for_each(omap_pm_clkdms_setup, NULL);
|
|
|
+ clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
|
|
|
+
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+ omap_pm_suspend = omap2_enter_full_retention;
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
|
|
|
+ * stabilisation */
|