1/* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7#include <asm/arm32_macros.S> 8#include <asm/macro.h> 9#include <asm-offsets.h> 10#include <asm/psci.h> 11#include <config.h> 12#include <linux/linkage.h> 13 14 .globl cpu_suspend 15 .globl cpu_do_suspend 16 .globl cpu_suspend_save 17 .globl cpu_resume 18 .globl cpu_do_resume 19 20/* 21 * int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) 22 * @arg will be passed to fn as argument 23 * return value: 0 - cpu resumed from suspended state. 24 * -1 - cpu not suspended. 25 */ 26ENTRY(cpu_suspend) 27 push {r4 - r12, lr} 28 29 mov r5, sp 30 sub sp, sp, #PM_CTX_SIZE 31 push {r0, r1} 32 33 /* r9 is gd, save it to __suspend_gd !!! */ 34 adr r4, __suspend_gd 35 str r9, [r4] 36 37 mov r1, r5 38 add r0, sp, #8 39 blx cpu_suspend_save 40 41 adr lr, aborted 42 /* Jump to arch specific suspend */ 43 pop {r0, pc} 44 45aborted: 46 /* cpu not suspended */ 47 add sp, sp, #PM_CTX_SIZE 48 /* Return -1 to the caller */ 49 mov r0, #(-1) 50 51suspend_return: 52 pop {r4 - r12, pc} 53ENDPROC(cpu_suspend) 54 55ENTRY(cpu_do_suspend) 56 push {r4 - r11} 57 58 read_midr r4 59 ubfx r5, r4, #4, #12 60 61 ldr r4, CORTEX_A7_PART_NUM 62 cmp r5, r4 63 beq a7_suspend 64 65 ldr r4, CORTEX_A9_PART_NUM 66 cmp r5, r4 67 beq a9_suspend 68 69 b other_suspend 70 71 /* A9 needs PCR/DIAG */ 72a9_suspend: 73 read_pcr r4 74 read_diag r5 75 stmia r0!, {r4 - r5} 76 77a7_suspend: 78 read_fcseidr r4 79 read_tpidruro r5 80 stmia r0!, {r4 - r5} 81 82other_suspend: 83 read_dacr r4 84 read_ttbr0 r5 85 read_ttbr1 r6 86 read_ttbcr r7 87 read_sctlr r8 88 read_actlr r9 89 read_cpacr r10 90 stmia r0!, {r4 - r10} 91 92 read_prrr r4 93 read_nmrr r5 94 read_vbar r6 95 mrs r7, CPSR 96 stmia r0, {r4 - r7} 97 98 pop {r4 - r11} 99 bx lr 100ENDPROC(cpu_do_suspend) 101 102ENTRY(cpu_resume) 103 /* Disable interrupt */ 104 cpsid aif 105 106 /* Load gd !! */ 107 adr r1, __suspend_gd 108 ldr r2, [r1] 109 110 /* Get pm_ctx */ 111 add r2, r2, #PM_CTX_PHYS 112 ldr r0, [r2] 113 114 /* Need to use r0!, because cpu_do_resume needs it */ 115 ldmia r0!, {sp, pc} 116ENDPROC(cpu_resume) 117 118/* 119 * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn; 120 * Restore the registers stored when cpu_do_suspend 121 * r0 points to the physical base address of the suspend_regs 122 * field of struct pm_ctx. 123 */ 124ENTRY(cpu_do_resume) 125 read_midr r4 126 ubfx r5, r4, #4, #12 127 128 ldr r4, CORTEX_A9_PART_NUM 129 cmp r5, r4 130 beq a9_resume 131 132 ldr r4, CORTEX_A7_PART_NUM 133 cmp r5, r4 134 beq a7_resume 135 136 /* v7 resume */ 137 mov ip, #0 138 /* Invalidate icache to PoU */ 139 write_iciallu 140 /* set reserved context */ 141 write_contextidr ip 142 b other_resume 143 144a9_resume: 145 /* 146 * A9 needs PCR/DIAG 147 */ 148 ldmia r0!, {r4 - r5} 149 write_pcr r4 150 write_diag r5 151 152a7_resume: 153 /* v7 resume */ 154 mov ip, #0 155 156 /* Invalidate icache to PoU */ 157 write_iciallu 158 /* set reserved context */ 159 write_contextidr ip 160 161 ldmia r0!, {r4 - r5} 162 write_fcseidr r4 163 write_tpidruro r5 164 165other_resume: 166 ldmia r0!, {r4 - r10} 167 /* Invalidate entire TLB */ 168 write_tlbiall 169 write_dacr r4 170 write_ttbr0 r5 171 write_ttbr1 r6 172 write_ttbcr r7 173 174 ldmia r0, {r4 - r7} 175 write_prrr r4 176 write_nmrr r5 177 write_vbar r6 178 179 write_actlr r9 180 write_cpacr r10 181 write_bpiall 182 isb 183 dsb 184 185 /* MMU will be enabled here */ 186 write_sctlr r8 187 isb 188 189 /* Restore interrupt */ 190 msr CPSR_c, r7 191 192 mov r0, #0 193 b suspend_return 194ENDPROC(cpu_do_resume) 195 196.align 4 197__suspend_gd: 198 .word 0x0 199CORTEX_A7_PART_NUM: 200 .word 0xC07 201CORTEX_A9_PART_NUM: 202 .word 0xC09 203