19952f691SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 29e32366fSJoseph Lo/* 39e32366fSJoseph Lo * Copyright (c) 2012, NVIDIA Corporation. All rights reserved. 49e32366fSJoseph Lo */ 59e32366fSJoseph Lo 69e32366fSJoseph Lo#include <linux/init.h> 7a0524accSThierry Reding#include <linux/linkage.h> 89e32366fSJoseph Lo 97e10cf74SJon Hunter#include <soc/tegra/flowctrl.h> 10304664eaSThierry Reding#include <soc/tegra/fuse.h> 11304664eaSThierry Reding 1278ee399fSDmitry Osipenko#include <asm/assembler.h> 139e32366fSJoseph Lo#include <asm/asm-offsets.h> 14a0524accSThierry Reding#include <asm/cache.h> 159e32366fSJoseph Lo 169e32366fSJoseph Lo#include "iomap.h" 179e32366fSJoseph Lo#include "reset.h" 189e32366fSJoseph Lo#include "sleep.h" 199e32366fSJoseph Lo 209e32366fSJoseph Lo#define PMC_SCRATCH41 0x140 219e32366fSJoseph Lo 22*a2faac39SNick Desaulniers.arch armv7-a 23*a2faac39SNick Desaulniers 249e32366fSJoseph Lo#ifdef CONFIG_PM_SLEEP 259e32366fSJoseph Lo/* 269e32366fSJoseph Lo * tegra_resume 279e32366fSJoseph Lo * 289e32366fSJoseph Lo * CPU boot vector when restarting the a CPU following 299e32366fSJoseph Lo * an LP2 transition. Also branched to by LP0 and LP1 resume after 309e32366fSJoseph Lo * re-enabling sdram. 3133d5c019SJoseph Lo * 3233d5c019SJoseph Lo * r6: SoC ID 33c04c7754SJoseph Lo * r8: CPU part number 349e32366fSJoseph Lo */ 359e32366fSJoseph LoENTRY(tegra_resume) 36c04c7754SJoseph Lo check_cpu_part_num 0xc09, r8, r9 37c04c7754SJoseph Lo bleq v7_invalidate_l1 389e32366fSJoseph Lo 399e32366fSJoseph Lo cpu_id r0 409e32366fSJoseph Lo cmp r0, #0 @ CPU0? 41a65dc10fSJoseph Lo THUMB( it ne ) 429e32366fSJoseph Lo bne cpu_resume @ no 439e32366fSJoseph Lo 44e4a68009SDmitry Osipenko tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 459e32366fSJoseph Lo /* Are we on Tegra20? */ 464b3e2edaSJoseph Lo cmp r6, #TEGRA20 479e32366fSJoseph Lo beq 1f @ Yes 489e32366fSJoseph Lo /* Clear the flow controller flags for this CPU. */ 49d70f7d31SDmitry Osipenko cpu_to_csr_reg r3, r0 50ecc4d9daSJoseph Lo mov32 r2, TEGRA_FLOW_CTRL_BASE 51d70f7d31SDmitry Osipenko ldr r1, [r2, r3] 529e32366fSJoseph Lo /* Clear event & intr flag */ 539e32366fSJoseph Lo orr r1, r1, \ 549e32366fSJoseph Lo #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 55ecc4d9daSJoseph Lo movw r0, #0x3FFD @ enable, cluster_switch, immed, bitmaps 56ecc4d9daSJoseph Lo @ & ext flags for CPU power mgnt 579e32366fSJoseph Lo bic r1, r1, r0 58d70f7d31SDmitry Osipenko str r1, [r2, r3] 599e32366fSJoseph Lo1: 609e32366fSJoseph Lo 61c04c7754SJoseph Lo mov32 r9, 0xc09 62c04c7754SJoseph Lo cmp r8, r9 63d127e9c5SJoseph Lo bne end_ca9_scu_l2_resume 649e32366fSJoseph Lo#ifdef CONFIG_HAVE_ARM_SCU 659e32366fSJoseph Lo /* enable SCU */ 669e32366fSJoseph Lo mov32 r0, TEGRA_ARM_PERIF_BASE 679e32366fSJoseph Lo ldr r1, [r0] 689e32366fSJoseph Lo orr r1, r1, #1 699e32366fSJoseph Lo str r1, [r0] 709e32366fSJoseph Lo#endif 7178ee399fSDmitry Osipenko bl tegra_resume_trusted_foundations 729e32366fSJoseph Lo 73b16cee70SRussell King#ifdef CONFIG_CACHE_L2X0 749e32366fSJoseph Lo /* L2 cache resume & re-enable */ 75b16cee70SRussell King bl l2c310_early_resume 76b16cee70SRussell King#endif 77d127e9c5SJoseph Loend_ca9_scu_l2_resume: 78d127e9c5SJoseph Lo mov32 r9, 0xc0f 79d127e9c5SJoseph Lo cmp r8, r9 80d127e9c5SJoseph Lo bleq tegra_init_l2_for_a15 819e32366fSJoseph Lo 829e32366fSJoseph Lo b cpu_resume 839e32366fSJoseph LoENDPROC(tegra_resume) 8478ee399fSDmitry Osipenko 8578ee399fSDmitry Osipenko/* 8678ee399fSDmitry Osipenko * tegra_resume_trusted_foundations 8778ee399fSDmitry Osipenko * 8878ee399fSDmitry Osipenko * Trusted Foundations firmware initialization. 8978ee399fSDmitry Osipenko * 9078ee399fSDmitry Osipenko * Doesn't return if firmware presents. 9178ee399fSDmitry Osipenko * Corrupted registers: r1, r2 9278ee399fSDmitry Osipenko */ 9378ee399fSDmitry OsipenkoENTRY(tegra_resume_trusted_foundations) 9478ee399fSDmitry Osipenko /* Check whether Trusted Foundations firmware presents. */ 9578ee399fSDmitry Osipenko mov32 r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET 9678ee399fSDmitry Osipenko ldr r1, =__tegra_cpu_reset_handler_data_offset + \ 9778ee399fSDmitry Osipenko RESET_DATA(TF_PRESENT) 9878ee399fSDmitry Osipenko ldr r1, [r2, r1] 9978ee399fSDmitry Osipenko cmp r1, #0 10078ee399fSDmitry Osipenko reteq lr 10178ee399fSDmitry Osipenko 10278ee399fSDmitry Osipenko .arch_extension sec 10336dc3b1aSDmitry Osipenko /* 10436dc3b1aSDmitry Osipenko * First call after suspend wakes firmware. No arguments required 10536dc3b1aSDmitry Osipenko * for some firmware versions. Downstream kernel of ASUS TF300T uses 10636dc3b1aSDmitry Osipenko * r0=3 for the wake-up notification. 10736dc3b1aSDmitry Osipenko */ 10836dc3b1aSDmitry Osipenko mov r0, #3 10978ee399fSDmitry Osipenko smc #0 11078ee399fSDmitry Osipenko 11178ee399fSDmitry Osipenko b cpu_resume 11278ee399fSDmitry OsipenkoENDPROC(tegra_resume_trusted_foundations) 1139e32366fSJoseph Lo#endif 1149e32366fSJoseph Lo 1159e32366fSJoseph Lo .align L1_CACHE_SHIFT 1169e32366fSJoseph LoENTRY(__tegra_cpu_reset_handler_start) 1179e32366fSJoseph Lo 1189e32366fSJoseph Lo/* 1199e32366fSJoseph Lo * __tegra_cpu_reset_handler: 1209e32366fSJoseph Lo * 1219e32366fSJoseph Lo * Common handler for all CPU reset events. 1229e32366fSJoseph Lo * 1239e32366fSJoseph Lo * Register usage within the reset handler: 1249e32366fSJoseph Lo * 125c34f30e5SStephen Warren * Others: scratch 1264b3e2edaSJoseph Lo * R6 = SoC ID 1279e32366fSJoseph Lo * R7 = CPU present (to the OS) mask 1289e32366fSJoseph Lo * R8 = CPU in LP1 state mask 1299e32366fSJoseph Lo * R9 = CPU in LP2 state mask 1309e32366fSJoseph Lo * R10 = CPU number 1319e32366fSJoseph Lo * R11 = CPU mask 1329e32366fSJoseph Lo * R12 = pointer to reset handler data 1339e32366fSJoseph Lo * 1349e32366fSJoseph Lo * NOTE: This code is copied to IRAM. All code and data accesses 1359e32366fSJoseph Lo * must be position-independent. 1369e32366fSJoseph Lo */ 1379e32366fSJoseph Lo 138dae84be5SDmitry Osipenko .arm 1399e32366fSJoseph Lo .align L1_CACHE_SHIFT 1409e32366fSJoseph LoENTRY(__tegra_cpu_reset_handler) 1419e32366fSJoseph Lo 1429e32366fSJoseph Lo cpsid aif, 0x13 @ SVC mode, interrupts disabled 143c34f30e5SStephen Warren 1444b3e2edaSJoseph Lo tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 1452af6597aSDmitry Osipenko 1462af6597aSDmitry Osipenko adr r12, __tegra_cpu_reset_handler_data 1472af6597aSDmitry Osipenko ldr r5, [r12, #RESET_DATA(TF_PRESENT)] 1482af6597aSDmitry Osipenko cmp r5, #0 1492af6597aSDmitry Osipenko bne after_errata 1502af6597aSDmitry Osipenko 151c34f30e5SStephen Warren#ifdef CONFIG_ARCH_TEGRA_2x_SOC 152c34f30e5SStephen Warrent20_check: 1534b3e2edaSJoseph Lo cmp r6, #TEGRA20 154c34f30e5SStephen Warren bne after_t20_check 155c34f30e5SStephen Warrent20_errata: 156c34f30e5SStephen Warren # Tegra20 is a Cortex-A9 r1p1 157c34f30e5SStephen Warren mrc p15, 0, r0, c1, c0, 0 @ read system control register 158c34f30e5SStephen Warren orr r0, r0, #1 << 14 @ erratum 716044 159c34f30e5SStephen Warren mcr p15, 0, r0, c1, c0, 0 @ write system control register 160c34f30e5SStephen Warren mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 161c34f30e5SStephen Warren orr r0, r0, #1 << 4 @ erratum 742230 162c34f30e5SStephen Warren orr r0, r0, #1 << 11 @ erratum 751472 163c34f30e5SStephen Warren mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 164c34f30e5SStephen Warren b after_errata 165c34f30e5SStephen Warrenafter_t20_check: 166c34f30e5SStephen Warren#endif 167c34f30e5SStephen Warren#ifdef CONFIG_ARCH_TEGRA_3x_SOC 168c34f30e5SStephen Warrent30_check: 1694b3e2edaSJoseph Lo cmp r6, #TEGRA30 170c34f30e5SStephen Warren bne after_t30_check 171c34f30e5SStephen Warrent30_errata: 172c34f30e5SStephen Warren # Tegra30 is a Cortex-A9 r2p9 173c34f30e5SStephen Warren mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register 174c34f30e5SStephen Warren orr r0, r0, #1 << 6 @ erratum 743622 175c34f30e5SStephen Warren orr r0, r0, #1 << 11 @ erratum 751472 176c34f30e5SStephen Warren mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register 177c34f30e5SStephen Warren b after_errata 178c34f30e5SStephen Warrenafter_t30_check: 179c34f30e5SStephen Warren#endif 180c34f30e5SStephen Warrenafter_errata: 1819e32366fSJoseph Lo mrc p15, 0, r10, c0, c0, 5 @ MPIDR 1829e32366fSJoseph Lo and r10, r10, #0x3 @ R10 = CPU number 1839e32366fSJoseph Lo mov r11, #1 1849e32366fSJoseph Lo mov r11, r11, lsl r10 @ R11 = CPU mask 1859e32366fSJoseph Lo 1869e32366fSJoseph Lo#ifdef CONFIG_SMP 1879e32366fSJoseph Lo /* Does the OS know about this CPU? */ 1889e32366fSJoseph Lo ldr r7, [r12, #RESET_DATA(MASK_PRESENT)] 1899e32366fSJoseph Lo tst r7, r11 @ if !present 1909e32366fSJoseph Lo bleq __die @ CPU not present (to OS) 1919e32366fSJoseph Lo#endif 1929e32366fSJoseph Lo 1935b795d05SJoseph Lo /* Waking up from LP1? */ 1945b795d05SJoseph Lo ldr r8, [r12, #RESET_DATA(MASK_LP1)] 1955b795d05SJoseph Lo tst r8, r11 @ if in_lp1 1965b795d05SJoseph Lo beq __is_not_lp1 1975b795d05SJoseph Lo cmp r10, #0 1985b795d05SJoseph Lo bne __die @ only CPU0 can be here 1995b795d05SJoseph Lo ldr lr, [r12, #RESET_DATA(STARTUP_LP1)] 2005b795d05SJoseph Lo cmp lr, #0 2015b795d05SJoseph Lo bleq __die @ no LP1 startup handler 2025b795d05SJoseph Lo THUMB( add lr, lr, #1 ) @ switch to Thumb mode 2035b795d05SJoseph Lo bx lr 2045b795d05SJoseph Lo__is_not_lp1: 2055b795d05SJoseph Lo 2069e32366fSJoseph Lo /* Waking up from LP2? */ 2079e32366fSJoseph Lo ldr r9, [r12, #RESET_DATA(MASK_LP2)] 2089e32366fSJoseph Lo tst r9, r11 @ if in_lp2 2099e32366fSJoseph Lo beq __is_not_lp2 2109e32366fSJoseph Lo ldr lr, [r12, #RESET_DATA(STARTUP_LP2)] 2119e32366fSJoseph Lo cmp lr, #0 2129e32366fSJoseph Lo bleq __die @ no LP2 startup handler 2139e32366fSJoseph Lo bx lr 2149e32366fSJoseph Lo 2159e32366fSJoseph Lo__is_not_lp2: 2169e32366fSJoseph Lo 2179e32366fSJoseph Lo#ifdef CONFIG_SMP 2189e32366fSJoseph Lo /* 21933d5c019SJoseph Lo * Can only be secondary boot (initial or hotplug) 22033d5c019SJoseph Lo * CPU0 can't be here for Tegra20/30 2219e32366fSJoseph Lo */ 22233d5c019SJoseph Lo cmp r6, #TEGRA114 22333d5c019SJoseph Lo beq __no_cpu0_chk 2249e32366fSJoseph Lo cmp r10, #0 2259e32366fSJoseph Lo bleq __die @ CPU0 cannot be here 22633d5c019SJoseph Lo__no_cpu0_chk: 2279e32366fSJoseph Lo ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)] 2289e32366fSJoseph Lo cmp lr, #0 2299e32366fSJoseph Lo bleq __die @ no secondary startup handler 2309e32366fSJoseph Lo bx lr 2319e32366fSJoseph Lo#endif 2329e32366fSJoseph Lo 2339e32366fSJoseph Lo/* 2349e32366fSJoseph Lo * We don't know why the CPU reset. Just kill it. 2359e32366fSJoseph Lo * The LR register will contain the address we died at + 4. 2369e32366fSJoseph Lo */ 2379e32366fSJoseph Lo 2389e32366fSJoseph Lo__die: 2399e32366fSJoseph Lo sub lr, lr, #4 2409e32366fSJoseph Lo mov32 r7, TEGRA_PMC_BASE 2419e32366fSJoseph Lo str lr, [r7, #PMC_SCRATCH41] 2429e32366fSJoseph Lo 2439e32366fSJoseph Lo mov32 r7, TEGRA_CLK_RESET_BASE 2449e32366fSJoseph Lo 2459e32366fSJoseph Lo /* Are we on Tegra20? */ 2464b3e2edaSJoseph Lo cmp r6, #TEGRA20 2479e32366fSJoseph Lo bne 1f 2489e32366fSJoseph Lo 2499e32366fSJoseph Lo#ifdef CONFIG_ARCH_TEGRA_2x_SOC 2509e32366fSJoseph Lo mov32 r0, 0x1111 2519e32366fSJoseph Lo mov r1, r0, lsl r10 2529e32366fSJoseph Lo str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET 2539e32366fSJoseph Lo#endif 2549e32366fSJoseph Lo1: 2559e32366fSJoseph Lo#ifdef CONFIG_ARCH_TEGRA_3x_SOC 2569e32366fSJoseph Lo mov32 r6, TEGRA_FLOW_CTRL_BASE 2579e32366fSJoseph Lo 2589e32366fSJoseph Lo cmp r10, #0 2599e32366fSJoseph Lo moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS 2609e32366fSJoseph Lo moveq r2, #FLOW_CTRL_CPU0_CSR 2619e32366fSJoseph Lo movne r1, r10, lsl #3 2629e32366fSJoseph Lo addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8) 2639e32366fSJoseph Lo addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8) 2649e32366fSJoseph Lo 2659e32366fSJoseph Lo /* Clear CPU "event" and "interrupt" flags and power gate 2669e32366fSJoseph Lo it when halting but not before it is in the "WFI" state. */ 2679e32366fSJoseph Lo ldr r0, [r6, +r2] 2689e32366fSJoseph Lo orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 2699e32366fSJoseph Lo orr r0, r0, #FLOW_CTRL_CSR_ENABLE 2709e32366fSJoseph Lo str r0, [r6, +r2] 2719e32366fSJoseph Lo 2729e32366fSJoseph Lo /* Unconditionally halt this CPU */ 2739e32366fSJoseph Lo mov r0, #FLOW_CTRL_WAITEVENT 2749e32366fSJoseph Lo str r0, [r6, +r1] 2759e32366fSJoseph Lo ldr r0, [r6, +r1] @ memory barrier 2769e32366fSJoseph Lo 2779e32366fSJoseph Lo dsb 2789e32366fSJoseph Lo isb 2799e32366fSJoseph Lo wfi @ CPU should be power gated here 2809e32366fSJoseph Lo 2819e32366fSJoseph Lo /* If the CPU didn't power gate above just kill it's clock. */ 2829e32366fSJoseph Lo 2839e32366fSJoseph Lo mov r0, r11, lsl #8 2849e32366fSJoseph Lo str r0, [r7, #348] @ CLK_CPU_CMPLX_SET 2859e32366fSJoseph Lo#endif 2869e32366fSJoseph Lo 2879e32366fSJoseph Lo /* If the CPU still isn't dead, just spin here. */ 2889e32366fSJoseph Lo b . 2899e32366fSJoseph LoENDPROC(__tegra_cpu_reset_handler) 2909e32366fSJoseph Lo 2919e32366fSJoseph Lo .align L1_CACHE_SHIFT 2929e32366fSJoseph Lo .type __tegra_cpu_reset_handler_data, %object 2939e32366fSJoseph Lo .globl __tegra_cpu_reset_handler_data 2942af6597aSDmitry Osipenko .globl __tegra_cpu_reset_handler_data_offset 2952af6597aSDmitry Osipenko .equ __tegra_cpu_reset_handler_data_offset, \ 2962af6597aSDmitry Osipenko . - __tegra_cpu_reset_handler_start 2979e32366fSJoseph Lo__tegra_cpu_reset_handler_data: 2989e32366fSJoseph Lo .rept TEGRA_RESET_DATA_SIZE 2999e32366fSJoseph Lo .long 0 3009e32366fSJoseph Lo .endr 3019e32366fSJoseph Lo .align L1_CACHE_SHIFT 3029e32366fSJoseph Lo 3039e32366fSJoseph LoENTRY(__tegra_cpu_reset_handler_end) 304