19e32366fSJoseph Lo/* 29e32366fSJoseph Lo * Copyright (c) 2012, NVIDIA Corporation. All rights reserved. 39e32366fSJoseph Lo * 49e32366fSJoseph Lo * This program is free software; you can redistribute it and/or modify it 59e32366fSJoseph Lo * under the terms and conditions of the GNU General Public License, 69e32366fSJoseph Lo * version 2, as published by the Free Software Foundation. 79e32366fSJoseph Lo * 89e32366fSJoseph Lo * This program is distributed in the hope it will be useful, but WITHOUT 99e32366fSJoseph Lo * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 109e32366fSJoseph Lo * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 119e32366fSJoseph Lo * more details. 129e32366fSJoseph Lo * 139e32366fSJoseph Lo * You should have received a copy of the GNU General Public License 149e32366fSJoseph Lo * along with this program. If not, see <http://www.gnu.org/licenses/>. 159e32366fSJoseph Lo */ 169e32366fSJoseph Lo 179e32366fSJoseph Lo#include <linux/linkage.h> 189e32366fSJoseph Lo#include <linux/init.h> 199e32366fSJoseph Lo 209e32366fSJoseph Lo#include <asm/cache.h> 219e32366fSJoseph Lo#include <asm/asm-offsets.h> 229e32366fSJoseph Lo#include <asm/hardware/cache-l2x0.h> 239e32366fSJoseph Lo 249e32366fSJoseph Lo#include "flowctrl.h" 259e32366fSJoseph Lo#include "iomap.h" 269e32366fSJoseph Lo#include "reset.h" 279e32366fSJoseph Lo#include "sleep.h" 289e32366fSJoseph Lo 299e32366fSJoseph Lo#define APB_MISC_GP_HIDREV 0x804 309e32366fSJoseph Lo#define PMC_SCRATCH41 0x140 319e32366fSJoseph Lo 329e32366fSJoseph Lo#define RESET_DATA(x) ((TEGRA_RESET_##x)*4) 339e32366fSJoseph Lo 349e32366fSJoseph Lo#ifdef CONFIG_PM_SLEEP 359e32366fSJoseph Lo/* 369e32366fSJoseph Lo * tegra_resume 379e32366fSJoseph Lo * 389e32366fSJoseph Lo * CPU boot vector when restarting the a CPU following 399e32366fSJoseph Lo * an LP2 transition. Also branched to by LP0 and LP1 resume after 409e32366fSJoseph Lo * re-enabling sdram. 419e32366fSJoseph Lo */ 429e32366fSJoseph LoENTRY(tegra_resume) 439e32366fSJoseph Lo bl v7_invalidate_l1 449e32366fSJoseph Lo 459e32366fSJoseph Lo cpu_id r0 469e32366fSJoseph Lo cmp r0, #0 @ CPU0? 47*a65dc10fSJoseph Lo THUMB( it ne ) 489e32366fSJoseph Lo bne cpu_resume @ no 499e32366fSJoseph Lo 509e32366fSJoseph Lo#ifdef CONFIG_ARCH_TEGRA_3x_SOC 519e32366fSJoseph Lo /* Are we on Tegra20? */ 529e32366fSJoseph Lo mov32 r6, TEGRA_APB_MISC_BASE 539e32366fSJoseph Lo ldr r0, [r6, #APB_MISC_GP_HIDREV] 549e32366fSJoseph Lo and r0, r0, #0xff00 559e32366fSJoseph Lo cmp r0, #(0x20 << 8) 569e32366fSJoseph Lo beq 1f @ Yes 579e32366fSJoseph Lo /* Clear the flow controller flags for this CPU. */ 589e32366fSJoseph Lo mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR 599e32366fSJoseph Lo ldr r1, [r2] 609e32366fSJoseph Lo /* Clear event & intr flag */ 619e32366fSJoseph Lo orr r1, r1, \ 629e32366fSJoseph Lo #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 639e32366fSJoseph Lo movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps 649e32366fSJoseph Lo bic r1, r1, r0 659e32366fSJoseph Lo str r1, [r2] 669e32366fSJoseph Lo1: 679e32366fSJoseph Lo#endif 689e32366fSJoseph Lo 699e32366fSJoseph Lo#ifdef CONFIG_HAVE_ARM_SCU 709e32366fSJoseph Lo /* enable SCU */ 719e32366fSJoseph Lo mov32 r0, TEGRA_ARM_PERIF_BASE 729e32366fSJoseph Lo ldr r1, [r0] 739e32366fSJoseph Lo orr r1, r1, #1 749e32366fSJoseph Lo str r1, [r0] 759e32366fSJoseph Lo#endif 769e32366fSJoseph Lo 779e32366fSJoseph Lo /* L2 cache resume & re-enable */ 789e32366fSJoseph Lo l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr 799e32366fSJoseph Lo 809e32366fSJoseph Lo b cpu_resume 819e32366fSJoseph LoENDPROC(tegra_resume) 829e32366fSJoseph Lo#endif 839e32366fSJoseph Lo 849e32366fSJoseph Lo#ifdef CONFIG_CACHE_L2X0 859e32366fSJoseph Lo .globl l2x0_saved_regs_addr 869e32366fSJoseph Lol2x0_saved_regs_addr: 879e32366fSJoseph Lo .long 0 889e32366fSJoseph Lo#endif 899e32366fSJoseph Lo 909e32366fSJoseph Lo .align L1_CACHE_SHIFT 919e32366fSJoseph LoENTRY(__tegra_cpu_reset_handler_start) 929e32366fSJoseph Lo 939e32366fSJoseph Lo/* 949e32366fSJoseph Lo * __tegra_cpu_reset_handler: 959e32366fSJoseph Lo * 969e32366fSJoseph Lo * Common handler for all CPU reset events. 979e32366fSJoseph Lo * 989e32366fSJoseph Lo * Register usage within the reset handler: 999e32366fSJoseph Lo * 100c34f30e5SStephen Warren * Others: scratch 101c34f30e5SStephen Warren * R6 = SoC ID << 8 1029e32366fSJoseph Lo * R7 = CPU present (to the OS) mask 1039e32366fSJoseph Lo * R8 = CPU in LP1 state mask 1049e32366fSJoseph Lo * R9 = CPU in LP2 state mask 1059e32366fSJoseph Lo * R10 = CPU number 1069e32366fSJoseph Lo * R11 = CPU mask 1079e32366fSJoseph Lo * R12 = pointer to reset handler data 1089e32366fSJoseph Lo * 1099e32366fSJoseph Lo * NOTE: This code is copied to IRAM. All code and data accesses 1109e32366fSJoseph Lo * must be position-independent. 1119e32366fSJoseph Lo */ 1129e32366fSJoseph Lo 1139e32366fSJoseph Lo .align L1_CACHE_SHIFT 1149e32366fSJoseph LoENTRY(__tegra_cpu_reset_handler) 1159e32366fSJoseph Lo 1169e32366fSJoseph Lo cpsid aif, 0x13 @ SVC mode, interrupts disabled 117c34f30e5SStephen Warren 118c34f30e5SStephen Warren mov32 r6, TEGRA_APB_MISC_BASE 119c34f30e5SStephen Warren ldr r6, [r6, #APB_MISC_GP_HIDREV] 120c34f30e5SStephen Warren and r6, r6, #0xff00 121c34f30e5SStephen Warren#ifdef CONFIG_ARCH_TEGRA_2x_SOC 122c34f30e5SStephen Warrent20_check: 123c34f30e5SStephen Warren cmp r6, #(0x20 << 8) 124c34f30e5SStephen Warren bne after_t20_check 125c34f30e5SStephen Warrent20_errata: 126c34f30e5SStephen Warren # Tegra20 is a Cortex-A9 r1p1 127c34f30e5SStephen Warren mrc p15, 0, r0, c1, c0, 0 @ read system control register 128c34f30e5SStephen Warren orr r0, r0, #1 << 14 @ erratum 716044 129c34f30e5SStephen Warren mcr p15, 0, r0, c1, c0, 0 @ write system control register 130c34f30e5SStephen Warren mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 131c34f30e5SStephen Warren orr r0, r0, #1 << 4 @ erratum 742230 132c34f30e5SStephen Warren orr r0, r0, #1 << 11 @ erratum 751472 133c34f30e5SStephen Warren mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 134c34f30e5SStephen Warren b after_errata 135c34f30e5SStephen Warrenafter_t20_check: 136c34f30e5SStephen Warren#endif 137c34f30e5SStephen Warren#ifdef CONFIG_ARCH_TEGRA_3x_SOC 138c34f30e5SStephen Warrent30_check: 139c34f30e5SStephen Warren cmp r6, #(0x30 << 8) 140c34f30e5SStephen Warren bne after_t30_check 141c34f30e5SStephen Warrent30_errata: 142c34f30e5SStephen Warren # Tegra30 is a Cortex-A9 r2p9 143c34f30e5SStephen Warren mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 144c34f30e5SStephen Warren orr r0, r0, #1 << 6 @ erratum 743622 145c34f30e5SStephen Warren orr r0, r0, #1 << 11 @ erratum 751472 146c34f30e5SStephen Warren mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 147c34f30e5SStephen Warren b after_errata 148c34f30e5SStephen Warrenafter_t30_check: 149c34f30e5SStephen Warren#endif 150c34f30e5SStephen Warrenafter_errata: 1519e32366fSJoseph Lo mrc p15, 0, r10, c0, c0, 5 @ MPIDR 1529e32366fSJoseph Lo and r10, r10, #0x3 @ R10 = CPU number 1539e32366fSJoseph Lo mov r11, #1 1549e32366fSJoseph Lo mov r11, r11, lsl r10 @ R11 = CPU mask 1559e32366fSJoseph Lo adr r12, __tegra_cpu_reset_handler_data 1569e32366fSJoseph Lo 1579e32366fSJoseph Lo#ifdef CONFIG_SMP 1589e32366fSJoseph Lo /* Does the OS know about this CPU? */ 1599e32366fSJoseph Lo ldr r7, [r12, #RESET_DATA(MASK_PRESENT)] 1609e32366fSJoseph Lo tst r7, r11 @ if !present 1619e32366fSJoseph Lo bleq __die @ CPU not present (to OS) 1629e32366fSJoseph Lo#endif 1639e32366fSJoseph Lo 1649e32366fSJoseph Lo#ifdef CONFIG_ARCH_TEGRA_2x_SOC 1659e32366fSJoseph Lo /* Are we on Tegra20? */ 166c34f30e5SStephen Warren cmp r6, #(0x20 << 8) 1679e32366fSJoseph Lo bne 1f 1689e32366fSJoseph Lo /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ 169c34f30e5SStephen Warren mov32 r5, TEGRA_PMC_BASE 1709e32366fSJoseph Lo mov r0, #0 1719e32366fSJoseph Lo cmp r10, #0 172c34f30e5SStephen Warren strne r0, [r5, #PMC_SCRATCH41] 1739e32366fSJoseph Lo1: 1749e32366fSJoseph Lo#endif 1759e32366fSJoseph Lo 1769e32366fSJoseph Lo /* Waking up from LP2? */ 1779e32366fSJoseph Lo ldr r9, [r12, #RESET_DATA(MASK_LP2)] 1789e32366fSJoseph Lo tst r9, r11 @ if in_lp2 1799e32366fSJoseph Lo beq __is_not_lp2 1809e32366fSJoseph Lo ldr lr, [r12, #RESET_DATA(STARTUP_LP2)] 1819e32366fSJoseph Lo cmp lr, #0 1829e32366fSJoseph Lo bleq __die @ no LP2 startup handler 1839e32366fSJoseph Lo bx lr 1849e32366fSJoseph Lo 1859e32366fSJoseph Lo__is_not_lp2: 1869e32366fSJoseph Lo 1879e32366fSJoseph Lo#ifdef CONFIG_SMP 1889e32366fSJoseph Lo /* 1899e32366fSJoseph Lo * Can only be secondary boot (initial or hotplug) but CPU 0 1909e32366fSJoseph Lo * cannot be here. 1919e32366fSJoseph Lo */ 1929e32366fSJoseph Lo cmp r10, #0 1939e32366fSJoseph Lo bleq __die @ CPU0 cannot be here 1949e32366fSJoseph Lo ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)] 1959e32366fSJoseph Lo cmp lr, #0 1969e32366fSJoseph Lo bleq __die @ no secondary startup handler 1979e32366fSJoseph Lo bx lr 1989e32366fSJoseph Lo#endif 1999e32366fSJoseph Lo 2009e32366fSJoseph Lo/* 2019e32366fSJoseph Lo * We don't know why the CPU reset. Just kill it. 2029e32366fSJoseph Lo * The LR register will contain the address we died at + 4. 2039e32366fSJoseph Lo */ 2049e32366fSJoseph Lo 2059e32366fSJoseph Lo__die: 2069e32366fSJoseph Lo sub lr, lr, #4 2079e32366fSJoseph Lo mov32 r7, TEGRA_PMC_BASE 2089e32366fSJoseph Lo str lr, [r7, #PMC_SCRATCH41] 2099e32366fSJoseph Lo 2109e32366fSJoseph Lo mov32 r7, TEGRA_CLK_RESET_BASE 2119e32366fSJoseph Lo 2129e32366fSJoseph Lo /* Are we on Tegra20? */ 2139e32366fSJoseph Lo mov32 r6, TEGRA_APB_MISC_BASE 2149e32366fSJoseph Lo ldr r0, [r6, #APB_MISC_GP_HIDREV] 2159e32366fSJoseph Lo and r0, r0, #0xff00 2169e32366fSJoseph Lo cmp r0, #(0x20 << 8) 2179e32366fSJoseph Lo bne 1f 2189e32366fSJoseph Lo 2199e32366fSJoseph Lo#ifdef CONFIG_ARCH_TEGRA_2x_SOC 2209e32366fSJoseph Lo mov32 r0, 0x1111 2219e32366fSJoseph Lo mov r1, r0, lsl r10 2229e32366fSJoseph Lo str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET 2239e32366fSJoseph Lo#endif 2249e32366fSJoseph Lo1: 2259e32366fSJoseph Lo#ifdef CONFIG_ARCH_TEGRA_3x_SOC 2269e32366fSJoseph Lo mov32 r6, TEGRA_FLOW_CTRL_BASE 2279e32366fSJoseph Lo 2289e32366fSJoseph Lo cmp r10, #0 2299e32366fSJoseph Lo moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS 2309e32366fSJoseph Lo moveq r2, #FLOW_CTRL_CPU0_CSR 2319e32366fSJoseph Lo movne r1, r10, lsl #3 2329e32366fSJoseph Lo addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8) 2339e32366fSJoseph Lo addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8) 2349e32366fSJoseph Lo 2359e32366fSJoseph Lo /* Clear CPU "event" and "interrupt" flags and power gate 2369e32366fSJoseph Lo it when halting but not before it is in the "WFI" state. */ 2379e32366fSJoseph Lo ldr r0, [r6, +r2] 2389e32366fSJoseph Lo orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 2399e32366fSJoseph Lo orr r0, r0, #FLOW_CTRL_CSR_ENABLE 2409e32366fSJoseph Lo str r0, [r6, +r2] 2419e32366fSJoseph Lo 2429e32366fSJoseph Lo /* Unconditionally halt this CPU */ 2439e32366fSJoseph Lo mov r0, #FLOW_CTRL_WAITEVENT 2449e32366fSJoseph Lo str r0, [r6, +r1] 2459e32366fSJoseph Lo ldr r0, [r6, +r1] @ memory barrier 2469e32366fSJoseph Lo 2479e32366fSJoseph Lo dsb 2489e32366fSJoseph Lo isb 2499e32366fSJoseph Lo wfi @ CPU should be power gated here 2509e32366fSJoseph Lo 2519e32366fSJoseph Lo /* If the CPU didn't power gate above just kill it's clock. */ 2529e32366fSJoseph Lo 2539e32366fSJoseph Lo mov r0, r11, lsl #8 2549e32366fSJoseph Lo str r0, [r7, #348] @ CLK_CPU_CMPLX_SET 2559e32366fSJoseph Lo#endif 2569e32366fSJoseph Lo 2579e32366fSJoseph Lo /* If the CPU still isn't dead, just spin here. */ 2589e32366fSJoseph Lo b . 2599e32366fSJoseph LoENDPROC(__tegra_cpu_reset_handler) 2609e32366fSJoseph Lo 2619e32366fSJoseph Lo .align L1_CACHE_SHIFT 2629e32366fSJoseph Lo .type __tegra_cpu_reset_handler_data, %object 2639e32366fSJoseph Lo .globl __tegra_cpu_reset_handler_data 2649e32366fSJoseph Lo__tegra_cpu_reset_handler_data: 2659e32366fSJoseph Lo .rept TEGRA_RESET_DATA_SIZE 2669e32366fSJoseph Lo .long 0 2679e32366fSJoseph Lo .endr 2689e32366fSJoseph Lo .align L1_CACHE_SHIFT 2699e32366fSJoseph Lo 2709e32366fSJoseph LoENTRY(__tegra_cpu_reset_handler_end) 271