diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/cpuidle44xx.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap4-common.c | 6 |
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 | ||
237 | extern void __init gic_init_irq(void); | 237 | extern void __init gic_init_irq(void); |
238 | extern void gic_dist_disable(void); | 238 | extern void gic_dist_disable(void); |
239 | extern void gic_dist_enable(void); | ||
239 | extern bool gic_dist_disabled(void); | 240 | extern bool gic_dist_disabled(void); |
240 | extern void gic_timer_retrigger(void); | 241 | extern void gic_timer_retrigger(void); |
241 | extern void omap_smc1(u32 fn, u32 arg); | 242 | extern 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 | ||
150 | fail: | 166 | fail: |
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 | ||
130 | void gic_dist_enable(void) | ||
131 | { | ||
132 | if (gic_dist_base_addr) | ||
133 | __raw_writel(0x1, gic_dist_base_addr + GIC_DIST_CTRL); | ||
134 | } | ||
135 | |||
130 | bool gic_dist_disabled(void) | 136 | bool 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); |