aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/common.h1
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c26
-rw-r--r--arch/arm/mach-omap2/omap-mpuss-lowpower.c3
-rw-r--r--arch/arm/mach-omap2/omap4-common.c6
4 files changed, 31 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index e51527835160..3adaa1d5cd10 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -236,6 +236,7 @@ static inline void __iomem *omap4_get_scu_base(void)
236 236
237extern void __init gic_init_irq(void); 237extern void __init gic_init_irq(void);
238extern void gic_dist_disable(void); 238extern void gic_dist_disable(void);
239extern void gic_dist_enable(void);
239extern bool gic_dist_disabled(void); 240extern bool gic_dist_disabled(void);
240extern void gic_timer_retrigger(void); 241extern void gic_timer_retrigger(void);
241extern void omap_smc1(u32 fn, u32 arg); 242extern void omap_smc1(u32 fn, u32 arg);
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 4c8982ae9529..4c158c838d40 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -80,6 +80,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
80 int index) 80 int index)
81{ 81{
82 struct idle_statedata *cx = state_ptr + index; 82 struct idle_statedata *cx = state_ptr + index;
83 u32 mpuss_can_lose_context = 0;
83 84
84 /* 85 /*
85 * CPU0 has to wait and stay ON until CPU1 is OFF state. 86 * CPU0 has to wait and stay ON until CPU1 is OFF state.
@@ -104,6 +105,9 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
104 } 105 }
105 } 106 }
106 107
108 mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
109 (cx->mpu_logic_state == PWRDM_POWER_OFF);
110
107 /* 111 /*
108 * Call idle CPU PM enter notifier chain so that 112 * Call idle CPU PM enter notifier chain so that
109 * VFP and per CPU interrupt context is saved. 113 * VFP and per CPU interrupt context is saved.
@@ -118,9 +122,8 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
118 * Call idle CPU cluster PM enter notifier chain 122 * Call idle CPU cluster PM enter notifier chain
119 * to save GIC and wakeupgen context. 123 * to save GIC and wakeupgen context.
120 */ 124 */
121 if ((cx->mpu_state == PWRDM_POWER_RET) && 125 if (mpuss_can_lose_context)
122 (cx->mpu_logic_state == PWRDM_POWER_OFF)) 126 cpu_cluster_pm_enter();
123 cpu_cluster_pm_enter();
124 } 127 }
125 128
126 omap4_enter_lowpower(dev->cpu, cx->cpu_state); 129 omap4_enter_lowpower(dev->cpu, cx->cpu_state);
@@ -128,9 +131,23 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
128 131
129 /* Wakeup CPU1 only if it is not offlined */ 132 /* Wakeup CPU1 only if it is not offlined */
130 if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { 133 if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {
134
135 if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD) &&
136 mpuss_can_lose_context)
137 gic_dist_disable();
138
131 clkdm_wakeup(cpu_clkdm[1]); 139 clkdm_wakeup(cpu_clkdm[1]);
132 omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON); 140 omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON);
133 clkdm_allow_idle(cpu_clkdm[1]); 141 clkdm_allow_idle(cpu_clkdm[1]);
142
143 if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD) &&
144 mpuss_can_lose_context) {
145 while (gic_dist_disabled()) {
146 udelay(1);
147 cpu_relax();
148 }
149 gic_timer_retrigger();
150 }
134 } 151 }
135 152
136 /* 153 /*
@@ -143,8 +160,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
143 * Call idle CPU cluster PM exit notifier chain 160 * Call idle CPU cluster PM exit notifier chain
144 * to restore GIC and wakeupgen context. 161 * to restore GIC and wakeupgen context.
145 */ 162 */
146 if (dev->cpu == 0 && (cx->mpu_state == PWRDM_POWER_RET) && 163 if (dev->cpu == 0 && mpuss_can_lose_context)
147 (cx->mpu_logic_state == PWRDM_POWER_OFF))
148 cpu_cluster_pm_exit(); 164 cpu_cluster_pm_exit();
149 165
150fail: 166fail:
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index f991016e2a6a..667915d236f3 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -271,6 +271,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
271 else 271 else
272 omap_pm_ops.finish_suspend(save_state); 272 omap_pm_ops.finish_suspend(save_state);
273 273
274 if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD) && cpu)
275 gic_dist_enable();
276
274 /* 277 /*
275 * Restore the CPUx power state to ON otherwise CPUx 278 * Restore the CPUx power state to ON otherwise CPUx
276 * power domain can transitions to programmed low power 279 * power domain can transitions to programmed low power
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index dd893ec4c8f2..6cd3f3772ecf 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -127,6 +127,12 @@ void gic_dist_disable(void)
127 __raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL); 127 __raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
128} 128}
129 129
130void gic_dist_enable(void)
131{
132 if (gic_dist_base_addr)
133 __raw_writel(0x1, gic_dist_base_addr + GIC_DIST_CTRL);
134}
135
130bool gic_dist_disabled(void) 136bool gic_dist_disabled(void)
131{ 137{
132 return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1); 138 return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1);