The C-SKY architecture does not support ACPI and no other standardized
mechanism for system poweroff.
On QEMU a virtual device "csky_exit" is available which can be used for
poweroff.
Add a driver for this virtual device.
There are more features provided by the device but these are not
required at this time and therefore not supported yet.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
The OF compatible will never show up in a DTS file, it is synthesized by
QEMU. Therefore I think it doesn't need explicit documentation.
---
drivers/virt/Kconfig | 11 ++++++++++
drivers/virt/Makefile | 1 +
drivers/virt/csky_exit.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+)
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index d8c848cf09a6afad65b28be20f5fd7e90a0c5307..652546c52d2e00138a782b949672d47c5f5d2189 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -41,6 +41,17 @@ config FSL_HV_MANAGER
4) A kernel interface for receiving callbacks when a managed
partition shuts down.
+config CSKY_EXIT
+ tristate "C-SKY QEMU shutdown driver"
+ depends on OF
+ depends on CSKY || COMPILE_TEST
+ help
+ This driver supports system shutdown via the virtual csky_exit device
+ provided by QEMU.
+
+ To compile this driver as a module, choose M here: the module will
+ be called csky_exit.
+
source "drivers/virt/vboxguest/Kconfig"
source "drivers/virt/nitro_enclaves/Kconfig"
diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile
index f29901bd782058d3552cdec2c2128ad47ce6fe27..5c62db9fbfa501a31c87c4902f835db91633daeb 100644
--- a/drivers/virt/Makefile
+++ b/drivers/virt/Makefile
@@ -3,6 +3,7 @@
# Makefile for drivers that support virtualization
#
+obj-$(CONFIG_CSKY_EXIT) += csky_exit.o
obj-$(CONFIG_FSL_HV_MANAGER) += fsl_hypervisor.o
obj-$(CONFIG_VMGENID) += vmgenid.o
obj-y += vboxguest/
diff --git a/drivers/virt/csky_exit.c b/drivers/virt/csky_exit.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f42eb74071ab9ac1b7e9ef03b32f9ba0ef2cf26
--- /dev/null
+++ b/drivers/virt/csky_exit.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * C-SKY QEMU shutdown driver
+ *
+ * Copyright (C) 2024 Thomas Weißschuh <linux@weissschuh.net>
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/types.h>
+
+#define CSKY_EXIT_COMMAND_EXIT 0
+
+static void csky_exit_command(void __iomem *base, u32 command, u64 value)
+{
+ writew(value, base + command);
+}
+
+static int csky_exit_poweroff(struct sys_off_data *data)
+{
+ csky_exit_command(data->cb_data, CSKY_EXIT_COMMAND_EXIT, 0);
+ return 0;
+}
+
+static int csky_exit_probe(struct platform_device *pdev)
+{
+ void __iomem *base;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ return devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_PLATFORM + 1,
+ csky_exit_poweroff, base);
+}
+
+static const struct of_device_id csky_exit_match[] = {
+ { .compatible = "csky,qemu-exit" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, csky_exit_match);
+
+static struct platform_driver csky_exit_driver = {
+ .driver.name = "csky_exit",
+ .driver.of_match_table = csky_exit_match,
+ .probe = csky_exit_probe,
+};
+module_platform_driver(csky_exit_driver);
+
+MODULE_AUTHOR("Thomas Weißschuh <linux@weissschuh.net>");
+MODULE_DESCRIPTION("C-SKY QEMU shutdown driver");
+MODULE_LICENSE("GPL");
--
2.46.2