0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/bitops.h>
0009 #include <linux/cpumask.h>
0010 #include <linux/init.h>
0011 #include <linux/io.h>
0012
0013 #include <linux/firmware/trusted_foundations.h>
0014
0015 #include <soc/tegra/fuse.h>
0016
0017 #include <asm/cacheflush.h>
0018 #include <asm/firmware.h>
0019 #include <asm/hardware/cache-l2x0.h>
0020
0021 #include "iomap.h"
0022 #include "irammap.h"
0023 #include "reset.h"
0024 #include "sleep.h"
0025
0026 #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
0027 TEGRA_IRAM_RESET_HANDLER_OFFSET)
0028
0029 static bool is_enabled;
0030
0031 static void __init tegra_cpu_reset_handler_set(const u32 reset_address)
0032 {
0033 void __iomem *evp_cpu_reset =
0034 IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
0035 void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);
0036 u32 reg;
0037
0038
0039
0040
0041
0042 writel(reset_address, evp_cpu_reset);
0043 wmb();
0044 reg = readl(evp_cpu_reset);
0045
0046
0047
0048
0049
0050 reg = readl(sb_ctrl);
0051 reg |= 2;
0052 writel(reg, sb_ctrl);
0053 wmb();
0054 }
0055
0056 static void __init tegra_cpu_reset_handler_enable(void)
0057 {
0058 void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE);
0059 const u32 reset_address = TEGRA_IRAM_RESET_BASE +
0060 tegra_cpu_reset_handler_offset;
0061 int err;
0062
0063 BUG_ON(is_enabled);
0064 BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE);
0065
0066 memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start,
0067 tegra_cpu_reset_handler_size);
0068
0069 err = call_firmware_op(set_cpu_boot_addr, 0, reset_address);
0070 switch (err) {
0071 case -ENOSYS:
0072 tegra_cpu_reset_handler_set(reset_address);
0073 fallthrough;
0074 case 0:
0075 is_enabled = true;
0076 break;
0077 default:
0078 pr_crit("Cannot set CPU reset handler: %d\n", err);
0079 BUG();
0080 }
0081 }
0082
0083 void __init tegra_cpu_reset_handler_init(void)
0084 {
0085 __tegra_cpu_reset_handler_data[TEGRA_RESET_TF_PRESENT] =
0086 trusted_foundations_registered();
0087
0088 #ifdef CONFIG_SMP
0089 __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
0090 *((u32 *)cpu_possible_mask);
0091 __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
0092 __pa_symbol((void *)secondary_startup);
0093 #endif
0094
0095 #ifdef CONFIG_PM_SLEEP
0096 __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] =
0097 TEGRA_IRAM_LPx_RESUME_AREA;
0098 __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
0099 __pa_symbol((void *)tegra_resume);
0100 #endif
0101
0102 tegra_cpu_reset_handler_enable();
0103 }