aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-07-02 04:54:01 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-07-02 04:54:01 -0400
commit29cb3cd208dd0e4471bb80bec4facc49ceb199fa (patch)
tree035128bf7af997d5e1e5208c900ba78c5a1df46d
parentcbe263497def23befb6f475977661bae5d1f82e4 (diff)
ARM: pm: allow suspend finisher to return error codes
There are SoCs where attempting to enter a low power state is ignored, and the CPU continues executing instructions with all state preserved. It is over-complex at that point to disable the MMU just to call the resume path. Instead, allow the suspend finisher to return error codes to abort suspend in this circumstance, where the cpu_suspend internals will then unwind the saved state on the stack. Also omit the tlb flush as no changes to the page tables will have happened. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/suspend.h9
-rw-r--r--arch/arm/kernel/sleep.S11
-rw-r--r--arch/arm/mach-exynos4/pm.c2
-rw-r--r--arch/arm/mach-omap2/pm34xx.c3
-rw-r--r--arch/arm/mach-pxa/include/mach/pm.h4
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c2
-rw-r--r--arch/arm/mach-s3c2412/pm.c4
-rw-r--r--arch/arm/mach-s3c2416/pm.c4
-rw-r--r--arch/arm/mach-s3c64xx/pm.c2
-rw-r--r--arch/arm/mach-sa1100/pm.c2
-rw-r--r--arch/arm/plat-samsung/include/plat/pm.h4
-rw-r--r--arch/arm/plat-samsung/pm.c2
12 files changed, 31 insertions, 18 deletions
diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h
index f8db9d096bc7..b0e4e1a02318 100644
--- a/arch/arm/include/asm/suspend.h
+++ b/arch/arm/include/asm/suspend.h
@@ -10,12 +10,13 @@ extern void cpu_resume(void);
10 * Hide the first two arguments to __cpu_suspend - these are an implementation 10 * Hide the first two arguments to __cpu_suspend - these are an implementation
11 * detail which platform code shouldn't have to know about. 11 * detail which platform code shouldn't have to know about.
12 */ 12 */
13static inline void cpu_suspend(unsigned long arg, void (*fn)(unsigned long)) 13static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
14{ 14{
15 extern void __cpu_suspend(int, long, unsigned long, 15 extern int __cpu_suspend(int, long, unsigned long,
16 void (*)(unsigned long)); 16 int (*)(unsigned long));
17 __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn); 17 int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
18 flush_tlb_all(); 18 flush_tlb_all();
19 return ret;
19} 20}
20 21
21#endif 22#endif
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index c156d0e5f455..dc902f2c6845 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -12,7 +12,6 @@
12 * r1 = v:p offset 12 * r1 = v:p offset
13 * r2 = suspend function arg0 13 * r2 = suspend function arg0
14 * r3 = suspend function 14 * r3 = suspend function
15 * Note: does not return until system resumes
16 */ 15 */
17ENTRY(__cpu_suspend) 16ENTRY(__cpu_suspend)
18 stmfd sp!, {r4 - r11, lr} 17 stmfd sp!, {r4 - r11, lr}
@@ -26,7 +25,7 @@ ENTRY(__cpu_suspend)
26#endif 25#endif
27 mov r6, sp @ current virtual SP 26 mov r6, sp @ current virtual SP
28 sub sp, sp, r5 @ allocate CPU state on stack 27 sub sp, sp, r5 @ allocate CPU state on stack
29 mov r0, sp @ save pointer 28 mov r0, sp @ save pointer to CPU save block
30 add ip, ip, r1 @ convert resume fn to phys 29 add ip, ip, r1 @ convert resume fn to phys
31 stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn 30 stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn
32 ldr r5, =sleep_save_sp 31 ldr r5, =sleep_save_sp
@@ -55,10 +54,17 @@ ENTRY(__cpu_suspend)
55#else 54#else
56 bl __cpuc_flush_kern_all 55 bl __cpuc_flush_kern_all
57#endif 56#endif
57 adr lr, BSYM(cpu_suspend_abort)
58 ldmfd sp!, {r0, pc} @ call suspend fn 58 ldmfd sp!, {r0, pc} @ call suspend fn
59ENDPROC(__cpu_suspend) 59ENDPROC(__cpu_suspend)
60 .ltorg 60 .ltorg
61 61
62cpu_suspend_abort:
63 ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn
64 mov sp, r2
65 ldmfd sp!, {r4 - r11, pc}
66ENDPROC(cpu_suspend_abort)
67
62/* 68/*
63 * r0 = control register value 69 * r0 = control register value
64 * r1 = v:p offset (preserved by cpu_do_resume) 70 * r1 = v:p offset (preserved by cpu_do_resume)
@@ -89,6 +95,7 @@ cpu_resume_after_mmu:
89 str r5, [r2, r4, lsl #2] @ restore old mapping 95 str r5, [r2, r4, lsl #2] @ restore old mapping
90 mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache 96 mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
91 bl cpu_init @ restore the und/abt/irq banked regs 97 bl cpu_init @ restore the und/abt/irq banked regs
98 mov r0, #0 @ return zero on success
92 ldmfd sp!, {r4 - r11, pc} 99 ldmfd sp!, {r4 - r11, pc}
93ENDPROC(cpu_resume_after_mmu) 100ENDPROC(cpu_resume_after_mmu)
94 101
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index 5c01c6076645..533c28f758ca 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -280,7 +280,7 @@ static struct sleep_save exynos4_l2cc_save[] = {
280 SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL), 280 SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
281}; 281};
282 282
283void exynos4_cpu_suspend(unsigned long arg) 283static int exynos4_cpu_suspend(unsigned long arg)
284{ 284{
285 unsigned long tmp; 285 unsigned long tmp;
286 unsigned long mask = 0xFFFFFFFF; 286 unsigned long mask = 0xFFFFFFFF;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7238a63e24e2..b77d82665abb 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -321,9 +321,10 @@ static void omap34xx_save_context(u32 *save)
321 *save++ = val; 321 *save++ = val;
322} 322}
323 323
324static void omap34xx_do_sram_idle(unsigned long save_state) 324static int omap34xx_do_sram_idle(unsigned long save_state)
325{ 325{
326 omap34xx_cpu_suspend(save_state); 326 omap34xx_cpu_suspend(save_state);
327 return 0;
327} 328}
328 329
329void omap_sram_idle(void) 330void omap_sram_idle(void)
diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h
index a566720527cf..51558bcee999 100644
--- a/arch/arm/mach-pxa/include/mach/pm.h
+++ b/arch/arm/mach-pxa/include/mach/pm.h
@@ -22,8 +22,8 @@ struct pxa_cpu_pm_fns {
22extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns; 22extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
23 23
24/* sleep.S */ 24/* sleep.S */
25extern void pxa25x_finish_suspend(unsigned long); 25extern int pxa25x_finish_suspend(unsigned long);
26extern void pxa27x_finish_suspend(unsigned long); 26extern int pxa27x_finish_suspend(unsigned long);
27 27
28extern int pxa_pm_enter(suspend_state_t state); 28extern int pxa_pm_enter(suspend_state_t state);
29extern int pxa_pm_prepare(void); 29extern int pxa_pm_prepare(void);
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 9fe947b5d5f7..ef1c56a67afc 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -148,7 +148,7 @@ static void pxa3xx_cpu_pm_suspend(void)
148 asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0)); 148 asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
149#endif 149#endif
150 150
151 extern void pxa3xx_finish_suspend(unsigned long); 151 extern int pxa3xx_finish_suspend(unsigned long);
152 152
153 /* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */ 153 /* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
154 CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM); 154 CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
index 9a1fb898db53..f4077efa51fa 100644
--- a/arch/arm/mach-s3c2412/pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -37,7 +37,7 @@
37 37
38extern void s3c2412_sleep_enter(void); 38extern void s3c2412_sleep_enter(void);
39 39
40static void s3c2412_cpu_suspend(unsigned long arg) 40static int s3c2412_cpu_suspend(unsigned long arg)
41{ 41{
42 unsigned long tmp; 42 unsigned long tmp;
43 43
@@ -48,6 +48,8 @@ static void s3c2412_cpu_suspend(unsigned long arg)
48 __raw_writel(tmp, S3C2412_PWRCFG); 48 __raw_writel(tmp, S3C2412_PWRCFG);
49 49
50 s3c2412_sleep_enter(); 50 s3c2412_sleep_enter();
51
52 panic("sleep resumed to originator?");
51} 53}
52 54
53static void s3c2412_pm_prepare(void) 55static void s3c2412_pm_prepare(void)
diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c
index 9e67a2a07a86..9ec54f1d8e75 100644
--- a/arch/arm/mach-s3c2416/pm.c
+++ b/arch/arm/mach-s3c2416/pm.c
@@ -24,7 +24,7 @@
24 24
25extern void s3c2412_sleep_enter(void); 25extern void s3c2412_sleep_enter(void);
26 26
27static void s3c2416_cpu_suspend(unsigned long arg) 27static int s3c2416_cpu_suspend(unsigned long arg)
28{ 28{
29 /* enable wakeup sources regardless of battery state */ 29 /* enable wakeup sources regardless of battery state */
30 __raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG); 30 __raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG);
@@ -33,6 +33,8 @@ static void s3c2416_cpu_suspend(unsigned long arg)
33 __raw_writel(0x2BED, S3C2443_PWRMODE); 33 __raw_writel(0x2BED, S3C2443_PWRMODE);
34 34
35 s3c2412_sleep_enter(); 35 s3c2412_sleep_enter();
36
37 panic("sleep resumed to originator?");
36} 38}
37 39
38static void s3c2416_pm_prepare(void) 40static void s3c2416_pm_prepare(void)
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
index 7cc1879af722..8bad64370689 100644
--- a/arch/arm/mach-s3c64xx/pm.c
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -112,7 +112,7 @@ void s3c_pm_save_core(void)
112 * this. 112 * this.
113 */ 113 */
114 114
115static void s3c64xx_cpu_suspend(unsigned long arg) 115static int s3c64xx_cpu_suspend(unsigned long arg)
116{ 116{
117 unsigned long tmp; 117 unsigned long tmp;
118 118
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index cf9a1e9fb70d..bf85b8b259d5 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -33,7 +33,7 @@
33#include <asm/system.h> 33#include <asm/system.h>
34#include <asm/mach/time.h> 34#include <asm/mach/time.h>
35 35
36extern void sa1100_finish_suspend(unsigned long); 36extern int sa1100_finish_suspend(unsigned long);
37 37
38#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x 38#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
39#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] 39#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 0a5b7faca836..f6749916d194 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -42,7 +42,7 @@ extern unsigned long s3c_irqwake_eintallow;
42/* per-cpu sleep functions */ 42/* per-cpu sleep functions */
43 43
44extern void (*pm_cpu_prep)(void); 44extern void (*pm_cpu_prep)(void);
45extern void (*pm_cpu_sleep)(unsigned long); 45extern int (*pm_cpu_sleep)(unsigned long);
46 46
47/* Flags for PM Control */ 47/* Flags for PM Control */
48 48
@@ -54,7 +54,7 @@ extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
54 54
55extern void s3c_cpu_resume(void); 55extern void s3c_cpu_resume(void);
56 56
57extern void s3c2410_cpu_suspend(unsigned long); 57extern int s3c2410_cpu_suspend(unsigned long);
58 58
59/* sleep save info */ 59/* sleep save info */
60 60
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index 69d6b040a019..5fa1742d019b 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -232,7 +232,7 @@ static void __maybe_unused s3c_pm_show_resume_irqs(int start,
232 232
233 233
234void (*pm_cpu_prep)(void); 234void (*pm_cpu_prep)(void);
235void (*pm_cpu_sleep)(unsigned long); 235int (*pm_cpu_sleep)(unsigned long);
236 236
237#define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) 237#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
238 238