This driver implements poweroff/reboot support for T-Head TH1520 SoCs
running the AON firmware by sending a message to the AON firmware's WDG
part.
This is a auxiliary device driver, and expects the AON channel to be
passed via the platform_data of the auxiliary device.
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
---
MAINTAINERS | 1 +
drivers/power/reset/Kconfig | 7 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/th1520-aon-reboot.c | 98 +++++++++++++++++++++++++
4 files changed, 107 insertions(+)
create mode 100644 drivers/power/reset/th1520-aon-reboot.c
diff --git a/MAINTAINERS b/MAINTAINERS
index daf520a13bdf6..e138a1e96ceea 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21730,6 +21730,7 @@ F: drivers/mailbox/mailbox-th1520.c
F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
F: drivers/pinctrl/pinctrl-th1520.c
F: drivers/pmdomain/thead/
+F: drivers/power/reset/th1520-aon-reboot.c
F: drivers/power/sequencing/pwrseq-thead-gpu.c
F: drivers/reset/reset-th1520.c
F: include/dt-bindings/clock/thead,th1520-clk-ap.h
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 77ea3129c7080..8248895ca9038 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -225,6 +225,13 @@ config POWER_RESET_ST
help
Reset support for STMicroelectronics boards.
+config POWER_RESET_TH1520_AON
+ tristate "T-Head TH1520 AON firmware poweroff and reset driver"
+ depends on TH1520_PM_DOMAINS
+ help
+ This driver supports power-off and reset operations for T-Head
+ TH1520 SoCs running the AON firmware.
+
config POWER_RESET_TORADEX_EC
tristate "Toradex Embedded Controller power-off and reset driver"
depends on ARCH_MXC || COMPILE_TEST
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index b7c2b5940be99..51da87e05ce76 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o
+obj-$(CONFIG_POWER_RESET_TH1520_AON) += th1520-aon-reboot.o
obj-$(CONFIG_POWER_RESET_TORADEX_EC) += tdx-ec-poweroff.o
obj-$(CONFIG_POWER_RESET_TPS65086) += tps65086-restart.o
obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o
diff --git a/drivers/power/reset/th1520-aon-reboot.c b/drivers/power/reset/th1520-aon-reboot.c
new file mode 100644
index 0000000000000..8256c1703ebe8
--- /dev/null
+++ b/drivers/power/reset/th1520-aon-reboot.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * T-HEAD TH1520 AON Firmware Reboot Driver
+ *
+ * Copyright (c) 2025 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/firmware/thead/thead,th1520-aon.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+
+#define TH1520_AON_REBOOT_PRIORITY 200
+
+struct th1520_aon_msg_empty_body {
+ struct th1520_aon_rpc_msg_hdr hdr;
+ u16 reserved[12];
+} __packed __aligned(1);
+
+static int th1520_aon_pwroff_handler(struct sys_off_data *data)
+{
+ struct th1520_aon_chan *aon_chan = data->cb_data;
+ struct th1520_aon_msg_empty_body msg = {};
+
+ msg.hdr.svc = TH1520_AON_RPC_SVC_WDG;
+ msg.hdr.func = TH1520_AON_WDG_FUNC_POWER_OFF;
+ msg.hdr.size = TH1520_AON_RPC_MSG_NUM;
+
+ th1520_aon_call_rpc(aon_chan, &msg);
+
+ return NOTIFY_DONE;
+}
+
+static int th1520_aon_restart_handler(struct sys_off_data *data)
+{
+ struct th1520_aon_chan *aon_chan = data->cb_data;
+ struct th1520_aon_msg_empty_body msg = {};
+
+ msg.hdr.svc = TH1520_AON_RPC_SVC_WDG;
+ msg.hdr.func = TH1520_AON_WDG_FUNC_RESTART;
+ msg.hdr.size = TH1520_AON_RPC_MSG_NUM;
+
+ th1520_aon_call_rpc(aon_chan, &msg);
+
+ return NOTIFY_DONE;
+}
+
+static int th1520_aon_reboot_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct device *dev = &adev->dev;
+ int ret;
+
+ /* Expect struct th1520_aon_chan to be passed via platform_data */
+ ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
+ TH1520_AON_REBOOT_PRIORITY,
+ th1520_aon_pwroff_handler,
+ adev->dev.platform_data);
+
+ if (ret) {
+ dev_err(dev, "Failed to register power off handler\n");
+ return ret;
+ }
+
+ ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART,
+ TH1520_AON_REBOOT_PRIORITY,
+ th1520_aon_restart_handler,
+ adev->dev.platform_data);
+
+ if (ret) {
+ dev_err(dev, "Failed to register restart handler\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct auxiliary_device_id th1520_aon_reboot_id_table[] = {
+ { .name = "th1520_pm_domains.reboot" },
+ {},
+};
+MODULE_DEVICE_TABLE(auxiliary, th1520_aon_reboot_id_table);
+
+static struct auxiliary_driver th1520_aon_reboot_driver = {
+ .driver = {
+ .name = "th1520-aon-reboot",
+ },
+ .probe = th1520_aon_reboot_probe,
+ .id_table = th1520_aon_reboot_id_table,
+};
+module_auxiliary_driver(th1520_aon_reboot_driver);
+
+MODULE_AUTHOR("Icenowy Zheng <uwu@icenowy.me>");
+MODULE_DESCRIPTION("T-HEAD TH1520 AON-firmware-based reboot driver");
+MODULE_LICENSE("GPL");
--
2.50.1
Hi, On Mon, Aug 18, 2025 at 03:49:05PM +0800, Icenowy Zheng wrote: > This driver implements poweroff/reboot support for T-Head TH1520 SoCs > running the AON firmware by sending a message to the AON firmware's WDG > part. > > This is a auxiliary device driver, and expects the AON channel to be > passed via the platform_data of the auxiliary device. > > Signed-off-by: Icenowy Zheng <uwu@icenowy.me> > --- Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> Greetings, -- Sebastian > MAINTAINERS | 1 + > drivers/power/reset/Kconfig | 7 ++ > drivers/power/reset/Makefile | 1 + > drivers/power/reset/th1520-aon-reboot.c | 98 +++++++++++++++++++++++++ > 4 files changed, 107 insertions(+) > create mode 100644 drivers/power/reset/th1520-aon-reboot.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index daf520a13bdf6..e138a1e96ceea 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -21730,6 +21730,7 @@ F: drivers/mailbox/mailbox-th1520.c > F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c > F: drivers/pinctrl/pinctrl-th1520.c > F: drivers/pmdomain/thead/ > +F: drivers/power/reset/th1520-aon-reboot.c > F: drivers/power/sequencing/pwrseq-thead-gpu.c > F: drivers/reset/reset-th1520.c > F: include/dt-bindings/clock/thead,th1520-clk-ap.h > diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig > index 77ea3129c7080..8248895ca9038 100644 > --- a/drivers/power/reset/Kconfig > +++ b/drivers/power/reset/Kconfig > @@ -225,6 +225,13 @@ config POWER_RESET_ST > help > Reset support for STMicroelectronics boards. > > +config POWER_RESET_TH1520_AON > + tristate "T-Head TH1520 AON firmware poweroff and reset driver" > + depends on TH1520_PM_DOMAINS > + help > + This driver supports power-off and reset operations for T-Head > + TH1520 SoCs running the AON firmware. > + > config POWER_RESET_TORADEX_EC > tristate "Toradex Embedded Controller power-off and reset driver" > depends on ARCH_MXC || COMPILE_TEST > diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile > index b7c2b5940be99..51da87e05ce76 100644 > --- a/drivers/power/reset/Makefile > +++ b/drivers/power/reset/Makefile > @@ -25,6 +25,7 @@ obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o > obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o > obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o > obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o > +obj-$(CONFIG_POWER_RESET_TH1520_AON) += th1520-aon-reboot.o > obj-$(CONFIG_POWER_RESET_TORADEX_EC) += tdx-ec-poweroff.o > obj-$(CONFIG_POWER_RESET_TPS65086) += tps65086-restart.o > obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o > diff --git a/drivers/power/reset/th1520-aon-reboot.c b/drivers/power/reset/th1520-aon-reboot.c > new file mode 100644 > index 0000000000000..8256c1703ebe8 > --- /dev/null > +++ b/drivers/power/reset/th1520-aon-reboot.c > @@ -0,0 +1,98 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * T-HEAD TH1520 AON Firmware Reboot Driver > + * > + * Copyright (c) 2025 Icenowy Zheng <uwu@icenowy.me> > + */ > + > +#include <linux/auxiliary_bus.h> > +#include <linux/firmware/thead/thead,th1520-aon.h> > +#include <linux/module.h> > +#include <linux/notifier.h> > +#include <linux/of.h> > +#include <linux/reboot.h> > +#include <linux/slab.h> > + > +#define TH1520_AON_REBOOT_PRIORITY 200 > + > +struct th1520_aon_msg_empty_body { > + struct th1520_aon_rpc_msg_hdr hdr; > + u16 reserved[12]; > +} __packed __aligned(1); > + > +static int th1520_aon_pwroff_handler(struct sys_off_data *data) > +{ > + struct th1520_aon_chan *aon_chan = data->cb_data; > + struct th1520_aon_msg_empty_body msg = {}; > + > + msg.hdr.svc = TH1520_AON_RPC_SVC_WDG; > + msg.hdr.func = TH1520_AON_WDG_FUNC_POWER_OFF; > + msg.hdr.size = TH1520_AON_RPC_MSG_NUM; > + > + th1520_aon_call_rpc(aon_chan, &msg); > + > + return NOTIFY_DONE; > +} > + > +static int th1520_aon_restart_handler(struct sys_off_data *data) > +{ > + struct th1520_aon_chan *aon_chan = data->cb_data; > + struct th1520_aon_msg_empty_body msg = {}; > + > + msg.hdr.svc = TH1520_AON_RPC_SVC_WDG; > + msg.hdr.func = TH1520_AON_WDG_FUNC_RESTART; > + msg.hdr.size = TH1520_AON_RPC_MSG_NUM; > + > + th1520_aon_call_rpc(aon_chan, &msg); > + > + return NOTIFY_DONE; > +} > + > +static int th1520_aon_reboot_probe(struct auxiliary_device *adev, > + const struct auxiliary_device_id *id) > +{ > + struct device *dev = &adev->dev; > + int ret; > + > + /* Expect struct th1520_aon_chan to be passed via platform_data */ > + ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF, > + TH1520_AON_REBOOT_PRIORITY, > + th1520_aon_pwroff_handler, > + adev->dev.platform_data); > + > + if (ret) { > + dev_err(dev, "Failed to register power off handler\n"); > + return ret; > + } > + > + ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, > + TH1520_AON_REBOOT_PRIORITY, > + th1520_aon_restart_handler, > + adev->dev.platform_data); > + > + if (ret) { > + dev_err(dev, "Failed to register restart handler\n"); > + return ret; > + } > + > + return 0; > +} > + > +static const struct auxiliary_device_id th1520_aon_reboot_id_table[] = { > + { .name = "th1520_pm_domains.reboot" }, > + {}, > +}; > +MODULE_DEVICE_TABLE(auxiliary, th1520_aon_reboot_id_table); > + > +static struct auxiliary_driver th1520_aon_reboot_driver = { > + .driver = { > + .name = "th1520-aon-reboot", > + }, > + .probe = th1520_aon_reboot_probe, > + .id_table = th1520_aon_reboot_id_table, > +}; > +module_auxiliary_driver(th1520_aon_reboot_driver); > + > +MODULE_AUTHOR("Icenowy Zheng <uwu@icenowy.me>"); > +MODULE_DESCRIPTION("T-HEAD TH1520 AON-firmware-based reboot driver"); > +MODULE_LICENSE("GPL"); > -- > 2.50.1 >
On Tue, Sep 16, 2025 at 08:22:02PM +0200, Sebastian Reichel wrote: > Hi, > > On Mon, Aug 18, 2025 at 03:49:05PM +0800, Icenowy Zheng wrote: > > This driver implements poweroff/reboot support for T-Head TH1520 SoCs > > running the AON firmware by sending a message to the AON firmware's WDG > > part. > > > > This is a auxiliary device driver, and expects the AON channel to be > > passed via the platform_data of the auxiliary device. > > > > Signed-off-by: Icenowy Zheng <uwu@icenowy.me> > > --- > > Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> > > Greetings, > > -- Sebastian Thanks for looking at this patch. What tree do you think it should go through? -Drew
Hi, On Tue, Sep 16, 2025 at 12:28:16PM -0700, Drew Fustini wrote: > On Tue, Sep 16, 2025 at 08:22:02PM +0200, Sebastian Reichel wrote: > > On Mon, Aug 18, 2025 at 03:49:05PM +0800, Icenowy Zheng wrote: > > > This driver implements poweroff/reboot support for T-Head TH1520 SoCs > > > running the AON firmware by sending a message to the AON firmware's WDG > > > part. > > > > > > This is a auxiliary device driver, and expects the AON channel to be > > > passed via the platform_data of the auxiliary device. > > > > > > Signed-off-by: Icenowy Zheng <uwu@icenowy.me> > > > --- > > > > Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> > > > > Greetings, > > > > -- Sebastian > > Thanks for looking at this patch. > > What tree do you think it should go through? I'm fine with Uffe taking this together with the second patch or I can take it and provide an immutable branch once the second patch is ready. Greetings, -- Sebastian
On Thu, 18 Sept 2025 at 00:18, Sebastian Reichel <sebastian.reichel@collabora.com> wrote: > > Hi, > > On Tue, Sep 16, 2025 at 12:28:16PM -0700, Drew Fustini wrote: > > On Tue, Sep 16, 2025 at 08:22:02PM +0200, Sebastian Reichel wrote: > > > On Mon, Aug 18, 2025 at 03:49:05PM +0800, Icenowy Zheng wrote: > > > > This driver implements poweroff/reboot support for T-Head TH1520 SoCs > > > > running the AON firmware by sending a message to the AON firmware's WDG > > > > part. > > > > > > > > This is a auxiliary device driver, and expects the AON channel to be > > > > passed via the platform_data of the auxiliary device. > > > > > > > > Signed-off-by: Icenowy Zheng <uwu@icenowy.me> > > > > --- > > > > > > Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> > > > > > > Greetings, > > > > > > -- Sebastian > > > > Thanks for looking at this patch. > > > > What tree do you think it should go through? > > I'm fine with Uffe taking this together with the second patch or I > can take it and provide an immutable branch once the second patch is > ready. Okay, when patch2 is good to go, I will pick up both patches (no need for an immutable branch then), np! Kind regards Uffe
On Mon, Aug 18, 2025 at 03:49:05PM +0800, Icenowy Zheng wrote: > This driver implements poweroff/reboot support for T-Head TH1520 SoCs > running the AON firmware by sending a message to the AON firmware's WDG > part. > > This is a auxiliary device driver, and expects the AON channel to be > passed via the platform_data of the auxiliary device. > > Signed-off-by: Icenowy Zheng <uwu@icenowy.me> > --- > MAINTAINERS | 1 + > drivers/power/reset/Kconfig | 7 ++ > drivers/power/reset/Makefile | 1 + > drivers/power/reset/th1520-aon-reboot.c | 98 +++++++++++++++++++++++++ > 4 files changed, 107 insertions(+) > create mode 100644 drivers/power/reset/th1520-aon-reboot.c ... > diff --git a/drivers/power/reset/th1520-aon-reboot.c b/drivers/power/reset/th1520-aon-reboot.c > new file mode 100644 > index 0000000000000..8256c1703ebe8 > --- /dev/null > +++ b/drivers/power/reset/th1520-aon-reboot.c > @@ -0,0 +1,98 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * T-HEAD TH1520 AON Firmware Reboot Driver > + * > + * Copyright (c) 2025 Icenowy Zheng <uwu@icenowy.me> > + */ > + > +#include <linux/auxiliary_bus.h> > +#include <linux/firmware/thead/thead,th1520-aon.h> > +#include <linux/module.h> > +#include <linux/notifier.h> > +#include <linux/of.h> > +#include <linux/reboot.h> > +#include <linux/slab.h> > + > +#define TH1520_AON_REBOOT_PRIORITY 200 > + > +struct th1520_aon_msg_empty_body { > + struct th1520_aon_rpc_msg_hdr hdr; > + u16 reserved[12]; > +} __packed __aligned(1); > + > +static int th1520_aon_pwroff_handler(struct sys_off_data *data) > +{ > + struct th1520_aon_chan *aon_chan = data->cb_data; > + struct th1520_aon_msg_empty_body msg = {}; > + > + msg.hdr.svc = TH1520_AON_RPC_SVC_WDG; > + msg.hdr.func = TH1520_AON_WDG_FUNC_POWER_OFF; > + msg.hdr.size = TH1520_AON_RPC_MSG_NUM; > + > + th1520_aon_call_rpc(aon_chan, &msg); It's possible for th1520_aon_call_rpc() to fail. Should we check for its return value and emit a warning/error if it fails? Though in case of failure there may not be much we could do... > + return NOTIFY_DONE; > +} Best regards, Yao Zi
© 2016 - 2025 Red Hat, Inc.