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