1/* 2 * arch/sh/kernel/cpu/sh3/swsusp.S 3 * 4 * Copyright (C) 2009 Magnus Damm 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10#include <linux/sys.h> 11#include <linux/errno.h> 12#include <linux/linkage.h> 13#include <asm/asm-offsets.h> 14#include <asm/page.h> 15 16#define k0 r0 17#define k1 r1 18#define k2 r2 19#define k3 r3 20#define k4 r4 21 22! swsusp_arch_resume() 23! - copy restore_pblist pages 24! - restore registers from swsusp_arch_regs_cpu0 25 26ENTRY(swsusp_arch_resume) 27 mov.l 1f, r15 28 mov.l 2f, r4 29 mov.l @r4, r4 30 31swsusp_copy_loop: 32 mov r4, r0 33 cmp/eq #0, r0 34 bt swsusp_restore_regs 35 36 mov.l @(PBE_ADDRESS, r4), r2 37 mov.l @(PBE_ORIG_ADDRESS, r4), r5 38 39 mov #(PAGE_SIZE >> 10), r3 40 shll8 r3 41 shlr2 r3 /* PAGE_SIZE / 16 */ 42swsusp_copy_page: 43 dt r3 44 mov.l @r2+,r1 /* 16n+0 */ 45 mov.l r1,@r5 46 add #4,r5 47 mov.l @r2+,r1 /* 16n+4 */ 48 mov.l r1,@r5 49 add #4,r5 50 mov.l @r2+,r1 /* 16n+8 */ 51 mov.l r1,@r5 52 add #4,r5 53 mov.l @r2+,r1 /* 16n+12 */ 54 mov.l r1,@r5 55 bf/s swsusp_copy_page 56 add #4,r5 57 58 bra swsusp_copy_loop 59 mov.l @(PBE_NEXT, r4), r4 60 61swsusp_restore_regs: 62 ! BL=0: R7->R0 is bank0 63 mov.l 3f, r8 64 mov.l 4f, r5 65 jsr @r5 66 nop 67 68 ! BL=1: R7->R0 is bank1 69 lds k2, pr 70 ldc k3, ssr 71 72 mov.l @r15+, r0 73 mov.l @r15+, r1 74 mov.l @r15+, r2 75 mov.l @r15+, r3 76 mov.l @r15+, r4 77 mov.l @r15+, r5 78 mov.l @r15+, r6 79 mov.l @r15+, r7 80 81 rte 82 nop 83 ! BL=0: R7->R0 is bank0 84 85 .align 2 861: .long swsusp_arch_regs_cpu0 872: .long restore_pblist 883: .long 0x20000000 ! RB=1 894: .long restore_regs 90 91! swsusp_arch_suspend() 92! - prepare pc for resume, return from function without swsusp_save on resume 93! - save registers in swsusp_arch_regs_cpu0 94! - call swsusp_save write suspend image 95 96ENTRY(swsusp_arch_suspend) 97 sts pr, r0 ! save pr in r0 98 mov r15, r2 ! save sp in r2 99 mov r8, r5 ! save r8 in r5 100 stc sr, r1 101 ldc r1, ssr ! save sr in ssr 102 mov.l 1f, r1 103 ldc r1, spc ! setup pc value for resuming 104 mov.l 5f, r15 ! use swsusp_arch_regs_cpu0 as stack 105 mov.l 6f, r3 106 add r3, r15 ! save from top of structure 107 108 ! BL=0: R7->R0 is bank0 109 mov.l 2f, r3 ! get new SR value for bank1 110 mov #0, r4 111 mov.l 7f, r1 112 jsr @r1 ! switch to bank1 and save bank1 r7->r0 113 not r4, r4 114 115 ! BL=1: R7->R0 is bank1 116 stc r2_bank, k0 ! fetch old sp from r2_bank0 117 mov.l 3f, k4 ! SR bits to clear in k4 118 mov.l 8f, k1 119 jsr @k1 ! switch to bank0 and save all regs 120 stc r0_bank, k3 ! fetch old pr from r0_bank0 121 122 ! BL=0: R7->R0 is bank0 123 mov r2, r15 ! restore old sp 124 mov r5, r8 ! restore old r8 125 stc ssr, r1 126 ldc r1, sr ! restore old sr 127 lds r0, pr ! restore old pr 128 mov.l 4f, r0 129 jmp @r0 130 nop 131 132swsusp_call_save: 133 mov r2, r15 ! restore old sp 134 mov r5, r8 ! restore old r8 135 lds r0, pr ! restore old pr 136 rts 137 mov #0, r0 138 139 .align 2 1401: .long swsusp_call_save 1412: .long 0x20000000 ! RB=1 1423: .long 0xdfffffff ! RB=0 1434: .long swsusp_save 1445: .long swsusp_arch_regs_cpu0 1456: .long SWSUSP_ARCH_REGS_SIZE 1467: .long save_low_regs 1478: .long save_regs 148