Merge tag 'sched-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel...
[linux/fpc-iii.git] / arch / sh / kernel / cpu / shmobile / sleep.S
blobf928c03151296cdf58b3b89e0c63aaadfc913179
1 /* SPDX-License-Identifier: GPL-2.0
2  *
3  * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
4  *
5  * Sleep mode and Standby modes support for SuperH Mobile
6  *
7  *  Copyright (C) 2009 Magnus Damm
8  */
10 #include <linux/sys.h>
11 #include <linux/errno.h>
12 #include <linux/linkage.h>
13 #include <asm/asm-offsets.h>
14 #include <asm/suspend.h>
17  * Kernel mode register usage, see entry.S:
18  *      k0      scratch
19  *      k1      scratch
20  */
21 #define k0      r0
22 #define k1      r1
24 /* manage self-refresh and enter standby mode. must be self-contained.
25  * this code will be copied to on-chip memory and executed from there.
26  */
27         .balign 4
28 ENTRY(sh_mobile_sleep_enter_start)
30         /* save mode flags */
31         mov.l   r4, @(SH_SLEEP_MODE, r5)
33         /* save original vbr */
34         stc     vbr, r0
35         mov.l   r0, @(SH_SLEEP_VBR, r5)
37         /* point vbr to our on-chip memory page */
38         ldc     r5, vbr
40         /* save return address */
41         sts     pr, r0
42         mov.l   r0, @(SH_SLEEP_SPC, r5)
44         /* save sr */
45         stc     sr, r0
46         mov.l   r0, @(SH_SLEEP_SR, r5)
48         /* save general purpose registers to stack if needed */
49         mov.l   @(SH_SLEEP_MODE, r5), r0
50         tst     #SUSP_SH_REGS, r0
51         bt      skip_regs_save
53         sts.l   pr, @-r15
54         mov.l   r14, @-r15
55         mov.l   r13, @-r15
56         mov.l   r12, @-r15
57         mov.l   r11, @-r15
58         mov.l   r10, @-r15
59         mov.l   r9, @-r15
60         mov.l   r8, @-r15
62         /* make sure bank0 is selected, save low registers */
63         mov.l   rb_bit, r9
64         not     r9, r9
65         bsr     set_sr
66          mov    #0, r10
68         bsr     save_low_regs
69          nop
71         /* switch to bank 1, save low registers */
72         mov.l   rb_bit, r10
73         bsr     set_sr
74          mov    #-1, r9
76         bsr     save_low_regs
77          nop
79         /* switch back to bank 0 */
80         mov.l   rb_bit, r9
81         not     r9, r9
82         bsr     set_sr
83          mov    #0, r10
85 skip_regs_save:
87         /* save sp, also set to internal ram */
88         mov.l   r15, @(SH_SLEEP_SP, r5)
89         mov     r5, r15
91         /* save stbcr */
92         bsr     save_register
93          mov    #SH_SLEEP_REG_STBCR, r0
95         /* save mmu and cache context if needed */
96         mov.l   @(SH_SLEEP_MODE, r5), r0
97         tst     #SUSP_SH_MMU, r0
98         bt      skip_mmu_save_disable
100         /* save mmu state */
101         bsr     save_register
102          mov    #SH_SLEEP_REG_PTEH, r0
104         bsr     save_register
105          mov    #SH_SLEEP_REG_PTEL, r0
107         bsr     save_register
108          mov    #SH_SLEEP_REG_TTB, r0
110         bsr     save_register
111          mov    #SH_SLEEP_REG_TEA, r0
113         bsr     save_register
114          mov    #SH_SLEEP_REG_MMUCR, r0
116         bsr     save_register
117          mov    #SH_SLEEP_REG_PTEA, r0
119         bsr     save_register
120          mov    #SH_SLEEP_REG_PASCR, r0
122         bsr     save_register
123          mov    #SH_SLEEP_REG_IRMCR, r0
125         /* invalidate TLBs and disable the MMU */
126         bsr     get_register
127          mov    #SH_SLEEP_REG_MMUCR, r0
128         mov     #4, r1
129         mov.l   r1, @r0
130         icbi    @r0
132         /* save cache registers and disable caches */
133         bsr     save_register
134          mov    #SH_SLEEP_REG_CCR, r0
136         bsr     save_register
137          mov    #SH_SLEEP_REG_RAMCR, r0
139         bsr     get_register
140          mov    #SH_SLEEP_REG_CCR, r0
141         mov     #0, r1
142         mov.l   r1, @r0
143         icbi    @r0
145 skip_mmu_save_disable:
146         /* call self-refresh entering code if needed */
147         mov.l   @(SH_SLEEP_MODE, r5), r0
148         tst     #SUSP_SH_SF, r0
149         bt      skip_set_sf
151         mov.l   @(SH_SLEEP_SF_PRE, r5), r0
152         jsr     @r0
153          nop
155 skip_set_sf:
156         mov.l   @(SH_SLEEP_MODE, r5), r0
157         tst     #SUSP_SH_STANDBY, r0
158         bt      test_rstandby
160         /* set mode to "software standby mode" */
161         bra     do_sleep
162          mov    #0x80, r1
164 test_rstandby:
165         tst     #SUSP_SH_RSTANDBY, r0
166         bt      test_ustandby
168         /* setup BAR register */
169         bsr     get_register
170          mov    #SH_SLEEP_REG_BAR, r0
171         mov.l   @(SH_SLEEP_RESUME, r5), r1
172         mov.l   r1, @r0
174         /* set mode to "r-standby mode" */
175         bra     do_sleep
176          mov    #0x20, r1
178 test_ustandby:
179         tst     #SUSP_SH_USTANDBY, r0
180         bt      force_sleep
182         /* set mode to "u-standby mode" */
183         bra     do_sleep
184          mov    #0x10, r1
186 force_sleep:
188         /* set mode to "sleep mode" */
189         mov     #0x00, r1
191 do_sleep:
192         /* setup and enter selected standby mode */
193         bsr     get_register
194          mov    #SH_SLEEP_REG_STBCR, r0
195         mov.l   r1, @r0
196 again:
197         sleep
198         bra     again
199          nop
201 save_register:
202         add     #SH_SLEEP_BASE_ADDR, r0
203         mov.l   @(r0, r5), r1
204         add     #-SH_SLEEP_BASE_ADDR, r0
205         mov.l   @r1, r1
206         add     #SH_SLEEP_BASE_DATA, r0
207         mov.l   r1, @(r0, r5)
208         add     #-SH_SLEEP_BASE_DATA, r0
209         rts
210          nop
212 get_register:
213         add     #SH_SLEEP_BASE_ADDR, r0
214         mov.l   @(r0, r5), r0
215         rts
216          nop
218 set_sr:
219         stc     sr, r8
220         and     r9, r8
221         or      r10, r8
222         ldc     r8, sr
223         rts
224          nop
226 save_low_regs:
227         mov.l   r7, @-r15
228         mov.l   r6, @-r15
229         mov.l   r5, @-r15
230         mov.l   r4, @-r15
231         mov.l   r3, @-r15
232         mov.l   r2, @-r15
233         mov.l   r1, @-r15
234         rts
235          mov.l  r0, @-r15
237         .balign 4
238 rb_bit: .long   0x20000000 ! RB=1
240 ENTRY(sh_mobile_sleep_enter_end)
242         .balign 4
243 ENTRY(sh_mobile_sleep_resume_start)
245         /* figure out start address */
246         bsr     0f
247          nop
249         sts     pr, k1
250         mov.l   1f, k0
251         and     k0, k1
253         /* store pointer to data area in VBR */
254         ldc     k1, vbr
256         /* setup sr with saved sr */
257         mov.l   @(SH_SLEEP_SR, k1), k0
258         ldc     k0, sr
260         /* now: user register set! */
261         stc     vbr, r5
263         /* setup spc with return address to c code */
264         mov.l   @(SH_SLEEP_SPC, r5), r0
265         ldc     r0, spc
267         /* restore vbr */
268         mov.l   @(SH_SLEEP_VBR, r5), r0
269         ldc     r0, vbr
271         /* setup ssr with saved sr */
272         mov.l   @(SH_SLEEP_SR, r5), r0
273         ldc     r0, ssr
275         /* restore sp */
276         mov.l   @(SH_SLEEP_SP, r5), r15
278         /* restore sleep mode register */
279         bsr     restore_register
280          mov    #SH_SLEEP_REG_STBCR, r0
282         /* call self-refresh resume code if needed */
283         mov.l   @(SH_SLEEP_MODE, r5), r0
284         tst     #SUSP_SH_SF, r0
285         bt      skip_restore_sf
287         mov.l   @(SH_SLEEP_SF_POST, r5), r0
288         jsr     @r0
289          nop
291 skip_restore_sf:
292         /* restore mmu and cache state if needed */
293         mov.l   @(SH_SLEEP_MODE, r5), r0
294         tst     #SUSP_SH_MMU, r0
295         bt      skip_restore_mmu
297         /* restore mmu state */
298         bsr     restore_register
299          mov    #SH_SLEEP_REG_PTEH, r0
301         bsr     restore_register
302          mov    #SH_SLEEP_REG_PTEL, r0
304         bsr     restore_register
305          mov    #SH_SLEEP_REG_TTB, r0
307         bsr     restore_register
308          mov    #SH_SLEEP_REG_TEA, r0
310         bsr     restore_register
311          mov    #SH_SLEEP_REG_PTEA, r0
313         bsr     restore_register
314          mov    #SH_SLEEP_REG_PASCR, r0
316         bsr     restore_register
317          mov    #SH_SLEEP_REG_IRMCR, r0
319         bsr     restore_register
320          mov    #SH_SLEEP_REG_MMUCR, r0
321         icbi    @r0
323         /* restore cache settings */
324         bsr     restore_register
325          mov    #SH_SLEEP_REG_RAMCR, r0
326         icbi    @r0
328         bsr     restore_register
329          mov    #SH_SLEEP_REG_CCR, r0
330         icbi    @r0
332 skip_restore_mmu:
334         /* restore general purpose registers if needed */
335         mov.l   @(SH_SLEEP_MODE, r5), r0
336         tst     #SUSP_SH_REGS, r0
337         bt      skip_restore_regs
339         /* switch to bank 1, restore low registers */
340         mov.l   _rb_bit, r10
341         bsr     _set_sr
342          mov    #-1, r9
344         bsr     restore_low_regs
345          nop
347         /* switch to bank0, restore low registers */
348         mov.l   _rb_bit, r9
349         not     r9, r9
350         bsr     _set_sr
351          mov    #0, r10
353         bsr     restore_low_regs
354          nop
356         /* restore the rest of the registers */
357         mov.l   @r15+, r8
358         mov.l   @r15+, r9
359         mov.l   @r15+, r10
360         mov.l   @r15+, r11
361         mov.l   @r15+, r12
362         mov.l   @r15+, r13
363         mov.l   @r15+, r14
364         lds.l   @r15+, pr
366 skip_restore_regs:
367         rte
368          nop
370 restore_register:
371         add     #SH_SLEEP_BASE_DATA, r0
372         mov.l   @(r0, r5), r1
373         add     #-SH_SLEEP_BASE_DATA, r0
374         add     #SH_SLEEP_BASE_ADDR, r0
375         mov.l   @(r0, r5), r0
376         mov.l   r1, @r0
377         rts
378          nop
380 _set_sr:
381         stc     sr, r8
382         and     r9, r8
383         or      r10, r8
384         ldc     r8, sr
385         rts
386          nop
388 restore_low_regs:
389         mov.l   @r15+, r0
390         mov.l   @r15+, r1
391         mov.l   @r15+, r2
392         mov.l   @r15+, r3
393         mov.l   @r15+, r4
394         mov.l   @r15+, r5
395         mov.l   @r15+, r6
396         rts
397          mov.l  @r15+, r7
399         .balign 4
400 _rb_bit:        .long   0x20000000 ! RB=1
401 1:      .long   ~0x7ff
402 ENTRY(sh_mobile_sleep_resume_end)