1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/* 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
|