diff options
Diffstat (limited to 'arch/sh/kernel/cpu/shmobile/sleep.S')
-rw-r--r-- | arch/sh/kernel/cpu/shmobile/sleep.S | 244 |
1 files changed, 91 insertions, 153 deletions
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S index a439e6c7824f..d3221d9b88be 100644 --- a/arch/sh/kernel/cpu/shmobile/sleep.S +++ b/arch/sh/kernel/cpu/shmobile/sleep.S | |||
@@ -20,79 +20,49 @@ | |||
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 stbcr */ |
55 | mova saved_mode, r0 | 52 | bsr save_register |
56 | mov.l r4, @r0 | 53 | mov #SH_SLEEP_REG_STBCR, r0 |
57 | |||
58 | /* put mode flags in r0 */ | ||
59 | mov r4, r0 | ||
60 | 54 | ||
55 | /* call self-refresh entering code if needed */ | ||
56 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
61 | tst #SUSP_SH_SF, r0 | 57 | tst #SUSP_SH_SF, r0 |
62 | bt skip_set_sf | 58 | bt skip_set_sf |
63 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 59 | |
64 | /* DBSC: put memory in self-refresh mode */ | 60 | mov.l @(SH_SLEEP_SF_PRE, r5), r0 |
65 | mov.l dben_reg, r4 | 61 | jsr @r0 |
66 | mov.l dben_data0, r1 | 62 | 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 | 63 | ||
95 | skip_set_sf: | 64 | skip_set_sf: |
65 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
96 | tst #SUSP_SH_STANDBY, r0 | 66 | tst #SUSP_SH_STANDBY, r0 |
97 | bt test_rstandby | 67 | bt test_rstandby |
98 | 68 | ||
@@ -123,124 +93,92 @@ force_sleep: | |||
123 | 93 | ||
124 | do_sleep: | 94 | do_sleep: |
125 | /* setup and enter selected standby mode */ | 95 | /* setup and enter selected standby mode */ |
126 | mov.l 5f, r4 | 96 | bsr get_register |
127 | mov.l r1, @r4 | 97 | mov #SH_SLEEP_REG_STBCR, r0 |
98 | mov.l r1, @r0 | ||
128 | again: | 99 | again: |
129 | sleep | 100 | sleep |
130 | bra again | 101 | bra again |
131 | nop | 102 | nop |
132 | 103 | ||
133 | restore_jump_vbr: | 104 | save_register: |
105 | add #SH_SLEEP_BASE_ADDR, r0 | ||
106 | mov.l @(r0, r5), r1 | ||
107 | add #-SH_SLEEP_BASE_ADDR, r0 | ||
108 | mov.l @r1, r1 | ||
109 | add #SH_SLEEP_BASE_DATA, r0 | ||
110 | mov.l r1, @(r0, r5) | ||
111 | add #-SH_SLEEP_BASE_DATA, r0 | ||
112 | rts | ||
113 | nop | ||
114 | |||
115 | get_register: | ||
116 | add #SH_SLEEP_BASE_ADDR, r0 | ||
117 | mov.l @(r0, r5), r0 | ||
118 | rts | ||
119 | nop | ||
120 | ENTRY(sh_mobile_sleep_enter_end) | ||
121 | |||
122 | .balign 4 | ||
123 | ENTRY(sh_mobile_sleep_resume_start) | ||
124 | |||
125 | /* figure out start address */ | ||
126 | bsr 0f | ||
127 | nop | ||
128 | 0: | ||
129 | sts pr, k1 | ||
130 | mov.l 1f, k0 | ||
131 | and k0, k1 | ||
132 | |||
133 | /* store pointer to data area in VBR */ | ||
134 | ldc k1, vbr | ||
135 | |||
136 | /* setup sr with saved sr */ | ||
137 | mov.l @(SH_SLEEP_SR, k1), k0 | ||
138 | ldc k0, sr | ||
139 | |||
140 | /* now: user register set! */ | ||
141 | stc vbr, r5 | ||
142 | |||
134 | /* setup spc with return address to c code */ | 143 | /* setup spc with return address to c code */ |
135 | mov.l saved_spc, k0 | 144 | mov.l @(SH_SLEEP_SPC, r5), r0 |
136 | ldc k0, spc | 145 | ldc r0, spc |
137 | 146 | ||
138 | /* restore vbr */ | 147 | /* restore vbr */ |
139 | mov.l saved_vbr, k0 | 148 | mov.l @(SH_SLEEP_VBR, r5), r0 |
140 | ldc k0, vbr | 149 | ldc r0, vbr |
141 | 150 | ||
142 | /* setup ssr with saved sr */ | 151 | /* setup ssr with saved sr */ |
143 | mov.l saved_sr, k0 | 152 | mov.l @(SH_SLEEP_SR, r5), r0 |
144 | ldc k0, ssr | 153 | ldc r0, ssr |
145 | |||
146 | /* get mode flags */ | ||
147 | mov.l saved_mode, k0 | ||
148 | 154 | ||
149 | done_sleep: | 155 | /* restore sleep mode register */ |
150 | /* reset standby mode to sleep mode */ | 156 | bsr restore_register |
151 | mov.l 5f, k4 | 157 | mov #SH_SLEEP_REG_STBCR, r0 |
152 | mov #0x00, k1 | ||
153 | mov.l k1, @k4 | ||
154 | 158 | ||
155 | tst #SUSP_SH_SF, k0 | 159 | /* call self-refresh resume code if needed */ |
160 | mov.l @(SH_SLEEP_MODE, r5), r0 | ||
161 | tst #SUSP_SH_SF, r0 | ||
156 | bt skip_restore_sf | 162 | bt skip_restore_sf |
157 | 163 | ||
158 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 164 | mov.l @(SH_SLEEP_SF_POST, r5), r0 |
159 | /* DBSC: put memory in auto-refresh mode */ | 165 | jsr @r0 |
160 | mov.l dbrfpdn0_reg, k4 | 166 | nop |
161 | mov.l dbrfpdn0_data0, k1 | 167 | |
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: | 168 | skip_restore_sf: |
201 | /* jump to vbr vector */ | 169 | rte |
202 | mov.l saved_vbr, k0 | ||
203 | mov.l offset_vbr, k4 | ||
204 | add k4, k0 | ||
205 | jmp @k0 | ||
206 | nop | 170 | nop |
207 | 171 | ||
208 | .balign 4 | 172 | restore_register: |
209 | saved_mode: .long 0 | 173 | add #SH_SLEEP_BASE_DATA, r0 |
210 | saved_spc: .long 0 | 174 | mov.l @(r0, r5), r1 |
211 | saved_sr: .long 0 | 175 | add #-SH_SLEEP_BASE_DATA, r0 |
212 | saved_vbr: .long 0 | 176 | add #SH_SLEEP_BASE_ADDR, r0 |
213 | offset_vbr: .long 0x600 | 177 | mov.l @(r0, r5), r0 |
214 | #ifdef CONFIG_CPU_SUBTYPE_SH7724 | 178 | mov.l r1, @r0 |
215 | dben_reg: .long 0xfd000010 /* DBEN */ | 179 | 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 | 180 | nop |
243 | sh_mobile_standby_end: | ||
244 | 181 | ||
245 | ENTRY(sh_mobile_standby_size) | 182 | .balign 4 |
246 | .long sh_mobile_standby_end - sh_mobile_standby | 183 | 1: .long ~0x7ff |
184 | ENTRY(sh_mobile_sleep_resume_end) | ||