* [PATCH v2 1/2] dt-bindings: firmware: amlogic,meson-gxbb-sm: add amlogic,meson-s4-sm
2026-11-06 10:18 [PATCH v2 0/2] firmware: meson: sm: make power-off work on S4 christian.koever-draxl
@ 2026-11-06 10:18 ` christian.koever-draxl
2026-11-06 13:09 ` Rob Herring
2026-11-06 10:18 ` [PATCH v2 2/2] firmware: meson: sm: make power-off work on S4 christian.koever-draxl
1 sibling, 1 reply; 4+ messages in thread
From: christian.koever-draxl @ 2026-11-06 10:18 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, neil.armstrong, khilman, jbrunet,
martin.blumenstingl
Cc: devicetree, linux-arm-kernel, linux-amlogic, linux-kernel,
Christian Stefan Kövér-Draxl
From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
The S4 secure monitor implements the GXBB interface, but its PSCI
SYSTEM_OFF needs an extra firmware call first (a shutdown flag), so the
driver has to tell it apart. Add an S4 compatible with the GXBB one as
fallback.
Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
---
.../devicetree/bindings/firmware/amlogic,meson-gxbb-sm.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/firmware/amlogic,meson-gxbb-sm.yaml b/Documentation/devicetree/bindings/firmware/amlogic,meson-gxbb-sm.yaml
index 8f50e698760e..6ff2ddfcaf54 100644
--- a/Documentation/devicetree/bindings/firmware/amlogic,meson-gxbb-sm.yaml
+++ b/Documentation/devicetree/bindings/firmware/amlogic,meson-gxbb-sm.yaml
@@ -18,7 +18,9 @@ properties:
oneOf:
- const: amlogic,meson-gxbb-sm
- items:
- - const: amlogic,meson-gx-sm
+ - enum:
+ - amlogic,meson-gx-sm
+ - amlogic,meson-s4-sm
- const: amlogic,meson-gxbb-sm
power-controller:
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v2 2/2] firmware: meson: sm: make power-off work on S4
2026-11-06 10:18 [PATCH v2 0/2] firmware: meson: sm: make power-off work on S4 christian.koever-draxl
2026-11-06 10:18 ` [PATCH v2 1/2] dt-bindings: firmware: amlogic,meson-gxbb-sm: add amlogic,meson-s4-sm christian.koever-draxl
@ 2026-11-06 10:18 ` christian.koever-draxl
1 sibling, 0 replies; 4+ messages in thread
From: christian.koever-draxl @ 2026-11-06 10:18 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, neil.armstrong, khilman, jbrunet,
martin.blumenstingl
Cc: devicetree, linux-arm-kernel, linux-amlogic, linux-kernel,
Christian Stefan Kövér-Draxl
From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
On S4 the firmware implements PSCI SYSTEM_OFF as DDR self-refresh. A
press of the power key afterwards jumps back to the kernel resume
address, where nothing is waiting, and the board hangs until it is
unplugged.
The vendor kernel avoids this in two steps, both needed:
- set the firmware shutdown flag (SMC 0x82000042, argument 1) right
before SYSTEM_OFF, which makes the firmware cold-boot on the power
key instead of resuming;
- take the secondary CPUs down through PSCI CPU_OFF first. With them
only parked in the kernel, the firmware wake-up path hangs as well.
Register a power-off prepare handler that does both, for the
amlogic,meson-s4-sm compatible only. It offlines the secondary CPUs
with remove_cpu(): machine_power_off() later only parks them with
smp_send_stop(), and CPU hotplug no longer works at that point.
Tested on an S905W2 board: poweroff followed by the power key
cold-boots the board.
Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
---
drivers/firmware/meson/meson_sm.c | 31 +++++++++++++++++++++++++
include/linux/firmware/meson/meson_sm.h | 1 +
2 files changed, 32 insertions(+)
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index ab9751a59b55..de0c8e809c51 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -10,6 +10,7 @@
#include <linux/arm-smccc.h>
#include <linux/bug.h>
+#include <linux/cpu.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -17,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/printk.h>
#include <linux/property.h>
+#include <linux/reboot.h>
#include <linux/types.h>
#include <linux/sizes.h>
#include <linux/slab.h>
@@ -48,6 +50,7 @@ static const struct meson_sm_chip gxbb_chip = {
CMD(SM_THERMAL_CALIB_READ, 0x82000047),
CMD(SM_A1_PWRC_SET, 0x82000093),
CMD(SM_A1_PWRC_GET, 0x82000095),
+ CMD(SM_SET_POWEROFF_FLAG, 0x82000042),
{ /* sentinel */ },
},
};
@@ -303,6 +306,28 @@ static struct attribute *meson_sm_sysfs_attrs[] = {
};
ATTRIBUTE_GROUPS(meson_sm_sysfs);
+/*
+ * The S4 firmware implements PSCI SYSTEM_OFF as DDR self-refresh: on the
+ * power key it jumps back to the kernel instead of booting, which hangs the
+ * board. Setting the shutdown flag first makes it cold-boot instead, and the
+ * secondary CPUs must have been taken down through PSCI CPU_OFF beforehand,
+ * otherwise the wake-up path hangs as well. machine_power_off() only parks
+ * them, so offline them here, while CPU hotplug still works.
+ */
+static int meson_sm_power_off_prepare(struct sys_off_data *data)
+{
+ unsigned int cpu, primary = cpumask_first(cpu_online_mask);
+
+ for_each_online_cpu(cpu) {
+ if (cpu != primary && remove_cpu(cpu))
+ pr_warn("meson-sm: failed to stop CPU%u\n", cpu);
+ }
+
+ meson_sm_call(data->cb_data, SM_SET_POWEROFF_FLAG, NULL, 1, 0, 0, 0, 0);
+
+ return NOTIFY_DONE;
+}
+
static const struct of_device_id meson_sm_ids[] = {
{ .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip },
{ /* sentinel */ },
@@ -343,6 +368,12 @@ static int __init meson_sm_probe(struct platform_device *pdev)
if (devm_of_platform_populate(dev))
goto unmap_out_base;
+ if (of_device_is_compatible(dev->of_node, "amlogic,meson-s4-sm") &&
+ devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF_PREPARE,
+ SYS_OFF_PRIO_DEFAULT,
+ meson_sm_power_off_prepare, fw))
+ dev_warn(dev, "failed to register the power-off handler\n");
+
pr_info("secure-monitor enabled\n");
return 0;
diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h
index 3ebc2bd9a976..3f2fa160e32f 100644
--- a/include/linux/firmware/meson/meson_sm.h
+++ b/include/linux/firmware/meson/meson_sm.h
@@ -15,6 +15,7 @@ enum {
SM_THERMAL_CALIB_READ,
SM_A1_PWRC_SET,
SM_A1_PWRC_GET,
+ SM_SET_POWEROFF_FLAG,
};
struct meson_sm_firmware;
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread