aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos4/pm.c
diff options
context:
space:
mode:
authorJaecheol Lee <jc.lee@samsung.com>2011-07-18 06:21:34 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-07-20 10:38:18 -0400
commite240ab1cfbf8e341c38847fe9aee8579a01ed303 (patch)
tree6b4dc049b4f8842d6044556bade07313c5ca2225 /arch/arm/mach-exynos4/pm.c
parente4cf2d1495fc6030c6b01e266aaa125061f58d5b (diff)
ARM: EXYNOS4: Support early wakeup entering sleep mode
Since early wakeup can be handled in pm so we don't need masking interrupts of external GIC. When the early wakeup interrupt happens, PMU(Power Management Unit) ignores WFI instruction. This means that PC(Program Counter) passed without any changes. This patch can handle that case by early wakeup interrupt. Signed-off-by: Jaecheol Lee <jc.lee@samsung.com> [kgene.kim@samsung.com: fixed return of exynos4_cpu_suspend()] Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-exynos4/pm.c')
-rw-r--r--arch/arm/mach-exynos4/pm.c40
1 files changed, 19 insertions, 21 deletions
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index a073a0156daa..1ff290f73837 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -210,7 +210,6 @@ static struct sleep_save exynos4_l2cc_save[] = {
210void exynos4_cpu_suspend(void) 210void exynos4_cpu_suspend(void)
211{ 211{
212 unsigned long tmp; 212 unsigned long tmp;
213 unsigned long mask = 0xFFFFFFFF;
214 213
215 /* Setting Central Sequence Register for power down mode */ 214 /* Setting Central Sequence Register for power down mode */
216 215
@@ -218,26 +217,6 @@ void exynos4_cpu_suspend(void)
218 tmp &= ~(S5P_CENTRAL_LOWPWR_CFG); 217 tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
219 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); 218 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
220 219
221 /* Setting Central Sequence option Register */
222
223 tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
224 tmp &= ~(S5P_USE_MASK);
225 tmp |= S5P_USE_STANDBY_WFI0;
226 __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
227
228 /* Clear all interrupt pending to avoid early wakeup */
229
230 __raw_writel(mask, (S5P_VA_GIC_DIST + 0x280));
231 __raw_writel(mask, (S5P_VA_GIC_DIST + 0x284));
232 __raw_writel(mask, (S5P_VA_GIC_DIST + 0x288));
233
234 /* Disable all interrupt */
235
236 __raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000));
237 __raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000));
238 __raw_writel(mask, (S5P_VA_GIC_DIST + 0x184));
239 __raw_writel(mask, (S5P_VA_GIC_DIST + 0x188));
240
241 outer_flush_all(); 220 outer_flush_all();
242 221
243 /* issue the standby signal into the pm unit. */ 222 /* issue the standby signal into the pm unit. */
@@ -322,6 +301,22 @@ arch_initcall(exynos4_pm_drvinit);
322 301
323static void exynos4_pm_resume(void) 302static void exynos4_pm_resume(void)
324{ 303{
304 unsigned long tmp;
305
306 /*
307 * If PMU failed while entering sleep mode, WFI will be
308 * ignored by PMU and then exiting cpu_do_idle().
309 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
310 * in this situation.
311 */
312 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
313 if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
314 tmp |= S5P_CENTRAL_LOWPWR_CFG;
315 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
316 /* No need to perform below restore code */
317 goto early_wakeup;
318 }
319
325 /* For release retention */ 320 /* For release retention */
326 321
327 __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION); 322 __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
@@ -342,6 +337,9 @@ static void exynos4_pm_resume(void)
342 /* enable L2X0*/ 337 /* enable L2X0*/
343 writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL); 338 writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
344#endif 339#endif
340
341early_wakeup:
342 return;
345} 343}
346 344
347static struct syscore_ops exynos4_pm_syscore_ops = { 345static struct syscore_ops exynos4_pm_syscore_ops = {