1 /* SPDX-License-Identifier: GPL-2.0
3 * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
5 * Sleep mode and Standby modes support for SuperH Mobile
7 * Copyright (C) 2009 Magnus Damm
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:
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.
28 ENTRY(sh_mobile_sleep_enter_start)
31 mov.l r4, @(SH_SLEEP_MODE, r5)
33 /* save original vbr */
35 mov.l r0, @(SH_SLEEP_VBR, r5)
37 /* point vbr to our on-chip memory page */
40 /* save return address */
42 mov.l r0, @(SH_SLEEP_SPC, r5)
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
62 /* make sure bank0 is selected, save low registers */
71 /* switch to bank 1, save low registers */
79 /* switch back to bank 0 */
87 /* save sp, also set to internal ram */
88 mov.l r15, @(SH_SLEEP_SP, r5)
93 mov #SH_SLEEP_REG_STBCR, r0
95 /* save mmu and cache context if needed */
96 mov.l @(SH_SLEEP_MODE, r5), r0
98 bt skip_mmu_save_disable
102 mov #SH_SLEEP_REG_PTEH, r0
105 mov #SH_SLEEP_REG_PTEL, r0
108 mov #SH_SLEEP_REG_TTB, r0
111 mov #SH_SLEEP_REG_TEA, r0
114 mov #SH_SLEEP_REG_MMUCR, r0
117 mov #SH_SLEEP_REG_PTEA, r0
120 mov #SH_SLEEP_REG_PASCR, r0
123 mov #SH_SLEEP_REG_IRMCR, r0
125 /* invalidate TLBs and disable the MMU */
127 mov #SH_SLEEP_REG_MMUCR, r0
132 /* save cache registers and disable caches */
134 mov #SH_SLEEP_REG_CCR, r0
137 mov #SH_SLEEP_REG_RAMCR, r0
140 mov #SH_SLEEP_REG_CCR, r0
145 skip_mmu_save_disable:
146 /* call self-refresh entering code if needed */
147 mov.l @(SH_SLEEP_MODE, r5), r0
151 mov.l @(SH_SLEEP_SF_PRE, r5), r0
156 mov.l @(SH_SLEEP_MODE, r5), r0
157 tst #SUSP_SH_STANDBY, r0
160 /* set mode to "software standby mode" */
165 tst #SUSP_SH_RSTANDBY, r0
168 /* setup BAR register */
170 mov #SH_SLEEP_REG_BAR, r0
171 mov.l @(SH_SLEEP_RESUME, r5), r1
174 /* set mode to "r-standby mode" */
179 tst #SUSP_SH_USTANDBY, r0
182 /* set mode to "u-standby mode" */
188 /* set mode to "sleep mode" */
192 /* setup and enter selected standby mode */
194 mov #SH_SLEEP_REG_STBCR, r0
202 add #SH_SLEEP_BASE_ADDR, r0
204 add #-SH_SLEEP_BASE_ADDR, r0
206 add #SH_SLEEP_BASE_DATA, r0
208 add #-SH_SLEEP_BASE_DATA, r0
213 add #SH_SLEEP_BASE_ADDR, r0
238 rb_bit: .long 0x20000000 ! RB=1
240 ENTRY(sh_mobile_sleep_enter_end)
243 ENTRY(sh_mobile_sleep_resume_start)
245 /* figure out start address */
253 /* store pointer to data area in VBR */
256 /* setup sr with saved sr */
257 mov.l @(SH_SLEEP_SR, k1), k0
260 /* now: user register set! */
263 /* setup spc with return address to c code */
264 mov.l @(SH_SLEEP_SPC, r5), r0
268 mov.l @(SH_SLEEP_VBR, r5), r0
271 /* setup ssr with saved sr */
272 mov.l @(SH_SLEEP_SR, r5), r0
276 mov.l @(SH_SLEEP_SP, r5), r15
278 /* restore sleep mode register */
280 mov #SH_SLEEP_REG_STBCR, r0
282 /* call self-refresh resume code if needed */
283 mov.l @(SH_SLEEP_MODE, r5), r0
287 mov.l @(SH_SLEEP_SF_POST, r5), r0
292 /* restore mmu and cache state if needed */
293 mov.l @(SH_SLEEP_MODE, r5), r0
297 /* restore mmu state */
299 mov #SH_SLEEP_REG_PTEH, r0
302 mov #SH_SLEEP_REG_PTEL, r0
305 mov #SH_SLEEP_REG_TTB, r0
308 mov #SH_SLEEP_REG_TEA, r0
311 mov #SH_SLEEP_REG_PTEA, r0
314 mov #SH_SLEEP_REG_PASCR, r0
317 mov #SH_SLEEP_REG_IRMCR, r0
320 mov #SH_SLEEP_REG_MMUCR, r0
323 /* restore cache settings */
325 mov #SH_SLEEP_REG_RAMCR, r0
329 mov #SH_SLEEP_REG_CCR, r0
334 /* restore general purpose registers if needed */
335 mov.l @(SH_SLEEP_MODE, r5), r0
336 tst #SUSP_SH_REGS, r0
339 /* switch to bank 1, restore low registers */
347 /* switch to bank0, restore low registers */
356 /* restore the rest of the registers */
371 add #SH_SLEEP_BASE_DATA, r0
373 add #-SH_SLEEP_BASE_DATA, r0
374 add #SH_SLEEP_BASE_ADDR, r0
400 _rb_bit: .long 0x20000000 ! RB=1
402 ENTRY(sh_mobile_sleep_resume_end)