[PATCH v25 06/10] power: reset: Add psci-reboot-mode driver

Shivendra Pratap shivendra.pratap at oss.qualcomm.com
Thu Sep 17 05:30:05 PDT 2026



On 9/16/2026 2:53 PM, Bartosz Golaszewski wrote:
> On Mon, 14 Sep 2026 16:59:10 +0200, Shivendra Pratap
> <shivendra.pratap at oss.qualcomm.com> 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 at oss.qualcomm.com>
>> Suggested-by: Lee Jones <lee at kernel.org>
>> Suggested-by: Bartosz Golaszewski <bartosz.golaszewski at oss.qualcomm.com>
>> Signed-off-by: Shivendra Pratap <shivendra.pratap at oss.qualcomm.com>
>> ---
>>   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



More information about the linux-arm-kernel mailing list