hc
2024-09-20 a36159eec6ca17402b0e146b86efaf76568dc353
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