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