[RFC PATCH] dt-bindings: power: Add power-limit-controller schema

From: Manaf Meethalavalappu Pallikunhi

Date: Thu Jul 09 2026 - 14:10:16 EST


This RFC proposes a new device tree binding schema for power limit
controllers that manage SoC power domains with hardware-enforced power
capping capabilities.

Background
==========
Modern SoCs implement sophisticated power management hardware that can
monitor and enforce power consumption limits across multiple power
domains. For example, Qualcomm's SPEL (SoC Power and Electrical Limits)
manages hierarchical power domains including system-level, SoC-level,
and individual subsystem domains (CPU clusters, GPU, modem, etc.).

These controllers help prevent thermal overload, maintain system
stability, and comply with platform power budgets. However, there is
currently no unified device tree representation that can describe their
hierarchical nature and diverse capabilities.

Proposed Schema Design
======================
The schema supports a flexible, hierarchical structure:

1. Power Limit Controller Node
- Root node representing the hardware controller
- Uses #power-limit-domain-cells for domain referencing

2. Power Domain Nodes (power-limit-domain@N)
- Individual domains/zones under the controller
- Each domain identified by a register index
- Optional parent-domain property for hierarchical relationships
- Can be either:
* Monitoring-only (no power-limits child node)
* Power-limiting (with power-limits child node)

3. Power Limit Constraints (power-limit@N)
- Multiple constraints per domain (PL1, PL2, PL3, etc.)
- Each constraint defines:
* Settable power limit (with min/max bounds)
* Settable time window for power averaging (with min/max bounds)
* Default values at boot/reset
* Constraint name for identification

Hierarchical Example (Qualcomm SPEL)
============================
System Domain (with PL1/PL2)
└── SoC Domain (with PL1/PL2)
├── CPU Cluster Domain (with PL1/PL2)
├── GPU Domain (monitoring-only)
└── Modem Domain (monitoring-only)

Before investing further in this direction, we would like to check with
the community on a few points:

1. Is a generic power-limit-controller binding the right approach here,
or should this remain a vendor-specific binding (e.g., under
qcom,spel)?

2. If a generic binding is acceptable, does this schema design look
reasonable as a starting point?

3. If this is the preferred direction, we would need to design a
generic driver that consumes this binding and exposes the domains
via the powercap sysfs interface — effectively requiring a
significant redesign of the existing Qualcomm SPEL driver to sit
on top of a vendor-agnostic core. Does that align with what the
community would expect here?

Any guidance on whether this is the right path forward — would
be greatly appreciated before we commit further engineering effort.

Signed-off-by: Manaf Meethalavalappu Pallikunhi <manaf.pallikunhi@xxxxxxxxxxxxxxxx>
---
.../power/limits/power-limit-controller.yaml | 238 ++++++++++++++++++
1 file changed, 238 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/limits/power-limit-controller.yaml

diff --git a/Documentation/devicetree/bindings/power/limits/power-limit-controller.yaml b/Documentation/devicetree/bindings/power/limits/power-limit-controller.yaml
new file mode 100644
index 000000000000..9cd4d9d6414d
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/limits/power-limit-controller.yaml
@@ -0,0 +1,238 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/limits/power-limit-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Power Limit Controller and Domains
+
+maintainers:
+ - Manaf Meethalavalappu Pallikunhi <manaf.pallikunhi@xxxxxxxxxxxxxxxx>
+
+description: |
+ Power limit controllers are hardware blocks that enforce power consumption
+ limits on SoC power domains to prevent thermal overload, maintain system
+ stability, and comply with platform power budgets.
+
+ The binding supports a hierarchical structure:
+ - A power limit controller
+ - Multiple power domains/zones under the controller
+ - Each domain can have power limit constraints or be monitoring-only
+ - Domains with constraints support multiple power limits (PL1, PL2, PL3, etc.)
+
+ Controller capabilities:
+ - Hardware-enforced power capping for one or more power domains
+ - Multiple configurable power limits per domain (sustained, burst, peak)
+ - Time window controls for power averaging
+ - Energy or power monitoring and reporting
+ - Power balancing algorithms across domains
+
+ This binding describes the common properties for power limit controller
+ provider nodes. Individual controller bindings should reference this schema
+ and add device-specific properties.
+
+select: false
+
+properties:
+ $nodename:
+ pattern: "^power-limits(@.*)?$"
+
+ '#power-limit-domain-cells':
+ description: |
+ Number of cells in a power limit domain specifier for child domains.
+ Typically 1, representing the domain index.
+ const: 1
+
+patternProperties:
+ "^power-limit-domain@[0-9]+$":
+ type: object
+ description: |
+ Individual power limit domain/zone under this controller.
+ Each domain can either:
+ - Have power limit constraints (with power-limits child node)
+ - Be monitoring-only (without power-limits child node)
+
+ properties:
+ reg:
+ description: Power domain index identifier
+ maxItems: 1
+
+ domain-name:
+ description: |
+ Name of this power domain (e.g., "system", "soc", "subsystem").
+ $ref: /schemas/types.yaml#/definitions/string
+
+ parent-domain:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: |
+ Reference to the parent power limit domain, if this domain is a
+ sub-domain of another domain. This establishes a hierarchical
+ relationship between domains.
+
+ For example, a "subsystem" domain might be a child of a "soc" domain,
+ or a "soc" domain might be a child of a "system" domain.
+
+ power-limits:
+ type: object
+ description: |
+ Container node for power limit constraints within this domain.
+ Each child node represents a power limit constraint index.
+
+ This node is optional. If omitted (or if monitoring-only is set),
+ the domain provides only power/energy measurement without limits.
+
+ patternProperties:
+ "^power-limit@[0-9]+$":
+ type: object
+ description: |
+ Individual power limit constraint configuration.
+
+ Each constraint defines:
+ - A settable power limit
+ - A settable time window
+ - Optional min/max bounds for power and time window
+ - A name identifier
+
+ Typical constraint indices:
+ - Index 0: PL1 (sustained/long-term power limit)
+ - Index 1: PL2 (burst/short-term power limit)
+ - Index 2: PL3 (peak/instantaneous power limit)
+
+ properties:
+ reg:
+ description: Power limit constraint index identifier
+ maxItems: 1
+
+ constraint-name:
+ description: |
+ Name of this power limit constraint (e.g., "long_term", "short_term").
+ $ref: /schemas/types.yaml#/definitions/string
+
+ power-limit-min-microwatt:
+ description: |
+ Minimum power limit that can be configured for this constraint.
+ Represents the lower bound of the allowable power range.
+
+ power-limit-max-microwatt:
+ description: |
+ Maximum power limit that can be configured for this constraint.
+ Represents the upper bound of the allowable power range.
+
+ power-limit-microwatt:
+ description: |
+ Default power limit value for this constraint at boot/reset.
+ This is the initial value that will be programmed.
+
+ time-window-min-microsecond:
+ description: |
+ Minimum time window for power averaging.
+ Shorter windows allow faster response to power excursions.
+
+ time-window-max-microsecond:
+ description: |
+ Maximum time window for power averaging.
+ Longer windows provide more stable power limiting.
+
+ time-window-microsecond:
+ description: |
+ Default time window value for power averaging at boot/reset.
+ This is the initial value that will be programmed.
+
+ required:
+ - reg
+
+ additionalProperties: true
+
+ additionalProperties: false
+
+ required:
+ - reg
+
+ additionalProperties: true
+
+additionalProperties: true
+
+examples:
+ - |
+ // Multi-domain power limit controller with mixed capabilities
+ // Demonstrates multiple domains with and without power limit constraints
+ power-limits@ef3b000 {
+ compatible = "qcom,glymur-spel";
+ reg = <0x0ef3b000 0x1000>;
+ #power-limit-domain-cells = <1>;
+
+ // Domain 0: System domain with full power limit control (PL1/PL2)
+ sys_domain: power-limit-domain@0 {
+ reg = <0>;
+ domain-name = "system";
+
+ power-limits {
+ // PL1: Sustained/Long-term Power Limit
+ power-limit@0 {
+ reg = <0>;
+ constraint-name = "long_term";
+
+ power-limit-min-microwatt = <15000000>; // 15W min
+ power-limit-max-microwatt = <28000000>; // 28W max
+ power-limit-microwatt = <20000000>; // 20W default
+
+ time-window-min-microsecond = <1000000>; // 1s min
+ time-window-max-microsecond = <10000000>; // 10s max
+ time-window-microsecond = <8000000>; // 8s default
+ };
+
+ // PL2: Burst/Short-term Power Limit
+ power-limit@1 {
+ reg = <1>;
+ constraint-name = "short_term";
+
+ power-limit-min-microwatt = <15000000>; // 15W min
+ power-limit-max-microwatt = <64000000>; // 64W max
+ power-limit-microwatt = <45000000>; // 45W default
+
+ time-window-min-microsecond = <10000>; // 10ms min
+ time-window-max-microsecond = <1000000>; // 1s max
+ time-window-microsecond = <28000>; // 28ms default
+ };
+ };
+ };
+
+ // Domain 1: SoC domain - child of system, monitoring only
+ soc_domain: power-limit-domain@1 {
+ reg = <1>;
+ domain-name = "soc";
+ parent-domain = <&sys_domain>;
+
+ // This domain exposes only:
+ // - power_uw (current power)
+ // - energy_uj (energy counter)
+ // - enabled (measurement control)
+ };
+
+ // Domain 2: Subsystem domain with single power limit
+ power-limit-domain@2 {
+ reg = <2>;
+ domain-name = "cpu";
+ parent-domain = <&soc_domain>;
+
+ power-limits {
+ power-limit@0 {
+ reg = <0>;
+ constraint-name = "subsystem";
+
+ power-limit-min-microwatt = <5000000>; // 5W
+ power-limit-max-microwatt = <15000000>; // 15W
+ power-limit-microwatt = <10000000>; // 10W
+
+ time-window-microsecond = <1000000>; // 1s
+ };
+ };
+ };
+
+ // Domain 3: Another subsystem - monitoring only (no power-limits node)
+ power-limit-domain@3 {
+ reg = <3>;
+ domain-name = "gpu";
+ parent-domain = <&soc_domain>;
+ };
+ };
--
2.43.0