1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * arch/arm/mach-tegra/reset.c 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2011,2012 NVIDIA Corporation. 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun #include <linux/bitops.h> 9*4882a593Smuzhiyun #include <linux/cpumask.h> 10*4882a593Smuzhiyun #include <linux/init.h> 11*4882a593Smuzhiyun #include <linux/io.h> 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun #include <linux/firmware/trusted_foundations.h> 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun #include <soc/tegra/fuse.h> 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #include <asm/cacheflush.h> 18*4882a593Smuzhiyun #include <asm/firmware.h> 19*4882a593Smuzhiyun #include <asm/hardware/cache-l2x0.h> 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun #include "iomap.h" 22*4882a593Smuzhiyun #include "irammap.h" 23*4882a593Smuzhiyun #include "reset.h" 24*4882a593Smuzhiyun #include "sleep.h" 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \ 27*4882a593Smuzhiyun TEGRA_IRAM_RESET_HANDLER_OFFSET) 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun static bool is_enabled; 30*4882a593Smuzhiyun tegra_cpu_reset_handler_set(const u32 reset_address)31*4882a593Smuzhiyunstatic void __init tegra_cpu_reset_handler_set(const u32 reset_address) 32*4882a593Smuzhiyun { 33*4882a593Smuzhiyun void __iomem *evp_cpu_reset = 34*4882a593Smuzhiyun IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); 35*4882a593Smuzhiyun void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); 36*4882a593Smuzhiyun u32 reg; 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun /* 39*4882a593Smuzhiyun * NOTE: This must be the one and only write to the EVP CPU reset 40*4882a593Smuzhiyun * vector in the entire system. 41*4882a593Smuzhiyun */ 42*4882a593Smuzhiyun writel(reset_address, evp_cpu_reset); 43*4882a593Smuzhiyun wmb(); 44*4882a593Smuzhiyun reg = readl(evp_cpu_reset); 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun /* 47*4882a593Smuzhiyun * Prevent further modifications to the physical reset vector. 48*4882a593Smuzhiyun * NOTE: Has no effect on chips prior to Tegra30. 49*4882a593Smuzhiyun */ 50*4882a593Smuzhiyun reg = readl(sb_ctrl); 51*4882a593Smuzhiyun reg |= 2; 52*4882a593Smuzhiyun writel(reg, sb_ctrl); 53*4882a593Smuzhiyun wmb(); 54*4882a593Smuzhiyun } 55*4882a593Smuzhiyun tegra_cpu_reset_handler_enable(void)56*4882a593Smuzhiyunstatic void __init tegra_cpu_reset_handler_enable(void) 57*4882a593Smuzhiyun { 58*4882a593Smuzhiyun void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); 59*4882a593Smuzhiyun const u32 reset_address = TEGRA_IRAM_RESET_BASE + 60*4882a593Smuzhiyun tegra_cpu_reset_handler_offset; 61*4882a593Smuzhiyun int err; 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun BUG_ON(is_enabled); 64*4882a593Smuzhiyun BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, 67*4882a593Smuzhiyun tegra_cpu_reset_handler_size); 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun err = call_firmware_op(set_cpu_boot_addr, 0, reset_address); 70*4882a593Smuzhiyun switch (err) { 71*4882a593Smuzhiyun case -ENOSYS: 72*4882a593Smuzhiyun tegra_cpu_reset_handler_set(reset_address); 73*4882a593Smuzhiyun fallthrough; 74*4882a593Smuzhiyun case 0: 75*4882a593Smuzhiyun is_enabled = true; 76*4882a593Smuzhiyun break; 77*4882a593Smuzhiyun default: 78*4882a593Smuzhiyun pr_crit("Cannot set CPU reset handler: %d\n", err); 79*4882a593Smuzhiyun BUG(); 80*4882a593Smuzhiyun } 81*4882a593Smuzhiyun } 82*4882a593Smuzhiyun tegra_cpu_reset_handler_init(void)83*4882a593Smuzhiyunvoid __init tegra_cpu_reset_handler_init(void) 84*4882a593Smuzhiyun { 85*4882a593Smuzhiyun __tegra_cpu_reset_handler_data[TEGRA_RESET_TF_PRESENT] = 86*4882a593Smuzhiyun trusted_foundations_registered(); 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun #ifdef CONFIG_SMP 89*4882a593Smuzhiyun __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] = 90*4882a593Smuzhiyun *((u32 *)cpu_possible_mask); 91*4882a593Smuzhiyun __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] = 92*4882a593Smuzhiyun __pa_symbol((void *)secondary_startup); 93*4882a593Smuzhiyun #endif 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP 96*4882a593Smuzhiyun __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] = 97*4882a593Smuzhiyun TEGRA_IRAM_LPx_RESUME_AREA; 98*4882a593Smuzhiyun __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] = 99*4882a593Smuzhiyun __pa_symbol((void *)tegra_resume); 100*4882a593Smuzhiyun #endif 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun tegra_cpu_reset_handler_enable(); 103*4882a593Smuzhiyun } 104