Merge branch 'pm-opp'
* pm-opp: PM / OPP: Add binding for 'opp-suspend' PM / OPP: Allow multiple OPP tables to be passed via DT PM / OPP: Add new bindings to address shortcomings of existing bindings
This commit is contained in:
commit
1af858fdd2
@ -1,8 +1,19 @@
|
||||
* Generic OPP Interface
|
||||
Generic OPP (Operating Performance Points) Bindings
|
||||
----------------------------------------------------
|
||||
|
||||
SoCs have a standard set of tuples consisting of frequency and
|
||||
voltage pairs that the device will support per voltage domain. These
|
||||
are called Operating Performance Points or OPPs.
|
||||
Devices work at voltage-current-frequency combinations and some implementations
|
||||
have the liberty of choosing these. These combinations are called Operating
|
||||
Performance Points aka OPPs. This document defines bindings for these OPPs
|
||||
applicable across wide range of devices. For illustration purpose, this document
|
||||
uses CPU as a device.
|
||||
|
||||
This document contain multiple versions of OPP binding and only one of them
|
||||
should be used per device.
|
||||
|
||||
Binding 1: operating-points
|
||||
============================
|
||||
|
||||
This binding only supports voltage-frequency pairs.
|
||||
|
||||
Properties:
|
||||
- operating-points: An array of 2-tuples items, and each item consists
|
||||
@ -23,3 +34,432 @@ cpu@0 {
|
||||
198000 850000
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
Binding 2: operating-points-v2
|
||||
============================
|
||||
|
||||
* Property: operating-points-v2
|
||||
|
||||
Devices supporting OPPs must set their "operating-points-v2" property with
|
||||
phandle to a OPP table in their DT node. The OPP core will use this phandle to
|
||||
find the operating points for the device.
|
||||
|
||||
Devices may want to choose OPP tables at runtime and so can provide a list of
|
||||
phandles here. But only *one* of them should be chosen at runtime. This must be
|
||||
accompanied by a corresponding "operating-points-names" property, to uniquely
|
||||
identify the OPP tables.
|
||||
|
||||
If required, this can be extended for SoC vendor specfic bindings. Such bindings
|
||||
should be documented as Documentation/devicetree/bindings/power/<vendor>-opp.txt
|
||||
and should have a compatible description like: "operating-points-v2-<vendor>".
|
||||
|
||||
Optional properties:
|
||||
- operating-points-names: Names of OPP tables (required if multiple OPP
|
||||
tables are present), to uniquely identify them. The same list must be present
|
||||
for all the CPUs which are sharing clock/voltage rails and hence the OPP
|
||||
tables.
|
||||
|
||||
* OPP Table Node
|
||||
|
||||
This describes the OPPs belonging to a device. This node can have following
|
||||
properties:
|
||||
|
||||
Required properties:
|
||||
- compatible: Allow OPPs to express their compatibility. It should be:
|
||||
"operating-points-v2".
|
||||
|
||||
- OPP nodes: One or more OPP nodes describing voltage-current-frequency
|
||||
combinations. Their name isn't significant but their phandle can be used to
|
||||
reference an OPP.
|
||||
|
||||
Optional properties:
|
||||
- opp-shared: Indicates that device nodes using this OPP Table Node's phandle
|
||||
switch their DVFS state together, i.e. they share clock/voltage/current lines.
|
||||
Missing property means devices have independent clock/voltage/current lines,
|
||||
but they share OPP tables.
|
||||
|
||||
- status: Marks the OPP table enabled/disabled.
|
||||
|
||||
|
||||
* OPP Node
|
||||
|
||||
This defines voltage-current-frequency combinations along with other related
|
||||
properties.
|
||||
|
||||
Required properties:
|
||||
- opp-hz: Frequency in Hz
|
||||
|
||||
Optional properties:
|
||||
- opp-microvolt: voltage in micro Volts.
|
||||
|
||||
A single regulator's voltage is specified with an array of size one or three.
|
||||
Single entry is for target voltage and three entries are for <target min max>
|
||||
voltages.
|
||||
|
||||
Entries for multiple regulators must be present in the same order as
|
||||
regulators are specified in device's DT node.
|
||||
|
||||
- opp-microamp: The maximum current drawn by the device in microamperes
|
||||
considering system specific parameters (such as transients, process, aging,
|
||||
maximum operating temperature range etc.) as necessary. This may be used to
|
||||
set the most efficient regulator operating mode.
|
||||
|
||||
Should only be set if opp-microvolt is set for the OPP.
|
||||
|
||||
Entries for multiple regulators must be present in the same order as
|
||||
regulators are specified in device's DT node. If this property isn't required
|
||||
for few regulators, then this should be marked as zero for them. If it isn't
|
||||
required for any regulator, then this property need not be present.
|
||||
|
||||
- clock-latency-ns: Specifies the maximum possible transition latency (in
|
||||
nanoseconds) for switching to this OPP from any other OPP.
|
||||
|
||||
- turbo-mode: Marks the OPP to be used only for turbo modes. Turbo mode is
|
||||
available on some platforms, where the device can run over its operating
|
||||
frequency for a short duration of time limited by the device's power, current
|
||||
and thermal limits.
|
||||
|
||||
- opp-suspend: Marks the OPP to be used during device suspend. Only one OPP in
|
||||
the table should have this.
|
||||
|
||||
- status: Marks the node enabled/disabled.
|
||||
|
||||
Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <0>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 0>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply0>;
|
||||
operating-points-v2 = <&cpu0_opp_table>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <1>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 0>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply0>;
|
||||
operating-points-v2 = <&cpu0_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu0_opp_table: opp_table0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = <1100000000>;
|
||||
opp-microvolt = <980000 1000000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
clock-latency-ns = <290000>;
|
||||
turbo-mode;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 2: Single cluster, Quad-core Qualcom-krait, switches DVFS states
|
||||
independently.
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "qcom,krait";
|
||||
reg = <0>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 0>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply0>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
compatible = "qcom,krait";
|
||||
reg = <1>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 1>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply1>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
|
||||
cpu@2 {
|
||||
compatible = "qcom,krait";
|
||||
reg = <2>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 2>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply2>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
|
||||
cpu@3 {
|
||||
compatible = "qcom,krait";
|
||||
reg = <3>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 3>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply3>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_opp_table: opp_table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
/*
|
||||
* Missing opp-shared property means CPUs switch DVFS states
|
||||
* independently.
|
||||
*/
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = <1100000000>;
|
||||
opp-microvolt = <980000 1000000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
opp-microamp = <90000;
|
||||
lock-latency-ns = <290000>;
|
||||
turbo-mode;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 3: Dual-cluster, Dual-core per cluster. CPUs within a cluster switch
|
||||
DVFS state together.
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "arm,cortex-a7";
|
||||
reg = <0>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 0>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply0>;
|
||||
operating-points-v2 = <&cluster0_opp>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
compatible = "arm,cortex-a7";
|
||||
reg = <1>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 0>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply0>;
|
||||
operating-points-v2 = <&cluster0_opp>;
|
||||
};
|
||||
|
||||
cpu@100 {
|
||||
compatible = "arm,cortex-a15";
|
||||
reg = <100>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 1>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply1>;
|
||||
operating-points-v2 = <&cluster1_opp>;
|
||||
};
|
||||
|
||||
cpu@101 {
|
||||
compatible = "arm,cortex-a15";
|
||||
reg = <101>;
|
||||
next-level-cache = <&L2>;
|
||||
clocks = <&clk_controller 1>;
|
||||
clock-names = "cpu";
|
||||
cpu-supply = <&cpu_supply1>;
|
||||
operating-points-v2 = <&cluster1_opp>;
|
||||
};
|
||||
};
|
||||
|
||||
cluster0_opp: opp_table0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>;
|
||||
opp-microamp = <70000>;
|
||||
clock-latency-ns = <300000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = <1100000000>;
|
||||
opp-microvolt = <980000 1000000 1010000>;
|
||||
opp-microamp = <80000>;
|
||||
clock-latency-ns = <310000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = <1200000000>;
|
||||
opp-microvolt = <1025000>;
|
||||
opp-microamp = <90000>;
|
||||
clock-latency-ns = <290000>;
|
||||
turbo-mode;
|
||||
};
|
||||
};
|
||||
|
||||
cluster1_opp: opp_table1 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp10 {
|
||||
opp-hz = <1300000000>;
|
||||
opp-microvolt = <1045000 1050000 1055000>;
|
||||
opp-microamp = <95000>;
|
||||
clock-latency-ns = <400000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp11 {
|
||||
opp-hz = <1400000000>;
|
||||
opp-microvolt = <1075000>;
|
||||
opp-microamp = <100000>;
|
||||
clock-latency-ns = <400000>;
|
||||
};
|
||||
opp12 {
|
||||
opp-hz = <1500000000>;
|
||||
opp-microvolt = <1010000 1100000 1110000>;
|
||||
opp-microamp = <95000>;
|
||||
clock-latency-ns = <400000>;
|
||||
turbo-mode;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 4: Handling multiple regulators
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
cpu@0 {
|
||||
compatible = "arm,cortex-a7";
|
||||
...
|
||||
|
||||
cpu-supply = <&cpu_supply0>, <&cpu_supply1>, <&cpu_supply2>;
|
||||
operating-points-v2 = <&cpu0_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu0_opp_table: opp_table0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-microvolt = <970000>, /* Supply 0 */
|
||||
<960000>, /* Supply 1 */
|
||||
<960000>; /* Supply 2 */
|
||||
opp-microamp = <70000>, /* Supply 0 */
|
||||
<70000>, /* Supply 1 */
|
||||
<70000>; /* Supply 2 */
|
||||
clock-latency-ns = <300000>;
|
||||
};
|
||||
|
||||
/* OR */
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>, /* Supply 0 */
|
||||
<960000 965000 975000>, /* Supply 1 */
|
||||
<960000 965000 975000>; /* Supply 2 */
|
||||
opp-microamp = <70000>, /* Supply 0 */
|
||||
<70000>, /* Supply 1 */
|
||||
<70000>; /* Supply 2 */
|
||||
clock-latency-ns = <300000>;
|
||||
};
|
||||
|
||||
/* OR */
|
||||
|
||||
opp00 {
|
||||
opp-hz = <1000000000>;
|
||||
opp-microvolt = <970000 975000 985000>, /* Supply 0 */
|
||||
<960000 965000 975000>, /* Supply 1 */
|
||||
<960000 965000 975000>; /* Supply 2 */
|
||||
opp-microamp = <70000>, /* Supply 0 */
|
||||
<0>, /* Supply 1 doesn't need this */
|
||||
<70000>; /* Supply 2 */
|
||||
clock-latency-ns = <300000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 5: Multiple OPP tables
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
cpu@0 {
|
||||
compatible = "arm,cortex-a7";
|
||||
...
|
||||
|
||||
cpu-supply = <&cpu_supply>
|
||||
operating-points-v2 = <&cpu0_opp_table_slow>, <&cpu0_opp_table_fast>;
|
||||
operating-points-names = "slow", "fast";
|
||||
};
|
||||
};
|
||||
|
||||
cpu0_opp_table_slow: opp_table_slow {
|
||||
compatible = "operating-points-v2";
|
||||
status = "okay";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = <600000000>;
|
||||
...
|
||||
};
|
||||
|
||||
opp01 {
|
||||
opp-hz = <800000000>;
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
cpu0_opp_table_fast: opp_table_fast {
|
||||
compatible = "operating-points-v2";
|
||||
status = "okay";
|
||||
opp-shared;
|
||||
|
||||
opp10 {
|
||||
opp-hz = <1000000000>;
|
||||
...
|
||||
};
|
||||
|
||||
opp11 {
|
||||
opp-hz = <1100000000>;
|
||||
...
|
||||
};
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user