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