diff options
Diffstat (limited to 'arch/sh/kernel/cpu/shmobile/sleep.S')
-rw-r--r-- | arch/sh/kernel/cpu/shmobile/sleep.S | 344 |
1 files changed, 193 insertions, 151 deletions
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S index a439e6c7824f..e9dd7fa0abd2 100644 --- a/arch/sh/kernel/cpu/shmobile/sleep.S +++ b/arch/sh/kernel/cpu/shmobile/sleep.S | |||
@@ -20,79 +20,103 @@ | |||
20 | * Kernel mode register usage, see entry.S: | 20 | * Kernel mode register usage, see entry.S: |
21 | * k0 scratch | 21 | * k0 scratch |
22 | * k1 scratch | 22 | * k1 scratch |
23 | * k4 scratch | ||
24 | */ | 23 | */ |
25 | #define k0 r0 | 24 | #define k0 r0 |
26 | #define k1 r1 | 25 | #define k1 r1 |
27 | #define k4 r4 | ||
28 | 26 | ||
29 | /* manage self-refresh and enter standby mode. | 27 | /* manage self-refresh and enter standby mode. must be self-contained. |
30 | * this code will be copied to on-chip memory and executed from there. | 28 | * this code will be copied to on-chip memory and executed from there. |
31 | */ | 29 | */ |
30 | .balign 4 | ||
31 | ENTRY(sh_mobile_sleep_enter_start) | ||
32 | 32 | ||
33 | .balign 4096,0,4096 | 33 | /* save mode flags */ |
34 | ENTRY(sh_mobile_standby) | 34 | mov.l r4, @(SH_SLEEP_MODE, r5) |
35 | 35 | ||
36 | /* save original vbr */ | 36 | /* save original vbr */ |
37 | stc vbr, r1 | 37 | stc vbr, r0 |
38 | mova saved_vbr, r0 | 38 | mov.l r0, @(SH_SLEEP_VBR, r5) |
39 | mov.l r1, @r0 | ||
40 | 39 | ||
41 | /* point vbr to our on-chip memory page */ | 40 | /* point vbr to our on-chip memory page */ |
42 | ldc r5, vbr | 41 | ldc r5, vbr |
43 | 42 | ||
44 | /* save return address */ | 43 | /* save return address */ |
45 | mova saved_spc, r0 | 44 | sts pr, r0 |
46 | sts pr, r5 | 45 | mov.l r0, @(SH_SLEEP_SPC, r5) |
47 | mov.l r5, @r0 | ||
48 | 46 | ||
49 | /* save sr */ | 47 | /* save sr */ |
50 | mova saved_sr, r0 | 48 | stc sr, r0 |
51 | stc sr, r5 | 49 | mov.l r0, @(SH_SLEEP_SR, r5) |
52 | mov.l r5, @r0 | ||
53 | 50 | ||
54 | /* save mode flags */ | 51 | /* save sp */ |
55 | mova saved_mode, r0 | 52 | mov.l r15, @(SH_SLEEP_SP, r5) |
56 | mov.l r4, @r0 | 53 | |
54 | /* save stbcr */ | ||
55 | bsr save_register | ||
56 | mov #SH_SLEEP_REG_STBCR, r0 | ||
57 | |||
58 | /* save mmu and cache context if needed */ | ||
59 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
60 | tst #SUSP_SH_MMU, r0 | ||
61 | bt skip_mmu_save_disable | ||
62 | |||
63 | /* save mmu state */ | ||
64 | bsr save_register | ||
65 | mov #SH_SLEEP_REG_PTEH, r0 | ||
66 | |||
67 | bsr save_register | ||
68 | mov #SH_SLEEP_REG_PTEL, r0 | ||
69 | |||
70 | bsr save_register | ||
71 | mov #SH_SLEEP_REG_TTB, r0 | ||
72 | |||
73 | bsr save_register | ||
74 | mov #SH_SLEEP_REG_TEA, r0 | ||
75 | |||
76 | bsr save_register | ||
77 | mov #SH_SLEEP_REG_MMUCR, r0 | ||
78 | |||
79 | bsr save_register | ||
80 | mov #SH_SLEEP_REG_PTEA, r0 | ||
81 | |||
82 | bsr save_register | ||
83 | mov #SH_SLEEP_REG_PASCR, r0 | ||
57 | 84 | ||
58 | /* put mode flags in r0 */ | 85 | bsr save_register |
59 | mov r4, r0 | 86 | mov #SH_SLEEP_REG_IRMCR, r0 |
60 | 87 | ||
88 | /* invalidate TLBs and disable the MMU */ | ||
89 | bsr get_register | ||
90 | mov #SH_SLEEP_REG_MMUCR, r0 | ||
91 | mov #4, r1 | ||
92 | mov.l r1, @r0 | ||
93 | icbi @r0 | ||
94 | |||
95 | /* save cache registers and disable caches */ | ||
96 | bsr save_register | ||
97 | mov #SH_SLEEP_REG_CCR, r0 | ||
98 | |||
99 | bsr save_register | ||
100 | mov #SH_SLEEP_REG_RAMCR, r0 | ||
101 | |||
102 | bsr get_register | ||
103 | mov #SH_SLEEP_REG_CCR, r0 | ||
104 | mov #0, r1 | ||
105 | mov.l r1, @r0 | ||
106 | icbi @r0 | ||
107 | |||
108 | skip_mmu_save_disable: | ||
109 | /* call self-refresh entering code if needed */ | ||
110 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
61 | tst #SUSP_SH_SF, r0 | 111 | tst #SUSP_SH_SF, r0 |
62 | bt skip_set_sf | 112 | bt skip_set_sf |
63 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 113 | |
64 | /* DBSC: put memory in self-refresh mode */ | 114 | mov.l @(SH_SLEEP_SF_PRE, r5), r0 |
65 | mov.l dben_reg, r4 | 115 | jsr @r0 |
66 | mov.l dben_data0, r1 | 116 | nop |
67 | mov.l r1, @r4 | ||
68 | |||
69 | mov.l dbrfpdn0_reg, r4 | ||
70 | mov.l dbrfpdn0_data0, r1 | ||
71 | mov.l r1, @r4 | ||
72 | |||
73 | mov.l dbcmdcnt_reg, r4 | ||
74 | mov.l dbcmdcnt_data0, r1 | ||
75 | mov.l r1, @r4 | ||
76 | |||
77 | mov.l dbcmdcnt_reg, r4 | ||
78 | mov.l dbcmdcnt_data1, r1 | ||
79 | mov.l r1, @r4 | ||
80 | |||
81 | mov.l dbrfpdn0_reg, r4 | ||
82 | mov.l dbrfpdn0_data1, r1 | ||
83 | mov.l r1, @r4 | ||
84 | #else | ||
85 | /* SBSC: disable power down and put in self-refresh mode */ | ||
86 | mov.l 1f, r4 | ||
87 | mov.l 2f, r1 | ||
88 | mov.l @r4, r2 | ||
89 | or r1, r2 | ||
90 | mov.l 3f, r3 | ||
91 | and r3, r2 | ||
92 | mov.l r2, @r4 | ||
93 | #endif | ||
94 | 117 | ||
95 | skip_set_sf: | 118 | skip_set_sf: |
119 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
96 | tst #SUSP_SH_STANDBY, r0 | 120 | tst #SUSP_SH_STANDBY, r0 |
97 | bt test_rstandby | 121 | bt test_rstandby |
98 | 122 | ||
@@ -104,6 +128,12 @@ test_rstandby: | |||
104 | tst #SUSP_SH_RSTANDBY, r0 | 128 | tst #SUSP_SH_RSTANDBY, r0 |
105 | bt test_ustandby | 129 | bt test_ustandby |
106 | 130 | ||
131 | /* setup BAR register */ | ||
132 | bsr get_register | ||
133 | mov #SH_SLEEP_REG_BAR, r0 | ||
134 | mov.l @(SH_SLEEP_RESUME, r5), r1 | ||
135 | mov.l r1, @r0 | ||
136 | |||
107 | /* set mode to "r-standby mode" */ | 137 | /* set mode to "r-standby mode" */ |
108 | bra do_sleep | 138 | bra do_sleep |
109 | mov #0x20, r1 | 139 | mov #0x20, r1 |
@@ -123,124 +153,136 @@ force_sleep: | |||
123 | 153 | ||
124 | do_sleep: | 154 | do_sleep: |
125 | /* setup and enter selected standby mode */ | 155 | /* setup and enter selected standby mode */ |
126 | mov.l 5f, r4 | 156 | bsr get_register |
127 | mov.l r1, @r4 | 157 | mov #SH_SLEEP_REG_STBCR, r0 |
158 | mov.l r1, @r0 | ||
128 | again: | 159 | again: |
129 | sleep | 160 | sleep |
130 | bra again | 161 | bra again |
131 | nop | 162 | nop |
132 | 163 | ||
133 | restore_jump_vbr: | 164 | save_register: |
165 | add #SH_SLEEP_BASE_ADDR, r0 | ||
166 | mov.l @(r0, r5), r1 | ||
167 | add #-SH_SLEEP_BASE_ADDR, r0 | ||
168 | mov.l @r1, r1 | ||
169 | add #SH_SLEEP_BASE_DATA, r0 | ||
170 | mov.l r1, @(r0, r5) | ||
171 | add #-SH_SLEEP_BASE_DATA, r0 | ||
172 | rts | ||
173 | nop | ||
174 | |||
175 | get_register: | ||
176 | add #SH_SLEEP_BASE_ADDR, r0 | ||
177 | mov.l @(r0, r5), r0 | ||
178 | rts | ||
179 | nop | ||
180 | ENTRY(sh_mobile_sleep_enter_end) | ||
181 | |||
182 | .balign 4 | ||
183 | ENTRY(sh_mobile_sleep_resume_start) | ||
184 | |||
185 | /* figure out start address */ | ||
186 | bsr 0f | ||
187 | nop | ||
188 | 0: | ||
189 | sts pr, k1 | ||
190 | mov.l 1f, k0 | ||
191 | and k0, k1 | ||
192 | |||
193 | /* store pointer to data area in VBR */ | ||
194 | ldc k1, vbr | ||
195 | |||
196 | /* setup sr with saved sr */ | ||
197 | mov.l @(SH_SLEEP_SR, k1), k0 | ||
198 | ldc k0, sr | ||
199 | |||
200 | /* now: user register set! */ | ||
201 | stc vbr, r5 | ||
202 | |||
134 | /* setup spc with return address to c code */ | 203 | /* setup spc with return address to c code */ |
135 | mov.l saved_spc, k0 | 204 | mov.l @(SH_SLEEP_SPC, r5), r0 |
136 | ldc k0, spc | 205 | ldc r0, spc |
137 | 206 | ||
138 | /* restore vbr */ | 207 | /* restore vbr */ |
139 | mov.l saved_vbr, k0 | 208 | mov.l @(SH_SLEEP_VBR, r5), r0 |
140 | ldc k0, vbr | 209 | ldc r0, vbr |
141 | 210 | ||
142 | /* setup ssr with saved sr */ | 211 | /* setup ssr with saved sr */ |
143 | mov.l saved_sr, k0 | 212 | mov.l @(SH_SLEEP_SR, r5), r0 |
144 | ldc k0, ssr | 213 | ldc r0, ssr |
145 | 214 | ||
146 | /* get mode flags */ | 215 | /* restore sp */ |
147 | mov.l saved_mode, k0 | 216 | mov.l @(SH_SLEEP_SP, r5), r15 |
148 | 217 | ||
149 | done_sleep: | 218 | /* restore sleep mode register */ |
150 | /* reset standby mode to sleep mode */ | 219 | bsr restore_register |
151 | mov.l 5f, k4 | 220 | mov #SH_SLEEP_REG_STBCR, r0 |
152 | mov #0x00, k1 | ||
153 | mov.l k1, @k4 | ||
154 | 221 | ||
155 | tst #SUSP_SH_SF, k0 | 222 | /* call self-refresh resume code if needed */ |
223 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
224 | tst #SUSP_SH_SF, r0 | ||
156 | bt skip_restore_sf | 225 | bt skip_restore_sf |
157 | 226 | ||
158 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 227 | mov.l @(SH_SLEEP_SF_POST, r5), r0 |
159 | /* DBSC: put memory in auto-refresh mode */ | 228 | jsr @r0 |
160 | mov.l dbrfpdn0_reg, k4 | 229 | nop |
161 | mov.l dbrfpdn0_data0, k1 | 230 | |
162 | mov.l k1, @k4 | ||
163 | |||
164 | nop /* sleep 140 ns */ | ||
165 | nop | ||
166 | nop | ||
167 | nop | ||
168 | |||
169 | mov.l dbcmdcnt_reg, k4 | ||
170 | mov.l dbcmdcnt_data0, k1 | ||
171 | mov.l k1, @k4 | ||
172 | |||
173 | mov.l dbcmdcnt_reg, k4 | ||
174 | mov.l dbcmdcnt_data1, k1 | ||
175 | mov.l k1, @k4 | ||
176 | |||
177 | mov.l dben_reg, k4 | ||
178 | mov.l dben_data1, k1 | ||
179 | mov.l k1, @k4 | ||
180 | |||
181 | mov.l dbrfpdn0_reg, k4 | ||
182 | mov.l dbrfpdn0_data2, k1 | ||
183 | mov.l k1, @k4 | ||
184 | #else | ||
185 | /* SBSC: set auto-refresh mode */ | ||
186 | mov.l 1f, k4 | ||
187 | mov.l @k4, k0 | ||
188 | mov.l 4f, k1 | ||
189 | and k1, k0 | ||
190 | mov.l k0, @k4 | ||
191 | mov.l 6f, k4 | ||
192 | mov.l 8f, k0 | ||
193 | mov.l @k4, k1 | ||
194 | mov #-1, k4 | ||
195 | add k4, k1 | ||
196 | or k1, k0 | ||
197 | mov.l 7f, k1 | ||
198 | mov.l k0, @k1 | ||
199 | #endif | ||
200 | skip_restore_sf: | 231 | skip_restore_sf: |
201 | /* jump to vbr vector */ | 232 | /* restore mmu and cache state if needed */ |
202 | mov.l saved_vbr, k0 | 233 | mov.l @(SH_SLEEP_MODE, r5), r0 |
203 | mov.l offset_vbr, k4 | 234 | tst #SUSP_SH_MMU, r0 |
204 | add k4, k0 | 235 | bt skip_restore_mmu |
205 | jmp @k0 | 236 | |
237 | /* restore mmu state */ | ||
238 | bsr restore_register | ||
239 | mov #SH_SLEEP_REG_PTEH, r0 | ||
240 | |||
241 | bsr restore_register | ||
242 | mov #SH_SLEEP_REG_PTEL, r0 | ||
243 | |||
244 | bsr restore_register | ||
245 | mov #SH_SLEEP_REG_TTB, r0 | ||
246 | |||
247 | bsr restore_register | ||
248 | mov #SH_SLEEP_REG_TEA, r0 | ||
249 | |||
250 | bsr restore_register | ||
251 | mov #SH_SLEEP_REG_PTEA, r0 | ||
252 | |||
253 | bsr restore_register | ||
254 | mov #SH_SLEEP_REG_PASCR, r0 | ||
255 | |||
256 | bsr restore_register | ||
257 | mov #SH_SLEEP_REG_IRMCR, r0 | ||
258 | |||
259 | bsr restore_register | ||
260 | mov #SH_SLEEP_REG_MMUCR, r0 | ||
261 | icbi @r0 | ||
262 | |||
263 | /* restore cache settings */ | ||
264 | bsr restore_register | ||
265 | mov #SH_SLEEP_REG_RAMCR, r0 | ||
266 | icbi @r0 | ||
267 | |||
268 | bsr restore_register | ||
269 | mov #SH_SLEEP_REG_CCR, r0 | ||
270 | icbi @r0 | ||
271 | |||
272 | skip_restore_mmu: | ||
273 | rte | ||
206 | nop | 274 | nop |
207 | 275 | ||
208 | .balign 4 | 276 | restore_register: |
209 | saved_mode: .long 0 | 277 | add #SH_SLEEP_BASE_DATA, r0 |
210 | saved_spc: .long 0 | 278 | mov.l @(r0, r5), r1 |
211 | saved_sr: .long 0 | 279 | add #-SH_SLEEP_BASE_DATA, r0 |
212 | saved_vbr: .long 0 | 280 | add #SH_SLEEP_BASE_ADDR, r0 |
213 | offset_vbr: .long 0x600 | 281 | mov.l @(r0, r5), r0 |
214 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 282 | mov.l r1, @r0 |
215 | dben_reg: .long 0xfd000010 /* DBEN */ | 283 | rts |
216 | dben_data0: .long 0 | ||
217 | dben_data1: .long 1 | ||
218 | dbrfpdn0_reg: .long 0xfd000040 /* DBRFPDN0 */ | ||
219 | dbrfpdn0_data0: .long 0 | ||
220 | dbrfpdn0_data1: .long 1 | ||
221 | dbrfpdn0_data2: .long 0x00010000 | ||
222 | dbcmdcnt_reg: .long 0xfd000014 /* DBCMDCNT */ | ||
223 | dbcmdcnt_data0: .long 2 | ||
224 | dbcmdcnt_data1: .long 4 | ||
225 | #else | ||
226 | 1: .long 0xfe400008 /* SDCR0 */ | ||
227 | 2: .long 0x00000400 | ||
228 | 3: .long 0xffff7fff | ||
229 | 4: .long 0xfffffbff | ||
230 | #endif | ||
231 | 5: .long 0xa4150020 /* STBCR */ | ||
232 | 6: .long 0xfe40001c /* RTCOR */ | ||
233 | 7: .long 0xfe400018 /* RTCNT */ | ||
234 | 8: .long 0xa55a0000 | ||
235 | |||
236 | |||
237 | /* interrupt vector @ 0x600 */ | ||
238 | .balign 0x400,0,0x400 | ||
239 | .long 0xdeadbeef | ||
240 | .balign 0x200,0,0x200 | ||
241 | bra restore_jump_vbr | ||
242 | nop | 284 | nop |
243 | sh_mobile_standby_end: | ||
244 | 285 | ||
245 | ENTRY(sh_mobile_standby_size) | 286 | .balign 4 |
246 | .long sh_mobile_standby_end - sh_mobile_standby | 287 | 1: .long ~0x7ff |
288 | ENTRY(sh_mobile_sleep_resume_end) | ||