diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index f290e484e5766e5f6307a5f840c639df6a2c389a..0fb619c52588fee0a668191c0ee16cc1a3e435d0 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -453,6 +453,18 @@ void omap_init_power_states(void) omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF; omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_CHECK_BM; + + /* + * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot + * enable OFF mode in a stable form for previous revisions. + * we disable C7 state as a result. + */ + if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) { + omap3_power_states[OMAP3_STATE_C7].valid = 0; + cpuidle_params_table[OMAP3_STATE_C7].valid = 0; + WARN_ONCE(1, "%s: core off state C7 disabled due to i583\n", + __func__); + } } struct cpuidle_driver omap3_idle_driver = { diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 29663cc01a59bdeaf261f79f788b3d5598bef1a4..b4e66f9e1945dcf2029117655fa8655c45f64f61 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -86,6 +86,7 @@ extern unsigned int omap24xx_cpu_suspend_sz; extern unsigned int omap34xx_cpu_suspend_sz; #define PM_RTA_ERRATUM_i608 (1 << 0) +#define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1) #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) extern u16 pm34xx_errata; diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 74bc15e71e9fe79497ecb25d0324596da498a103..a81ed251e6672695c4c5efef605e3020197960e9 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -917,12 +917,29 @@ void omap3_pm_off_mode_enable(int enable) state = PWRDM_POWER_RET; #ifdef CONFIG_CPU_IDLE - omap3_cpuidle_update_states(state, state); + /* + * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot + * enable OFF mode in a stable form for previous revisions, restrict + * instead to RET + */ + if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) + omap3_cpuidle_update_states(state, PWRDM_POWER_RET); + else + omap3_cpuidle_update_states(state, state); #endif list_for_each_entry(pwrst, &pwrst_list, node) { - pwrst->next_state = state; - omap_set_pwrdm_state(pwrst->pwrdm, state); + if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) && + pwrst->pwrdm == core_pwrdm && + state == PWRDM_POWER_OFF) { + pwrst->next_state = PWRDM_POWER_RET; + WARN_ONCE(1, + "%s: Core OFF disabled due to errata i583\n", + __func__); + } else { + pwrst->next_state = state; + } + omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); } } @@ -1000,6 +1017,8 @@ static void __init pm_errata_configure(void) pm34xx_errata |= PM_RTA_ERRATUM_i608; /* Enable the l2 cache toggling in sleep logic */ enable_omap3630_toggle_l2_on_restore(); + if (omap_rev() < OMAP3630_REV_ES1_2) + pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583; } }