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