| /* | |
| * arch/sh/kernel/cpu/sh3/swsusp.S | |
| * | |
| * Copyright (C) 2009 Magnus Damm | |
| * | |
| * This file is subject to the terms and conditions of the GNU General Public | |
| * License. See the file "COPYING" in the main directory of this archive | |
| * for more details. | |
| */ | |
| #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 |