aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2014-10-21 16:24:36 -0400
committerTony Lindgren <tony@atomide.com>2014-11-10 19:02:05 -0500
commita30d81b98a778c4ce113ba9c2e03deb2f9522d66 (patch)
tree78982b794c2cf738ced4d104b26595ff30b3a7dd
parentb9f5fe6425ef1622fb0f16f0fa33f19b993863a6 (diff)
ARM: OMAP4+: PM: Program CPU logic power state
CPU logic power state is never programmed in either the initialization or the suspend/resume logic, instead, we depend on mpuss to program this properly. However, this leaves CPU logic power state indeterminate and most probably in reset configuration (If bootloader or other similar software have'nt monkeyed with the register). This can make powerstate= RET be either programmed for CSWR (logic=ret) or OSWR(logic = OFF) and in OSWR, there can be context loss when the code does not expect it. To prevent all these confusions, just support clearly ON, INA, CSWR, OFF which is the intent of the existing code by explicitly programming logic state. NOTE: since this is a hot path (using in cpuidle), the exit path just programs powerstate (logic state is immaterial when powerstate is ON). Without doing this, we end up with lockups when CPUs enter OSWR and multiple blocks loose context, when we expect them to hit CSWR. Signed-off-by: Nishanth Menon <nm@ti.com> Acked-by: Kevin Hilman <khilman@linaro.org> Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r--arch/arm/mach-omap2/omap-mpuss-lowpower.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 6944ae3674e8..79f49d904a06 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -227,7 +227,7 @@ static void __init save_l2x0_context(void)
227int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) 227int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
228{ 228{
229 struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu); 229 struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
230 unsigned int save_state = 0; 230 unsigned int save_state = 0, cpu_logic_state = PWRDM_POWER_RET;
231 unsigned int wakeup_cpu; 231 unsigned int wakeup_cpu;
232 232
233 if (omap_rev() == OMAP4430_REV_ES1_0) 233 if (omap_rev() == OMAP4430_REV_ES1_0)
@@ -239,6 +239,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
239 save_state = 0; 239 save_state = 0;
240 break; 240 break;
241 case PWRDM_POWER_OFF: 241 case PWRDM_POWER_OFF:
242 cpu_logic_state = PWRDM_POWER_OFF;
242 save_state = 1; 243 save_state = 1;
243 break; 244 break;
244 case PWRDM_POWER_RET: 245 case PWRDM_POWER_RET:
@@ -270,6 +271,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
270 271
271 cpu_clear_prev_logic_pwrst(cpu); 272 cpu_clear_prev_logic_pwrst(cpu);
272 pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); 273 pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
274 pwrdm_set_logic_retst(pm_info->pwrdm, cpu_logic_state);
273 set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume)); 275 set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume));
274 omap_pm_ops.scu_prepare(cpu, power_state); 276 omap_pm_ops.scu_prepare(cpu, power_state);
275 l2x0_pwrst_prepare(cpu, save_state); 277 l2x0_pwrst_prepare(cpu, save_state);