[PATCH v25 04/10] firmware: psci: Add support for PSCI auxiliary devices
From: Shivendra Pratap <hidden>
Date: 2026-09-14 15:00:20
Also in:
linux-arm-msm, linux-devicetree, linux-pm, lkml
Subsystem:
cpu idle time management framework, cpuidle driver - arm psci pm domain, power state coordination interface (psci), the rest · Maintainers:
"Rafael J. Wysocki", Daniel Lezcano, Ulf Hansson, Mark Rutland, Lorenzo Pieralisi, Linus Torvalds
PSCI has multiple kernel consumers, such as cpuidle-psci-domain. Currently, both the PSCI core driver and cpuidle-psci-domain bind directly to the same PSCI node "arm,psci-1.0". Additional consumers, if introduced, would also need to bind in the same way, leading to multiple drivers attached to a single device node. Introduce a PSCI auxiliary-device provider that binds to "arm,psci-1.0" and registers PSCI child devices on the auxiliary bus. As the first user, register cpuidle-psci-domain as an auxiliary device. Update cpuidle-psci-domain to probe as an auxiliary driver and use the PSCI device node for power-domain traversal. Suggested-by: Ulf Hansson <redacted> Suggested-by: Lee Jones <lee@kernel.org> Suggested-by: Bartosz Golaszewski <redacted> Signed-off-by: Shivendra Pratap <redacted> --- MAINTAINERS | 1 + drivers/cpuidle/Kconfig.arm | 1 + drivers/cpuidle/cpuidle-psci-domain.c | 31 +++++++++++++++----------- drivers/firmware/psci/Kconfig | 14 ++++++++++++ drivers/firmware/psci/Makefile | 1 + drivers/firmware/psci/psci-devices.c | 41 +++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 13 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 207a6e2db70c..9c0334ee2ed2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS@@ -21932,6 +21932,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/arm/psci.yaml F: drivers/firmware/psci/ +F: drivers/firmware/psci/psci-devices.c F: include/linux/psci.h F: include/uapi/linux/psci.h
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index b88b01aa5829..f22e18b05053 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm@@ -36,6 +36,7 @@ config ARM_PSCI_CPUIDLE_DOMAIN bool "PSCI CPU idle Domain" depends on ARM_PSCI_CPUIDLE depends on PM_GENERIC_DOMAINS_OF + depends on ARM_PSCI_DEVICES select DT_IDLE_GENPD default y help
diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
index b9e4ad7d43a3..0ce6a83f6588 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c@@ -9,10 +9,11 @@ #define pr_fmt(fmt) "CPUidle PSCI: " fmt +#include <linux/auxiliary_bus.h> #include <linux/cpu.h> #include <linux/device.h> #include <linux/kernel.h> -#include <linux/platform_device.h> +#include <linux/module.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <linux/psci.h>
@@ -122,14 +123,10 @@ static void psci_pd_remove(void) } } -static const struct of_device_id psci_of_match[] = { - { .compatible = "arm,psci-1.0" }, - {} -}; - -static int psci_cpuidle_domain_probe(struct platform_device *pdev) +static int psci_cpuidle_domain_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) { - struct device_node *np = pdev->dev.of_node; + struct device_node *np = auxdev->dev.of_node; bool use_osi = psci_has_osi_support(); int ret = 0, pd_count = 0;
@@ -177,16 +174,24 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev) return ret; } -static struct platform_driver psci_cpuidle_domain_driver = { - .probe = psci_cpuidle_domain_probe, +static const struct auxiliary_device_id psci_cpuidle_domain_id_table[] = { + { .name = "arm-psci.psci-cpuidle-domain" }, + { } +}; +MODULE_DEVICE_TABLE(auxiliary, psci_cpuidle_domain_id_table); + +static struct auxiliary_driver psci_cpuidle_domain_driver = { + .probe = psci_cpuidle_domain_probe, .driver = { - .name = "psci-cpuidle-domain", - .of_match_table = psci_of_match, + .suppress_bind_attrs = true, }, + .id_table = psci_cpuidle_domain_id_table, }; static int __init psci_idle_init_domains(void) { - return platform_driver_register(&psci_cpuidle_domain_driver); + return __auxiliary_driver_register(&psci_cpuidle_domain_driver, + THIS_MODULE, + "psci-cpuidle-domain"); } core_initcall(psci_idle_init_domains);
diff --git a/drivers/firmware/psci/Kconfig b/drivers/firmware/psci/Kconfig
index 97944168b5e6..68e381f1a618 100644
--- a/drivers/firmware/psci/Kconfig
+++ b/drivers/firmware/psci/Kconfig@@ -2,6 +2,20 @@ config ARM_PSCI_FW bool +config ARM_PSCI_DEVICES + bool "PSCI auxiliary device support" + depends on ARM_PSCI_FW + depends on OF + select AUXILIARY_BUS + default y + help + Say Y here to enable auxiliary device support for PSCI. + + This creates auxiliary devices for PSCI functionality implemented + outside the core PSCI firmware driver. These devices allow PSCI + child drivers to bind through the auxiliary bus while sharing the + PSCI firmware device as their parent. + config ARM_PSCI_CHECKER bool "ARM PSCI checker" depends on ARM_PSCI_FW && HOTPLUG_CPU && CPU_IDLE && !TORTURE_TEST
diff --git a/drivers/firmware/psci/Makefile b/drivers/firmware/psci/Makefile
index 1956b882470f..8e75a0ed6f74 100644
--- a/drivers/firmware/psci/Makefile
+++ b/drivers/firmware/psci/Makefile@@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 # obj-$(CONFIG_ARM_PSCI_FW) += psci.o +obj-$(CONFIG_ARM_PSCI_DEVICES) += psci-devices.o obj-$(CONFIG_ARM_PSCI_CHECKER) += psci_checker.o
diff --git a/drivers/firmware/psci/psci-devices.c b/drivers/firmware/psci/psci-devices.c
new file mode 100644
index 000000000000..f1eca61e3269
--- /dev/null
+++ b/drivers/firmware/psci/psci-devices.c@@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include <linux/auxiliary_bus.h> +#include <linux/init.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +static int arm_psci_probe(struct platform_device *pdev) +{ + struct auxiliary_device *auxdev; + + auxdev = __devm_auxiliary_device_create(&pdev->dev, "arm-psci", + "psci-cpuidle-domain", NULL, 0); + if (!auxdev) + return -ENOMEM; + + return 0; +} + +static const struct of_device_id arm_psci_of_match[] = { + { .compatible = "arm,psci-1.0" }, + { } +}; + +static struct platform_driver arm_psci_driver = { + .probe = arm_psci_probe, + .driver = { + .name = "arm-psci", + .of_match_table = arm_psci_of_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init arm_psci_init(void) +{ + return platform_driver_register(&arm_psci_driver); +} +core_initcall(arm_psci_init);
--
2.34.1