/* SPDX-License-Identifier: GPL-2.0 * * arch/sh/kernel/cpu/sh3/swsusp.S * * Copyright (C) 2009 Magnus Damm */ #include <linux/sys.h> #include <linux/errno.h> #include <linux/linkage.h> #include <asm/asm-offsets.h> #include <asm/page.h> #define k0 r0 #define k1 r1 #define k2 r2 #define k3 r3 #define k4 r4 ! swsusp_arch_resume() ! - copy restore_pblist pages ! - restore registers from swsusp_arch_regs_cpu0 ENTRY(swsusp_arch_resume) mov.l 1f, r15 mov.l 2f, r4 mov.l @r4, r4 swsusp_copy_loop: mov r4, r0 cmp/eq #0, r0 bt swsusp_restore_regs mov.l @(PBE_ADDRESS, r4), r2 mov.l @(PBE_ORIG_ADDRESS, r4), r5 mov #(PAGE_SIZE >> 10), r3 shll8 r3 shlr2 r3 /* PAGE_SIZE / 16 */ swsusp_copy_page: dt r3 mov.l @r2+,r1 /* 16n+0 */ mov.l r1,@r5 add #4,r5 mov.l @r2+,r1 /* 16n+4 */ mov.l r1,@r5 add #4,r5 mov.l @r2+,r1 /* 16n+8 */ mov.l r1,@r5 add #4,r5 mov.l @r2+,r1 /* 16n+12 */ mov.l r1,@r5 bf/s swsusp_copy_page add #4,r5 bra swsusp_copy_loop mov.l @(PBE_NEXT, r4), r4 swsusp_restore_regs: ! BL=0: R7->R0 is bank0 mov.l 3f, r8 mov.l 4f, r5 jsr @r5 nop ! BL=1: R7->R0 is bank1 lds k2, pr ldc k3, ssr mov.l @r15+, r0 mov.l @r15+, r1 mov.l @r15+, r2 mov.l @r15+, r3 mov.l @r15+, r4 mov.l @r15+, r5 mov.l @r15+, r6 mov.l @r15+, r7 rte nop ! BL=0: R7->R0 is bank0 .align 2 1: .long swsusp_arch_regs_cpu0 2: .long restore_pblist 3: .long 0x20000000 ! RB=1 4: .long restore_regs ! swsusp_arch_suspend() ! - prepare pc for resume, return from function without swsusp_save on resume ! - save registers in swsusp_arch_regs_cpu0 ! - call swsusp_save write suspend image ENTRY(swsusp_arch_suspend) sts pr, r0 ! save pr in r0 mov r15, r2 ! save sp in r2 mov r8, r5 ! save r8 in r5 stc sr, r1 ldc r1, ssr ! save sr in ssr mov.l 1f, r1 ldc r1, spc ! setup pc value for resuming mov.l 5f, r15 ! use swsusp_arch_regs_cpu0 as stack mov.l 6f, r3 add r3, r15 ! save from top of structure ! BL=0: R7->R0 is bank0 mov.l 2f, r3 ! get new SR value for bank1 mov #0, r4 mov.l 7f, r1 jsr @r1 ! switch to bank1 and save bank1 r7->r0 not r4, r4 ! BL=1: R7->R0 is bank1 stc r2_bank, k0 ! fetch old sp from r2_bank0 mov.l 3f, k4 ! SR bits to clear in k4 mov.l 8f, k1 jsr @k1 ! switch to bank0 and save all regs stc r0_bank, k3 ! fetch old pr from r0_bank0 ! BL=0: R7->R0 is bank0 mov r2, r15 ! restore old sp mov r5, r8 ! restore old r8 stc ssr, r1 ldc r1, sr ! restore old sr lds r0, pr ! restore old pr mov.l 4f, r0 jmp @r0 nop swsusp_call_save: mov r2, r15 ! restore old sp mov r5, r8 ! restore old r8 lds r0, pr ! restore old pr rts mov #0, r0 .align 2 1: .long swsusp_call_save 2: .long 0x20000000 ! RB=1 3: .long 0xdfffffff ! RB=0 4: .long swsusp_save 5: .long swsusp_arch_regs_cpu0 6: .long SWSUSP_ARCH_REGS_SIZE 7: .long save_low_regs 8: .long save_regs