2 * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
4 * Sleep mode and Standby modes support for SuperH Mobile
6 * Copyright (C) 2009 Magnus Damm
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
13 #include <linux/sys.h>
14 #include <linux/errno.h>
15 #include <linux/linkage.h>
16 #include <asm/asm-offsets.h>
17 #include <asm/suspend.h>
20 * Kernel mode register usage, see entry.S:
27 /* manage self-refresh and enter standby mode. must be self-contained.
28 * this code will be copied to on-chip memory and executed from there.
31 ENTRY(sh_mobile_sleep_enter_start)
34 mov.l r4, @(SH_SLEEP_MODE, r5)
36 /* save original vbr */
38 mov.l r0, @(SH_SLEEP_VBR, r5)
40 /* point vbr to our on-chip memory page */
43 /* save return address */
45 mov.l r0, @(SH_SLEEP_SPC, r5)
49 mov.l r0, @(SH_SLEEP_SR, r5)
51 /* save general purpose registers to stack if needed */
52 mov.l @(SH_SLEEP_MODE, r5), r0
65 /* make sure bank0 is selected, save low registers */
74 /* switch to bank 1, save low registers */
82 /* switch back to bank 0 */
90 /* save sp, also set to internal ram */
91 mov.l r15, @(SH_SLEEP_SP, r5)
96 mov #SH_SLEEP_REG_STBCR, r0
98 /* save mmu and cache context if needed */
99 mov.l @(SH_SLEEP_MODE, r5), r0
101 bt skip_mmu_save_disable
105 mov #SH_SLEEP_REG_PTEH, r0
108 mov #SH_SLEEP_REG_PTEL, r0
111 mov #SH_SLEEP_REG_TTB, r0
114 mov #SH_SLEEP_REG_TEA, r0
117 mov #SH_SLEEP_REG_MMUCR, r0
120 mov #SH_SLEEP_REG_PTEA, r0
123 mov #SH_SLEEP_REG_PASCR, r0
126 mov #SH_SLEEP_REG_IRMCR, r0
128 /* invalidate TLBs and disable the MMU */
130 mov #SH_SLEEP_REG_MMUCR, r0
135 /* save cache registers and disable caches */
137 mov #SH_SLEEP_REG_CCR, r0
140 mov #SH_SLEEP_REG_RAMCR, r0
143 mov #SH_SLEEP_REG_CCR, r0
148 skip_mmu_save_disable:
149 /* call self-refresh entering code if needed */
150 mov.l @(SH_SLEEP_MODE, r5), r0
154 mov.l @(SH_SLEEP_SF_PRE, r5), r0
159 mov.l @(SH_SLEEP_MODE, r5), r0
160 tst #SUSP_SH_STANDBY, r0
163 /* set mode to "software standby mode" */
168 tst #SUSP_SH_RSTANDBY, r0
171 /* setup BAR register */
173 mov #SH_SLEEP_REG_BAR, r0
174 mov.l @(SH_SLEEP_RESUME, r5), r1
177 /* set mode to "r-standby mode" */
182 tst #SUSP_SH_USTANDBY, r0
185 /* set mode to "u-standby mode" */
191 /* set mode to "sleep mode" */
195 /* setup and enter selected standby mode */
197 mov #SH_SLEEP_REG_STBCR, r0
205 add #SH_SLEEP_BASE_ADDR, r0
207 add #-SH_SLEEP_BASE_ADDR, r0
209 add #SH_SLEEP_BASE_DATA, r0
211 add #-SH_SLEEP_BASE_DATA, r0
216 add #SH_SLEEP_BASE_ADDR, r0
241 rb_bit: .long 0x20000000 ! RB=1
243 ENTRY(sh_mobile_sleep_enter_end)
246 ENTRY(sh_mobile_sleep_resume_start)
248 /* figure out start address */
256 /* store pointer to data area in VBR */
259 /* setup sr with saved sr */
260 mov.l @(SH_SLEEP_SR, k1), k0
263 /* now: user register set! */
266 /* setup spc with return address to c code */
267 mov.l @(SH_SLEEP_SPC, r5), r0
271 mov.l @(SH_SLEEP_VBR, r5), r0
274 /* setup ssr with saved sr */
275 mov.l @(SH_SLEEP_SR, r5), r0
279 mov.l @(SH_SLEEP_SP, r5), r15
281 /* restore sleep mode register */
283 mov #SH_SLEEP_REG_STBCR, r0
285 /* call self-refresh resume code if needed */
286 mov.l @(SH_SLEEP_MODE, r5), r0
290 mov.l @(SH_SLEEP_SF_POST, r5), r0
295 /* restore mmu and cache state if needed */
296 mov.l @(SH_SLEEP_MODE, r5), r0
300 /* restore mmu state */
302 mov #SH_SLEEP_REG_PTEH, r0
305 mov #SH_SLEEP_REG_PTEL, r0
308 mov #SH_SLEEP_REG_TTB, r0
311 mov #SH_SLEEP_REG_TEA, r0
314 mov #SH_SLEEP_REG_PTEA, r0
317 mov #SH_SLEEP_REG_PASCR, r0
320 mov #SH_SLEEP_REG_IRMCR, r0
323 mov #SH_SLEEP_REG_MMUCR, r0
326 /* restore cache settings */
328 mov #SH_SLEEP_REG_RAMCR, r0
332 mov #SH_SLEEP_REG_CCR, r0
337 /* restore general purpose registers if needed */
338 mov.l @(SH_SLEEP_MODE, r5), r0
339 tst #SUSP_SH_REGS, r0
342 /* switch to bank 1, restore low registers */
350 /* switch to bank0, restore low registers */
359 /* restore the rest of the registers */
374 add #SH_SLEEP_BASE_DATA, r0
376 add #-SH_SLEEP_BASE_DATA, r0
377 add #SH_SLEEP_BASE_ADDR, r0
403 _rb_bit: .long 0x20000000 ! RB=1
405 ENTRY(sh_mobile_sleep_resume_end)