summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap-mpuss-lowpower.c
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2014-10-21 15:24:36 -0500
committerTony Lindgren <tony@atomide.com>2014-11-10 16:02:05 -0800
commita30d81b98a778c4ce113ba9c2e03deb2f9522d66 (patch)
tree78982b794c2cf738ced4d104b26595ff30b3a7dd /arch/arm/mach-omap2/omap-mpuss-lowpower.c
parentb9f5fe6425ef1622fb0f16f0fa33f19b993863a6 (diff)
downloadlinux-a30d81b98a778c4ce113ba9c2e03deb2f9522d66.tar.bz2
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>
Diffstat (limited to 'arch/arm/mach-omap2/omap-mpuss-lowpower.c')
-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)
int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
{
struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
- unsigned int save_state = 0;
+ unsigned int save_state = 0, cpu_logic_state = PWRDM_POWER_RET;
unsigned int wakeup_cpu;
if (omap_rev() == OMAP4430_REV_ES1_0)
@@ -239,6 +239,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
save_state = 0;
break;
case PWRDM_POWER_OFF:
+ cpu_logic_state = PWRDM_POWER_OFF;
save_state = 1;
break;
case PWRDM_POWER_RET:
@@ -270,6 +271,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
cpu_clear_prev_logic_pwrst(cpu);
pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
+ pwrdm_set_logic_retst(pm_info->pwrdm, cpu_logic_state);
set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume));
omap_pm_ops.scu_prepare(cpu, power_state);
l2x0_pwrst_prepare(cpu, save_state);