xref: /optee_os/core/arch/arm/sm/pm_a32.S (revision b1469ba0bfd0371eb52bd50f5c52eeda7a8f5f1e)
1/*
2 * Copyright 2017 NXP
3 *
4 * Peng Fan <peng.fan@nxp.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <arm.h>
30#include <arm32_macros.S>
31#include <arm32_macros_cortex_a9.S>
32#include <asm.S>
33#include <asm-defines.h>
34#include <keep.h>
35#include <kernel/asan.h>
36#include <kernel/unwind.h>
37#include <platform_config.h>
38
39.section .text
40
41/*
42 * int sm_pm_cpu_suspend(uint32_t arg, int (*fn)(uint32_t))
43 * @arg will be passed to fn as argument
44 * return value: 0 - cpu resumed from suspended state.
45 *		 -1 - cpu not suspended.
46 */
47FUNC sm_pm_cpu_suspend, :
48UNWIND(	.fnstart)
49UNWIND(	.cantunwind)
50	push	{r4 - r12, lr}
51	mov	r5, sp
52	sub	sp, sp, #SM_PM_CTX_SIZE
53	push	{r0, r1}
54
55	mov	r1, r5
56	add	r0, sp, #8
57	blx	sm_pm_cpu_suspend_save
58	adr	lr, aborted
59	/* Jump to arch specific suspend */
60	pop	{r0, pc}
61aborted:
62	/* cpu not suspended */
63	add	sp, sp, #SM_PM_CTX_SIZE
64	/* Return -1 to the caller */
65	mov	r0, #(-1)
66suspend_return:
67	pop	{r4 - r12, pc}
68UNWIND(	.fnend)
69END_FUNC sm_pm_cpu_suspend
70
71FUNC sm_pm_cpu_do_suspend, :
72UNWIND(	.fnstart)
73UNWIND(	.cantunwind)
74	push	{r4 - r11}
75	read_midr r4
76	ubfx	r5, r4, #4, #12
77	ldr     r4, =CORTEX_A7_PART_NUM
78	cmp	r5, r4
79	beq	a7_suspend
80	ldr     r4, =CORTEX_A9_PART_NUM
81	cmp	r5, r4
82	beq	a9_suspend
83	/* cpu not supported */
84	b	.
85	/* A9 needs PCR/DIAG */
86a9_suspend:
87	read_pcr r4
88	read_diag r5
89	stmia	r0!, {r4 - r5}
90a7_suspend:
91	read_fcseidr r4
92	read_tpidruro r5
93	stmia	r0!, {r4 - r5}
94	read_dacr r4
95#ifdef CFG_WITH_LPAE
96#error "Not supported"
97#else
98	read_ttbr0 r5
99	read_ttbr1 r6
100	read_ttbcr r7
101#endif
102	read_sctlr r8
103	read_actlr r9
104	read_cpacr r10
105	read_mvbar r11
106	stmia	r0!, {r4 - r11}
107	read_prrr r4
108	read_nmrr r5
109	read_vbar r6
110	read_nsacr r7
111	stmia	r0, {r4 - r7}
112	pop	{r4 - r11}
113	bx	lr
114UNWIND(	.fnend)
115END_FUNC sm_pm_cpu_do_suspend
116
117FUNC sm_pm_cpu_resume, :
118UNWIND(	.fnstart)
119UNWIND(	.cantunwind)
120	cpsid	aif
121
122	/* Call into the runtime address of get_core_pos */
123	adr	r0, _core_pos
124	ldr	r1, [r0]
125	add	r0, r0, r1
126	blx	r0
127
128	/*
129	 * At this point, MMU is not enabled now.
130	 * 1. Get the runtime physical address of _suspend_sp
131	 * 2. Get the offset from _suspend_sp to &thread_core_local
132	 * 3. Get the runtime physical address of thread_core_local
133	 * Since moving towards non-linear mapping,
134	 * `ldr r0, =thread_core_local` is not used here.
135	 */
136	adr	r4, _suspend_sp
137	ldr	r5, [r4]
138	add	r4, r4, r5
139
140	mov_imm r1, THREAD_CORE_LOCAL_SIZE
141	mla	r0, r0, r1, r4
142
143	ldr	r0, [r0, #THREAD_CORE_LOCAL_SM_PM_CTX_PHYS]
144	/* Need to use r0!, because sm_pm_cpu_do_resume needs it */
145	ldmia	r0!, {sp, pc}
146UNWIND(	.fnend)
147END_FUNC sm_pm_cpu_resume
148
149/*
150 * The following will be located in text section whose attribute is
151 * marked as readonly, but we only need to read here
152 * _suspend_sp stores the offset between thread_core_local to _suspend_sp.
153 * _core_pos stores the offset between get_core_pos to _core_pos.
154 */
155.align 2
156.extern thread_core_local
157_suspend_sp:
158	.long	thread_core_local - .
159.extern get_core_pos
160_core_pos:
161	.long	get_core_pos - .
162
163/*
164 * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn;
165 * Restore the registers stored when sm_pm_cpu_do_suspend
166 * r0 points to the physical base address of the suspend_regs
167 * field of struct sm_pm_ctx.
168 */
169FUNC sm_pm_cpu_do_resume, :
170UNWIND(	.fnstart)
171UNWIND(	.cantunwind)
172	read_midr r4
173	ubfx	r5, r4, #4, #12
174	ldr     r4, =CORTEX_A7_PART_NUM
175	cmp	r5, r4
176	beq	a7_resume
177
178	/*
179	 * A9 needs PCR/DIAG
180	 */
181	ldmia   r0!, {r4 - r5}
182	write_pcr r4
183	write_diag r5
184
185a7_resume:
186	/* v7 resume */
187	mov	ip, #0
188	/* Invalidate icache to PoU */
189	write_iciallu
190	/* set reserved context */
191	write_contextidr ip
192	ldmia	r0!, {r4 - r5}
193	write_fcseidr r4
194	write_tpidruro r5
195	ldmia	r0!, {r4 - r11}
196	/* Invalidate entire TLB */
197	write_tlbiall
198	write_dacr r4
199#ifdef CFG_WITH_LPAE
200#error "Not supported -"
201#else
202	write_ttbr0 r5
203	write_ttbr1 r6
204	write_ttbcr r7
205#endif
206
207	ldmia	r0, {r4 - r7}
208	write_prrr r4
209	write_nmrr r5
210	write_vbar r6
211	write_nsacr r7
212
213	write_actlr r9
214	write_cpacr r10
215	write_mvbar r11
216	write_bpiall
217	isb
218	dsb
219	/* MMU will be enabled here */
220	write_sctlr r8
221	isb
222	mov	r0, #0
223	b	suspend_return
224UNWIND(	.fnend)
225END_FUNC sm_pm_cpu_do_resume
226
227