1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * OMAP44xx sleep code. 4 * 5 * Copyright (C) 2011 Texas Instruments, Inc. 6 * Santosh Shilimkar <santosh.shilimkar@ti 7 */ 8 9 #include <linux/linkage.h> 10 #include <asm/assembler.h> 11 #include <asm/smp_scu.h> 12 #include <asm/page.h> 13 #include <asm/hardware/cache-l2x0.h> 14 15 #include "omap-secure.h" 16 17 #include "common.h" 18 #include "omap44xx.h" 19 #include "omap4-sar-layout.h" 20 21 .arch armv7-a 22 23 #if defined(CONFIG_SMP) && defined(CONFIG_PM) 24 25 .arch_extension sec 26 .macro DO_SMC 27 dsb 28 smc #0 29 dsb 30 .endm 31 32 #ifdef CONFIG_ARCH_OMAP4 33 34 /* 35 * ============================= 36 * == CPU suspend finisher == 37 * ============================= 38 * 39 * void omap4_finish_suspend(unsigned long cpu 40 * 41 * This function code saves the CPU context an 42 * power down sequence. Calling WFI effectivel 43 * power domains states to the desired target 44 * 45 * @cpu_state : contains context save state (r 46 * 0 - No context lost 47 * 1 - CPUx L1 and logic lost: MPUSS CSWR 48 * 2 - CPUx L1 and logic lost + GIC lost: 49 * 3 - CPUx L1 and logic lost + GIC + L2 50 * @return: This function never returns for CP 51 * Post WFI, CPU transitions to DORMANT or OFF 52 * from this follows a full CPU reset path via 53 * The restore function pointer is stored at C 54 * It returns to the caller for CPU INACTIVE a 55 * CPU failed to transition to targeted OFF/DO 56 * 57 * omap4_finish_suspend() calls v7_flush_dcach 58 * stack frame and it expects the caller to ta 59 * stack frame is saved to avoid possible stac 60 */ 61 ENTRY(omap4_finish_suspend) 62 stmfd sp!, {r4-r12, lr} 63 cmp r0, #0x0 64 beq do_WFI 65 66 /* 67 * Flush all data from the L1 data cac 68 * SCTLR.C bit. 69 */ 70 bl omap4_get_sar_ram_base 71 ldr r9, [r0, #OMAP_TYPE_OFFSET] 72 cmp r9, #0x1 73 bne skip_secure_l1_clean 74 mov r0, #SCU_PM_NORMAL 75 mov r1, #0xFF 76 stmfd r13!, {r4-r12, r14} 77 ldr r12, =OMAP4_MON_SCU_PWR_INDEX 78 DO_SMC 79 ldmfd r13!, {r4-r12, r14} 80 skip_secure_l1_clean: 81 bl v7_flush_dcache_all 82 83 /* 84 * Clear the SCTLR.C bit to prevent fu 85 * allocation. Clearing SCTLR.C would 86 * strongly ordered and would not hit 87 */ 88 mrc p15, 0, r0, c1, c0, 0 89 bic r0, r0, #(1 << 2) 90 mcr p15, 0, r0, c1, c0, 0 91 isb 92 93 bl v7_invalidate_l1 94 95 /* 96 * Switch the CPU from Symmetric Multi 97 * to AsymmetricMultiprocessing (AMP) 98 * the SCU power status to DORMANT or 99 * This enables the CPU to be taken ou 100 * preventing the CPU from receiving c 101 * maintenance operations broadcast by 102 */ 103 bl omap4_get_sar_ram_base 104 mov r8, r0 105 ldr r9, [r8, #OMAP_TYPE_OFFSET] 106 cmp r9, #0x1 107 bne scu_gp_set 108 mrc p15, 0, r0, c0, c0, 5 109 ands r0, r0, #0x0f 110 ldreq r0, [r8, #SCU_OFFSET0] 111 ldrne r0, [r8, #SCU_OFFSET1] 112 mov r1, #0x00 113 stmfd r13!, {r4-r12, r14} 114 ldr r12, =OMAP4_MON_SCU_PWR_INDEX 115 DO_SMC 116 ldmfd r13!, {r4-r12, r14} 117 b skip_scu_gp_set 118 scu_gp_set: 119 mrc p15, 0, r0, c0, c0, 5 120 ands r0, r0, #0x0f 121 ldreq r1, [r8, #SCU_OFFSET0] 122 ldrne r1, [r8, #SCU_OFFSET1] 123 bl omap4_get_scu_base 124 bl scu_power_mode 125 skip_scu_gp_set: 126 mrc p15, 0, r0, c1, c1, 2 127 tst r0, #(1 << 18) 128 mrcne p15, 0, r0, c1, c0, 1 129 bicne r0, r0, #(1 << 6) 130 mcrne p15, 0, r0, c1, c0, 1 131 isb 132 dsb 133 #ifdef CONFIG_CACHE_L2X0 134 /* 135 * Clean and invalidate the L2 cache. 136 * Common cache-l2x0.c functions can't 137 * uses spinlocks. We are out of coher 138 * disabled. The spinlock implementati 139 * instruction which can fail without 140 * OMAP4 hardware doesn't support excl 141 * overcome exclusive access issue. Be 142 * lead to deadlock. 143 */ 144 bl omap4_get_sar_ram_base 145 mov r8, r0 146 mrc p15, 0, r5, c0, c0, 5 147 ands r5, r5, #0x0f 148 ldreq r0, [r8, #L2X0_SAVE_OFFSET0] 149 ldrne r0, [r8, #L2X0_SAVE_OFFSET1] 150 cmp r0, #3 151 bne do_WFI 152 #ifdef CONFIG_PL310_ERRATA_727915 153 mov r0, #0x03 154 mov r12, #OMAP4_MON_L2X0_DBG_CTRL_ 155 DO_SMC 156 #endif 157 bl omap4_get_l2cache_base 158 mov r2, r0 159 ldr r0, =0xffff 160 str r0, [r2, #L2X0_CLEAN_INV_WAY] 161 wait: 162 ldr r0, [r2, #L2X0_CLEAN_INV_WAY] 163 ldr r1, =0xffff 164 ands r0, r0, r1 165 bne wait 166 #ifdef CONFIG_PL310_ERRATA_727915 167 mov r0, #0x00 168 mov r12, #OMAP4_MON_L2X0_DBG_CTRL_ 169 DO_SMC 170 #endif 171 l2x_sync: 172 bl omap4_get_l2cache_base 173 mov r2, r0 174 mov r0, #0x0 175 str r0, [r2, #L2X0_CACHE_SYNC] 176 sync: 177 ldr r0, [r2, #L2X0_CACHE_SYNC] 178 ands r0, r0, #0x1 179 bne sync 180 #endif 181 182 do_WFI: 183 bl omap_do_wfi 184 185 /* 186 * CPU is here when it failed to enter 187 * no low power state was attempted. 188 */ 189 mrc p15, 0, r0, c1, c0, 0 190 tst r0, #(1 << 2) 191 orreq r0, r0, #(1 << 2) 192 mcreq p15, 0, r0, c1, c0, 0 193 isb 194 195 /* 196 * Ensure the CPU power state is set t 197 * SCU power state so that CPU is back 198 * In non-coherent mode CPU can lock-u 199 * system deadlock. 200 */ 201 mrc p15, 0, r0, c1, c0, 1 202 tst r0, #(1 << 6) 203 orreq r0, r0, #(1 << 6) 204 mcreq p15, 0, r0, c1, c0, 1 205 isb 206 bl omap4_get_sar_ram_base 207 mov r8, r0 208 ldr r9, [r8, #OMAP_TYPE_OFFSET] 209 cmp r9, #0x1 210 bne scu_gp_clear 211 mov r0, #SCU_PM_NORMAL 212 mov r1, #0x00 213 stmfd r13!, {r4-r12, r14} 214 ldr r12, =OMAP4_MON_SCU_PWR_INDEX 215 DO_SMC 216 ldmfd r13!, {r4-r12, r14} 217 b skip_scu_gp_clear 218 scu_gp_clear: 219 bl omap4_get_scu_base 220 mov r1, #SCU_PM_NORMAL 221 bl scu_power_mode 222 skip_scu_gp_clear: 223 isb 224 dsb 225 ldmfd sp!, {r4-r12, pc} 226 ENDPROC(omap4_finish_suspend) 227 228 /* 229 * ============================ 230 * == CPU resume entry point == 231 * ============================ 232 * 233 * void omap4_cpu_resume(void) 234 * 235 * ROM code jumps to this function while wakin 236 * OFF or DORMANT state. Physical address of t 237 * stored in the SAR RAM while entering to OFF 238 * The restore function pointer is stored at C 239 */ 240 ENTRY(omap4_cpu_resume) 241 /* 242 * Configure ACTRL and enable NS SMP b 243 * OMAP44XX EMU/HS devices - CPU0 SMP 244 * init and for CPU1, a secure PPA API 245 * while executing NS_SMP API on CPU1 246 * OMAP443X GP devices- SMP bit isn't 247 * OMAP446X GP devices - SMP bit acces 248 */ 249 ldr r8, =OMAP44XX_SAR_RAM_BASE 250 ldr r9, [r8, #OMAP_TYPE_OFFSET] 251 cmp r9, #0x1 252 bne skip_ns_smp_enable 253 mrc p15, 0, r0, c0, c0, 5 254 ands r0, r0, #0x0f 255 beq skip_ns_smp_enable 256 ppa_actrl_retry: 257 mov r0, #OMAP4_PPA_CPU_ACTRL_SMP_I 258 adr r1, ppa_zero_params_offset 259 ldr r3, [r1] 260 add r3, r3, r1 261 mov r1, #0x0 262 mov r2, #0x4 263 mov r6, #0xff 264 mov r12, #0x00 265 DO_SMC 266 cmp r0, #0x0 267 beq enable_smp_bit 268 b ppa_actrl_retry 269 enable_smp_bit: 270 mrc p15, 0, r0, c1, c0, 1 271 tst r0, #(1 << 6) 272 orreq r0, r0, #(1 << 6) 273 mcreq p15, 0, r0, c1, c0, 1 274 isb 275 skip_ns_smp_enable: 276 #ifdef CONFIG_CACHE_L2X0 277 /* 278 * Restore the L2 AUXCTRL and enable t 279 * OMAP4_MON_L2X0_AUXCTRL_INDEX = Pro 280 * OMAP4_MON_L2X0_CTRL_INDEX = Enable 281 * register r0 contains value to be pr 282 * L2 cache is already invalidate by R 283 * of MPUSS OFF wakeup path. 284 */ 285 ldr r2, =OMAP44XX_L2CACHE_BASE 286 ldr r0, [r2, #L2X0_CTRL] 287 and r0, #0x0f 288 cmp r0, #1 289 beq skip_l2en 290 ldr r3, =OMAP44XX_SAR_RAM_BASE 291 ldr r1, [r3, #OMAP_TYPE_OFFSET] 292 cmp r1, #0x1 293 bne set_gp_por 294 ldr r0, =OMAP4_PPA_L2_POR_INDEX 295 ldr r1, =OMAP44XX_SAR_RAM_BASE 296 ldr r4, [r1, #L2X0_PREFETCH_CTRL_O 297 adr r1, ppa_por_params_offset 298 ldr r3, [r1] 299 add r3, r3, r1 300 str r4, [r3, #0x04] 301 mov r1, #0x0 302 mov r2, #0x4 303 mov r6, #0xff 304 mov r12, #0x00 305 DO_SMC 306 b set_aux_ctrl 307 set_gp_por: 308 ldr r1, =OMAP44XX_SAR_RAM_BASE 309 ldr r0, [r1, #L2X0_PREFETCH_CTRL_O 310 ldr r12, =OMAP4_MON_L2X0_PREFETCH_ 311 DO_SMC 312 set_aux_ctrl: 313 ldr r1, =OMAP44XX_SAR_RAM_BASE 314 ldr r0, [r1, #L2X0_AUXCTRL_OFFSET] 315 ldr r12, =OMAP4_MON_L2X0_AUXCTRL_I 316 DO_SMC 317 mov r0, #0x1 318 ldr r12, =OMAP4_MON_L2X0_CTRL_INDE 319 DO_SMC 320 skip_l2en: 321 #endif 322 323 b cpu_resume 324 ppa_por_params_offset: 325 .long ppa_por_params - . 326 ENDPROC(omap4_cpu_resume) 327 #endif /* CONFIG_ARCH_OMAP4 */ 328 329 #endif /* defined(CONFIG_SMP) && defined(CONF 330 331 ENTRY(omap_do_wfi) 332 stmfd sp!, {lr} 333 #ifdef CONFIG_OMAP_INTERCONNECT_BARRIER 334 /* Drain interconnect write buffers. * 335 bl omap_interconnect_sync 336 #endif 337 338 /* 339 * Execute an ISB instruction to ensur 340 * CP15 register changes have been com 341 */ 342 isb 343 344 /* 345 * Execute a barrier instruction to en 346 * TLB and branch predictor maintenanc 347 * by any CPU in the cluster have comp 348 */ 349 dsb 350 dmb 351 352 /* 353 * Execute a WFI instruction and wait 354 * STANDBYWFI output is asserted to in 355 * CPU is in idle and low power state. 356 * prefetch the instructions so add NO 357 * NOPs as per Cortex-A9 pipeline. 358 */ 359 wfi 360 nop 361 nop 362 nop 363 nop 364 nop 365 nop 366 nop 367 nop 368 nop 369 nop 370 nop 371 nop 372 nop 373 nop 374 nop 375 nop 376 377 ldmfd sp!, {pc} 378 ppa_zero_params_offset: 379 .long ppa_zero_params - . 380 ENDPROC(omap_do_wfi) 381 382 .data 383 .align 2 384 ppa_zero_params: 385 .word 0 386 387 ppa_por_params: 388 .word 1, 0
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.