@@ -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.
*/
@@ -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);