Re: [PATCH v25 06/10] power: reset: Add psci-reboot-mode driver
From: Shivendra Pratap
Date: Thu Sep 17 2026 - 09:24:49 EST
On 9/16/2026 2:53 PM, Bartosz Golaszewski wrote:
On Mon, 14 Sep 2026 16:59:10 +0200, Shivendra Pratap
<shivendra.pratap@xxxxxxxxxxxxxxxx> said:
PSCI supports different types of resets like SYSTEM_RESET, SYSTEM_RESET2
ARCH WARM reset and SYSTEM_RESET2 vendor-specific resets. Currently
there is no common driver that handles all supported psci resets at one
place. Additionally, there is no common mechanism to issue the supported
psci resets from userspace.
Add psci-reboot-mode as an auxiliary device created by the psci-devices
driver. Define two types of PSCI resets, predefined-resets and
vendor-specific resets. Predefined-resets are defined by psci driver
and vendor-specific resets are defined by SoC vendors, under the
psci:reboot-mode node of SoC device tree.
Register the driver with the reboot-mode framework to interface these
resets to userspace. When userspace initiates a supported command, pass
the reset arguments to the PSCI driver to enable command-based reset.
This change allows userspace to issue supported PSCI reset commands
using the standard reboot system calls while enabling SoC vendors to
define their specific resets for PSCI.
Suggested-by: Ulf Hansson <ulf.hansson@xxxxxxxxxxxxxxxx>
Suggested-by: Lee Jones <lee@xxxxxxxxxx>
Suggested-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
Signed-off-by: Shivendra Pratap <shivendra.pratap@xxxxxxxxxxxxxxxx>
---
MAINTAINERS | 1 +
drivers/firmware/psci/psci-devices.c | 71 +++++++++++++++++++++-
drivers/power/reset/Kconfig | 10 ++++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/psci-reboot-mode.c | 104 +++++++++++++++++++++++++++++++++
5 files changed, 185 insertions(+), 2 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 9c0334ee2ed2..1c0f111ba197 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21933,6 +21933,7 @@ S: Maintained
F: Documentation/devicetree/bindings/arm/psci.yaml
F: drivers/firmware/psci/
F: drivers/firmware/psci/psci-devices.c
+F: drivers/power/reset/psci-reboot-mode.c
F: include/linux/psci.h
F: include/uapi/linux/psci.h
diff --git a/drivers/firmware/psci/psci-devices.c b/drivers/firmware/psci/psci-devices.c
index f1eca61e3269..43e6743202f9 100644
--- a/drivers/firmware/psci/psci-devices.c
+++ b/drivers/firmware/psci/psci-devices.c
@@ -4,19 +4,86 @@
*/
#include <linux/auxiliary_bus.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/psci.h>
+#include <linux/slab.h>
+
+static void arm_psci_auxiliary_device_release(struct device *dev)
+{
+ struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
+
+ of_node_put(dev->of_node);
+ kfree(auxdev);
+}
+
+static struct auxiliary_device *
+arm_psci_auxiliary_device_create(struct device *dev, const char *devname,
+ struct device_node *np)
+{
+ struct auxiliary_device *auxdev;
+ int ret;
+
+ auxdev = kzalloc_obj(*auxdev);
+ if (!auxdev)
+ return NULL;
+
+ auxdev->id = 0;
+ auxdev->name = devname;
+ auxdev->dev.parent = dev;
+ auxdev->dev.release = arm_psci_auxiliary_device_release;
+
+ if (np)
+ device_set_node(&auxdev->dev, of_fwnode_handle(of_node_get(np)));
+
+ ret = auxiliary_device_init(auxdev);
+ if (ret) {
+ of_node_put(auxdev->dev.of_node);
+ kfree(auxdev);
+ return NULL;
+ }
+
+ ret = __auxiliary_device_add(auxdev, "arm-psci");
+ if (ret) {
+ auxiliary_device_uninit(auxdev);
+ return NULL;
+ }
+
+ ret = devm_add_action_or_reset(dev, auxiliary_device_destroy, auxdev);
+ if (ret)
+ return NULL;
+
+ return auxdev;
+}
static int arm_psci_probe(struct platform_device *pdev)
{
struct auxiliary_device *auxdev;
+#ifdef CONFIG_PSCI_REBOOT_MODE
+ struct device_node *reboot_mode_np = NULL;
+#endif
- auxdev = __devm_auxiliary_device_create(&pdev->dev, "arm-psci",
- "psci-cpuidle-domain", NULL, 0);
+ auxdev = arm_psci_auxiliary_device_create(&pdev->dev,
+ "psci-cpuidle-domain",
+ pdev->dev.of_node);
if (!auxdev)
return -ENOMEM;
+#ifdef CONFIG_PSCI_REBOOT_MODE
+ if (psci_has_system_reset2_support())
+ reboot_mode_np = of_get_child_by_name(pdev->dev.of_node,
+ "reboot-mode");
+
+ auxdev = arm_psci_auxiliary_device_create(&pdev->dev,
+ "psci-reboot-mode",
+ reboot_mode_np);
+ of_node_put(reboot_mode_np);
+ if (!auxdev)
+ dev_warn(&pdev->dev, "failed to create PSCI reboot mode device\n");
+#endif
+
return 0;
}
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index bce996bbef28..5c349f41e097 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -360,6 +360,16 @@ config NVMEM_REBOOT_MODE
then the bootloader can read it and take different
action according to the mode.
+config PSCI_REBOOT_MODE
+ bool "PSCI reboot mode driver"
+ depends on ARM_PSCI_DEVICES
+ select REBOOT_MODE
Needs: select AUXILIARY_BUS
Ack.
+ help
+ Say y here to enable the PSCI reboot mode driver. The driver
+ registers with the reboot-mode framework to configure PSCI
+ reset commands, which are executed by the PSCI driver during
+ psci_sys_reset().
+
config POWER_MLXBF
tristate "Mellanox BlueField power handling driver"
depends on (GPIO_MLXBF2 || GPIO_MLXBF3) && ACPI
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index e31cab4ba78e..45d8aaaffaa1 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -41,5 +41,6 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
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_PSCI_REBOOT_MODE) += psci-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/psci-reboot-mode.c b/drivers/power/reset/psci-reboot-mode.c
new file mode 100644
index 000000000000..bf2dd6626feb
--- /dev/null
+++ b/drivers/power/reset/psci-reboot-mode.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/array_size.h>
+#include <linux/auxiliary_bus.h>
+#include <linux/device.h>
[
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kconfig.h>
]
Why are you including these?
errno.h and init.h were added for EINVAL and subsys_initcall()
- will remove these. available in psci.h
kconfig.h for IS_ENABLED(CONFIG_64BIT)
- will retain this.
thanks,
Shivendra