Loading...
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 |