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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
| /*
| * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
| *
| * SPDX-License-Identifier: GPL-2.0+
| */
|
| #include <asm/arm32_macros.S>
| #include <asm/macro.h>
| #include <asm-offsets.h>
| #include <asm/psci.h>
| #include <config.h>
| #include <linux/linkage.h>
|
| .globl cpu_suspend
| .globl cpu_do_suspend
| .globl cpu_suspend_save
| .globl cpu_resume
| .globl cpu_do_resume
|
| /*
| * int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
| * @arg will be passed to fn as argument
| * return value: 0 - cpu resumed from suspended state.
| * -1 - cpu not suspended.
| */
| ENTRY(cpu_suspend)
| push {r4 - r12, lr}
|
| mov r5, sp
| sub sp, sp, #PM_CTX_SIZE
| push {r0, r1}
|
| /* r9 is gd, save it to __suspend_gd !!! */
| adr r4, __suspend_gd
| str r9, [r4]
|
| mov r1, r5
| add r0, sp, #8
| blx cpu_suspend_save
|
| adr lr, aborted
| /* Jump to arch specific suspend */
| pop {r0, pc}
|
| aborted:
| /* cpu not suspended */
| add sp, sp, #PM_CTX_SIZE
| /* Return -1 to the caller */
| mov r0, #(-1)
|
| suspend_return:
| pop {r4 - r12, pc}
| ENDPROC(cpu_suspend)
|
| ENTRY(cpu_do_suspend)
| push {r4 - r11}
|
| read_midr r4
| ubfx r5, r4, #4, #12
|
| ldr r4, CORTEX_A7_PART_NUM
| cmp r5, r4
| beq a7_suspend
|
| ldr r4, CORTEX_A9_PART_NUM
| cmp r5, r4
| beq a9_suspend
|
| b other_suspend
|
| /* A9 needs PCR/DIAG */
| a9_suspend:
| read_pcr r4
| read_diag r5
| stmia r0!, {r4 - r5}
|
| a7_suspend:
| read_fcseidr r4
| read_tpidruro r5
| stmia r0!, {r4 - r5}
|
| other_suspend:
| read_dacr r4
| read_ttbr0 r5
| read_ttbr1 r6
| read_ttbcr r7
| read_sctlr r8
| read_actlr r9
| read_cpacr r10
| stmia r0!, {r4 - r10}
|
| read_prrr r4
| read_nmrr r5
| read_vbar r6
| mrs r7, CPSR
| stmia r0, {r4 - r7}
|
| pop {r4 - r11}
| bx lr
| ENDPROC(cpu_do_suspend)
|
| ENTRY(cpu_resume)
| /* Disable interrupt */
| cpsid aif
|
| /* Load gd !! */
| adr r1, __suspend_gd
| ldr r2, [r1]
|
| /* Get pm_ctx */
| add r2, r2, #PM_CTX_PHYS
| ldr r0, [r2]
|
| /* Need to use r0!, because cpu_do_resume needs it */
| ldmia r0!, {sp, pc}
| ENDPROC(cpu_resume)
|
| /*
| * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn;
| * Restore the registers stored when cpu_do_suspend
| * r0 points to the physical base address of the suspend_regs
| * field of struct pm_ctx.
| */
| ENTRY(cpu_do_resume)
| read_midr r4
| ubfx r5, r4, #4, #12
|
| ldr r4, CORTEX_A9_PART_NUM
| cmp r5, r4
| beq a9_resume
|
| ldr r4, CORTEX_A7_PART_NUM
| cmp r5, r4
| beq a7_resume
|
| /* v7 resume */
| mov ip, #0
| /* Invalidate icache to PoU */
| write_iciallu
| /* set reserved context */
| write_contextidr ip
| b other_resume
|
| a9_resume:
| /*
| * A9 needs PCR/DIAG
| */
| ldmia r0!, {r4 - r5}
| write_pcr r4
| write_diag r5
|
| a7_resume:
| /* v7 resume */
| mov ip, #0
|
| /* Invalidate icache to PoU */
| write_iciallu
| /* set reserved context */
| write_contextidr ip
|
| ldmia r0!, {r4 - r5}
| write_fcseidr r4
| write_tpidruro r5
|
| other_resume:
| ldmia r0!, {r4 - r10}
| /* Invalidate entire TLB */
| write_tlbiall
| write_dacr r4
| write_ttbr0 r5
| write_ttbr1 r6
| write_ttbcr r7
|
| ldmia r0, {r4 - r7}
| write_prrr r4
| write_nmrr r5
| write_vbar r6
|
| write_actlr r9
| write_cpacr r10
| write_bpiall
| isb
| dsb
|
| /* MMU will be enabled here */
| write_sctlr r8
| isb
|
| /* Restore interrupt */
| msr CPSR_c, r7
|
| mov r0, #0
| b suspend_return
| ENDPROC(cpu_do_resume)
|
| .align 4
| __suspend_gd:
| .word 0x0
| CORTEX_A7_PART_NUM:
| .word 0xC07
| CORTEX_A9_PART_NUM:
| .word 0xC09
|
|