aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 25655eb69408..eb93e45d3271 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -53,6 +53,9 @@ static struct omap4_idle_statedata omap4_idle_data[] = {
53static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS]; 53static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS];
54static struct clockdomain *cpu_clkdm[NR_CPUS]; 54static struct clockdomain *cpu_clkdm[NR_CPUS];
55 55
56static atomic_t abort_barrier;
57static bool cpu_done[NR_CPUS];
58
56/** 59/**
57 * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions 60 * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions
58 * @dev: cpuidle device 61 * @dev: cpuidle device
@@ -90,8 +93,20 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
90 * out of coherency and in OFF mode. 93 * out of coherency and in OFF mode.
91 */ 94 */
92 if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { 95 if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {
93 while (pwrdm_read_pwrst(cpu_pd[1]) != PWRDM_POWER_OFF) 96 while (pwrdm_read_pwrst(cpu_pd[1]) != PWRDM_POWER_OFF) {
94 cpu_relax(); 97 cpu_relax();
98
99 /*
100 * CPU1 could have already entered & exited idle
101 * without hitting off because of a wakeup
102 * or a failed attempt to hit off mode. Check for
103 * that here, otherwise we could spin forever
104 * waiting for CPU1 off.
105 */
106 if (cpu_done[1])
107 goto fail;
108
109 }
95 } 110 }
96 111
97 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); 112 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
@@ -116,6 +131,7 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
116 } 131 }
117 132
118 omap4_enter_lowpower(dev->cpu, cx->cpu_state); 133 omap4_enter_lowpower(dev->cpu, cx->cpu_state);
134 cpu_done[dev->cpu] = true;
119 135
120 /* Wakeup CPU1 only if it is not offlined */ 136 /* Wakeup CPU1 only if it is not offlined */
121 if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { 137 if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {
@@ -138,6 +154,10 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
138 154
139 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); 155 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
140 156
157fail:
158 cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
159 cpu_done[dev->cpu] = false;
160
141 local_fiq_enable(); 161 local_fiq_enable();
142 162
143 return index; 163 return index;