mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
622 lines
18 KiB
622 lines
18 KiB
Generic OPP (Operating Performance Points) Bindings |
|
---------------------------------------------------- |
|
|
|
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 |
|
of frequency and voltage like <freq-kHz vol-uV>. |
|
freq: clock frequency in kHz |
|
vol: voltage in microvolt |
|
|
|
Examples: |
|
|
|
cpu@0 { |
|
compatible = "arm,cortex-a9"; |
|
reg = <0>; |
|
next-level-cache = <&L2>; |
|
operating-points = < |
|
/* kHz uV */ |
|
792000 1100000 |
|
396000 950000 |
|
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. |
|
|
|
This can contain more than one phandle for power domain providers that provide |
|
multiple power domains. That is, one phandle for each power domain. If only one |
|
phandle is available, then the same OPP table will be used for all power domains |
|
provided by the power domain provider. |
|
|
|
If required, this can be extended for SoC vendor specific 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>". |
|
|
|
* 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. These are mandatory except for the case where the OPP table |
|
is present only to indicate dependency between devices using the opp-shared |
|
property. |
|
|
|
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, expressed as a 64-bit big-endian integer. This is a |
|
required property for all device nodes, unless another "required" property to |
|
uniquely identify the OPP nodes exists. Devices like power domains must have |
|
another (implementation dependent) property. |
|
|
|
- opp-peak-kBps: Peak bandwidth in kilobytes per second, expressed as an array |
|
of 32-bit big-endian integers. Each element of the array represents the |
|
peak bandwidth value of each interconnect path. The number of elements should |
|
match the number of interconnect paths. |
|
|
|
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 shall be provided in the same field separated |
|
by angular brackets <>. The OPP binding doesn't provide any provisions to |
|
relate the values to their power supplies or the order in which the supplies |
|
need to be configured and that is left for the implementation specific |
|
binding. |
|
|
|
Entries for all regulators shall be of the same size, i.e. either all use a |
|
single value or triplets. |
|
|
|
- opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to |
|
the above opp-microvolt property, but allows multiple voltage ranges to be |
|
provided for the same OPP. At runtime, the platform can pick a <name> and |
|
matching opp-microvolt-<name> property will be enabled for all OPPs. If the |
|
platform doesn't pick a specific <name> or the <name> doesn't match with any |
|
opp-microvolt-<name> properties, then opp-microvolt property shall be used, if |
|
present. |
|
|
|
- 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 shall be provided in the same field separated |
|
by angular brackets <>. If current values aren't required for a regulator, |
|
then it shall be filled with 0. If current values aren't required for any of |
|
the regulators, then this field is not required. The OPP binding doesn't |
|
provide any provisions to relate the values to their power supplies or the |
|
order in which the supplies need to be configured and that is left for the |
|
implementation specific binding. |
|
|
|
- opp-microamp-<name>: Named opp-microamp property. Similar to |
|
opp-microvolt-<name> property, but for microamp instead. |
|
|
|
- opp-level: A value representing the performance level of the device, |
|
expressed as a 32-bit integer. |
|
|
|
- opp-avg-kBps: Average bandwidth in kilobytes per second, expressed as an array |
|
of 32-bit big-endian integers. Each element of the array represents the |
|
average bandwidth value of each interconnect path. The number of elements |
|
should match the number of interconnect paths. This property is only |
|
meaningful in OPP tables where opp-peak-kBps is 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. If multiple OPPs |
|
in the table have this, the OPP with highest opp-hz will be used. |
|
|
|
- opp-supported-hw: This property allows a platform to enable only a subset of |
|
the OPPs from the larger set present in the OPP table, based on the current |
|
version of the hardware (already known to the operating system). |
|
|
|
Each block present in the array of blocks in this property, represents a |
|
sub-group of hardware versions supported by the OPP. i.e. <sub-group A>, |
|
<sub-group B>, etc. The OPP will be enabled if _any_ of these sub-groups match |
|
the hardware's version. |
|
|
|
Each sub-group is a platform defined array representing the hierarchy of |
|
hardware versions supported by the platform. For a platform with three |
|
hierarchical levels of version (X.Y.Z), this field shall look like |
|
|
|
opp-supported-hw = <X1 Y1 Z1>, <X2 Y2 Z2>, <X3 Y3 Z3>. |
|
|
|
Each level (eg. X1) in version hierarchy is represented by a 32 bit value, one |
|
bit per version and so there can be maximum 32 versions per level. Logical AND |
|
(&) operation is performed for each level with the hardware's level version |
|
and a non-zero output for _all_ the levels in a sub-group means the OPP is |
|
supported by hardware. A value of 0xFFFFFFFF for each level in the sub-group |
|
will enable the OPP for all versions for the hardware. |
|
|
|
- status: Marks the node enabled/disabled. |
|
|
|
- required-opps: This contains phandle to an OPP node in another device's OPP |
|
table. It may contain an array of phandles, where each phandle points to an |
|
OPP of a different device. It should not contain multiple phandles to the OPP |
|
nodes in the same OPP table. This specifies the minimum required OPP of the |
|
device(s), whose OPP's phandle is present in this property, for the |
|
functioning of the current device at the current OPP (where this property is |
|
present). |
|
|
|
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; |
|
|
|
opp-1000000000 { |
|
opp-hz = /bits/ 64 <1000000000>; |
|
opp-microvolt = <975000 970000 985000>; |
|
opp-microamp = <70000>; |
|
clock-latency-ns = <300000>; |
|
opp-suspend; |
|
}; |
|
opp-1100000000 { |
|
opp-hz = /bits/ 64 <1100000000>; |
|
opp-microvolt = <1000000 980000 1010000>; |
|
opp-microamp = <80000>; |
|
clock-latency-ns = <310000>; |
|
}; |
|
opp-1200000000 { |
|
opp-hz = /bits/ 64 <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. |
|
*/ |
|
|
|
opp-1000000000 { |
|
opp-hz = /bits/ 64 <1000000000>; |
|
opp-microvolt = <975000 970000 985000>; |
|
opp-microamp = <70000>; |
|
clock-latency-ns = <300000>; |
|
opp-suspend; |
|
}; |
|
opp-1100000000 { |
|
opp-hz = /bits/ 64 <1100000000>; |
|
opp-microvolt = <1000000 980000 1010000>; |
|
opp-microamp = <80000>; |
|
clock-latency-ns = <310000>; |
|
}; |
|
opp-1200000000 { |
|
opp-hz = /bits/ 64 <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; |
|
|
|
opp-1000000000 { |
|
opp-hz = /bits/ 64 <1000000000>; |
|
opp-microvolt = <975000 970000 985000>; |
|
opp-microamp = <70000>; |
|
clock-latency-ns = <300000>; |
|
opp-suspend; |
|
}; |
|
opp-1100000000 { |
|
opp-hz = /bits/ 64 <1100000000>; |
|
opp-microvolt = <1000000 980000 1010000>; |
|
opp-microamp = <80000>; |
|
clock-latency-ns = <310000>; |
|
}; |
|
opp-1200000000 { |
|
opp-hz = /bits/ 64 <1200000000>; |
|
opp-microvolt = <1025000>; |
|
opp-microamp = <90000>; |
|
clock-latency-ns = <290000>; |
|
turbo-mode; |
|
}; |
|
}; |
|
|
|
cluster1_opp: opp_table1 { |
|
compatible = "operating-points-v2"; |
|
opp-shared; |
|
|
|
opp-1300000000 { |
|
opp-hz = /bits/ 64 <1300000000>; |
|
opp-microvolt = <1050000 1045000 1055000>; |
|
opp-microamp = <95000>; |
|
clock-latency-ns = <400000>; |
|
opp-suspend; |
|
}; |
|
opp-1400000000 { |
|
opp-hz = /bits/ 64 <1400000000>; |
|
opp-microvolt = <1075000>; |
|
opp-microamp = <100000>; |
|
clock-latency-ns = <400000>; |
|
}; |
|
opp-1500000000 { |
|
opp-hz = /bits/ 64 <1500000000>; |
|
opp-microvolt = <1100000 1010000 1110000>; |
|
opp-microamp = <95000>; |
|
clock-latency-ns = <400000>; |
|
turbo-mode; |
|
}; |
|
}; |
|
}; |
|
|
|
Example 4: Handling multiple regulators |
|
|
|
/ { |
|
cpus { |
|
cpu@0 { |
|
compatible = "vendor,cpu-type"; |
|
... |
|
|
|
vcc0-supply = <&cpu_supply0>; |
|
vcc1-supply = <&cpu_supply1>; |
|
vcc2-supply = <&cpu_supply2>; |
|
operating-points-v2 = <&cpu0_opp_table>; |
|
}; |
|
}; |
|
|
|
cpu0_opp_table: opp_table0 { |
|
compatible = "operating-points-v2"; |
|
opp-shared; |
|
|
|
opp-1000000000 { |
|
opp-hz = /bits/ 64 <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 */ |
|
|
|
opp-1000000000 { |
|
opp-hz = /bits/ 64 <1000000000>; |
|
opp-microvolt = <975000 970000 985000>, /* Supply 0 */ |
|
<965000 960000 975000>, /* Supply 1 */ |
|
<965000 960000 975000>; /* Supply 2 */ |
|
opp-microamp = <70000>, /* Supply 0 */ |
|
<70000>, /* Supply 1 */ |
|
<70000>; /* Supply 2 */ |
|
clock-latency-ns = <300000>; |
|
}; |
|
|
|
/* OR */ |
|
|
|
opp-1000000000 { |
|
opp-hz = /bits/ 64 <1000000000>; |
|
opp-microvolt = <975000 970000 985000>, /* Supply 0 */ |
|
<965000 960000 975000>, /* Supply 1 */ |
|
<965000 960000 975000>; /* Supply 2 */ |
|
opp-microamp = <70000>, /* Supply 0 */ |
|
<0>, /* Supply 1 doesn't need this */ |
|
<70000>; /* Supply 2 */ |
|
clock-latency-ns = <300000>; |
|
}; |
|
}; |
|
}; |
|
|
|
Example 5: opp-supported-hw |
|
(example: three level hierarchy of versions: cuts, substrate and process) |
|
|
|
/ { |
|
cpus { |
|
cpu@0 { |
|
compatible = "arm,cortex-a7"; |
|
... |
|
|
|
cpu-supply = <&cpu_supply> |
|
operating-points-v2 = <&cpu0_opp_table_slow>; |
|
}; |
|
}; |
|
|
|
opp_table { |
|
compatible = "operating-points-v2"; |
|
opp-shared; |
|
|
|
opp-600000000 { |
|
/* |
|
* Supports all substrate and process versions for 0xF |
|
* cuts, i.e. only first four cuts. |
|
*/ |
|
opp-supported-hw = <0xF 0xFFFFFFFF 0xFFFFFFFF> |
|
opp-hz = /bits/ 64 <600000000>; |
|
... |
|
}; |
|
|
|
opp-800000000 { |
|
/* |
|
* Supports: |
|
* - cuts: only one, 6th cut (represented by 6th bit). |
|
* - substrate: supports 16 different substrate versions |
|
* - process: supports 9 different process versions |
|
*/ |
|
opp-supported-hw = <0x20 0xff0000ff 0x0000f4f0> |
|
opp-hz = /bits/ 64 <800000000>; |
|
... |
|
}; |
|
|
|
opp-900000000 { |
|
/* |
|
* Supports: |
|
* - All cuts and substrate where process version is 0x2. |
|
* - All cuts and process where substrate version is 0x2. |
|
*/ |
|
opp-supported-hw = <0xFFFFFFFF 0xFFFFFFFF 0x02>, <0xFFFFFFFF 0x01 0xFFFFFFFF> |
|
opp-hz = /bits/ 64 <900000000>; |
|
... |
|
}; |
|
}; |
|
}; |
|
|
|
Example 6: opp-microvolt-<name>, opp-microamp-<name>: |
|
(example: device with two possible microvolt ranges: slow and fast) |
|
|
|
/ { |
|
cpus { |
|
cpu@0 { |
|
compatible = "arm,cortex-a7"; |
|
... |
|
|
|
operating-points-v2 = <&cpu0_opp_table>; |
|
}; |
|
}; |
|
|
|
cpu0_opp_table: opp_table0 { |
|
compatible = "operating-points-v2"; |
|
opp-shared; |
|
|
|
opp-1000000000 { |
|
opp-hz = /bits/ 64 <1000000000>; |
|
opp-microvolt-slow = <915000 900000 925000>; |
|
opp-microvolt-fast = <975000 970000 985000>; |
|
opp-microamp-slow = <70000>; |
|
opp-microamp-fast = <71000>; |
|
}; |
|
|
|
opp-1200000000 { |
|
opp-hz = /bits/ 64 <1200000000>; |
|
opp-microvolt-slow = <915000 900000 925000>, /* Supply vcc0 */ |
|
<925000 910000 935000>; /* Supply vcc1 */ |
|
opp-microvolt-fast = <975000 970000 985000>, /* Supply vcc0 */ |
|
<965000 960000 975000>; /* Supply vcc1 */ |
|
opp-microamp = <70000>; /* Will be used for both slow/fast */ |
|
}; |
|
}; |
|
}; |
|
|
|
Example 7: Single cluster Quad-core ARM cortex A53, OPP points from firmware, |
|
distinct clock controls but two sets of clock/voltage/current lines. |
|
|
|
/ { |
|
cpus { |
|
#address-cells = <2>; |
|
#size-cells = <0>; |
|
|
|
cpu@0 { |
|
compatible = "arm,cortex-a53"; |
|
reg = <0x0 0x100>; |
|
next-level-cache = <&A53_L2>; |
|
clocks = <&dvfs_controller 0>; |
|
operating-points-v2 = <&cpu_opp0_table>; |
|
}; |
|
cpu@1 { |
|
compatible = "arm,cortex-a53"; |
|
reg = <0x0 0x101>; |
|
next-level-cache = <&A53_L2>; |
|
clocks = <&dvfs_controller 1>; |
|
operating-points-v2 = <&cpu_opp0_table>; |
|
}; |
|
cpu@2 { |
|
compatible = "arm,cortex-a53"; |
|
reg = <0x0 0x102>; |
|
next-level-cache = <&A53_L2>; |
|
clocks = <&dvfs_controller 2>; |
|
operating-points-v2 = <&cpu_opp1_table>; |
|
}; |
|
cpu@3 { |
|
compatible = "arm,cortex-a53"; |
|
reg = <0x0 0x103>; |
|
next-level-cache = <&A53_L2>; |
|
clocks = <&dvfs_controller 3>; |
|
operating-points-v2 = <&cpu_opp1_table>; |
|
}; |
|
|
|
}; |
|
|
|
cpu_opp0_table: opp0_table { |
|
compatible = "operating-points-v2"; |
|
opp-shared; |
|
}; |
|
|
|
cpu_opp1_table: opp1_table { |
|
compatible = "operating-points-v2"; |
|
opp-shared; |
|
}; |
|
};
|
|
|