diff mbox

omap3: Restore the powerdomian states post wfi in omap_sram_idle

Message ID 1286012590-1013-1-git-send-email-santosh.shilimkar@ti.com (mailing list archive)
State New, archived
Delegated to: Kevin Hilman
Headers show

Commit Message

Santosh Shilimkar Oct. 2, 2010, 9:43 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 8ea012e..54a8c27 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -267,6 +267,17 @@  static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	}
 
 	/*
+	 * Program PER explicitly like core to avoid any unsupported
+	 * PER/CORE combination which can lead to deadlock
+	 */
+	if (sleep_while_idle) {
+		if (enable_off_mode)
+			pwrdm_set_next_pwrst(per_pd, PWRDM_POWER_OFF);
+		else
+			pwrdm_set_next_pwrst(per_pd, PWRDM_POWER_RET);
+	}
+
+	/*
 	 * Prevent PER off if CORE is not in retention or off as this
 	 * would disable PER wakeups completely.
 	 */
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 570ce1d..ca5fb12 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -455,6 +455,23 @@  void omap_sram_idle(void)
 	if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
 		restore_table_entry();
 
+	/*
+	 * Restore the mpu, neon per and core power domain
+	 * states to ON otherwise power domain can transition
+	 * to already programmed low power state while issuing WFI
+	 * outside the idle thread when dependencies are met.
+	 * On HS/EMU devices, mpu can do WFI as part of secure code
+	 * execution like waiting on DMA interrupt or waiting for
+	 * encryption to be done etc.
+	 * This can result in undesired power domain transition
+	 * if the power state control is not restored from
+	 * previously programmed OFF/RET stated as part of cpuidle.
+	 */
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
+	pwrdm_set_next_pwrst(neon_pwrdm, PWRDM_POWER_ON);
+	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);
+	pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_ON);
+
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
 		core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);