# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---

$id: http://devicetree.org/schemas/display/msm/gpu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Adreno or Snapdragon GPUs

maintainers:
  - Rob Clark <robdclark@gmail.com>

# dtschema does not select nodes based on pattern+const, so add custom select
# as a work-around:
select:
  properties:
    compatible:
      contains:
        enum:
          - qcom,adreno
          - amd,imageon
  required:
    - compatible

properties:
  compatible:
    oneOf:
      - description: |
          The driver is parsing the compat string for Adreno to
          figure out the chip-id.
        items:
          - pattern: '^qcom,adreno-[0-9a-f]{8}$'
          - const: qcom,adreno
      - description: |
          The driver is parsing the compat string for Adreno to
          figure out the gpu-id and patch level.
        items:
          - pattern: '^qcom,adreno-[3-7][0-9][0-9]\.[0-9]+$'
          - const: qcom,adreno
      - description: |
          The driver is parsing the compat string for Imageon to
          figure out the gpu-id and patch level.
        items:
          - pattern: '^amd,imageon-200\.[0-1]$'
          - const: amd,imageon

  clocks:
    minItems: 2
    maxItems: 7

  clock-names:
    minItems: 2
    maxItems: 7

  reg:
    minItems: 1
    maxItems: 3

  reg-names:
    minItems: 1
    items:
      - const: kgsl_3d0_reg_memory
      - const: cx_mem
      - const: cx_dbgc

  interrupts:
    maxItems: 1

  interrupt-names:
    maxItems: 1

  interconnects:
    minItems: 1
    maxItems: 2

  interconnect-names:
    minItems: 1
    items:
      - const: gfx-mem
      - const: ocmem

  iommus:
    minItems: 1
    maxItems: 64

  sram:
    $ref: /schemas/types.yaml#/definitions/phandle-array
    minItems: 1
    maxItems: 4
    items:
      maxItems: 1
    description: |
      phandles to one or more reserved on-chip SRAM regions.
      phandle to the On Chip Memory (OCMEM) that's present on some a3xx and
      a4xx Snapdragon SoCs. See
      Documentation/devicetree/bindings/sram/qcom,ocmem.yaml

  operating-points-v2: true
  opp-table:
    type: object

  power-domains:
    maxItems: 1

  zap-shader:
    type: object
    additionalProperties: false
    description: |
      For a5xx and a6xx devices this node contains a memory-region that
      points to reserved memory to store the zap shader that can be used to
      help bring the GPU out of secure mode.
    properties:
      memory-region:
        maxItems: 1

      firmware-name:
        description: |
          Default name of the firmware to load to the remote processor.

  "#cooling-cells":
    const: 2

  nvmem-cell-names:
    maxItems: 1

  nvmem-cells:
    description: efuse registers
    maxItems: 1

  qcom,gmu:
    $ref: /schemas/types.yaml#/definitions/phandle
    description: |
      For GMU attached devices a phandle to the GMU device that will
      control the power for the GPU.


required:
  - compatible
  - reg
  - interrupts

additionalProperties: false

allOf:
  - if:
      properties:
        compatible:
          contains:
            pattern: '^qcom,adreno-[3-5][0-9][0-9]\.[0-9]+$'

    then:
      properties:
        clocks:
          minItems: 2
          maxItems: 7

        clock-names:
          items:
            anyOf:
              - const: core
                description: GPU Core clock
              - const: iface
                description: GPU Interface clock
              - const: mem
                description: GPU Memory clock
              - const: mem_iface
                description: GPU Memory Interface clock
              - const: alt_mem_iface
                description: GPU Alternative Memory Interface clock
              - const: gfx3d
                description: GPU 3D engine clock
              - const: rbbmtimer
                description: GPU RBBM Timer for Adreno 5xx series
              - const: rbcpr
                description: GPU RB Core Power Reduction clock
          minItems: 2
          maxItems: 7

      required:
        - clocks
        - clock-names

  - if:
      properties:
        compatible:
          contains:
            enum:
              - qcom,adreno-610.0
              - qcom,adreno-619.1
    then:
      properties:
        clocks:
          minItems: 6
          maxItems: 6

        clock-names:
          items:
            - const: core
              description: GPU Core clock
            - const: iface
              description: GPU Interface clock
            - const: mem_iface
              description: GPU Memory Interface clock
            - const: alt_mem_iface
              description: GPU Alternative Memory Interface clock
            - const: gmu
              description: CX GMU clock
            - const: xo
              description: GPUCC clocksource clock

        reg-names:
          minItems: 1
          items:
            - const: kgsl_3d0_reg_memory
            - const: cx_dbgc

      required:
        - clocks
        - clock-names
    else:
      if:
        properties:
          compatible:
            contains:
              pattern: '^qcom,adreno-[67][0-9][0-9]\.[0-9]+$'

      then: # Starting with A6xx, the clocks are usually defined in the GMU node
        properties:
          clocks: false
          clock-names: false

          reg-names:
            minItems: 1
            items:
              - const: kgsl_3d0_reg_memory
              - const: cx_mem
              - const: cx_dbgc

examples:
  - |

    // Example a3xx/4xx:

    #include <dt-bindings/clock/qcom,mmcc-msm8974.h>
    #include <dt-bindings/clock/qcom,rpmcc.h>
    #include <dt-bindings/interrupt-controller/irq.h>
    #include <dt-bindings/interrupt-controller/arm-gic.h>

    gpu: gpu@fdb00000 {
        compatible = "qcom,adreno-330.2", "qcom,adreno";

        reg = <0xfdb00000 0x10000>;
        reg-names = "kgsl_3d0_reg_memory";

        clock-names = "core", "iface", "mem_iface";
        clocks = <&mmcc OXILI_GFX3D_CLK>,
                 <&mmcc OXILICX_AHB_CLK>,
                 <&mmcc OXILICX_AXI_CLK>;

        interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
        interrupt-names = "kgsl_3d0_irq";

        sram = <&gpu_sram>;
        power-domains = <&mmcc OXILICX_GDSC>;
        operating-points-v2 = <&gpu_opp_table>;
        iommus = <&gpu_iommu 0>;
        #cooling-cells = <2>;
    };

    ocmem@fdd00000 {
        compatible = "qcom,msm8974-ocmem";

        reg = <0xfdd00000 0x2000>,
              <0xfec00000 0x180000>;
        reg-names = "ctrl", "mem";

        clocks = <&rpmcc RPM_SMD_OCMEMGX_CLK>,
                 <&mmcc OCMEMCX_OCMEMNOC_CLK>;
        clock-names = "core", "iface";

        #address-cells = <1>;
        #size-cells = <1>;
        ranges = <0 0xfec00000 0x100000>;

        gpu_sram: gpu-sram@0 {
            reg = <0x0 0x100000>;
        };
    };
  - |

    // Example a6xx (with GMU):

    #include <dt-bindings/clock/qcom,gpucc-sdm845.h>
    #include <dt-bindings/clock/qcom,gcc-sdm845.h>
    #include <dt-bindings/power/qcom-rpmpd.h>
    #include <dt-bindings/interrupt-controller/irq.h>
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    #include <dt-bindings/interconnect/qcom,sdm845.h>

    reserved-memory {
        #address-cells = <2>;
        #size-cells = <2>;

        zap_shader_region: gpu@8f200000 {
            compatible = "shared-dma-pool";
            reg = <0x0 0x90b00000 0x0 0xa00000>;
            no-map;
        };
    };

    gpu@5000000 {
        compatible = "qcom,adreno-630.2", "qcom,adreno";

        reg = <0x5000000 0x40000>, <0x509e000 0x10>;
        reg-names = "kgsl_3d0_reg_memory", "cx_mem";

        #cooling-cells = <2>;

        interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;

        iommus = <&adreno_smmu 0>;

        operating-points-v2 = <&gpu_opp_table>;

        interconnects = <&rsc_hlos MASTER_GFX3D &rsc_hlos SLAVE_EBI1>;
        interconnect-names = "gfx-mem";

        qcom,gmu = <&gmu>;

        gpu_opp_table: opp-table {
            compatible = "operating-points-v2";

            opp-430000000 {
                opp-hz = /bits/ 64 <430000000>;
                opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
                opp-peak-kBps = <5412000>;
            };

            opp-355000000 {
                opp-hz = /bits/ 64 <355000000>;
                opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
                opp-peak-kBps = <3072000>;
            };

            opp-267000000 {
                opp-hz = /bits/ 64 <267000000>;
                opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
                opp-peak-kBps = <3072000>;
            };

            opp-180000000 {
                opp-hz = /bits/ 64 <180000000>;
                opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
                opp-peak-kBps = <1804000>;
            };
        };

        zap-shader {
            memory-region = <&zap_shader_region>;
            firmware-name = "qcom/LENOVO/81JL/qcdxkmsuc850.mbn";
        };
    };
