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