1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (c) 2012, NVIDIA Corporation. All rights reserved. 4 */ 5 6#include <linux/init.h> 7#include <linux/linkage.h> 8 9#include <soc/tegra/flowctrl.h> 10#include <soc/tegra/fuse.h> 11 12#include <asm/assembler.h> 13#include <asm/asm-offsets.h> 14#include <asm/cache.h> 15 16#include "iomap.h" 17#include "reset.h" 18#include "sleep.h" 19 20#define PMC_SCRATCH41 0x140 21 22#ifdef CONFIG_PM_SLEEP 23/* 24 * tegra_resume 25 * 26 * CPU boot vector when restarting the a CPU following 27 * an LP2 transition. Also branched to by LP0 and LP1 resume after 28 * re-enabling sdram. 29 * 30 * r6: SoC ID 31 * r8: CPU part number 32 */ 33ENTRY(tegra_resume) 34 check_cpu_part_num 0xc09, r8, r9 35 bleq v7_invalidate_l1 36 37 cpu_id r0 38 cmp r0, #0 @ CPU0? 39 THUMB( it ne ) 40 bne cpu_resume @ no 41 42 tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 43 /* Are we on Tegra20? */ 44 cmp r6, #TEGRA20 45 beq 1f @ Yes 46 /* Clear the flow controller flags for this CPU. */ 47 cpu_to_csr_reg r3, r0 48 mov32 r2, TEGRA_FLOW_CTRL_BASE 49 ldr r1, [r2, r3] 50 /* Clear event & intr flag */ 51 orr r1, r1, \ 52 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 53 movw r0, #0x3FFD @ enable, cluster_switch, immed, bitmaps 54 @ & ext flags for CPU power mgnt 55 bic r1, r1, r0 56 str r1, [r2, r3] 571: 58 59 mov32 r9, 0xc09 60 cmp r8, r9 61 bne end_ca9_scu_l2_resume 62#ifdef CONFIG_HAVE_ARM_SCU 63 /* enable SCU */ 64 mov32 r0, TEGRA_ARM_PERIF_BASE 65 ldr r1, [r0] 66 orr r1, r1, #1 67 str r1, [r0] 68#endif 69 bl tegra_resume_trusted_foundations 70 71#ifdef CONFIG_CACHE_L2X0 72 /* L2 cache resume & re-enable */ 73 bl l2c310_early_resume 74#endif 75end_ca9_scu_l2_resume: 76 mov32 r9, 0xc0f 77 cmp r8, r9 78 bleq tegra_init_l2_for_a15 79 80 b cpu_resume 81ENDPROC(tegra_resume) 82 83/* 84 * tegra_resume_trusted_foundations 85 * 86 * Trusted Foundations firmware initialization. 87 * 88 * Doesn't return if firmware presents. 89 * Corrupted registers: r1, r2 90 */ 91ENTRY(tegra_resume_trusted_foundations) 92 /* Check whether Trusted Foundations firmware presents. */ 93 mov32 r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET 94 ldr r1, =__tegra_cpu_reset_handler_data_offset + \ 95 RESET_DATA(TF_PRESENT) 96 ldr r1, [r2, r1] 97 cmp r1, #0 98 reteq lr 99 100 .arch_extension sec 101 /* First call after suspend wakes firmware. No arguments required. */ 102 smc #0 103 104 b cpu_resume 105ENDPROC(tegra_resume_trusted_foundations) 106#endif 107 108 .align L1_CACHE_SHIFT 109ENTRY(__tegra_cpu_reset_handler_start) 110 111/* 112 * __tegra_cpu_reset_handler: 113 * 114 * Common handler for all CPU reset events. 115 * 116 * Register usage within the reset handler: 117 * 118 * Others: scratch 119 * R6 = SoC ID 120 * R7 = CPU present (to the OS) mask 121 * R8 = CPU in LP1 state mask 122 * R9 = CPU in LP2 state mask 123 * R10 = CPU number 124 * R11 = CPU mask 125 * R12 = pointer to reset handler data 126 * 127 * NOTE: This code is copied to IRAM. All code and data accesses 128 * must be position-independent. 129 */ 130 131 .arm 132 .align L1_CACHE_SHIFT 133ENTRY(__tegra_cpu_reset_handler) 134 135 cpsid aif, 0x13 @ SVC mode, interrupts disabled 136 137 tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 138 139 adr r12, __tegra_cpu_reset_handler_data 140 ldr r5, [r12, #RESET_DATA(TF_PRESENT)] 141 cmp r5, #0 142 bne after_errata 143 144#ifdef CONFIG_ARCH_TEGRA_2x_SOC 145t20_check: 146 cmp r6, #TEGRA20 147 bne after_t20_check 148t20_errata: 149 # Tegra20 is a Cortex-A9 r1p1 150 mrc p15, 0, r0, c1, c0, 0 @ read system control register 151 orr r0, r0, #1 << 14 @ erratum 716044 152 mcr p15, 0, r0, c1, c0, 0 @ write system control register 153 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 154 orr r0, r0, #1 << 4 @ erratum 742230 155 orr r0, r0, #1 << 11 @ erratum 751472 156 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 157 b after_errata 158after_t20_check: 159#endif 160#ifdef CONFIG_ARCH_TEGRA_3x_SOC 161t30_check: 162 cmp r6, #TEGRA30 163 bne after_t30_check 164t30_errata: 165 # Tegra30 is a Cortex-A9 r2p9 166 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 167 orr r0, r0, #1 << 6 @ erratum 743622 168 orr r0, r0, #1 << 11 @ erratum 751472 169 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 170 b after_errata 171after_t30_check: 172#endif 173after_errata: 174 mrc p15, 0, r10, c0, c0, 5 @ MPIDR 175 and r10, r10, #0x3 @ R10 = CPU number 176 mov r11, #1 177 mov r11, r11, lsl r10 @ R11 = CPU mask 178 179#ifdef CONFIG_SMP 180 /* Does the OS know about this CPU? */ 181 ldr r7, [r12, #RESET_DATA(MASK_PRESENT)] 182 tst r7, r11 @ if !present 183 bleq __die @ CPU not present (to OS) 184#endif 185 186 /* Waking up from LP1? */ 187 ldr r8, [r12, #RESET_DATA(MASK_LP1)] 188 tst r8, r11 @ if in_lp1 189 beq __is_not_lp1 190 cmp r10, #0 191 bne __die @ only CPU0 can be here 192 ldr lr, [r12, #RESET_DATA(STARTUP_LP1)] 193 cmp lr, #0 194 bleq __die @ no LP1 startup handler 195 THUMB( add lr, lr, #1 ) @ switch to Thumb mode 196 bx lr 197__is_not_lp1: 198 199 /* Waking up from LP2? */ 200 ldr r9, [r12, #RESET_DATA(MASK_LP2)] 201 tst r9, r11 @ if in_lp2 202 beq __is_not_lp2 203 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)] 204 cmp lr, #0 205 bleq __die @ no LP2 startup handler 206 bx lr 207 208__is_not_lp2: 209 210#ifdef CONFIG_SMP 211 /* 212 * Can only be secondary boot (initial or hotplug) 213 * CPU0 can't be here for Tegra20/30 214 */ 215 cmp r6, #TEGRA114 216 beq __no_cpu0_chk 217 cmp r10, #0 218 bleq __die @ CPU0 cannot be here 219__no_cpu0_chk: 220 ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)] 221 cmp lr, #0 222 bleq __die @ no secondary startup handler 223 bx lr 224#endif 225 226/* 227 * We don't know why the CPU reset. Just kill it. 228 * The LR register will contain the address we died at + 4. 229 */ 230 231__die: 232 sub lr, lr, #4 233 mov32 r7, TEGRA_PMC_BASE 234 str lr, [r7, #PMC_SCRATCH41] 235 236 mov32 r7, TEGRA_CLK_RESET_BASE 237 238 /* Are we on Tegra20? */ 239 cmp r6, #TEGRA20 240 bne 1f 241 242#ifdef CONFIG_ARCH_TEGRA_2x_SOC 243 mov32 r0, 0x1111 244 mov r1, r0, lsl r10 245 str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET 246#endif 2471: 248#ifdef CONFIG_ARCH_TEGRA_3x_SOC 249 mov32 r6, TEGRA_FLOW_CTRL_BASE 250 251 cmp r10, #0 252 moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS 253 moveq r2, #FLOW_CTRL_CPU0_CSR 254 movne r1, r10, lsl #3 255 addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8) 256 addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8) 257 258 /* Clear CPU "event" and "interrupt" flags and power gate 259 it when halting but not before it is in the "WFI" state. */ 260 ldr r0, [r6, +r2] 261 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 262 orr r0, r0, #FLOW_CTRL_CSR_ENABLE 263 str r0, [r6, +r2] 264 265 /* Unconditionally halt this CPU */ 266 mov r0, #FLOW_CTRL_WAITEVENT 267 str r0, [r6, +r1] 268 ldr r0, [r6, +r1] @ memory barrier 269 270 dsb 271 isb 272 wfi @ CPU should be power gated here 273 274 /* If the CPU didn't power gate above just kill it's clock. */ 275 276 mov r0, r11, lsl #8 277 str r0, [r7, #348] @ CLK_CPU_CMPLX_SET 278#endif 279 280 /* If the CPU still isn't dead, just spin here. */ 281 b . 282ENDPROC(__tegra_cpu_reset_handler) 283 284 .align L1_CACHE_SHIFT 285 .type __tegra_cpu_reset_handler_data, %object 286 .globl __tegra_cpu_reset_handler_data 287 .globl __tegra_cpu_reset_handler_data_offset 288 .equ __tegra_cpu_reset_handler_data_offset, \ 289 . - __tegra_cpu_reset_handler_start 290__tegra_cpu_reset_handler_data: 291 .rept TEGRA_RESET_DATA_SIZE 292 .long 0 293 .endr 294 .align L1_CACHE_SHIFT 295 296ENTRY(__tegra_cpu_reset_handler_end) 297