From 93df0473689b86cc2e0f84c7184c1b93917994d4 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Wed, 21 Jan 2026 12:09:16 +0530 Subject: [PATCH 1/5] arm: psci: Add API to check for support of specific PSCI function Add an API to check if a specific PSCI function is supported or not. This is based on the psci_features() function present in Linux kernel (drivers/firmware/psci/psci.c). Reviewed-by: Casey Connolly Reviewed-by: Sumit Garg Signed-off-by: Varadarajan Narayanan --- arch/arm/cpu/armv8/fwcall.c | 15 +++++++++++++++ arch/arm/include/asm/system.h | 1 + 2 files changed, 16 insertions(+) diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c index 87de09979b18..f834d770dd68 100644 --- a/arch/arm/cpu/armv8/fwcall.c +++ b/arch/arm/cpu/armv8/fwcall.c @@ -129,3 +129,18 @@ void __noreturn psci_system_off(void) while (1) ; } + +int psci_features(u32 psci_func_id) +{ + struct pt_regs regs; + + regs.regs[0] = ARM_PSCI_1_0_FN_PSCI_FEATURES; + regs.regs[1] = psci_func_id; + + if (use_smc_for_psci) + smc_call(®s); + else + hvc_call(®s); + + return regs.regs[0]; +} diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 9e3ad57073d5..5ed6833c155c 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -342,6 +342,7 @@ void smc_call(struct pt_regs *args); void __noreturn psci_system_reset(void); void __noreturn psci_system_reset2(u32 reset_level, u32 cookie); void __noreturn psci_system_off(void); +int psci_features(u32 psci_func_id); #ifdef CONFIG_ARMV8_PSCI extern char __secure_start[]; From 24d99837b61fc0b03d900f12b671ef8ad4221e66 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Wed, 21 Jan 2026 12:09:17 +0530 Subject: [PATCH 2/5] drivers: sysreset: Add sysreset op that can take arguments Add a 'request_arg' op to struct sysreset_ops to enable sysreset drivers to receive arguments given to the 'reset' command. Process the request_arg() op before the usual request() op. Reviewed-by: Casey Connolly Reviewed-by: Sumit Garg Signed-off-by: Varadarajan Narayanan Reviewed-by: Tom Rini --- drivers/sysreset/Kconfig | 8 +++++++ drivers/sysreset/sysreset-uclass.c | 37 ++++++++++++++++++++++++++++++ include/sysreset.h | 18 +++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 16ef434a8d9c..f589ad154186 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -49,6 +49,14 @@ config SYSRESET_CMD_RESET help Enable sysreset implementation of the reset command. +config SYSRESET_CMD_RESET_ARGS + bool "Enable reset command to take arguments" + help + Pass on the arguments received by the 'reset' command to the + sysreset driver(s). The sysreset driver(s) may make use of the + additional arguments for implementing arch/board specific + functionality. + if CMD_POWEROFF config SYSRESET_CMD_POWEROFF diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c index 536ac7271427..f25e09e9cd06 100644 --- a/drivers/sysreset/sysreset-uclass.c +++ b/drivers/sysreset/sysreset-uclass.c @@ -32,6 +32,18 @@ int sysreset_request(struct udevice *dev, enum sysreset_t type) return ops->request(dev, type); } +#if IS_ENABLED(CONFIG_SYSRESET_CMD_RESET_ARGS) +int sysreset_request_arg(struct udevice *dev, int argc, char * const argv[]) +{ + struct sysreset_ops *ops = sysreset_get_ops(dev); + + if (!ops->request_arg) + return -ENOSYS; + + return ops->request_arg(dev, argc, argv); +} +#endif /* CONFIG_SYSRESET_CMD_RESET_ARGS */ + int sysreset_get_status(struct udevice *dev, char *buf, int size) { struct sysreset_ops *ops = sysreset_get_ops(dev); @@ -71,6 +83,26 @@ int sysreset_walk(enum sysreset_t type) return ret; } +#if IS_ENABLED(CONFIG_SYSRESET_CMD_RESET_ARGS) +int sysreset_walk_arg(int argc, char * const argv[]) +{ + struct udevice *dev; + int ret = -ENOSYS; + + while (ret != -EINPROGRESS && ret != -EPROTONOSUPPORT) { + for (uclass_first_device(UCLASS_SYSRESET, &dev); + dev; + uclass_next_device(&dev)) { + ret = sysreset_request_arg(dev, argc, argv); + if (ret == -EINPROGRESS || ret == -EPROTONOSUPPORT) + break; + } + } + + return ret; +} +#endif /* CONFIG_SYSRESET_CMD_RESET_ARGS */ + int sysreset_get_last_walk(void) { struct udevice *dev; @@ -132,6 +164,11 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) printf("resetting ...\n"); mdelay(100); +#if IS_ENABLED(CONFIG_SYSRESET_CMD_RESET_ARGS) + if (argc > 1 && sysreset_walk_arg(argc, argv) == -EINPROGRESS) + return 0; +#endif + sysreset_walk_halt(reset_type); return 0; diff --git a/include/sysreset.h b/include/sysreset.h index ff20abdeed3c..d1cc9ebc542a 100644 --- a/include/sysreset.h +++ b/include/sysreset.h @@ -43,6 +43,24 @@ struct sysreset_ops { * (in which case this method will not actually return) */ int (*request)(struct udevice *dev, enum sysreset_t type); + + /** + * @request_arg: Reset handler implementations that might need to process + * arguments given to the 'reset' command. + * + * Note that this function may return before the reset takes effect. + * + * @dev: Device to be used for system reset + * @argc: No. of items in @argv + * @argv: Arguments given to 'reset' command + * Return: + * -EINPROGRESS if the reset has started and will complete soon + * -EPROTONOSUPPORT if not supported by this device + * 0 if the reset has already happened + * (in which case this method will not actually return) + */ + int (*request_arg)(struct udevice *dev, int argc, char * const argv[]); + /** * @get_status: get printable reset status information * From f098e5d77d80210056eb19b1bf45ca9a91a67813 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Wed, 21 Jan 2026 12:09:18 +0530 Subject: [PATCH 3/5] sysreset: Implement PSCI based reset to EDL mode for QCOM SoCs Implement request_arg() sysreset_op for QCOM SoCs that use PSCI to reset to EDL (Emergency Download) mode. Reviewed-by: Casey Connolly Reviewed-by: Sumit Garg Signed-off-by: Varadarajan Narayanan --- drivers/firmware/psci.c | 4 +++ drivers/sysreset/Kconfig | 6 ++++ drivers/sysreset/Makefile | 1 + drivers/sysreset/sysreset_qcom-psci.c | 45 +++++++++++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 drivers/sysreset/sysreset_qcom-psci.c diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index 2e3223e1c32a..b6838a244d2b 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -186,6 +186,10 @@ static int psci_bind(struct udevice *dev) NULL); if (ret) pr_debug("PSCI System Reset was not bound.\n"); + if (IS_ENABLED(CONFIG_SYSRESET_QCOM_PSCI) && + device_bind_driver(dev, "qcom_psci-sysreset", + "qcom_psci-sysreset", NULL)) + pr_debug("QCOM PSCI System Reset was not bound.\n"); } /* From PSCI v1.0 onward we can discover services through ARM_SMCCC_FEATURE */ diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index f589ad154186..f4a6610eef31 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -301,6 +301,12 @@ config SYSRESET_RAA215300 help Add support for the system reboot via the Renesas RAA215300 PMIC. +config SYSRESET_QCOM_PSCI + bool "Support reset to EDL for Qualcomm SoCs via PSCI" + help + Add support for the reset to EDL (Emergency Download) on Qualcomm + SoCs via PSCI. + config SYSRESET_QCOM_PSHOLD bool "Support sysreset for Qualcomm SoCs via PSHOLD" help diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index d18a5d523605..b5b99235b6ef 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_SYSRESET_RESETCTL) += sysreset_resetctl.o obj-$(CONFIG_$(PHASE_)SYSRESET_AT91) += sysreset_at91.o obj-$(CONFIG_$(PHASE_)SYSRESET_X86) += sysreset_x86.o obj-$(CONFIG_SYSRESET_RAA215300) += sysreset_raa215300.o +obj-$(CONFIG_SYSRESET_QCOM_PSCI) += sysreset_qcom-psci.o obj-$(CONFIG_SYSRESET_QCOM_PSHOLD) += sysreset_qcom-pshold.o obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o obj-$(CONFIG_SYSRESET_QEMU_VIRT_CTRL) += sysreset_qemu_virt_ctrl.o diff --git a/drivers/sysreset/sysreset_qcom-psci.c b/drivers/sysreset/sysreset_qcom-psci.c new file mode 100644 index 000000000000..3627bbf5c820 --- /dev/null +++ b/drivers/sysreset/sysreset_qcom-psci.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Masahiro Yamada + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include + +static int qcom_psci_sysreset_get_status(struct udevice *dev, char *buf, int size) +{ + return -EOPNOTSUPP; +} + +static int qcom_psci_sysreset_request_arg(struct udevice *dev, int argc, + char * const argv[]) +{ + if (!strncasecmp(argv[1], "-edl", 4)) { + /* Supported in qcs9100, qcs8300, sc7280, qcs615 */ + if (psci_features(ARM_PSCI_1_1_FN64_SYSTEM_RESET2) == + ARM_PSCI_RET_SUCCESS) { + psci_system_reset2(0, 1); + return -EINPROGRESS; + } + printf("PSCI SYSTEM_RESET2 not supported\n"); + } + + return -EPROTONOSUPPORT; +} + +static struct sysreset_ops qcom_psci_sysreset_ops = { + .request_arg = qcom_psci_sysreset_request_arg, + .get_status = qcom_psci_sysreset_get_status, +}; + +U_BOOT_DRIVER(qcom_psci_sysreset) = { + .name = "qcom_psci-sysreset", + .id = UCLASS_SYSRESET, + .ops = &qcom_psci_sysreset_ops, + .flags = DM_FLAG_PRE_RELOC, +}; From acb9ebdbe87ccb9834ddd67b831ef7d599be19e5 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Wed, 21 Jan 2026 12:09:19 +0530 Subject: [PATCH 4/5] cmd: boot: Add '-edl' option to reset command documentation Add help text about '-edl' option to reset command definition and related documentation. Reviewed-by: Casey Connolly Reviewed-by: Sumit Garg Signed-off-by: Varadarajan Narayanan --- cmd/boot.c | 3 +++ doc/usage/cmd/reset.rst | 2 ++ 2 files changed, 5 insertions(+) diff --git a/cmd/boot.c b/cmd/boot.c index 23496cafdf5c..d80f9d8c05dd 100644 --- a/cmd/boot.c +++ b/cmd/boot.c @@ -60,6 +60,9 @@ U_BOOT_CMD( reset, 2, 0, do_reset, "Perform RESET of the CPU", "- cold boot without level specifier\n" +#ifdef CONFIG_SYSRESET_QCOM_PSCI + "reset -edl - Boot to Emergency DownLoad mode\n" +#endif "reset -w - warm reset if implemented" ); diff --git a/doc/usage/cmd/reset.rst b/doc/usage/cmd/reset.rst index 126db21cdb81..366b17eea166 100644 --- a/doc/usage/cmd/reset.rst +++ b/doc/usage/cmd/reset.rst @@ -22,6 +22,8 @@ DDR and peripherals, on some boards also resets external PMIC. -w Do warm WARM, reset CPU but keep peripheral/DDR/PMIC active. +-edl + Boot to Emergency DownLoad mode on supported Qualcomm platforms. Return value ------------ From 22917a860dac0793768fe2094e51386db77c7772 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Wed, 21 Jan 2026 12:09:20 +0530 Subject: [PATCH 5/5] qcom_defconfig: enable psci based sysreset Enable CONFIG_SYSRESET_QCOM_PSCI to allow U-Boot to reset to Emergency Download mode. Reviewed-by: Sumit Garg Signed-off-by: Varadarajan Narayanan --- configs/qcom_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig index baad5f094552..d0bf1b81d2b0 100644 --- a/configs/qcom_defconfig +++ b/configs/qcom_defconfig @@ -130,7 +130,9 @@ CONFIG_QCOM_RPMH=y CONFIG_SPMI_MSM=y CONFIG_SYSINFO=y CONFIG_SYSINFO_SMBIOS=y +CONFIG_SYSRESET_CMD_RESET_ARGS=y CONFIG_SYSRESET_QCOM_PSHOLD=y +CONFIG_SYSRESET_QCOM_PSCI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y