[PATCH v10 12/13] powercap: arm_scmi: Add get_power_uw to synthetic node

Philip Radford philip.radford at arm.com
Tue Nov 3 15:10:06 PST 2026


Exposes the current power usage from the immediate children of the
synthetic (root) powercap node. Iterates over pr->spzones and sums per-zone
power. Domains without powercap monitoring are skipped. If none of the
children can be measured, return -ENODATA.

Signed-off-by: Philip Radford <philip.radford at arm.com>
---
V9->V10
- skip immediate child zones that do not support power monitoring
- return -ENODATA if none of the synthetic root children can be measured
---
 drivers/powercap/arm_scmi_powercap.c | 46 ++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c
index 88003564581e..d0255fd42007 100644
--- a/drivers/powercap/arm_scmi_powercap.c
+++ b/drivers/powercap/arm_scmi_powercap.c
@@ -17,6 +17,9 @@
 #define to_scmi_powercap_zone(z)		\
 	container_of(z, struct scmi_powercap_zone, zone)
 
+#define to_scmi_powercap_root(z)		\
+	container_of(z, struct scmi_powercap_root, instance_root.zone)
+
 static const struct scmi_powercap_proto_ops *powercap_ops;
 
 struct scmi_powercap_zone {
@@ -431,9 +434,48 @@ static int instance_root_release(struct powercap_zone *pz)
 	return 0;
 }
 
-static int instance_root_get_power_uw(struct powercap_zone *pz, u64 *v)
+static int instance_root_get_power_uw(struct powercap_zone *pz, u64 *power_uw)
 {
-	*v = 0;
+	struct scmi_powercap_root *pr = to_scmi_powercap_root(pz);
+	struct scmi_powercap_zone *child;
+
+	u64 p, acc = 0;
+	int i, ret;
+	bool measured = false;
+
+	if (!pz || !power_uw)
+		return -EINVAL;
+
+	for (i = 0; i < pr->num_zones; i++) {
+		child = &pr->spzones[i];
+
+		if (!child->registered || child->invalid)
+			continue;
+
+		if (child->info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID)
+			continue;
+
+		/*
+		 * The synthetic root reports the sum of measureable immediate children.
+		 * Control-only children do not contribute to the sum.
+		 */
+		if (!child->info->powercap_monitoring)
+			continue;
+
+		ret = scmi_powercap_get_power_uw(&child->zone, &p);
+		if (ret) {
+			dev_dbg(child->dev, "Failed to read child power: %d\n", ret);
+			return ret;
+		}
+
+		acc += p;
+		measured = true;
+	}
+
+	if (!measured)
+		return -ENODATA;
+
+	*power_uw = acc;
 	return 0;
 }
 
-- 
2.34.1




More information about the linux-arm-kernel mailing list