aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorStrashko, Grygorii <grygorii.strashko@ti.com>2013-10-22 15:07:15 -0400
committerOlof Johansson <olof@lixom.net>2014-01-31 17:57:32 -0500
commit74ed7bdcb41d32c7628c3bd1478b076e5b1ad8a4 (patch)
tree66fd985590234a77ccbca36a9fbc06df7b968281 /arch/arm
parente7651b819e90da924991d727d3c007200a18670d (diff)
ARM: OMAP4460: cpuidle: Extend PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD on cpuidle
The same workaround as ff999b8a0983ee15668394ed49e38d3568fc6859 "ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX GIC ..." need to be applied not only when system is booting, but when MPUSS hits OSWR state through CPUIdle too. Without this WA the same issue is reproduced now on boards PandaES and Tablet/Blaze with SOM OMAP4460 when CONFIG_CPU_IDLE is enabled. After MPUSS has enterred OSWR and waken up: - GIC distributor became disabled forever - scheduling is not performed any more Cc: Kevin Hilman <khilman@linaro.org> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Reported-by: Taras Kondratiuk <taras.kondratiuk@linaro.org> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Kevin Hilman <khilman@linaro.org> Signed-off-by: Olof Johansson <olof@lixom.net>
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);