# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/opp/opp-v2.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Generic OPP (Operating Performance Points) Bindings

maintainers:
  - Viresh Kumar <viresh.kumar@linaro.org>

allOf:
  - $ref: opp-v2-base.yaml#

properties:
  compatible:
    const: operating-points-v2

unevaluatedProperties: false

examples:
  - |
    /*
     * 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";
            device_type = "cpu";
            reg = <0>;
            next-level-cache = <&L2>;
            clocks = <&clk_controller 0>;
            clock-names = "cpu";
            cpu-supply = <&cpu_supply0>;
            operating-points-v2 = <&cpu0_opp_table0>;
        };

        cpu@1 {
            compatible = "arm,cortex-a9";
            device_type = "cpu";
            reg = <1>;
            next-level-cache = <&L2>;
            clocks = <&clk_controller 0>;
            clock-names = "cpu";
            cpu-supply = <&cpu_supply0>;
            operating-points-v2 = <&cpu0_opp_table0>;
        };
    };

    cpu0_opp_table0: opp-table {
        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";
            device_type = "cpu";
            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";
            device_type = "cpu";
            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";
            device_type = "cpu";
            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";
            device_type = "cpu";
            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";
            device_type = "cpu";
            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";
            device_type = "cpu";
            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";
            device_type = "cpu";
            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";
            device_type = "cpu";
            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-table-0 {
        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-table-1 {
        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 {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu@0 {
            compatible = "foo,cpu-type";
            device_type = "cpu";
            reg = <0>;

            vcc0-supply = <&cpu_supply0>;
            vcc1-supply = <&cpu_supply1>;
            vcc2-supply = <&cpu_supply2>;
            operating-points-v2 = <&cpu0_opp_table4>;
        };
    };

    cpu0_opp_table4: opp-table-0 {
        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-1000000001 {
            opp-hz = /bits/ 64 <1000000001>;
            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-1000000002 {
            opp-hz = /bits/ 64 <1000000002>;
            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 {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu@0 {
            compatible = "arm,cortex-a7";
            device_type = "cpu";
            reg = <0>;
            cpu-supply = <&cpu_supply>;
            operating-points-v2 = <&cpu0_opp_table_slow>;
        };
    };

    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 {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu@0 {
            compatible = "arm,cortex-a7";
            device_type = "cpu";
            reg = <0>;
            operating-points-v2 = <&cpu0_opp_table6>;
        };
    };

    cpu0_opp_table6: opp-table-0 {
        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";
            device_type = "cpu";
            reg = <0x0 0x100>;
            next-level-cache = <&A53_L2>;
            clocks = <&dvfs_controller 0>;
            operating-points-v2 = <&cpu_opp0_table>;
        };
        cpu@1 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            reg = <0x0 0x101>;
            next-level-cache = <&A53_L2>;
            clocks = <&dvfs_controller 1>;
            operating-points-v2 = <&cpu_opp0_table>;
        };
        cpu@2 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            reg = <0x0 0x102>;
            next-level-cache = <&A53_L2>;
            clocks = <&dvfs_controller 2>;
            operating-points-v2 = <&cpu_opp1_table>;
        };
        cpu@3 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            reg = <0x0 0x103>;
            next-level-cache = <&A53_L2>;
            clocks = <&dvfs_controller 3>;
            operating-points-v2 = <&cpu_opp1_table>;
        };

    };

    cpu_opp0_table: opp-table-0 {
        compatible = "operating-points-v2";
        opp-shared;
    };

    cpu_opp1_table: opp-table-1 {
        compatible = "operating-points-v2";
        opp-shared;
    };
...
