diff mbox series

firmware: psci: register PSCI power domains to stub driver

Message ID 20240628-topic-sm8x50-psci-power-domain-v1-1-4608830f194a@linaro.org
State New
Headers show
Series firmware: psci: register PSCI power domains to stub driver | expand

Commit Message

Neil Armstrong June 28, 2024, 9:54 a.m. UTC
On some SoCs, like Qualcomm SoCs, the PSCI cluster power domain
is used by system-wide firmware interfaces to make sure none
of the CPUs are suspended before submitting requests.

While on U-boot we only use the first core and we never
suspend it, the Device Tree still references it and blocks
those nodes to be probed.

Simply bind the PSCI power-domain subnoded to a stub power
domain driver in order to solve the runtime dependencies.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/firmware/psci.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)


---
base-commit: 9e9f78f7aa0124ef0e622532043acf87e84008dc
change-id: 20240628-topic-sm8x50-psci-power-domain-27dd90a7f298

Best regards,
diff mbox series

Patch

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 03544d76ed4..fc72bc17274 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -23,6 +23,7 @@ 
 #include <linux/libfdt.h>
 #include <linux/printk.h>
 #include <linux/psci.h>
+#include <power-domain-uclass.h>
 
 #define DRIVER_NAME "psci"
 
@@ -172,6 +173,10 @@  static int bind_smccc_features(struct udevice *dev, int psci_method)
 
 static int psci_bind(struct udevice *dev)
 {
+#if IS_ENABLED(CONFIG_POWER_DOMAIN)
+	ofnode node;
+#endif
+
 	/* No SYSTEM_RESET support for PSCI 0.1 */
 	if (device_is_compatible(dev, "arm,psci-0.2") ||
 	    device_is_compatible(dev, "arm,psci-1.0")) {
@@ -188,6 +193,16 @@  static int psci_bind(struct udevice *dev)
 	if (IS_ENABLED(CONFIG_ARM_SMCCC_FEATURES) && device_is_compatible(dev, "arm,psci-1.0"))
 		dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
 
+	/* Bind power-domain subnodes */
+#if IS_ENABLED(CONFIG_POWER_DOMAIN)
+	dev_for_each_subnode(node, dev) {
+		if (device_bind_driver_to_node(dev, "psci_power_domain",
+					       ofnode_get_name(node),
+					       node, NULL))
+			pr_warn("failed to bind %s\n", ofnode_get_name(node));
+	}
+#endif
+
 	return 0;
 }
 
@@ -324,3 +339,29 @@  U_BOOT_DRIVER(psci) = {
 #endif
 	.flags = DM_FLAG_PRE_RELOC,
 };
+
+#if IS_ENABLED(CONFIG_POWER_DOMAIN)
+/* Accept #power-domain-cells == 0 */
+static int psci_power_domain_xlate(struct power_domain *power_domain,
+				   struct ofnode_phandle_args *args)
+{
+	return args->args_count == 0 ? 0 : -EINVAL;
+}
+
+static const struct power_domain_ops psci_power_ops = {
+	.of_xlate = psci_power_domain_xlate,
+};
+
+static int psci_power_domain_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+U_BOOT_DRIVER(psci_power_domain) = {
+	.name = "psci_power_domain",
+	.id = UCLASS_POWER_DOMAIN,
+	.ops = &psci_power_ops,
+	.probe = psci_power_domain_probe,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+#endif