| // SPDX-License-Identifier: GPL-2.0-or-later | |
| /* | |
| * Copyright (C) 2025, Kuan-Wei Chiu <visitorckw@gmail.com> | |
| * | |
| * 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), | |
| }; |