|
@@ -293,3 +293,96 @@ void omap_sram_idle(void)
|
|
|
/*
|
|
|
* On EMU/HS devices ROM code restores a SRDC value
|
|
|
* from scratchpad which has automatic self refresh on timeout
|
|
|
+ * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
|
|
|
+ * Hence store/restore the SDRC_POWER register here.
|
|
|
+ */
|
|
|
+ if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
|
|
|
+ (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
|
|
|
+ omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
|
|
|
+ core_next_state == PWRDM_POWER_OFF)
|
|
|
+ sdrc_pwr = sdrc_read_reg(SDRC_POWER);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * omap3_arm_context is the location where some ARM context
|
|
|
+ * get saved. The rest is placed on the stack, and restored
|
|
|
+ * from there before resuming.
|
|
|
+ */
|
|
|
+ if (save_state)
|
|
|
+ omap34xx_save_context(omap3_arm_context);
|
|
|
+ if (save_state == 1 || save_state == 3)
|
|
|
+ cpu_suspend(save_state, omap34xx_do_sram_idle);
|
|
|
+ else
|
|
|
+ omap34xx_do_sram_idle(save_state);
|
|
|
+
|
|
|
+ /* Restore normal SDRC POWER settings */
|
|
|
+ if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
|
|
|
+ (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
|
|
|
+ omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
|
|
|
+ core_next_state == PWRDM_POWER_OFF)
|
|
|
+ sdrc_write_reg(sdrc_pwr, SDRC_POWER);
|
|
|
+
|
|
|
+ /* CORE */
|
|
|
+ if (core_next_state < PWRDM_POWER_ON) {
|
|
|
+ core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
|
|
|
+ if (core_prev_state == PWRDM_POWER_OFF) {
|
|
|
+ omap3_core_restore_context();
|
|
|
+ omap3_cm_restore_context();
|
|
|
+ omap3_sram_restore_context();
|
|
|
+ omap2_sms_restore_context();
|
|
|
+ }
|
|
|
+ if (core_next_state == PWRDM_POWER_OFF)
|
|
|
+ omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
|
|
|
+ OMAP3430_GR_MOD,
|
|
|
+ OMAP3_PRM_VOLTCTRL_OFFSET);
|
|
|
+ }
|
|
|
+ omap3_intc_resume_idle();
|
|
|
+
|
|
|
+ pwrdm_post_transition(NULL);
|
|
|
+
|
|
|
+ /* PER */
|
|
|
+ if (per_next_state < PWRDM_POWER_ON)
|
|
|
+ omap2_gpio_resume_after_idle();
|
|
|
+}
|
|
|
+
|
|
|
+static void omap3_pm_idle(void)
|
|
|
+{
|
|
|
+ local_fiq_disable();
|
|
|
+
|
|
|
+ if (omap_irq_pending())
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ trace_power_start(POWER_CSTATE, 1, smp_processor_id());
|
|
|
+ trace_cpu_idle(1, smp_processor_id());
|
|
|
+
|
|
|
+ omap_sram_idle();
|
|
|
+
|
|
|
+ trace_power_end(smp_processor_id());
|
|
|
+ trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
|
|
|
+
|
|
|
+out:
|
|
|
+ local_fiq_enable();
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+static int omap3_pm_suspend(void)
|
|
|
+{
|
|
|
+ struct power_state *pwrst;
|
|
|
+ int state, ret = 0;
|
|
|
+
|
|
|
+ /* Read current next_pwrsts */
|
|
|
+ list_for_each_entry(pwrst, &pwrst_list, node)
|
|
|
+ pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
|
|
|
+ /* Set ones wanted by suspend */
|
|
|
+ list_for_each_entry(pwrst, &pwrst_list, node) {
|
|
|
+ if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
|
|
|
+ goto restore;
|
|
|
+ if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
|
|
|
+ goto restore;
|
|
|
+ }
|
|
|
+
|
|
|
+ omap3_intc_suspend();
|
|
|
+
|
|
|
+ omap_sram_idle();
|
|
|
+
|
|
|
+restore:
|
|
|
+ /* Restore next_pwrsts */
|