Hi, On Sun, Feb 22, 2026 at 05:32:24PM +0000, Kuan-Wei Chiu wrote: > Add a new driver for the 'virt-ctrl' device found on QEMU virt machines > (e.g. m68k). This device provides a simple interface for system reset > and power off [1]. > > This driver utilizes the modern system-off API to register callbacks > for both system restart and power off. It also registers a reboot > notifier to catch SYS_HALT events, ensuring that LINUX_REBOOT_CMD_HALT > is properly handled. It is designed to be generic and can be reused by > other architectures utilizing this QEMU device. > > Link: https://gitlab.com/qemu-project/qemu/-/blob/v10.2.0/hw/misc/virt_ctrl.c [1] > Signed-off-by: Kuan-Wei Chiu > --- I think this should be merged with the second patch via the m68k tree: Acked-by: Sebastian Reichel Greetings, -- Sebastian > Changes in v3: > - Add a reboot notifier to handle SYS_HALT. > - Implement virt_ctrl_write32() to handle native endianness. > > I noticed devm_register_sys_off_handler() currently lacks a > SYS_OFF_MODE_HALT. Therefore, I registered a standard reboot notifier > for SYS_HALT, while keeping restart and power-off on the sys-off API. > > MAINTAINERS | 6 ++ > drivers/power/reset/Kconfig | 10 +++ > drivers/power/reset/Makefile | 1 + > drivers/power/reset/qemu-virt-ctrl.c | 122 +++++++++++++++++++++++++++ > 4 files changed, 139 insertions(+) > create mode 100644 drivers/power/reset/qemu-virt-ctrl.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 55af015174a5..aa9eb8540637 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -21441,6 +21441,12 @@ S: Maintained > F: drivers/firmware/qemu_fw_cfg.c > F: include/uapi/linux/qemu_fw_cfg.h > > +QEMU VIRT MACHINE SYSTEM CONTROLLER DRIVER > +M: Kuan-Wei Chiu > +L: linux-pm@vger.kernel.org > +S: Maintained > +F: drivers/power/reset/qemu-virt-ctrl.c > + > QLOGIC QL41xxx FCOE DRIVER > M: Saurav Kashyap > M: Javed Hasan > diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig > index f6c1bcbb57de..99e3334726a5 100644 > --- a/drivers/power/reset/Kconfig > +++ b/drivers/power/reset/Kconfig > @@ -354,4 +354,14 @@ config POWER_MLXBF > help > This driver supports reset or low power mode handling for Mellanox BlueField. > > +config POWER_RESET_QEMU_VIRT_CTRL > + tristate "QEMU Virt Machine System Controller" > + depends on HAS_IOMEM > + help > + This driver supports the system reset and power off functionality > + provided by the QEMU 'virt-ctrl' device. > + > + Say Y here if you are running Linux on a QEMU virtual machine that > + provides this controller, such as the m68k virt machine. > + > endif > diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile > index 0e4ae6f6b5c5..d7ae97241a83 100644 > --- a/drivers/power/reset/Makefile > +++ b/drivers/power/reset/Makefile > @@ -41,3 +41,4 @@ obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o > obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o > obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o > obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o > +obj-$(CONFIG_POWER_RESET_QEMU_VIRT_CTRL) += qemu-virt-ctrl.o > diff --git a/drivers/power/reset/qemu-virt-ctrl.c b/drivers/power/reset/qemu-virt-ctrl.c > new file mode 100644 > index 000000000000..f40d04afd4e3 > --- /dev/null > +++ b/drivers/power/reset/qemu-virt-ctrl.c > @@ -0,0 +1,122 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * QEMU Virt Machine System Controller Driver > + * > + * Copyright (C) 2026 Kuan-Wei Chiu > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +/* Registers */ > +#define VIRT_CTRL_REG_FEATURES 0x00 > +#define VIRT_CTRL_REG_CMD 0x04 > + > +/* Commands */ > +#define CMD_NOOP 0 > +#define CMD_RESET 1 > +#define CMD_HALT 2 > +#define CMD_PANIC 3 > + > +struct qemu_virt_ctrl { > + void __iomem *base; > + struct notifier_block reboot_nb; > +}; > + > +static inline void virt_ctrl_write32(u32 val, void __iomem *addr) > +{ > + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) > + iowrite32be(val, addr); > + else > + iowrite32(val, addr); > +} > + > +static int qemu_virt_ctrl_power_off(struct sys_off_data *data) > +{ > + void __iomem *base = data->cb_data; > + > + virt_ctrl_write32(CMD_HALT, base + VIRT_CTRL_REG_CMD); > + > + return NOTIFY_DONE; > +} > + > +static int qemu_virt_ctrl_restart(struct sys_off_data *data) > +{ > + void __iomem *base = data->cb_data; > + > + virt_ctrl_write32(CMD_RESET, base + VIRT_CTRL_REG_CMD); > + > + return NOTIFY_DONE; > +} > + > +static int qemu_virt_ctrl_reboot_notify(struct notifier_block *nb, > + unsigned long action, void *data) > +{ > + struct qemu_virt_ctrl *ctrl = container_of(nb, struct qemu_virt_ctrl, reboot_nb); > + > + if (action == SYS_HALT) > + virt_ctrl_write32(CMD_HALT, ctrl->base + VIRT_CTRL_REG_CMD); > + > + return NOTIFY_DONE; > +} > + > +static int qemu_virt_ctrl_probe(struct platform_device *pdev) > +{ > + struct qemu_virt_ctrl *ctrl; > + int ret; > + > + ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); > + if (!ctrl) > + return -ENOMEM; > + > + ctrl->base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(ctrl->base)) > + return PTR_ERR(ctrl->base); > + > + ret = devm_register_sys_off_handler(&pdev->dev, > + SYS_OFF_MODE_RESTART, > + SYS_OFF_PRIO_DEFAULT, > + qemu_virt_ctrl_restart, > + ctrl->base); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, > + "cannot register restart handler\n"); > + > + ret = devm_register_sys_off_handler(&pdev->dev, > + SYS_OFF_MODE_POWER_OFF, > + SYS_OFF_PRIO_DEFAULT, > + qemu_virt_ctrl_power_off, > + ctrl->base); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, > + "cannot register power-off handler\n"); > + > + ctrl->reboot_nb.notifier_call = qemu_virt_ctrl_reboot_notify; > + ret = devm_register_reboot_notifier(&pdev->dev, &ctrl->reboot_nb); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, "cannot register reboot notifier\n"); > + > + return 0; > +} > + > +static const struct platform_device_id qemu_virt_ctrl_id[] = { > + { "qemu-virt-ctrl", 0 }, > + { } > +}; > +MODULE_DEVICE_TABLE(platform, qemu_virt_ctrl_id); > + > +static struct platform_driver qemu_virt_ctrl_driver = { > + .probe = qemu_virt_ctrl_probe, > + .driver = { > + .name = "qemu-virt-ctrl", > + }, > + .id_table = qemu_virt_ctrl_id, > +}; > +module_platform_driver(qemu_virt_ctrl_driver); > + > +MODULE_AUTHOR("Kuan-Wei Chiu "); > +MODULE_DESCRIPTION("QEMU Virt Machine System Controller Driver"); > +MODULE_LICENSE("GPL"); > -- > 2.53.0.345.g96ddfc5eaa-goog >