diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-06 12:39:31 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-22 12:11:25 -0500 |
commit | 2e2f3d3792de5913897b6bb49ac13915b0b020d5 (patch) | |
tree | 02126d58ee15cf94c7335604ef8f9e8eb21d7378 /arch | |
parent | 96c20015dae59e58d055c1e2e17a811e0d1f1d03 (diff) |
ARM: pm: convert samsung platforms to generic suspend/resume support
Tested-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-s3c64xx/sleep.S | 63 | ||||
-rw-r--r-- | arch/arm/mach-s5pv210/sleep.S | 105 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/sleep.S | 57 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/pm.h | 12 | ||||
-rw-r--r-- | arch/arm/plat-samsung/pm.c | 16 |
5 files changed, 14 insertions, 239 deletions
diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S index b2ef44317368..afe5a762f46e 100644 --- a/arch/arm/mach-s3c64xx/sleep.S +++ b/arch/arm/mach-s3c64xx/sleep.S | |||
@@ -32,25 +32,13 @@ | |||
32 | * code after resume. | 32 | * code after resume. |
33 | * | 33 | * |
34 | * entry: | 34 | * entry: |
35 | * r0 = pointer to the save block | 35 | * r1 = v:p offset |
36 | */ | 36 | */ |
37 | 37 | ||
38 | ENTRY(s3c_cpu_save) | 38 | ENTRY(s3c_cpu_save) |
39 | stmfd sp!, { r4 - r12, lr } | 39 | stmfd sp!, { r4 - r12, lr } |
40 | 40 | ldr r3, =resume_with_mmu | |
41 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID | 41 | bl cpu_suspend |
42 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID | ||
43 | mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 | ||
44 | mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 | ||
45 | mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control | ||
46 | mrc p15, 0, r9, c1, c0, 0 @ Control register | ||
47 | mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register | ||
48 | mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls | ||
49 | |||
50 | stmia r0, { r4 - r13 } @ Save CP registers and SP | ||
51 | |||
52 | @@ save our state to ram | ||
53 | bl s3c_pm_cb_flushcache | ||
54 | 42 | ||
55 | @@ call final suspend code | 43 | @@ call final suspend code |
56 | ldr r0, =pm_cpu_sleep | 44 | ldr r0, =pm_cpu_sleep |
@@ -61,18 +49,6 @@ ENTRY(s3c_cpu_save) | |||
61 | resume_with_mmu: | 49 | resume_with_mmu: |
62 | ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save | 50 | ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save |
63 | 51 | ||
64 | .data | ||
65 | |||
66 | /* the next bit is code, but it requires easy access to the | ||
67 | * s3c_sleep_save_phys data before the MMU is switched on, so | ||
68 | * we store the code that needs this variable in the .data where | ||
69 | * the value can be written to (the .text segment is RO). | ||
70 | */ | ||
71 | |||
72 | .global s3c_sleep_save_phys | ||
73 | s3c_sleep_save_phys: | ||
74 | .word 0 | ||
75 | |||
76 | /* Sleep magic, the word before the resume entry point so that the | 52 | /* Sleep magic, the word before the resume entry point so that the |
77 | * bootloader can check for a resumeable image. */ | 53 | * bootloader can check for a resumeable image. */ |
78 | 54 | ||
@@ -110,35 +86,4 @@ ENTRY(s3c_cpu_resume) | |||
110 | orr r0, r0, #1 << 15 @ GPN15 | 86 | orr r0, r0, #1 << 15 @ GPN15 |
111 | str r0, [ r3, #S3C64XX_GPNDAT ] | 87 | str r0, [ r3, #S3C64XX_GPNDAT ] |
112 | #endif | 88 | #endif |
113 | 89 | b cpu_resume | |
114 | /* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches | ||
115 | * are thoroughly cleaned just in case the bootloader didn't do it | ||
116 | * for us. */ | ||
117 | mov r0, #0 | ||
118 | mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache | ||
119 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
120 | mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache | ||
121 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
122 | @@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs | ||
123 | @@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches | ||
124 | |||
125 | ldr r0, s3c_sleep_save_phys | ||
126 | ldmia r0, { r4 - r13 } | ||
127 | |||
128 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID | ||
129 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID | ||
130 | mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 | ||
131 | mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 | ||
132 | mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control | ||
133 | mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register | ||
134 | |||
135 | mov r0, #0 @ restore copro access controls | ||
136 | mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls | ||
137 | mcr p15, 0, r0, c7, c5, 4 | ||
138 | |||
139 | ldr r2, =resume_with_mmu | ||
140 | mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */ | ||
141 | nop | ||
142 | mov pc, r2 /* jump back */ | ||
143 | |||
144 | .end | ||
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S index d4d222b716b4..a3d649466fb1 100644 --- a/arch/arm/mach-s5pv210/sleep.S +++ b/arch/arm/mach-s5pv210/sleep.S | |||
@@ -35,50 +35,24 @@ | |||
35 | /* s3c_cpu_save | 35 | /* s3c_cpu_save |
36 | * | 36 | * |
37 | * entry: | 37 | * entry: |
38 | * r0 = save address (virtual addr of s3c_sleep_save_phys) | 38 | * r1 = v:p offset |
39 | */ | 39 | */ |
40 | 40 | ||
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 | 44 | ldr r3, =resume_with_mmu | |
45 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID | 45 | bl cpu_suspend |
46 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID | ||
47 | mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 | ||
48 | mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 | ||
49 | mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control | ||
50 | mrc p15, 0, r9, c1, c0, 0 @ Control register | ||
51 | mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register | ||
52 | mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls | ||
53 | mrc p15, 0, r12, c10, c2, 0 @ Read PRRR | ||
54 | mrc p15, 0, r3, c10, c2, 1 @ READ NMRR | ||
55 | |||
56 | stmia r0, { r3 - r13 } | ||
57 | |||
58 | bl s3c_pm_cb_flushcache | ||
59 | 46 | ||
60 | ldr r0, =pm_cpu_sleep | 47 | ldr r0, =pm_cpu_sleep |
61 | ldr r0, [ r0 ] | 48 | ldr r0, [ r0 ] |
62 | mov pc, r0 | 49 | mov pc, r0 |
63 | 50 | ||
64 | resume_with_mmu: | 51 | resume_with_mmu: |
65 | /* | ||
66 | * After MMU is turned on, restore the previous MMU table. | ||
67 | */ | ||
68 | ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET) | ||
69 | add r4, r4, r9 | ||
70 | str r12, [r4] | ||
71 | |||
72 | ldmfd sp!, { r3 - r12, pc } | 52 | ldmfd sp!, { r3 - r12, pc } |
73 | 53 | ||
74 | .ltorg | 54 | .ltorg |
75 | 55 | ||
76 | .data | ||
77 | |||
78 | .global s3c_sleep_save_phys | ||
79 | s3c_sleep_save_phys: | ||
80 | .word 0 | ||
81 | |||
82 | /* sleep magic, to allow the bootloader to check for an valid | 56 | /* sleep magic, to allow the bootloader to check for an valid |
83 | * image to resume to. Must be the first word before the | 57 | * image to resume to. Must be the first word before the |
84 | * s3c_cpu_resume entry. | 58 | * s3c_cpu_resume entry. |
@@ -96,75 +70,4 @@ s3c_sleep_save_phys: | |||
96 | */ | 70 | */ |
97 | 71 | ||
98 | ENTRY(s3c_cpu_resume) | 72 | ENTRY(s3c_cpu_resume) |
99 | mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE | 73 | b cpu_resume |
100 | msr cpsr_c, r0 | ||
101 | |||
102 | mov r1, #0 | ||
103 | mcr p15, 0, r1, c8, c7, 0 @ invalidate TLBs | ||
104 | mcr p15, 0, r1, c7, c5, 0 @ invalidate I Cache | ||
105 | |||
106 | ldr r0, s3c_sleep_save_phys @ address of restore block | ||
107 | ldmia r0, { r3 - r13 } | ||
108 | |||
109 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID | ||
110 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID | ||
111 | |||
112 | mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control | ||
113 | mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 | ||
114 | mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 | ||
115 | |||
116 | mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register | ||
117 | |||
118 | mov r0, #0 | ||
119 | mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB | ||
120 | |||
121 | mov r0, #0 @ restore copro access | ||
122 | mcr p15, 0, r11, c1, c0, 2 @ Co-processor access | ||
123 | mcr p15, 0, r0, c7, c5, 4 | ||
124 | |||
125 | mcr p15, 0, r12, c10, c2, 0 @ write PRRR | ||
126 | mcr p15, 0, r3, c10, c2, 1 @ write NMRR | ||
127 | |||
128 | /* | ||
129 | * In Cortex-A8, when MMU is turned on, the pipeline is flushed. | ||
130 | * And there are no valid entries in the MMU table at this point. | ||
131 | * So before turning on the MMU, the MMU entry for the DRAM address | ||
132 | * range is added. After the MMU is turned on, the other entries | ||
133 | * in the MMU table will be restored. | ||
134 | */ | ||
135 | |||
136 | /* r6 = Translation Table BASE0 */ | ||
137 | mov r4, r6 | ||
138 | mov r4, r4, LSR #14 | ||
139 | mov r4, r4, LSL #14 | ||
140 | |||
141 | /* Load address for adding to MMU table list */ | ||
142 | ldr r11, =0xE010F000 @ INFORM0 reg. | ||
143 | ldr r10, [r11, #0] | ||
144 | mov r10, r10, LSR #18 | ||
145 | bic r10, r10, #0x3 | ||
146 | orr r4, r4, r10 | ||
147 | |||
148 | /* Calculate MMU table entry */ | ||
149 | mov r10, r10, LSL #18 | ||
150 | ldr r5, =0x40E | ||
151 | orr r10, r10, r5 | ||
152 | |||
153 | /* Back up originally data */ | ||
154 | ldr r12, [r4] | ||
155 | |||
156 | /* Add calculated MMU table entry into MMU table list */ | ||
157 | str r10, [r4] | ||
158 | |||
159 | ldr r2, =resume_with_mmu | ||
160 | mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc | ||
161 | |||
162 | nop | ||
163 | nop | ||
164 | nop | ||
165 | nop | ||
166 | nop @ second-to-last before mmu | ||
167 | |||
168 | mov pc, r2 @ go back to virtual address | ||
169 | |||
170 | .ltorg | ||
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S index e73e3b6e88d2..fd7032f84ae7 100644 --- a/arch/arm/plat-s3c24xx/sleep.S +++ b/arch/arm/plat-s3c24xx/sleep.S | |||
@@ -44,23 +44,13 @@ | |||
44 | /* s3c_cpu_save | 44 | /* s3c_cpu_save |
45 | * | 45 | * |
46 | * entry: | 46 | * entry: |
47 | * r0 = save address (virtual addr of s3c_sleep_save_phys) | 47 | * r1 = v:p offset |
48 | */ | 48 | */ |
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 | 52 | ldr r3, =resume_with_mmu | |
53 | @@ store co-processor registers | 53 | bl cpu_suspend |
54 | |||
55 | mrc p15, 0, r4, c13, c0, 0 @ PID | ||
56 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID | ||
57 | mrc p15, 0, r6, c2, c0, 0 @ translation table base address | ||
58 | mrc p15, 0, r7, c1, c0, 0 @ control register | ||
59 | |||
60 | stmia r0, { r4 - r13 } | ||
61 | |||
62 | @@ write our state back to RAM | ||
63 | bl s3c_pm_cb_flushcache | ||
64 | 54 | ||
65 | @@ jump to final code to send system to sleep | 55 | @@ jump to final code to send system to sleep |
66 | ldr r0, =pm_cpu_sleep | 56 | ldr r0, =pm_cpu_sleep |
@@ -76,20 +66,6 @@ resume_with_mmu: | |||
76 | 66 | ||
77 | .ltorg | 67 | .ltorg |
78 | 68 | ||
79 | @@ the next bits sit in the .data segment, even though they | ||
80 | @@ happen to be code... the s3c_sleep_save_phys needs to be | ||
81 | @@ accessed by the resume code before it can restore the MMU. | ||
82 | @@ This means that the variable has to be close enough for the | ||
83 | @@ code to read it... since the .text segment needs to be RO, | ||
84 | @@ the data segment can be the only place to put this code. | ||
85 | |||
86 | .data | ||
87 | |||
88 | .global s3c_sleep_save_phys | ||
89 | s3c_sleep_save_phys: | ||
90 | .word 0 | ||
91 | |||
92 | |||
93 | /* sleep magic, to allow the bootloader to check for an valid | 69 | /* sleep magic, to allow the bootloader to check for an valid |
94 | * image to resume to. Must be the first word before the | 70 | * image to resume to. Must be the first word before the |
95 | * s3c_cpu_resume entry. | 71 | * s3c_cpu_resume entry. |
@@ -100,10 +76,6 @@ s3c_sleep_save_phys: | |||
100 | /* s3c_cpu_resume | 76 | /* s3c_cpu_resume |
101 | * | 77 | * |
102 | * resume code entry for bootloader to call | 78 | * resume code entry for bootloader to call |
103 | * | ||
104 | * we must put this code here in the data segment as we have no | ||
105 | * other way of restoring the stack pointer after sleep, and we | ||
106 | * must not write to the code segment (code is read-only) | ||
107 | */ | 79 | */ |
108 | 80 | ||
109 | ENTRY(s3c_cpu_resume) | 81 | ENTRY(s3c_cpu_resume) |
@@ -134,25 +106,4 @@ ENTRY(s3c_cpu_resume) | |||
134 | beq 1001b | 106 | beq 1001b |
135 | #endif /* CONFIG_DEBUG_RESUME */ | 107 | #endif /* CONFIG_DEBUG_RESUME */ |
136 | 108 | ||
137 | mov r1, #0 | 109 | b cpu_resume |
138 | mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs | ||
139 | mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches | ||
140 | |||
141 | ldr r0, s3c_sleep_save_phys @ address of restore block | ||
142 | ldmia r0, { r4 - r13 } | ||
143 | |||
144 | mcr p15, 0, r4, c13, c0, 0 @ PID | ||
145 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID | ||
146 | mcr p15, 0, r6, c2, c0, 0 @ translation table base | ||
147 | |||
148 | #ifdef CONFIG_DEBUG_RESUME | ||
149 | mov r3, #'R' | ||
150 | strb r3, [ r2, #S3C2410_UTXH ] | ||
151 | #endif | ||
152 | |||
153 | ldr r2, =resume_with_mmu | ||
154 | mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, etc | ||
155 | nop @ second-to-last before mmu | ||
156 | mov pc, r2 @ go back to virtual address | ||
157 | |||
158 | .ltorg | ||
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index d9025e377675..4aa697dfe13f 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h | |||
@@ -50,13 +50,11 @@ extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */ | |||
50 | 50 | ||
51 | /* from sleep.S */ | 51 | /* from sleep.S */ |
52 | 52 | ||
53 | extern int s3c_cpu_save(unsigned long *saveblk); | 53 | extern int s3c_cpu_save(unsigned long *saveblk, long); |
54 | extern void s3c_cpu_resume(void); | 54 | extern void s3c_cpu_resume(void); |
55 | 55 | ||
56 | extern void s3c2410_cpu_suspend(void); | 56 | extern void s3c2410_cpu_suspend(void); |
57 | 57 | ||
58 | extern unsigned long s3c_sleep_save_phys; | ||
59 | |||
60 | /* sleep save info */ | 58 | /* sleep save info */ |
61 | 59 | ||
62 | /** | 60 | /** |
@@ -179,13 +177,5 @@ extern void s3c_pm_restore_gpios(void); | |||
179 | */ | 177 | */ |
180 | extern void s3c_pm_save_gpios(void); | 178 | extern void s3c_pm_save_gpios(void); |
181 | 179 | ||
182 | /** | ||
183 | * s3c_pm_cb_flushcache - callback for assembly code | ||
184 | * | ||
185 | * Callback to issue flush_cache_all() as this call is | ||
186 | * not a directly callable object. | ||
187 | */ | ||
188 | extern void s3c_pm_cb_flushcache(void); | ||
189 | |||
190 | extern void s3c_pm_save_core(void); | 180 | extern void s3c_pm_save_core(void); |
191 | extern void s3c_pm_restore_core(void); | 181 | extern void s3c_pm_restore_core(void); |
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c index 02d531fb3f81..d5b58d31903c 100644 --- a/arch/arm/plat-samsung/pm.c +++ b/arch/arm/plat-samsung/pm.c | |||
@@ -241,8 +241,6 @@ void (*pm_cpu_sleep)(void); | |||
241 | 241 | ||
242 | static int s3c_pm_enter(suspend_state_t state) | 242 | static int s3c_pm_enter(suspend_state_t state) |
243 | { | 243 | { |
244 | static unsigned long regs_save[16]; | ||
245 | |||
246 | /* ensure the debug is initialised (if enabled) */ | 244 | /* ensure the debug is initialised (if enabled) */ |
247 | 245 | ||
248 | s3c_pm_debug_init(); | 246 | s3c_pm_debug_init(); |
@@ -266,12 +264,6 @@ static int s3c_pm_enter(suspend_state_t state) | |||
266 | return -EINVAL; | 264 | return -EINVAL; |
267 | } | 265 | } |
268 | 266 | ||
269 | /* store the physical address of the register recovery block */ | ||
270 | |||
271 | s3c_sleep_save_phys = virt_to_phys(regs_save); | ||
272 | |||
273 | S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); | ||
274 | |||
275 | /* save all necessary core registers not covered by the drivers */ | 267 | /* save all necessary core registers not covered by the drivers */ |
276 | 268 | ||
277 | s3c_pm_save_gpios(); | 269 | s3c_pm_save_gpios(); |
@@ -305,7 +297,7 @@ static int s3c_pm_enter(suspend_state_t state) | |||
305 | * we resume as it saves its own register state and restores it | 297 | * we resume as it saves its own register state and restores it |
306 | * during the resume. */ | 298 | * during the resume. */ |
307 | 299 | ||
308 | s3c_cpu_save(regs_save); | 300 | s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET); |
309 | 301 | ||
310 | /* restore the cpu state using the kernel's cpu init code. */ | 302 | /* restore the cpu state using the kernel's cpu init code. */ |
311 | 303 | ||
@@ -336,12 +328,6 @@ static int s3c_pm_enter(suspend_state_t state) | |||
336 | return 0; | 328 | return 0; |
337 | } | 329 | } |
338 | 330 | ||
339 | /* callback from assembly code */ | ||
340 | void s3c_pm_cb_flushcache(void) | ||
341 | { | ||
342 | flush_cache_all(); | ||
343 | } | ||
344 | |||
345 | static int s3c_pm_prepare(void) | 331 | static int s3c_pm_prepare(void) |
346 | { | 332 | { |
347 | /* prepare check area if configured */ | 333 | /* prepare check area if configured */ |