diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-06-13 10:58:34 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-06-24 03:48:43 -0400 |
| commit | e8856a8797e76e6883ae81f8f9ecbb231cc535df (patch) | |
| tree | f256d1100f2458e01ca2680052466b24bbabe664 | |
| parent | dbc125168fd7dda4ffb24a29548746c7bd3b3d87 (diff) | |
ARM: pm: convert cpu_suspend() to a normal function
cpu_suspend() has a weird calling method which makes it only possible to
call from assembly code: it returns with a modified stack pointer to
finish the suspend, but on resume, it 'returns' via a provided pointer.
We can make cpu_suspend() appear to be a normal function merely by
swapping the resume pointer argument and the link register.
Do so, and update all callers to take account of this more traditional
behaviour.
Acked-by: Frank Hofmann <frank.hofmann@tomtom.com>
Tested-by: Kevin Hilman <khilman@ti.com>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | arch/arm/include/asm/system.h | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/sleep.S | 10 | ||||
| -rw-r--r-- | arch/arm/mach-exynos4/sleep.S | 7 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/sleep.S | 13 | ||||
| -rw-r--r-- | arch/arm/mach-s3c64xx/sleep.S | 9 | ||||
| -rw-r--r-- | arch/arm/mach-s5pv210/sleep.S | 7 | ||||
| -rw-r--r-- | arch/arm/mach-sa1100/sleep.S | 13 | ||||
| -rw-r--r-- | arch/arm/plat-s3c24xx/sleep.S | 10 |
8 files changed, 31 insertions, 40 deletions
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 832888d0c20c..50be6055df89 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
| @@ -106,6 +106,8 @@ extern void __show_regs(struct pt_regs *); | |||
| 106 | 106 | ||
| 107 | extern int cpu_architecture(void); | 107 | extern int cpu_architecture(void); |
| 108 | extern void cpu_init(void); | 108 | extern void cpu_init(void); |
| 109 | extern void cpu_suspend(int, long, unsigned long, void (*)(unsigned long)); | ||
| 110 | extern void cpu_resume(void); | ||
| 109 | 111 | ||
| 110 | void arm_machine_restart(char mode, const char *cmd); | 112 | void arm_machine_restart(char mode, const char *cmd); |
| 111 | extern void (*arm_pm_restart)(char str, const char *cmd); | 113 | extern void (*arm_pm_restart)(char str, const char *cmd); |
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index b924bcc32dcd..e0626779fe92 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S | |||
| @@ -11,13 +11,11 @@ | |||
| 11 | * Save CPU state for a suspend | 11 | * Save CPU state for a suspend |
| 12 | * r1 = v:p offset | 12 | * r1 = v:p offset |
| 13 | * r2 = suspend function arg0 | 13 | * r2 = suspend function arg0 |
| 14 | * r3 = virtual return function | 14 | * r3 = suspend function |
| 15 | * Note: sp is decremented to allocate space for CPU state on stack | 15 | * Note: does not return until system resumes |
| 16 | * r0-r3,ip,lr corrupted | ||
| 17 | */ | 16 | */ |
| 18 | ENTRY(cpu_suspend) | 17 | ENTRY(cpu_suspend) |
| 19 | stmfd sp!, {r3} | 18 | stmfd sp!, {r4 - r11, lr} |
| 20 | stmfd sp!, {r4 - r11} | ||
| 21 | #ifdef MULTI_CPU | 19 | #ifdef MULTI_CPU |
| 22 | ldr r10, =processor | 20 | ldr r10, =processor |
| 23 | ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state | 21 | ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state |
| @@ -33,7 +31,7 @@ ENTRY(cpu_suspend) | |||
| 33 | stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn | 31 | stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn |
| 34 | ldr r5, =sleep_save_sp | 32 | ldr r5, =sleep_save_sp |
| 35 | add r6, sp, r1 @ convert SP to phys | 33 | add r6, sp, r1 @ convert SP to phys |
| 36 | stmfd sp!, {r2, lr} @ save suspend func arg and pointer | 34 | stmfd sp!, {r2, r3} @ save suspend func arg and pointer |
| 37 | #ifdef CONFIG_SMP | 35 | #ifdef CONFIG_SMP |
| 38 | ALT_SMP(mrc p15, 0, lr, c0, c0, 5) | 36 | ALT_SMP(mrc p15, 0, lr, c0, c0, 5) |
| 39 | ALT_UP(mov lr, #0) | 37 | ALT_UP(mov lr, #0) |
diff --git a/arch/arm/mach-exynos4/sleep.S b/arch/arm/mach-exynos4/sleep.S index 6b62425417a6..d9a2287b4641 100644 --- a/arch/arm/mach-exynos4/sleep.S +++ b/arch/arm/mach-exynos4/sleep.S | |||
| @@ -42,16 +42,15 @@ | |||
| 42 | ENTRY(s3c_cpu_save) | 42 | ENTRY(s3c_cpu_save) |
| 43 | 43 | ||
| 44 | stmfd sp!, { r3 - r12, lr } | 44 | stmfd sp!, { r3 - r12, lr } |
| 45 | ldr r3, =resume_with_mmu | 45 | adr r3, BSYM(exynos4_finish_suspend) |
| 46 | bl cpu_suspend | 46 | bl cpu_suspend |
| 47 | ldmfd sp!, { r3 - r12, pc } | ||
| 47 | 48 | ||
| 49 | exynos4_finish_suspend: | ||
| 48 | ldr r0, =pm_cpu_sleep | 50 | ldr r0, =pm_cpu_sleep |
| 49 | ldr r0, [ r0 ] | 51 | ldr r0, [ r0 ] |
| 50 | mov pc, r0 | 52 | mov pc, r0 |
| 51 | 53 | ||
| 52 | resume_with_mmu: | ||
| 53 | ldmfd sp!, { r3 - r12, pc } | ||
| 54 | |||
| 55 | .ltorg | 54 | .ltorg |
| 56 | 55 | ||
| 57 | /* | 56 | /* |
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index 613ddfa2c295..3a67887e6dbd 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S | |||
| @@ -35,9 +35,11 @@ ENTRY(pxa3xx_cpu_suspend) | |||
| 35 | #endif | 35 | #endif |
| 36 | stmfd sp!, {r2 - r12, lr} @ save registers on stack | 36 | stmfd sp!, {r2 - r12, lr} @ save registers on stack |
| 37 | mov r1, r0 | 37 | mov r1, r0 |
| 38 | ldr r3, =pxa_cpu_resume @ resume function | 38 | adr r3, BSYM(pxa3xx_finish_suspend) |
| 39 | bl cpu_suspend | 39 | bl cpu_suspend |
| 40 | b pxa_cpu_resume | ||
| 40 | 41 | ||
| 42 | pxa3xx_finish_suspend: | ||
| 41 | mov r0, #0x06 @ S2D3C4 mode | 43 | mov r0, #0x06 @ S2D3C4 mode |
| 42 | mcr p14, 0, r0, c7, c0, 0 @ enter sleep | 44 | mcr p14, 0, r0, c7, c0, 0 @ enter sleep |
| 43 | 45 | ||
| @@ -60,9 +62,11 @@ ENTRY(pxa27x_cpu_suspend) | |||
| 60 | #endif | 62 | #endif |
| 61 | stmfd sp!, {r2 - r12, lr} @ save registers on stack | 63 | stmfd sp!, {r2 - r12, lr} @ save registers on stack |
| 62 | mov r2, r0 @ save sleep mode | 64 | mov r2, r0 @ save sleep mode |
| 63 | ldr r3, =pxa_cpu_resume @ resume function | 65 | adr r3, BSYM(pxa27x_finish_suspend) |
| 64 | bl cpu_suspend | 66 | bl cpu_suspend |
| 67 | b pxa_cpu_resume | ||
| 65 | 68 | ||
| 69 | pxa27x_finish_suspend: | ||
| 66 | @ Put the processor to sleep | 70 | @ Put the processor to sleep |
| 67 | @ (also workaround for sighting 28071) | 71 | @ (also workaround for sighting 28071) |
| 68 | 72 | ||
| @@ -110,8 +114,11 @@ ENTRY(pxa27x_cpu_suspend) | |||
| 110 | ENTRY(pxa25x_cpu_suspend) | 114 | ENTRY(pxa25x_cpu_suspend) |
| 111 | stmfd sp!, {r2 - r12, lr} @ save registers on stack | 115 | stmfd sp!, {r2 - r12, lr} @ save registers on stack |
| 112 | mov r2, r0 @ save sleep mode | 116 | mov r2, r0 @ save sleep mode |
| 113 | ldr r3, =pxa_cpu_resume @ resume function | 117 | adr r3, BSYM(pxa25x_finish_suspend) |
| 114 | bl cpu_suspend | 118 | bl cpu_suspend |
| 119 | b pxa_cpu_resume | ||
| 120 | |||
| 121 | pxa25x_finish_suspend: | ||
| 115 | @ prepare value for sleep mode | 122 | @ prepare value for sleep mode |
| 116 | mov r1, r0 @ sleep mode | 123 | mov r1, r0 @ sleep mode |
| 117 | 124 | ||
diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S index 1f87732b2320..dc4f58202101 100644 --- a/arch/arm/mach-s3c64xx/sleep.S +++ b/arch/arm/mach-s3c64xx/sleep.S | |||
| @@ -36,18 +36,15 @@ | |||
| 36 | 36 | ||
| 37 | ENTRY(s3c_cpu_save) | 37 | ENTRY(s3c_cpu_save) |
| 38 | stmfd sp!, { r4 - r12, lr } | 38 | stmfd sp!, { r4 - r12, lr } |
| 39 | ldr r3, =resume_with_mmu | 39 | adr r3, BSYM(s3c64xx_finish_suspend) |
| 40 | bl cpu_suspend | 40 | bl cpu_suspend |
| 41 | ldmfd sp!, { r4 - r12, pc } | ||
| 41 | 42 | ||
| 43 | s3c64xx_finish_suspend: | ||
| 42 | @@ call final suspend code | 44 | @@ call final suspend code |
| 43 | ldr r0, =pm_cpu_sleep | 45 | ldr r0, =pm_cpu_sleep |
| 44 | ldr pc, [r0] | 46 | ldr pc, [r0] |
| 45 | 47 | ||
| 46 | @@ return to the caller, after the MMU is turned on. | ||
| 47 | @@ restore the last bits of the stack and return. | ||
| 48 | resume_with_mmu: | ||
| 49 | ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save | ||
| 50 | |||
| 51 | /* Sleep magic, the word before the resume entry point so that the | 48 | /* Sleep magic, the word before the resume entry point so that the |
| 52 | * bootloader can check for a resumeable image. */ | 49 | * bootloader can check for a resumeable image. */ |
| 53 | 50 | ||
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S index a3d649466fb1..1182fc848a79 100644 --- a/arch/arm/mach-s5pv210/sleep.S +++ b/arch/arm/mach-s5pv210/sleep.S | |||
| @@ -41,16 +41,15 @@ | |||
| 41 | ENTRY(s3c_cpu_save) | 41 | ENTRY(s3c_cpu_save) |
| 42 | 42 | ||
| 43 | stmfd sp!, { r3 - r12, lr } | 43 | stmfd sp!, { r3 - r12, lr } |
| 44 | ldr r3, =resume_with_mmu | 44 | adr r3, BSYM(s5pv210_finish_suspend) |
| 45 | bl cpu_suspend | 45 | bl cpu_suspend |
| 46 | ldmfd sp!, { r3 - r12, pc } | ||
| 46 | 47 | ||
| 48 | s5pv210_finish_suspend: | ||
| 47 | ldr r0, =pm_cpu_sleep | 49 | ldr r0, =pm_cpu_sleep |
| 48 | ldr r0, [ r0 ] | 50 | ldr r0, [ r0 ] |
| 49 | mov pc, r0 | 51 | mov pc, r0 |
| 50 | 52 | ||
| 51 | resume_with_mmu: | ||
| 52 | ldmfd sp!, { r3 - r12, pc } | ||
| 53 | |||
| 54 | .ltorg | 53 | .ltorg |
| 55 | 54 | ||
| 56 | /* sleep magic, to allow the bootloader to check for an valid | 55 | /* sleep magic, to allow the bootloader to check for an valid |
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index 122ab3c66923..f3fe39773f8b 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S | |||
| @@ -31,9 +31,11 @@ | |||
| 31 | ENTRY(sa1100_cpu_suspend) | 31 | ENTRY(sa1100_cpu_suspend) |
| 32 | stmfd sp!, {r4 - r12, lr} @ save registers on stack | 32 | stmfd sp!, {r4 - r12, lr} @ save registers on stack |
| 33 | mov r1, r0 | 33 | mov r1, r0 |
| 34 | ldr r3, =sa1100_cpu_resume @ return function | 34 | adr r3, BSYM(sa1100_finish_suspend) |
| 35 | bl cpu_suspend | 35 | bl cpu_suspend |
| 36 | ldmfd sp!, {r4 - r12, pc} @ return to caller | ||
| 36 | 37 | ||
| 38 | sa1100_finish_suspend: | ||
| 37 | @ disable clock switching | 39 | @ disable clock switching |
| 38 | mcr p15, 0, r1, c15, c2, 2 | 40 | mcr p15, 0, r1, c15, c2, 2 |
| 39 | 41 | ||
| @@ -139,12 +141,3 @@ sa1110_sdram_controller_fix: | |||
| 139 | str r13, [r12] | 141 | str r13, [r12] |
| 140 | 142 | ||
| 141 | 20: b 20b @ loop waiting for sleep | 143 | 20: b 20b @ loop waiting for sleep |
| 142 | |||
| 143 | /* | ||
| 144 | * cpu_sa1100_resume() | ||
| 145 | * | ||
| 146 | * entry point from bootloader into kernel during resume | ||
| 147 | */ | ||
| 148 | .align 5 | ||
| 149 | sa1100_cpu_resume: | ||
| 150 | ldmfd sp!, {r4 - r12, pc} @ return to caller | ||
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S index fd7032f84ae7..f822e6282dd4 100644 --- a/arch/arm/plat-s3c24xx/sleep.S +++ b/arch/arm/plat-s3c24xx/sleep.S | |||
| @@ -49,21 +49,17 @@ | |||
| 49 | 49 | ||
| 50 | ENTRY(s3c_cpu_save) | 50 | ENTRY(s3c_cpu_save) |
| 51 | stmfd sp!, { r4 - r12, lr } | 51 | stmfd sp!, { r4 - r12, lr } |
| 52 | ldr r3, =resume_with_mmu | 52 | adr r3, BSYM(s3c24xx_finish_suspend) |
| 53 | bl cpu_suspend | 53 | bl cpu_suspend |
| 54 | ldmfd sp!, { r4 - r12, pc } | ||
| 54 | 55 | ||
| 56 | s3c24xx_finish_suspend: | ||
| 55 | @@ jump to final code to send system to sleep | 57 | @@ jump to final code to send system to sleep |
| 56 | ldr r0, =pm_cpu_sleep | 58 | ldr r0, =pm_cpu_sleep |
| 57 | @@ldr pc, [ r0 ] | 59 | @@ldr pc, [ r0 ] |
| 58 | ldr r0, [ r0 ] | 60 | ldr r0, [ r0 ] |
| 59 | mov pc, r0 | 61 | mov pc, r0 |
| 60 | 62 | ||
| 61 | @@ return to the caller, after having the MMU | ||
| 62 | @@ turned on, this restores the last bits from the | ||
| 63 | @@ stack | ||
| 64 | resume_with_mmu: | ||
| 65 | ldmfd sp!, { r4 - r12, pc } | ||
| 66 | |||
| 67 | .ltorg | 63 | .ltorg |
| 68 | 64 | ||
| 69 | /* sleep magic, to allow the bootloader to check for an valid | 65 | /* sleep magic, to allow the bootloader to check for an valid |
