On Dec 2, 2013, at 10:20 AM, Lorenzo Pieralisi <lorenzo.pieralisi@xxxxxxx> wrote: > ARM based platforms implement a variety of power management schemes that > allow processors to enter at run-time low-power states, aka C-states > in ACPI jargon. The parameters defining these C-states vary on a per-platform > basis forcing the OS to hardcode the state parameters in platform > specific static tables whose size grows as the number of platforms supported > in the kernel increases and hampers device drivers standardization. > > Therefore, this patch aims at standardizing C-state device tree bindings for > ARM platforms. Bindings define C-state parameters inclusive of entry methods > and state latencies, to allow operating systems to retrieve the > configuration entries from the device tree and initialize the related > power management drivers, paving the way for common code in the kernel > to deal with power states and removing the need for static data in current > and previous kernel versions. Where is this spec’d today in the kernel? > > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@xxxxxxx> > --- > Documentation/devicetree/bindings/arm/c-states.txt | 830 +++++++++++++++++++++ > 1 file changed, 830 insertions(+) > create mode 100644 Documentation/devicetree/bindings/arm/c-states.txt > > diff --git a/Documentation/devicetree/bindings/arm/c-states.txt b/Documentation/devicetree/bindings/arm/c-states.txt > new file mode 100644 > index 0000000..f568417 > --- /dev/null > +++ b/Documentation/devicetree/bindings/arm/c-states.txt > @@ -0,0 +1,830 @@ > +========================================== > +ARM C-states binding description > +========================================== > + > +========================================== > +1 - Introduction > +========================================== > + > +ARM systems contain HW capable of managing power consumption dynamically, > +where cores can be put in different low-power states (ranging from simple > +wfi to power gating) according to OSPM policies. Borrowing concepts > +from the ACPI specification[1], the CPU states representing the range of > +dynamic states that a processor can enter at run-time, aka C-state, can be > +specified through device tree bindings representing the parameters required to > +enter/exit specific C-states on a given processor. > + > +The state an ARM CPU can be put into is loosely identified by one of the > +following operating modes: > + > +- Running: > + # Processor core is executing instructions > + > +- Wait for Interrupt: > + # An ARM processor enters wait for interrupt (WFI) low power > + state by executing a wfi instruction. When a processor enters > + wfi state it disables most of the clocks while keeping the processor > + powered up. This state is standard on all ARM processors and it is > + defined as C1 in the remainder of this document. > + > +- Dormant: > + # Dormant mode is entered by executing wfi instructions and by sending > + platform specific commands to the platform power controller (coupled > + with processor specific SW/HW control sequences). > + In dormant mode, most of the processor control and debug logic is > + powered up but cache RAM can be put in retention state, providing > + additional power savings. > + > +- Sleep: > + # Sleep mode is entered by executing the wfi instruction and by sending > + platform specific commands to the platform power controller (coupled > + with processor specific SW/HW control sequences). In sleep mode, a > + processor and its caches are shutdown, the entire processor state is > + lost. > + > +Building on top of the previous processor modes, ARM platforms implement power > +management schemes that allow an OS PM implementation to put the processor in > +different CPU states (C-states). C-states parameters (eg latency) are > +platform specific and need to be characterized with bindings that provide the > +required information to OSPM code so that it can build the required tables and > +use them at runtime. > + > +The device tree binding definition for ARM C-states is the subject of this > +document. > + > +=========================================== > +2 - cpu-power-states node > +=========================================== > + > +ARM processor C-states are defined within the cpu-power-states node, which is > +a direct child of the cpus node and provides a container where the processor > +states, defined as device tree nodes, are listed. > + > +- cpu-power-states node > + > + Usage: Optional - On ARM systems, is a container of processor C-state > + nodes. If the system does not provide CPU power > + management capabilities or the processor just > + supports WFI (C1 state) a cpu-power-states node is > + not required. > + > + Description: cpu-power-states node is a container node, where its > + subnodes describe the CPU low-power C-states. > + > + Node name must be "cpu-power-states". > + > + The cpu-power-states node's parent node must be cpus node. > + > + The cpu-power-states node's child nodes can be: > + > + - one or more state nodes > + > + The cpu-power-states node must contain the following properties: > + > + - compatible > + Value type: <stringlist> > + Usage: Required > + Definition: Must be "arm,cpu-power-states". > + > + - #address-cells > + Usage: Required > + Value type: <u32> > + Definition: must be set to 1. > + > + - #size-cells > + Usage: Required > + Value type: <u32> > + Definition: must be set to 0. > + > + Any other configuration is considered invalid. > + > +The nodes describing the C-states (state) can only be defined within the > +cpu-power-states node. > + > +Any other configuration is consider invalid and therefore must be ignored. > + > +=========================================== > +2 - state node > +=========================================== > + > +A state node represents a C-state description and must be defined as follows: > + > +- state node > + > + Description: must be child of the cpu-power-states node. > + > + The state node name must be "state", with unit address provided by the > + "reg" property following standard DT requirements[4]. > + > + A state node defines the following properties: > + > + - reg > + Usage: Required > + Value type: <u32> > + Definition: Standard device tree property [4] used for > + enumeration purposes. I’m not sure what purpose reg is really serving here. > + > + - index > + Usage: Required > + Value type: <u32> > + Definition: It represents C-state index, starting from 2 (index > + 0 represents the processor state "running" and > + index 1 represents processor mode "WFI"; indexes 0 > + and 1 are standard ARM states that need not be > + described). any reason not to call it c-state-index" > + > + - entry-method > + Value type: <stringlist> > + Usage: Required > + Definition: Describes the method by which a CPU enters the > + C-state. This property is required and must be one > + of: > + > + - "psci" > + ARM Standard firmware interface > + > + - "[vendor],[method]" > + An implementation dependent string with > + format "vendor,method", where vendor is a string > + denoting the name of the manufacturer and > + method is a string specifying the mechanism > + used to enter the C-state. > + > + - psci-power-state > + Usage: Required if entry-method property value is set to > + "psci". > + Value type: <u32> > + Definition: power_state parameter to pass to the PSCI > + suspend call to enter the C-state. > + > + - latency > + Usage: Required > + Value type: <u32> > + Definition: Worst case latency in microseconds required to > + enter and exit the C-state. > + > + - min-residency > + Usage: Required > + Value type: <u32> > + Definition: Time in microseconds required for the CPU to be in > + the C-state to make up for the dynamic power > + consumed to enter/exit the C-state in order to > + break even in terms of power consumption compared > + to C1 state (wfi). > + This parameter depends on the operating conditions > + (operating point, cache state) and must assume > + worst case scenario. > + > + - cpus > + Usage: Optional > + Value type: <phandle> > + Definition: If defined, the phandle points to a node in the > + cpu-map[2] representing all CPUs on which C-state > + is valid. If not present or system is UP, the > + C-state has to be considered valid for all CPUs in > + the system. > + > + - affinity > + Usage: Optional > + Value type: <phandle> > + Definition: If defined, phandle points to a node in the > + cpu-map[2] that represents all CPUs that are > + affected (ie share) by the C-state and have to > + be coordinated on C-state entry/exit. If not > + present or system is UP, the C-state is local to > + a CPU and need no coordination (ie it is a CPU > + state, that does not require coordination with > + other CPUs). If present, the affinity property > + must contain a phandle to a cpu-map node that > + represents a subset, possibly inclusive of the > + CPUs described through the cpus property. > + > + - power-depth > + Usage: Required > + Value type: <u32> > + Definition: Integer value, starting from 2 (value 0 meaning > + running and value 1 representing power depth of > + wfi (C1)), that defines the level of depth of a > + power state. > + The system denotes power states with different > + depths, an increasing value meaning less power > + consumption and might involve powering down more > + components. Devices that are affected by > + C-states entry must define the maximum power > + depth supported in their respective device tree > + bindings so that OSPM can take decision on how > + to handle the device in question when the C-state > + is entered. All devices (per-CPU or external) with > + a power depth lower than the one defined in the > + C-state entry stop operating when the C-state > + is entered and action is required by OSPM to > + guarantee their logic and memory content is saved > + restored to guarantee proper functioning. How is this different from the c-state index? > + > + - cache-level-lost: > + Usage: Required if "entry-method" differs from "psci". > + Value type: <u32> > + Definition: An integer value representing the uppermost cache > + level (inclusive) that is lost upon state entry. > + This property requires the definition of cache > + nodes as specified in [3]. Cache levels that are > + shared between processors, according to [3], should > + coordinate cache cleaning and invalidation to > + maximize performance (ie a shared cache level > + must be cleaned only if all CPUs sharing the > + cache entered the state). If missing, cache > + state has to be considered retained. > + > + - processor-state-retained: > + Usage: See definition > + Value type: <none> > + Definition: if present CPU processor logic is retained on > + power down, otherwise it is lost. > + > + > +=========================================== > +3 - Examples > +=========================================== > + > +Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters): > + > +cpus { > + #size-cells = <0>; > + #address-cells = <2>; > + > + cpu-map { > + CLUSTER0: cluster0 { > + CLUSTER2: cluster0 { > + core0 { > + thread0 { > + cpu = <&CPU0>; > + }; > + thread1 { > + cpu = <&CPU1>; > + }; > + }; > + > + core1 { > + thread0 { > + cpu = <&CPU2>; > + }; > + thread1 { > + cpu = <&CPU3>; > + }; > + }; > + }; > + > + CLUSTER3: cluster1 { > + core0 { > + thread0 { > + cpu = <&CPU4>; > + }; > + thread1 { > + cpu = <&CPU5>; > + }; > + }; > + > + core1 { > + thread0 { > + cpu = <&CPU6>; > + }; > + thread1 { > + cpu = <&CPU7>; > + }; > + }; > + }; > + }; > + > + CLUSTER1: cluster1 { > + CLUSTER4: cluster0 { > + core0 { > + thread0 { > + cpu = <&CPU8>; > + }; > + thread1 { > + cpu = <&CPU9>; > + }; > + }; > + core1 { > + thread0 { > + cpu = <&CPU10>; > + }; > + thread1 { > + cpu = <&CPU11>; > + }; > + }; > + }; > + > + CLUSTER5: cluster1 { > + core0 { > + thread0 { > + cpu = <&CPU12>; > + }; > + thread1 { > + cpu = <&CPU13>; > + }; > + }; > + core1 { > + thread0 { > + cpu = <&CPU14>; > + }; > + thread1 { > + cpu = <&CPU15>; > + }; > + }; > + }; > + }; > + }; > + > + cpu-power-states { > + compatible = "arm,cpu-power-states"; > + #size-cells = <0>; > + #address-cells = <1>; > + > + state@0 { > + reg = <0>; > + index = <2>; > + entry-method = "psci"; > + psci-power-state = <0x1010000>; > + latency = <400>; > + min-residency = <300>; > + power-depth = <2>; > + cache-level-lost = <1>; > + cpus = <&CLUSTER0>; > + }; > + > + state@1 { > + reg = <1>; > + index = <2>; > + entry-method = "psci"; > + psci-power-state = <0x1010000>; > + latency = <400>; > + min-residency = <500>; > + power-depth = <2>; > + cache-level-lost = <1>; > + cpus = <&CLUSTER1>; > + }; > + > + state@2 { > + reg = <2>; > + index = <3>; > + entry-method = "psci"; > + psci-power-state = <0x3010000>; > + latency = <1000>; > + power-depth = <4>; > + cache-level-lost = <2>; > + cpus = <&CLUSTER0>; > + affinity = <&CLUSTER0>; > + }; > + > + state@3 { > + reg = <3>; > + index = <3>; > + entry-method = "psci"; > + latency = <4500>; > + min-residency = <6500>; > + psci-power-state = <0x3010000>; > + power-depth = <4>; > + cache-level-lost = <2>; > + cpus = <&CLUSTER1>; > + affinity = <&CLUSTER1>; > + }; > + }; > + > + CPU0: cpu@0 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x0>; > + enable-method = "psci"; > + next-cache-level = <&L1_0>; > + L1_0: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + L2_0: l2-cache { > + compatible = "cache"; > + cache-level = <2>; > + }; > + }; > + > + CPU1: cpu@1 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x1>; > + enable-method = "psci"; > + next-cache-level = <&L1_1>; > + L1_1: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU2: cpu@100 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x100>; > + enable-method = "psci"; > + next-cache-level = <&L1_2>; > + L1_2: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU3: cpu@101 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x101>; > + enable-method = "psci"; > + next-cache-level = <&L1_3>; > + L1_3: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU4: cpu@10000 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x10000>; > + enable-method = "psci"; > + next-cache-level = <&L1_4>; > + L1_4: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU5: cpu@10001 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x10001>; > + enable-method = "psci"; > + next-cache-level = <&L1_5>; > + L1_5: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU6: cpu@10100 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x10100>; > + enable-method = "psci"; > + next-cache-level = <&L1_6>; > + L1_6: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU7: cpu@10101 { > + device_type = "cpu"; > + compatible = "arm,cortex-a57"; > + reg = <0x0 0x10101>; > + enable-method = "psci"; > + next-cache-level = <&L1_7>; > + L1_7: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU8: cpu@100000000 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x0>; > + enable-method = "psci"; > + next-cache-level = <&L1_8>; > + L1_8: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + L2_1: l2-cache { > + compatible = "cache"; > + cache-level = <2>; > + }; > + }; > + > + CPU9: cpu@100000001 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x1>; > + enable-method = "psci"; > + next-cache-level = <&L1_9>; > + L1_9: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU10: cpu@100000100 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x100>; > + enable-method = "psci"; > + next-cache-level = <&L1_10>; > + L1_10: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU11: cpu@100000101 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x101>; > + enable-method = "psci"; > + next-cache-level = <&L1_11>; > + L1_11: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU12: cpu@100010000 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x10000>; > + enable-method = "psci"; > + next-cache-level = <&L1_12>; > + L1_12: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU13: cpu@100010001 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x10001>; > + enable-method = "psci"; > + next-cache-level = <&L1_13>; > + L1_13: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU14: cpu@100010100 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x10100>; > + enable-method = "psci"; > + next-cache-level = <&L1_14>; > + L1_14: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU15: cpu@100010101 { > + device_type = "cpu"; > + compatible = "arm,cortex-a53"; > + reg = <0x1 0x10101>; > + enable-method = "psci"; > + next-cache-level = <&L1_15>; > + L1_15: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > +}; > + > +Example 2 (ARM 32-bit, 8-cpu system, two clusters): > + > +cpus { > + #size-cells = <0>; > + #address-cells = <1>; > + > + cpu-map { > + CLUSTER0: cluster0 { > + core0 { > + thread0 { > + cpu = <&CPU0>; > + }; > + thread1 { > + cpu = <&CPU1>; > + }; > + }; > + > + core1 { > + thread0 { > + cpu = <&CPU2>; > + }; > + thread1 { > + cpu = <&CPU3>; > + }; > + }; > + }; > + > + CLUSTER1: cluster1 { > + core0 { > + thread0 { > + cpu = <&CPU4>; > + }; > + thread1 { > + cpu = <&CPU5>; > + }; > + }; > + > + core1 { > + thread0 { > + cpu = <&CPU6>; > + }; > + thread1 { > + cpu = <&CPU7>; > + }; > + }; > + }; > + }; > + > + cpu-power-states { > + compatible = "arm,cpu-power-states"; > + #size-cells = <0>; > + #address-cells = <1>; > + > + state@0 { > + reg = <0>; > + index = <2>; > + entry-method = "psci"; > + psci-power-state = <0x1010000>; > + latency = <400>; > + min-residency = <300>; > + power-depth = <2>; > + cpus = <&CLUSTER0>; > + }; > + > + state@1 { > + reg = <1>; > + index = <2>; > + entry-method = "psci"; > + psci-power-state = <0x1010000>; > + latency = <400>; > + min-residency = <500>; > + power-depth = <2>; > + cpus = <&CLUSTER1>; > + }; > + > + state@2 { > + reg = <2>; > + index = <3>; > + entry-method = "psci"; > + psci-power-state = <0x2010000>; > + latency = <3000>; > + min-residency = <3000>; > + cache-level-lost = <2>; > + power-depth = <3>; > + cpus = <&CLUSTER0>; > + affinity = <&CLUSTER0>; > + }; > + > + state@3 { > + reg = <3>; > + index = <3>; > + entry-method = "psci"; > + psci-power-state = <0x2010000>; > + latency = <4000>; > + min-residency = <5000>; > + cache-level-lost = <2>; > + power-depth = <3>; > + cpus = <&CLUSTER1>; > + affinity = <&CLUSTER1>; > + }; > + }; > + > + CPU0: cpu@0 { > + device_type = "cpu"; > + compatible = "arm,cortex-a15"; > + reg = <0x0>; > + next-cache-level = <&L1_0>; > + L1_0: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + }; > + L2_0: l2-cache { > + compatible = "cache"; > + cache-level = <2>; > + }; > + }; > + > + CPU1: cpu@1 { > + device_type = "cpu"; > + compatible = "arm,cortex-a15"; > + reg = <0x1>; > + next-cache-level = <&L1_1>; > + L1_1: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU2: cpu@2 { > + device_type = "cpu"; > + compatible = "arm,cortex-a15"; > + reg = <0x2>; > + next-cache-level = <&L1_2>; > + L1_2: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU3: cpu@3 { > + device_type = "cpu"; > + compatible = "arm,cortex-a15"; > + reg = <0x3>; > + next-cache-level = <&L1_3>; > + L1_3: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_0>; > + }; > + }; > + > + CPU4: cpu@100 { > + device_type = "cpu"; > + compatible = "arm,cortex-a7"; > + reg = <0x100>; > + next-cache-level = <&L1_4>; > + L1_4: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + }; > + L2_1: l2-cache { > + compatible = "cache"; > + cache-level = <2>; > + }; > + }; > + > + CPU5: cpu@101 { > + device_type = "cpu"; > + compatible = "arm,cortex-a7"; > + reg = <0x101>; > + next-cache-level = <&L1_5>; > + L1_5: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU6: cpu@102 { > + device_type = "cpu"; > + compatible = "arm,cortex-a7"; > + reg = <0x102>; > + next-cache-level = <&L1_6>; > + L1_6: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > + > + CPU7: cpu@103 { > + device_type = "cpu"; > + compatible = "arm,cortex-a7"; > + reg = <0x103>; > + next-cache-level = <&L1_7>; > + L1_7: l1-cache { > + compatible = "cache"; > + cache-level = <1>; > + next-cache-level = <&L2_1>; > + }; > + }; > +}; > + > +=========================================== > +4 - References > +=========================================== > + > +[1] ACPI v5.0 specification > + http://www.acpi.info/spec50.htm > + > +[2] ARM Linux kernel documentation - topology bindings > + Documentation/devicetree/bindings/arm/topology.txt > + > +[3] ARM Linux kernel documentation - cache bindings > + Documentation/devicetree/bindings/arm/cache.txt > + > +[4] ePAPR standard > + https://www.power.org/documentation/epapr-version-1-1/ > -- > 1.8.4 > > > -- > To unsubscribe from this list: send the line "unsubscribe devicetree" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html