Hi Varadarajan,
You have almost entirely ignored my feedback on the previous revision.
If there's some technical disagreement or you don't understand my
feedback then please let me know (in private if you prefer).
This approach is fundamentally wrong, full of layering violations and
totally unsustainable (imagine if every vendor started polluting core
code with their custom stuff).
These abstractions need to be improved to add this feature properly and
there's no getting around it.
Kind regards,
Casey (she/they)
On 4/30/25 10:54, Varadarajan Narayanan wrote:
The SYSRESET_PSCI interface presently available doesn't support booting
into Emergency DownLoad (EDL) mode. The EDL mode is used to flash the
board with different firmware.
Since EDL is Qcom specific, implement a Qcom specific SYSRESET_PSCI
handler that handles resetting to EDL in addition to the usual cold/warm
reset and poweroff.
Signed-off-by: Varadarajan Narayanan <quic_var...@quicinc.com>
---
v2: * Update commit message
* Elaborate Kconfig help text
* Use '-edl' instead of 'edl' for consistency with other arguments of reset
command
* Remove 'weak' for qcom_psci_sysreset_get_status() and make it static
* Mention 'SYSRESET_EDL' is Qcom specific in the enum's comments
---
drivers/firmware/psci.c | 4 +++
drivers/sysreset/Kconfig | 7 ++++
drivers/sysreset/Makefile | 1 +
drivers/sysreset/sysreset-uclass.c | 7 ++--
drivers/sysreset/sysreset_qcom-psci.c | 48 +++++++++++++++++++++++++++
include/sysreset.h | 7 ++++
6 files changed, 72 insertions(+), 2 deletions(-)
create mode 100644 drivers/sysreset/sysreset_qcom-psci.c
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 2e3223e1c32..b6838a244d2 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 4972905482a..d407c322bdb 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -285,6 +285,13 @@ config SYSRESET_RAA215300
help
Add support for the system reboot via the Renesas RAA215300 PMIC.
+config SYSRESET_QCOM_PSCI
+ bool "Support sysreset for Qualcomm SoCs via PSCI"
+ help
+ Add support for the system reboot on Qualcomm SoCs via PSCI.
+ This allows warm/cold reset, poweroff and reset to EDL (Emergency
+ Download)
+
config SYSRESET_QCOM_PSHOLD
bool "Support sysreset for Qualcomm SoCs via PSHOLD"
help
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index ded91a4d325..58eb0e356e1 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -29,5 +29,6 @@ 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
diff --git a/drivers/sysreset/sysreset-uclass.c
b/drivers/sysreset/sysreset-uclass.c
index 536ac727142..ff9bc962ec0 100644
--- a/drivers/sysreset/sysreset-uclass.c
+++ b/drivers/sysreset/sysreset-uclass.c
@@ -125,8 +125,11 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
if (argc > 2)
return CMD_RET_USAGE;
- if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w') {
- reset_type = SYSRESET_WARM;
+ if (argc == 2) {
+ if (argv[1][0] == '-' && argv[1][1] == 'w')
+ reset_type = SYSRESET_WARM;
+ else if (!strncmp("-edl", argv[1], 4))
+ reset_type = SYSRESET_EDL;
}
printf("resetting ...\n");
diff --git a/drivers/sysreset/sysreset_qcom-psci.c
b/drivers/sysreset/sysreset_qcom-psci.c
new file mode 100644
index 00000000000..9d0606c059b
--- /dev/null
+++ b/drivers/sysreset/sysreset_qcom-psci.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Masahiro Yamada <yamada.masah...@socionext.com>
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <dm.h>
+#include <sysreset.h>
+#include <asm/system.h>
+#include <linux/errno.h>
+#include <linux/psci.h>
+
+static int qcom_psci_sysreset_get_status(struct udevice *dev, char *buf, int
size)
+{
+ return -EOPNOTSUPP;
+}
+
+static int qcom_psci_sysreset_request(struct udevice *dev, enum sysreset_t
type)
+{
+ switch (type) {
+ case SYSRESET_WARM:
+ case SYSRESET_COLD:
+ psci_sys_reset(type);
+ break;
+ case SYSRESET_POWER_OFF:
+ psci_sys_poweroff();
+ break;
+ case SYSRESET_EDL:
+ psci_system_reset2(0, 1);
+ break;
+ default:
+ return -EPROTONOSUPPORT;
+ }
+
+ return -EINPROGRESS;
+}
+
+static struct sysreset_ops qcom_psci_sysreset_ops = {
+ .request = qcom_psci_sysreset_request,
+ .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,
+};
diff --git a/include/sysreset.h b/include/sysreset.h
index ff20abdeed3..d0f60ed2456 100644
--- a/include/sysreset.h
+++ b/include/sysreset.h
@@ -21,6 +21,13 @@ enum sysreset_t {
SYSRESET_POWER,
/** @SYSRESET_POWER_OFF: turn off power */
SYSRESET_POWER_OFF,
+#if IS_ENABLED(CONFIG_SYSRESET_QCOM_PSCI)
+ /**
+ * @SYSRESET_EDL: Reset and boot into Emergency DownLoader.
+ * This is supported only in recent Qcom SoCs.
+ */
+ SYSRESET_EDL,
+#endif
/** @SYSRESET_COUNT: number of available reset types */
SYSRESET_COUNT,
};
--
Casey (she/they)