From 484758e7a60d8df82616ade56d7114359637cc5f Mon Sep 17 00:00:00 2001 From: Ishan Shah Date: Sun, 15 Sep 2024 07:26:51 +0000 Subject: [PATCH] NVIDIA: SAUCE: drivers: nv_ist: Add IST debugfs options Adding a driver to handle setup and trigger for IST through the L4T kernel. This driver "hijacks" the current Hotplug entry/exit flow to instead trigger the core to enter the RIST state. Upon failure or success, the core will then be left in the "unplugged" state, to be brought back online at a later time manually. This set of changes is mainly meant for testing RIST in L4T-based systems. This is not intended for production use-cases. TPS-589 Signed-off-by: Ishan Shah Signed-off-by: Laxman Dewangan Acked-by: Noah Wager Acked-by: Jacob Martin Signed-off-by: Noah Wager --- arch/arm64/kernel/psci.c | 22 +++++-- drivers/misc/Makefile | 1 + drivers/misc/nv_ist.c | 136 +++++++++++++++++++++++++++++++++++++++ include/misc/nv_ist.h | 29 +++++++++ 4 files changed, 181 insertions(+), 7 deletions(-) create mode 100644 drivers/misc/nv_ist.c create mode 100644 include/misc/nv_ist.h diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 29a8e444db83..e5421751eb2d 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -21,6 +21,10 @@ #include #include +#ifdef CONFIG_HOTPLUG_CPU +#include +#endif + static int __init cpu_psci_cpu_init(unsigned int cpu) { return 0; @@ -67,14 +71,18 @@ static int cpu_psci_cpu_disable(unsigned int cpu) static void cpu_psci_cpu_die(unsigned int cpu) { - /* - * There are no known implementations of PSCI actually using the - * power state field, pass a sensible default for now. - */ - u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN << - PSCI_0_2_POWER_STATE_TYPE_SHIFT; + if (is_ist_enabled(cpu)) { + cpu_enter_ist(cpu); + } else { + /* + * There are no known implementations of PSCI actually using the + * power state field, pass a sensible default for now. + */ + u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN << + PSCI_0_2_POWER_STATE_TYPE_SHIFT; - psci_ops.cpu_off(state); + psci_ops.cpu_off(state); + } } static int cpu_psci_cpu_kill(unsigned int cpu) diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index ea6ea5bbbc9c..3fc04c2c8e35 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,6 +58,7 @@ obj-y += cardreader/ obj-$(CONFIG_PVPANIC) += pvpanic/ obj-$(CONFIG_UACCE) += uacce/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o +obj-$(CONFIG_ARM_PSCI_FW) += nv_ist.o obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o obj-$(CONFIG_OPEN_DICE) += open-dice.o diff --git a/drivers/misc/nv_ist.c b/drivers/misc/nv_ist.c new file mode 100644 index 000000000000..501bdc4b7f4b --- /dev/null +++ b/drivers/misc/nv_ist.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* RIST START SMC */ +/* https://confluence.nvidia.com/display/TFA/Central+Registry+for+SMCs */ +#define NV_IST_FN_RIST_START 0xC200FF0A + +struct ist_smc_vars { + bool enable; + u32 tid; + u32 smc_id; +}; + +static struct ist_smc_vars *cpu_settings; +static struct dentry *dbgfs_root; + +bool is_ist_enabled(unsigned int cpu) +{ + return cpu_settings != NULL && cpu_settings[cpu].enable; +} + +void cpu_enter_ist(unsigned int cpu) +{ + struct arm_smccc_res res; + + if ((cpu_settings != NULL && cpu_settings[cpu].enable)) { + pr_debug("CPU %x is entering SMC %x\n", cpu, cpu_settings[cpu].smc_id); + arm_smccc_smc(cpu_settings[cpu].smc_id, + cpu_settings[cpu].tid, + 0, 0, 0, 0, 0, 0, &res); + } +} + +static int create_ist_debugfs_entries(void) +{ + char subdir_name[6]; /* cpu + XX + \n */ + struct dentry *subdir; + int cpu; + + dbgfs_root = debugfs_create_dir("nv_ist", NULL); + if (!dbgfs_root) { + return -ENOENT; + } + + for (cpu = cpumask_first(cpu_possible_mask); + cpu < nr_cpu_ids; + cpu = cpumask_next(cpu, cpu_possible_mask)) { + snprintf(subdir_name, 6, "cpu%d", cpu); + subdir = debugfs_create_dir(subdir_name, dbgfs_root); + + if (subdir == NULL) + goto err; + + debugfs_create_bool("enable", 0644, + subdir, &(cpu_settings[cpu].enable)); + + debugfs_create_u32("test_id", 0644, + subdir, &(cpu_settings[cpu].tid)); + } + + return 0; +err: + debugfs_remove_recursive(dbgfs_root); + return -ENOENT; +} + +static int tegra_ist_probe(struct platform_device *pdev) +{ + size_t i; + int err = 0; + + /* Zero-initialized */ + cpu_settings = devm_kcalloc(&pdev->dev, nr_cpu_ids, + sizeof(struct ist_smc_vars), GFP_KERNEL); + + /* Setting the PSCI-ID to RIST_START SMC */ + for (i = 0; i < nr_cpu_ids; i++) { + cpu_settings[i].enable = false; + cpu_settings[i].tid = 0U; + cpu_settings[i].smc_id = NV_IST_FN_RIST_START; + } + /* Create debugfs */ + err = create_ist_debugfs_entries(); + + if (err) + devm_kfree(&pdev->dev, cpu_settings); + + return err; +} + +static int tegra_ist_remove(struct platform_device *pdev) +{ + debugfs_remove_recursive(dbgfs_root); + return 0; +} + +static const struct of_device_id tegra_ist_of_match[] = { + { .compatible = "nvidia,tegra26x-ist" }, + { }, /* Terminal */ +}; + +static struct platform_driver nv_ist_driver = { + .probe = tegra_ist_probe, + .remove = tegra_ist_remove, + .driver = { + .name = "nv_ist", + .of_match_table = tegra_ist_of_match, + }, +}; +module_platform_driver(nv_ist_driver); + +MODULE_AUTHOR("Ishan Shah "); +MODULE_DESCRIPTION("NV IST Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/misc/nv_ist.h b/include/misc/nv_ist.h new file mode 100644 index 000000000000..623b04338f0d --- /dev/null +++ b/include/misc/nv_ist.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _MISC_NV_IST_H +#define _MISC_NV_IST_H + +#if IS_ENABLED(CONFIG_ARM_PSCI_FW) + +bool is_ist_enabled(unsigned int cpu); +void cpu_enter_ist(unsigned int cpu); + +#else /* ! CONFIG_ARM_PSCI_FW */ + +static inline bool is_ist_enabled(unsigned int cpu) { return false; } +static inline void cpu_enter_ist(unsigned int cpu) { } + +#endif /* CONFIG_ARM_PSCI_FW */ + +#endif /* _MISC_NV_IST_H */