reset-handler.S (7106B)
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 /* 102 * First call after suspend wakes firmware. No arguments required 103 * for some firmware versions. Downstream kernel of ASUS TF300T uses 104 * r0=3 for the wake-up notification. 105 */ 106 mov r0, #3 107 smc #0 108 109 b cpu_resume 110ENDPROC(tegra_resume_trusted_foundations) 111#endif 112 113 .align L1_CACHE_SHIFT 114ENTRY(__tegra_cpu_reset_handler_start) 115 116/* 117 * __tegra_cpu_reset_handler: 118 * 119 * Common handler for all CPU reset events. 120 * 121 * Register usage within the reset handler: 122 * 123 * Others: scratch 124 * R6 = SoC ID 125 * R7 = CPU present (to the OS) mask 126 * R8 = CPU in LP1 state mask 127 * R9 = CPU in LP2 state mask 128 * R10 = CPU number 129 * R11 = CPU mask 130 * R12 = pointer to reset handler data 131 * 132 * NOTE: This code is copied to IRAM. All code and data accesses 133 * must be position-independent. 134 */ 135 136 .arm 137 .align L1_CACHE_SHIFT 138ENTRY(__tegra_cpu_reset_handler) 139 140 cpsid aif, 0x13 @ SVC mode, interrupts disabled 141 142 tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 143 144 adr r12, __tegra_cpu_reset_handler_data 145 ldr r5, [r12, #RESET_DATA(TF_PRESENT)] 146 cmp r5, #0 147 bne after_errata 148 149#ifdef CONFIG_ARCH_TEGRA_2x_SOC 150t20_check: 151 cmp r6, #TEGRA20 152 bne after_t20_check 153t20_errata: 154 # Tegra20 is a Cortex-A9 r1p1 155 mrc p15, 0, r0, c1, c0, 0 @ read system control register 156 orr r0, r0, #1 << 14 @ erratum 716044 157 mcr p15, 0, r0, c1, c0, 0 @ write system control register 158 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 159 orr r0, r0, #1 << 4 @ erratum 742230 160 orr r0, r0, #1 << 11 @ erratum 751472 161 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 162 b after_errata 163after_t20_check: 164#endif 165#ifdef CONFIG_ARCH_TEGRA_3x_SOC 166t30_check: 167 cmp r6, #TEGRA30 168 bne after_t30_check 169t30_errata: 170 # Tegra30 is a Cortex-A9 r2p9 171 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 172 orr r0, r0, #1 << 6 @ erratum 743622 173 orr r0, r0, #1 << 11 @ erratum 751472 174 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 175 b after_errata 176after_t30_check: 177#endif 178after_errata: 179 mrc p15, 0, r10, c0, c0, 5 @ MPIDR 180 and r10, r10, #0x3 @ R10 = CPU number 181 mov r11, #1 182 mov r11, r11, lsl r10 @ R11 = CPU mask 183 184#ifdef CONFIG_SMP 185 /* Does the OS know about this CPU? */ 186 ldr r7, [r12, #RESET_DATA(MASK_PRESENT)] 187 tst r7, r11 @ if !present 188 bleq __die @ CPU not present (to OS) 189#endif 190 191 /* Waking up from LP1? */ 192 ldr r8, [r12, #RESET_DATA(MASK_LP1)] 193 tst r8, r11 @ if in_lp1 194 beq __is_not_lp1 195 cmp r10, #0 196 bne __die @ only CPU0 can be here 197 ldr lr, [r12, #RESET_DATA(STARTUP_LP1)] 198 cmp lr, #0 199 bleq __die @ no LP1 startup handler 200 THUMB( add lr, lr, #1 ) @ switch to Thumb mode 201 bx lr 202__is_not_lp1: 203 204 /* Waking up from LP2? */ 205 ldr r9, [r12, #RESET_DATA(MASK_LP2)] 206 tst r9, r11 @ if in_lp2 207 beq __is_not_lp2 208 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)] 209 cmp lr, #0 210 bleq __die @ no LP2 startup handler 211 bx lr 212 213__is_not_lp2: 214 215#ifdef CONFIG_SMP 216 /* 217 * Can only be secondary boot (initial or hotplug) 218 * CPU0 can't be here for Tegra20/30 219 */ 220 cmp r6, #TEGRA114 221 beq __no_cpu0_chk 222 cmp r10, #0 223 bleq __die @ CPU0 cannot be here 224__no_cpu0_chk: 225 ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)] 226 cmp lr, #0 227 bleq __die @ no secondary startup handler 228 bx lr 229#endif 230 231/* 232 * We don't know why the CPU reset. Just kill it. 233 * The LR register will contain the address we died at + 4. 234 */ 235 236__die: 237 sub lr, lr, #4 238 mov32 r7, TEGRA_PMC_BASE 239 str lr, [r7, #PMC_SCRATCH41] 240 241 mov32 r7, TEGRA_CLK_RESET_BASE 242 243 /* Are we on Tegra20? */ 244 cmp r6, #TEGRA20 245 bne 1f 246 247#ifdef CONFIG_ARCH_TEGRA_2x_SOC 248 mov32 r0, 0x1111 249 mov r1, r0, lsl r10 250 str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET 251#endif 2521: 253#ifdef CONFIG_ARCH_TEGRA_3x_SOC 254 mov32 r6, TEGRA_FLOW_CTRL_BASE 255 256 cmp r10, #0 257 moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS 258 moveq r2, #FLOW_CTRL_CPU0_CSR 259 movne r1, r10, lsl #3 260 addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8) 261 addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8) 262 263 /* Clear CPU "event" and "interrupt" flags and power gate 264 it when halting but not before it is in the "WFI" state. */ 265 ldr r0, [r6, +r2] 266 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 267 orr r0, r0, #FLOW_CTRL_CSR_ENABLE 268 str r0, [r6, +r2] 269 270 /* Unconditionally halt this CPU */ 271 mov r0, #FLOW_CTRL_WAITEVENT 272 str r0, [r6, +r1] 273 ldr r0, [r6, +r1] @ memory barrier 274 275 dsb 276 isb 277 wfi @ CPU should be power gated here 278 279 /* If the CPU didn't power gate above just kill it's clock. */ 280 281 mov r0, r11, lsl #8 282 str r0, [r7, #348] @ CLK_CPU_CMPLX_SET 283#endif 284 285 /* If the CPU still isn't dead, just spin here. */ 286 b . 287ENDPROC(__tegra_cpu_reset_handler) 288 289 .align L1_CACHE_SHIFT 290 .type __tegra_cpu_reset_handler_data, %object 291 .globl __tegra_cpu_reset_handler_data 292 .globl __tegra_cpu_reset_handler_data_offset 293 .equ __tegra_cpu_reset_handler_data_offset, \ 294 . - __tegra_cpu_reset_handler_start 295__tegra_cpu_reset_handler_data: 296 .rept TEGRA_RESET_DATA_SIZE 297 .long 0 298 .endr 299 .align L1_CACHE_SHIFT 300 301ENTRY(__tegra_cpu_reset_handler_end)