Introduce a new sysreset driver for the QEMU Virtual System Controller.
This device is found on QEMU "virt" machines (such as the m68k virt
target) and provides a mechanism to trigger system reset and power-off
events.

The driver maps U-Boot sysreset types to the corresponding controller
commands:
- SYSRESET_WARM / SYSRESET_COLD -> VIRT_CTRL_CMD_RESET
- SYSRESET_POWER_OFF -> VIRT_CTRL_CMD_HALT

Signed-off-by: Kuan-Wei Chiu <[email protected]>
---
Changes in v6:
- Introduce new driver to replace board-file reset implementation.

 MAINTAINERS                                |  6 +++
 drivers/sysreset/Kconfig                   |  8 ++++
 drivers/sysreset/Makefile                  |  1 +
 drivers/sysreset/sysreset_qemu_virt_ctrl.c | 55 ++++++++++++++++++++++
 include/qemu_virt_ctrl.h                   | 13 +++++
 5 files changed, 83 insertions(+)
 create mode 100644 drivers/sysreset/sysreset_qemu_virt_ctrl.c
 create mode 100644 include/qemu_virt_ctrl.h

diff --git a/MAINTAINERS b/MAINTAINERS
index efecb213be7..34081769ecd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1598,6 +1598,12 @@ S:       Maintained
 T:     git https://source.denx.de/u-boot/custodians/u-boot-mpc85xx.git
 F:     arch/powerpc/cpu/mpc85xx/
 
+QEMU VIRTUAL SYSTEM CONTROLLER
+M:     Kuan-Wei Chiu <[email protected]>
+S:     Maintained
+F:     drivers/sysreset/sysreset_qemu_virt_ctrl.c
+F:     include/qemu_virt_ctrl.h
+
 RAW NAND
 M:     Dario Binacchi <[email protected]>
 M:     Michael Trimarchi <[email protected]>
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index 0181f6cd581..120e7510f15 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -298,6 +298,14 @@ config SYSRESET_QCOM_PSHOLD
        help
          Add support for the system reboot on Qualcomm SoCs via PSHOLD.
 
+config SYSRESET_QEMU_VIRT_CTRL
+       bool "QEMU Virtual System Controller support"
+       depends on SYSRESET
+       help
+         Enable support for the QEMU Virtual System Controller.
+         This device is used in QEMU machines (e.g. m68k virt) to trigger
+         system reset and poweroff events.
+
 endif
 
 endmenu
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index f5c78b25896..d18a5d52360 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_$(PHASE_)SYSRESET_X86) += sysreset_x86.o
 obj-$(CONFIG_SYSRESET_RAA215300) += sysreset_raa215300.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_qemu_virt_ctrl.c 
b/drivers/sysreset/sysreset_qemu_virt_ctrl.c
new file mode 100644
index 00000000000..e7cacc9b6e9
--- /dev/null
+++ b/drivers/sysreset/sysreset_qemu_virt_ctrl.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025, Kuan-Wei Chiu <[email protected]>
+ *
+ * QEMU Virtual System Controller Driver
+ */
+
+#include <dm.h>
+#include <qemu_virt_ctrl.h>
+#include <sysreset.h>
+#include <asm/io.h>
+#include <linux/err.h>
+
+/* Register offsets */
+#define VIRT_CTRL_REG_FEATURES  0x00
+#define VIRT_CTRL_REG_CMD       0x04
+
+/* Commands */
+#define VIRT_CTRL_CMD_NOOP      0x00
+#define VIRT_CTRL_CMD_RESET     0x01
+#define VIRT_CTRL_CMD_HALT      0x02
+#define VIRT_CTRL_CMD_PANIC     0x03
+
+static int qemu_virt_ctrl_request(struct udevice *dev, enum sysreset_t type)
+{
+       struct qemu_virt_ctrl_plat *plat = dev_get_plat(dev);
+       u32 val;
+
+       switch (type) {
+       case SYSRESET_WARM:
+       case SYSRESET_COLD:
+               val = VIRT_CTRL_CMD_RESET;
+               break;
+       case SYSRESET_POWER_OFF:
+               val = VIRT_CTRL_CMD_HALT;
+               break;
+       default:
+               return -EPROTONOSUPPORT;
+       }
+
+       writel(val, plat->reg + VIRT_CTRL_REG_CMD);
+
+       return -EINPROGRESS;
+}
+
+static struct sysreset_ops qemu_virt_ctrl_ops = {
+       .request = qemu_virt_ctrl_request,
+};
+
+U_BOOT_DRIVER(sysreset_qemu_virt_ctrl) = {
+       .name = "sysreset_qemu_virt_ctrl",
+       .id = UCLASS_SYSRESET,
+       .ops = &qemu_virt_ctrl_ops,
+       .plat_auto = sizeof(struct qemu_virt_ctrl_plat),
+};
diff --git a/include/qemu_virt_ctrl.h b/include/qemu_virt_ctrl.h
new file mode 100644
index 00000000000..05aad82b767
--- /dev/null
+++ b/include/qemu_virt_ctrl.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2025, Kuan-Wei Chiu <[email protected]>
+ */
+
+#ifndef _QEMU_VIRT_CTRL_H_
+#define _QEMU_VIRT_CTRL_H_
+
+struct qemu_virt_ctrl_plat {
+       phys_addr_t reg;
+};
+
+#endif /* _QEMU_VIRT_CTRL_H_ */
-- 
2.52.0.457.g6b5491de43-goog

Reply via email to