xref: /optee_os/core/arch/arm/sm/pm_a32.S (revision a4c2e0cb4e4fcb0c760fb3daf9172e682a4e3628)
11bb92983SJerome Forissier/* SPDX-License-Identifier: BSD-2-Clause */
286e50a60SPeng Fan/*
386e50a60SPeng Fan * Copyright 2017 NXP
486e50a60SPeng Fan *
586e50a60SPeng Fan * Peng Fan <peng.fan@nxp.com>
686e50a60SPeng Fan */
786e50a60SPeng Fan
886e50a60SPeng Fan#include <arm32_macros_cortex_a9.S>
989fe7c3cSJerome Forissier#include <arm32_macros.S>
1089fe7c3cSJerome Forissier#include <arm.h>
1186e50a60SPeng Fan#include <asm.S>
1289fe7c3cSJerome Forissier#include <generated/asm-defines.h>
1386e50a60SPeng Fan#include <keep.h>
1486e50a60SPeng Fan#include <kernel/asan.h>
1586e50a60SPeng Fan#include <platform_config.h>
1686e50a60SPeng Fan
1786e50a60SPeng Fan.section .text
1886e50a60SPeng Fan
1986e50a60SPeng Fan/*
2086e50a60SPeng Fan * int sm_pm_cpu_suspend(uint32_t arg, int (*fn)(uint32_t))
2186e50a60SPeng Fan * @arg will be passed to fn as argument
2286e50a60SPeng Fan * return value: 0 - cpu resumed from suspended state.
2386e50a60SPeng Fan *		 -1 - cpu not suspended.
2486e50a60SPeng Fan */
2586e50a60SPeng FanFUNC sm_pm_cpu_suspend, :
2686e50a60SPeng FanUNWIND(	.cantunwind)
2786e50a60SPeng Fan	push	{r4 - r12, lr}
2886e50a60SPeng Fan	mov	r5, sp
2986e50a60SPeng Fan	sub	sp, sp, #SM_PM_CTX_SIZE
3086e50a60SPeng Fan	push	{r0, r1}
3186e50a60SPeng Fan
3286e50a60SPeng Fan	mov	r1, r5
3386e50a60SPeng Fan	add	r0, sp, #8
3486e50a60SPeng Fan	blx	sm_pm_cpu_suspend_save
3586e50a60SPeng Fan	adr	lr, aborted
3686e50a60SPeng Fan	/* Jump to arch specific suspend */
3786e50a60SPeng Fan	pop	{r0, pc}
3886e50a60SPeng Fanaborted:
3986e50a60SPeng Fan	/* cpu not suspended */
4086e50a60SPeng Fan	add	sp, sp, #SM_PM_CTX_SIZE
4186e50a60SPeng Fan	/* Return -1 to the caller */
4286e50a60SPeng Fan	mov	r0, #(-1)
4386e50a60SPeng Fansuspend_return:
4486e50a60SPeng Fan	pop	{r4 - r12, pc}
4586e50a60SPeng FanEND_FUNC sm_pm_cpu_suspend
4686e50a60SPeng Fan
4786e50a60SPeng FanFUNC sm_pm_cpu_do_suspend, :
4886e50a60SPeng FanUNWIND(	.cantunwind)
4986e50a60SPeng Fan	push	{r4 - r11}
5086e50a60SPeng Fan	read_midr r4
5186e50a60SPeng Fan	ubfx	r5, r4, #4, #12
520d2c657cSClément Léger	ldr     r4, =CORTEX_A5_PART_NUM
530d2c657cSClément Léger	cmp	r5, r4
540d2c657cSClément Léger	beq	a5_a7_suspend
5586e50a60SPeng Fan	ldr     r4, =CORTEX_A7_PART_NUM
5686e50a60SPeng Fan	cmp	r5, r4
570d2c657cSClément Léger	beq	a5_a7_suspend
5886e50a60SPeng Fan	ldr     r4, =CORTEX_A9_PART_NUM
5986e50a60SPeng Fan	cmp	r5, r4
6086e50a60SPeng Fan	beq	a9_suspend
6186e50a60SPeng Fan	/* cpu not supported */
6286e50a60SPeng Fan	b	.
6386e50a60SPeng Fan	/* A9 needs PCR/DIAG */
6486e50a60SPeng Fana9_suspend:
6586e50a60SPeng Fan	read_pcr r4
6686e50a60SPeng Fan	read_diag r5
6786e50a60SPeng Fan	stmia	r0!, {r4 - r5}
680d2c657cSClément Légera5_a7_suspend:
6986e50a60SPeng Fan	read_fcseidr r4
7086e50a60SPeng Fan	read_tpidruro r5
7186e50a60SPeng Fan	stmia	r0!, {r4 - r5}
7286e50a60SPeng Fan	read_dacr r4
7386e50a60SPeng Fan#ifdef CFG_WITH_LPAE
7486e50a60SPeng Fan#error "Not supported"
7586e50a60SPeng Fan#else
7686e50a60SPeng Fan	read_ttbr0 r5
7786e50a60SPeng Fan	read_ttbr1 r6
7886e50a60SPeng Fan	read_ttbcr r7
7986e50a60SPeng Fan#endif
8086e50a60SPeng Fan	read_sctlr r8
8186e50a60SPeng Fan	read_actlr r9
8286e50a60SPeng Fan	read_cpacr r10
8386e50a60SPeng Fan	read_mvbar r11
8486e50a60SPeng Fan	stmia	r0!, {r4 - r11}
8586e50a60SPeng Fan	read_prrr r4
8686e50a60SPeng Fan	read_nmrr r5
8786e50a60SPeng Fan	read_vbar r6
8886e50a60SPeng Fan	read_nsacr r7
8986e50a60SPeng Fan	stmia	r0, {r4 - r7}
9086e50a60SPeng Fan	pop	{r4 - r11}
9186e50a60SPeng Fan	bx	lr
9286e50a60SPeng FanEND_FUNC sm_pm_cpu_do_suspend
9386e50a60SPeng Fan
9486e50a60SPeng FanFUNC sm_pm_cpu_resume, :
9586e50a60SPeng FanUNWIND(	.cantunwind)
9686e50a60SPeng Fan	cpsid	aif
9786e50a60SPeng Fan
98af8e0424SEtienne Carriere	/* Call into the runtime address of __get_core_pos */
9986e50a60SPeng Fan	adr	r0, _core_pos
10086e50a60SPeng Fan	ldr	r1, [r0]
10186e50a60SPeng Fan	add	r0, r0, r1
10286e50a60SPeng Fan	blx	r0
10386e50a60SPeng Fan
10486e50a60SPeng Fan	/*
10586e50a60SPeng Fan	 * At this point, MMU is not enabled now.
10686e50a60SPeng Fan	 * 1. Get the runtime physical address of _suspend_sp
107*a4c2e0cbSJens Wiklander	 * 2. Get the offset from _suspend_sp to thread_core_local
10886e50a60SPeng Fan	 * 3. Get the runtime physical address of thread_core_local
10986e50a60SPeng Fan	 * Since moving towards non-linear mapping,
110*a4c2e0cbSJens Wiklander	 * `ldr r0, =thread_core_local
111*a4c2e0cbSJens Wiklander	 *  ldr r0 [r0]` is not used here.
11286e50a60SPeng Fan	 */
11386e50a60SPeng Fan	adr	r4, _suspend_sp
11486e50a60SPeng Fan	ldr	r5, [r4]
11586e50a60SPeng Fan	add	r4, r4, r5
116*a4c2e0cbSJens Wiklander	ldr	r4, [r4]
11786e50a60SPeng Fan
11886e50a60SPeng Fan	mov_imm r1, THREAD_CORE_LOCAL_SIZE
11986e50a60SPeng Fan	mla	r0, r0, r1, r4
12086e50a60SPeng Fan
12186e50a60SPeng Fan	ldr	r0, [r0, #THREAD_CORE_LOCAL_SM_PM_CTX_PHYS]
12286e50a60SPeng Fan	/* Need to use r0!, because sm_pm_cpu_do_resume needs it */
12386e50a60SPeng Fan	ldmia	r0!, {sp, pc}
12486e50a60SPeng FanEND_FUNC sm_pm_cpu_resume
12586e50a60SPeng Fan
12686e50a60SPeng Fan/*
1278473540dSJens Wiklander * The following will be located in text section whose attribute is
1288473540dSJens Wiklander * marked as readonly, but we only need to read here
1298473540dSJens Wiklander * _suspend_sp stores the offset between thread_core_local to _suspend_sp.
130af8e0424SEtienne Carriere * _core_pos stores the offset between __get_core_pos to _core_pos.
1318473540dSJens Wiklander */
1328473540dSJens Wiklander.align 2
133*a4c2e0cbSJens Wiklander.extern thread_core_local_pa
1348473540dSJens Wiklander_suspend_sp:
135*a4c2e0cbSJens Wiklander	.long	thread_core_local_pa - .
136af8e0424SEtienne Carriere.extern __get_core_pos
1378473540dSJens Wiklander_core_pos:
138af8e0424SEtienne Carriere	.long	__get_core_pos - .
1398473540dSJens Wiklander
1408473540dSJens Wiklander/*
141066be2bcSPeng Fan * void sm_pm_cpu_do_resume(paddr suspend_regs) __noreturn;
14286e50a60SPeng Fan * Restore the registers stored when sm_pm_cpu_do_suspend
14386e50a60SPeng Fan * r0 points to the physical base address of the suspend_regs
14486e50a60SPeng Fan * field of struct sm_pm_ctx.
14586e50a60SPeng Fan */
14686e50a60SPeng FanFUNC sm_pm_cpu_do_resume, :
14786e50a60SPeng FanUNWIND(	.cantunwind)
14886e50a60SPeng Fan	read_midr r4
14986e50a60SPeng Fan	ubfx	r5, r4, #4, #12
1500d2c657cSClément Léger	ldr     r4, =CORTEX_A5_PART_NUM
1510d2c657cSClément Léger	cmp	r5, r4
1520d2c657cSClément Léger	beq	a5_a7_resume
15386e50a60SPeng Fan	ldr     r4, =CORTEX_A7_PART_NUM
15486e50a60SPeng Fan	cmp	r5, r4
1550d2c657cSClément Léger	beq	a5_a7_resume
15686e50a60SPeng Fan
15786e50a60SPeng Fan	/*
15886e50a60SPeng Fan	 * A9 needs PCR/DIAG
15986e50a60SPeng Fan	 */
16086e50a60SPeng Fan	ldmia   r0!, {r4 - r5}
16186e50a60SPeng Fan	write_pcr r4
16286e50a60SPeng Fan	write_diag r5
16386e50a60SPeng Fan
1640d2c657cSClément Légera5_a7_resume:
16586e50a60SPeng Fan	/* v7 resume */
16686e50a60SPeng Fan	mov	ip, #0
16786e50a60SPeng Fan	/* Invalidate icache to PoU */
16886e50a60SPeng Fan	write_iciallu
16986e50a60SPeng Fan	/* set reserved context */
17086e50a60SPeng Fan	write_contextidr ip
17186e50a60SPeng Fan	ldmia	r0!, {r4 - r5}
17286e50a60SPeng Fan	write_fcseidr r4
17386e50a60SPeng Fan	write_tpidruro r5
17486e50a60SPeng Fan	ldmia	r0!, {r4 - r11}
17586e50a60SPeng Fan	/* Invalidate entire TLB */
17686e50a60SPeng Fan	write_tlbiall
17786e50a60SPeng Fan	write_dacr r4
17886e50a60SPeng Fan#ifdef CFG_WITH_LPAE
17986e50a60SPeng Fan#error "Not supported -"
18086e50a60SPeng Fan#else
18186e50a60SPeng Fan	write_ttbr0 r5
18286e50a60SPeng Fan	write_ttbr1 r6
18386e50a60SPeng Fan	write_ttbcr r7
18486e50a60SPeng Fan#endif
18586e50a60SPeng Fan
18686e50a60SPeng Fan	ldmia	r0, {r4 - r7}
18786e50a60SPeng Fan	write_prrr r4
18886e50a60SPeng Fan	write_nmrr r5
18986e50a60SPeng Fan	write_vbar r6
19086e50a60SPeng Fan	write_nsacr r7
19186e50a60SPeng Fan
19286e50a60SPeng Fan	write_actlr r9
19386e50a60SPeng Fan	write_cpacr r10
19486e50a60SPeng Fan	write_mvbar r11
19586e50a60SPeng Fan	write_bpiall
19686e50a60SPeng Fan	isb
19786e50a60SPeng Fan	dsb
19886e50a60SPeng Fan	/* MMU will be enabled here */
19986e50a60SPeng Fan	write_sctlr r8
20086e50a60SPeng Fan	isb
20186e50a60SPeng Fan	mov	r0, #0
20286e50a60SPeng Fan	b	suspend_return
20386e50a60SPeng FanEND_FUNC sm_pm_cpu_do_resume
20486e50a60SPeng Fan
205