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