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