|
@@ -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>;
|
|
|
+ ...
|
|
|
+ };
|
|
|
+ };
|
|
|
+};
|