diff --git a/Documentation/ABI/testing/configfs-stp-policy-p_ost b/Documentation/ABI/testing/configfs-stp-policy-p_ost new file mode 100644 index 0000000000000..8fb160b50c40b --- /dev/null +++ b/Documentation/ABI/testing/configfs-stp-policy-p_ost @@ -0,0 +1,9 @@ +What: /config/stp-policy/:p_ost.//entity +Date: May 2026 +KernelVersion: 7.1 +Description: + Set the entity ID which identifies the trace source in the + OST packet header. Entity ID values (0~239) are defined by + the TS owner. Currently supported values are ftrace, console + and diag. RW. + diff --git a/Documentation/ABI/testing/debugfs-aest b/Documentation/ABI/testing/debugfs-aest new file mode 100644 index 0000000000000..cc41ea7032c72 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-aest @@ -0,0 +1,99 @@ +What: /sys/kernel/debug/aest/./ +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + Directory represented a AEST device, means device type, + like: + + - processor + - memory + - smmu + - ... + + is the unique ID for this device. + +What: /sys/kernel/debug/aest/.//* +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + Attibute for aest node which belong this device, the format + of node name is: - + + See more at: + https://developer.arm.com/documentation/den0085/latest/ + +What: /sys/kernel/debug/aest/.//ce_threshold +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) Write the ce threshold to all records of this node. Failed + if input exceeded the maximum threshold + +What: /sys/kernel/debug/aest/.//err_count +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RO) Outputs error statistics for all error records of this node. + +What: /sys/kernel/debug/aest/.//record/err_* +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + (RO) Read err_* register and return val. + +What: /sys/kernel/debug/aest/.//record/ce_threshold +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RW) Read and write the ce threshold to this record. Failed + if input exceeded the maximum threshold + +What: /sys/kernel/debug/aest/.//record/err_count +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RO) Outputs error statistics for all this records. + +What: /sys/kernel/debug/aest/.//record/inject/err_* +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RW) These registers are used to simulate soft injection errors + by holding error register values. You can write any values + to them. To trigger the injection, you need to write soft_inject + at last. The validity of the injected error depends on the + value written to err_status. + + Accepts values - any. + +What: /sys/kernel/debug/aest/.//record/inject/soft_inject +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) Write any value to this file to trigger the error + injection. Make sure you have specified all necessary error + parameters, i.e. this write should be the last step when + injecting errors. + + Accepts values - any. + +What: /sys/kernel/debug/aest/.//record/inject/hard_inject +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) If the AEST table provides error injection registers, + you can write to them via this interface. For instance, + values can be written to the ERXPFGCTL register. The post-injection + behavior is then determined by the hardware specification. + + Accepts values - any. diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu new file mode 100644 index 0000000000000..a6b6019c8ef17 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -0,0 +1,51 @@ +What: /sys/bus/amba/devices//enable_tgu +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the enable/disable status of TGU + Accepts only one of the 2 values - 0 or 1. + 0 : disable TGU. + 1 : enable TGU. + +What: /sys/bus/amba/devices//step[0:7]_priority[0:3]/reg[0:17] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the sensed signal with specific step and priority for TGU. + +What: /sys/bus/amba/devices//step[0:7]_condition_decode/reg[0:3] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the decode mode with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_condition_select/reg[0:3] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the next action with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_timer/reg[0:1] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the timer value with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_counter/reg[0:1] +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the counter value with specific step for TGU. + +What: /sys/bus/amba/devices//reset_tgu +Date: April 2026 +KernelVersion: 7.1 +Contact: Jinlong Mao , Songwei Chai +Description: + (Write) Write 1 to reset the dataset for TGU. diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu b/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu new file mode 100644 index 0000000000000..beef0be219690 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-ctcu @@ -0,0 +1,9 @@ +What: /sys/bus/coresight/devices//irq_enabled[0:1] +Date: June 2026 +KernelVersion: 7.3 +Contact: Tingwei Zhang ; Jinlong Mao ; Jie Gan +Description: + (RW) Configure the flag to enable interrupt to count data during CTCU enablement. + An interrupt is generated when the data size exceeds the value set in the IRQ register. + 0 : disable + 1 : enable diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti index a2aef7f5a6d74..9d7831ac455b8 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti @@ -128,12 +128,102 @@ KernelVersion: 5.7 Contact: Mike Leach or Mathieu Poirier Description: (Read) read current status of input trigger signals +What: /sys/bus/coresight/devices//regs/triginstatus[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) read current status of QCOM extended input trigger signals. + What: /sys/bus/coresight/devices//regs/trigoutstatus Date: March 2020 KernelVersion: 5.7 Contact: Mike Leach or Mathieu Poirier Description: (Read) read current status of output trigger signals. +What: /sys/bus/coresight/devices//regs/trigoutstatus[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) read current status of QCOM extended output trigger signals. + +What: /sys/bus/coresight/devices//regs/itctrl +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Control integration mode. + +What: /sys/bus/coresight/devices//regs/itchin +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the values of the CTCHIN inputs. + +What: /sys/bus/coresight/devices//regs/itchinack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Write) Write the value of the CTCHINACK input. + +What: /sys/bus/coresight/devices//regs/ittrigin +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the values of the CTTRIGIN inputs. + +What: /sys/bus/coresight/devices//regs/ittrigin[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) Read the values of the QCOM extended CTTRIGIN inputs. + +What: /sys/bus/coresight/devices//regs/ittriginack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Write) Write the value of the CTTRIGINACK input. + +What: /sys/bus/coresight/devices//regs/ittriginack[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Write) Write the value of the QCOM extended CTTRIGINACK input. + +What: /sys/bus/coresight/devices//regs/itchout +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Read or write the value of the CTCHOUT outputs. + +What: /sys/bus/coresight/devices//regs/itchoutack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the value of the CTCHOUTACK input. + +What: /sys/bus/coresight/devices//regs/ittrigout +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Read or write the value of the CTTRIGOUT outputs. + +What: /sys/bus/coresight/devices//regs/ittrigout[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (RW) Read or write the value of the QCOM extended CTTRIGOUT outputs. + +What: /sys/bus/coresight/devices//regs/ittrigoutack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the value of the CTTRIGOUTACK input. + +What: /sys/bus/coresight/devices//regs/ittrigoutack[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) Read the value of the QCOM extended CTTRIGOUTACK input. + What: /sys/bus/coresight/devices//channels/trigin_attach Date: March 2020 KernelVersion: 5.7 diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 2bab0db2d2f0f..67223f73ee606 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -7,3 +7,19 @@ Description: EUD based on a 1 or a 0 value. By enabling EUD, the user is able to activate the mini-usb hub of EUD for debug and trace capabilities. + +What: /sys/bus/platform/drivers/qcom_eud/.../port +Date: January 2026 +Contact: Elson Serrao +Description: + Selects which USB port the Embedded USB Debugger (EUD) + is mapped to on platforms providing multiple High-Speed + USB ports. + + Valid values: + 0 - Primary USB port + 1 - Secondary USB port + + The attribute is writable only while EUD is disabled. + Reading the attribute returns the currently selected + USB port number. diff --git a/Documentation/devicetree/bindings/arm/arm,aest.yaml b/Documentation/devicetree/bindings/arm/arm,aest.yaml new file mode 100644 index 0000000000000..7809a0d382703 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,aest.yaml @@ -0,0 +1,406 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,aest.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Arm Error Source Table (AEST) + +maintainers: + - Umang Chheda + +description: + The Arm Error Source Table (AEST) describes RAS error sources and their + register interfaces. Each error source exposes one or more error records + through either system registers or a memory-mapped register window, and + may signal errors via interrupts. The top-level node acts as a container + for one or more child nodes, each describing a single AEST error source. + Refer to the Arm AEST specification (DEN0085 / DDI 0587B) for details. + Flag bit constants for use in DT source files are defined in + . + +properties: + compatible: + const: arm,aest + + "#address-cells": + const: 2 + + "#size-cells": + const: 2 + + ranges: true + +required: + - compatible + +additionalProperties: false + +patternProperties: + "^aest-[a-z0-9-]+(@[0-9a-f]+)?$": + type: object + description: + An AEST error source node describing one error source defined by + the Arm AEST specification. + + properties: + compatible: + description: + Identifies the type of AEST error source. Each value corresponds to + a distinct error source class defined by the Arm AEST specification. + arm,aest-proxy represents a proxy error source that forwards errors + from another error source. + enum: + - arm,aest-processor + - arm,aest-memory + - arm,aest-smmu + - arm,aest-gic + - arm,aest-pcie + - arm,aest-vendor + - arm,aest-proxy + + reg: + description: + Register ranges for the error source. Absence of reg implies + system-register access (interface type 0). A single range implies + memory-mapped access (interface type 1). Two ranges imply + single-record memory-mapped access (interface type 2). + minItems: 1 + maxItems: 4 + + reg-names: + description: + Names for the register ranges. The base error-record window is + unnamed (or first entry). Optional named ranges provide access to + the fault-injection, error-group, and interrupt-config register + windows defined by the AEST specification. + minItems: 1 + maxItems: 4 + items: + enum: + - fault-inject + - err-group + - irq-config + + interrupts: + description: Interrupts associated with the error source. + minItems: 1 + maxItems: 2 + + interrupt-names: + description: Names of the interrupts associated with the error source. + minItems: 1 + maxItems: 2 + items: + enum: + - fhi + - eri + + arm,fhi-flags: + description: + Bitmask of flags for the fault-handling interrupt (FHI), as defined + in the AEST node interrupt structure flags field. Constants are + defined in - AEST_IRQ_MODE_LEVEL (0), + AEST_IRQ_MODE_EDGE (1). + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,eri-flags: + description: + Bitmask of flags for the error-recovery interrupt (ERI), as defined + in the AEST node interrupt structure flags field. Constants are + defined in . + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,interface-flags: + description: | + Bitmask of interface flags for the error source, as defined in the + AEST node interface flags field. Constants are defined in + : + AEST_XFACE_SHARED (bit 0) - shared error source, + AEST_XFACE_CLEAR_MISC (bit 1) - clear MISC registers on error, + AEST_XFACE_ERROR_DEVICE (bit 2) - error node device present, + AEST_XFACE_AFFINITY (bit 3) - affinity information valid, + AEST_XFACE_ERROR_GROUP (bit 4) - error group register window present, + AEST_XFACE_FAULT_INJECT (bit 5) - fault injection register window present, + AEST_XFACE_INT_CONFIG (bit 6) - interrupt config register window present. + For system-register interface nodes (no reg property), only + AEST_XFACE_CLEAR_MISC is meaningful; the MMIO window flags + (AEST_XFACE_ERROR_GROUP, AEST_XFACE_FAULT_INJECT, + AEST_XFACE_INT_CONFIG) have no effect without a base address. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,group-format: + description: | + Page-granularity of the error record group register window, which + determines the MMIO mapping size, the number of ERRGSR registers, + and the width of the record-implemented and status-reporting bitmaps. + Constants are defined in : + AEST_GROUP_FORMAT_4K (0) - 4K window, 1 ERRGSR, up to 64 records, + AEST_GROUP_FORMAT_16K (1) - 16K window, 4 ERRGSRs, up to 256 records, + AEST_GROUP_FORMAT_64K (2) - 64K window, 14 ERRGSRs, up to 896 records. + Required for memory-mapped nodes (reg present) where it controls + the ioremap size and ERRGSR layout. For system-register nodes + (no reg property) this property is optional and defaults to + AEST_GROUP_FORMAT_4K. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + arm,num-records: + description: Number of error records implemented by this error source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,record-impl: + description: + Bitmap of implemented error records within this error source. Bit N + set to 0 means error record N is implemented and must be polled. + $ref: /schemas/types.yaml#/definitions/uint64-array + + arm,status-reporting: + description: + Bitmap indicating which error records support status reporting via + the ERRGSR register. Bit N set to 1 means record N does not report + through ERRGSR and must be polled explicitly. + $ref: /schemas/types.yaml#/definitions/uint64-array + + arm,addressing-mode: + description: + Bitmap indicating the address type reported in ERR_ADDR for each + error record. Bit N set to 0 means record N reports System Physical + Addresses (SPA); bit N set to 1 means record N reports node-specific + Logical Addresses (LA) that require OS translation to SPA. + $ref: /schemas/types.yaml#/definitions/uint64-array + + arm,processor-flags: + description: + Bitmask indicating the scope of a processor error source, as defined + in the AEST processor node flags field. Constants are defined in + - AEST_PROC_GLOBAL (bit 0), + AEST_PROC_SHARED (bit 1). + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,resource-type: + description: | + Type of processor resource associated with this error source. + Constants are defined in : + AEST_RESOURCE_CACHE (0), + AEST_RESOURCE_TLB (1), + AEST_RESOURCE_GENERIC (2). + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + arm,cache-ref: + description: + Phandle to the cache node associated with this processor error source. + $ref: /schemas/types.yaml#/definitions/phandle + + arm,tlb-level: + description: TLB level identifier for this processor TLB error source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,resource-ref: + description: + Generic resource reference identifier for this processor error source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,proximity-domain: + description: + SRAT proximity domain of the memory node associated with this error + source. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,smmu-ref: + description: + Phandle to the SMMU node in the IORT associated with this error + source. + $ref: /schemas/types.yaml#/definitions/phandle + + arm,smmu-subcomponent: + description: + SMMU subcomponent reference identifier for this error source, as + defined in the AEST SMMU node structure. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,gic-type: + description: | + GIC component type for this error source, as defined in the AEST GIC + node structure. Constants are defined in : + AEST_GIC_CPU (0), + AEST_GIC_DISTRIBUTOR (1), + AEST_GIC_REDISTRIBUTOR (2), + AEST_GIC_ITS (3). + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + arm,gic-instance: + description: + GIC instance identifier for this error source, used to distinguish + multiple instances of the same GIC component type. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,pcie-segment: + description: + PCI segment number of the PCIe root port associated with this error + source, corresponding to the IORT node reference. + $ref: /schemas/types.yaml#/definitions/uint32 + + arm,vendor-hid: + description: + 8-character ACPI Hardware ID string identifying the vendor error + source, as defined in the AEST vendor node structure. + $ref: /schemas/types.yaml#/definitions/string + + arm,vendor-uid: + description: + ACPI unique instance identifier for this vendor error source, used + to distinguish multiple instances with the same hardware ID. + $ref: /schemas/types.yaml#/definitions/uint32 + + required: + - compatible + - arm,num-records + + allOf: + - if: + required: + - reg + then: + required: + - arm,group-format + - if: + properties: + compatible: + contains: + const: arm,aest-processor + then: + properties: + arm,processor-flags: {} + arm,resource-type: {} + arm,cache-ref: {} + arm,tlb-level: {} + arm,resource-ref: {} + else: + properties: + arm,processor-flags: false + arm,resource-type: false + arm,cache-ref: false + arm,tlb-level: false + arm,resource-ref: false + + - if: + properties: + compatible: + contains: + const: arm,aest-memory + then: + required: + - arm,proximity-domain + properties: + arm,proximity-domain: {} + else: + properties: + arm,proximity-domain: false + + - if: + properties: + compatible: + contains: + const: arm,aest-smmu + then: + required: + - arm,smmu-ref + properties: + arm,smmu-ref: {} + arm,smmu-subcomponent: {} + else: + properties: + arm,smmu-ref: false + arm,smmu-subcomponent: false + + - if: + properties: + compatible: + contains: + const: arm,aest-gic + then: + properties: + arm,gic-type: {} + arm,gic-instance: {} + else: + properties: + arm,gic-type: false + arm,gic-instance: false + + - if: + properties: + compatible: + contains: + const: arm,aest-pcie + then: + required: + - arm,pcie-segment + properties: + arm,pcie-segment: {} + else: + properties: + arm,pcie-segment: false + + - if: + properties: + compatible: + contains: + const: arm,aest-vendor + then: + required: + - arm,vendor-hid + properties: + arm,vendor-hid: {} + arm,vendor-uid: {} + else: + properties: + arm,vendor-hid: false + arm,vendor-uid: false + + unevaluatedProperties: false + +examples: + - | + #include + #include + + aest { + compatible = "arm,aest"; + #address-cells = <2>; + #size-cells = <2>; + + /* System-register based processor error source (no reg property) */ + aest-processor-0 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x3>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + arm,resource-type = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + /* Memory-mapped memory controller error source */ + aest-memory-0@50010000 { + compatible = "arm,aest-memory"; + reg = <0x0 0x50010000 0x0 0x1000>, + <0x0 0x50011000 0x0 0x1000>, + <0x0 0x50012000 0x0 0x1000>; + reg-names = "err-group", "fault-inject", "irq-config"; + arm,group-format = ; + arm,num-records = <4>; + arm,record-impl = /bits/ 64 <0xf>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,interface-flags = ; + arm,proximity-domain = <0>; + interrupts = , + ; + interrupt-names = "fhi", "eri"; + }; + }; diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml index b0693cd46d27a..8756ecce4d11a 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-funnel.yaml @@ -57,6 +57,11 @@ properties: power-domains: maxItems: 1 + qcom,cpu-bound-components: + type: boolean + description: + Indicates whether the funnel is located physically within cpu cluster. + label: description: Description of a coresight device. diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml index 17ea936b796fd..2c6e78f02ed84 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-dynamic-replicator.yaml @@ -67,6 +67,11 @@ properties: Indicates that the replicator will lose register context when AMBA clock is removed which is observed in some replicator designs. + qcom,cpu-bound-components: + type: boolean + description: + Indicates whether the replicator is located physically within cpu cluster. + in-ports: $ref: /schemas/graph.yaml#/properties/ports additionalProperties: false diff --git a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml index 9dc096698c657..046ad8639e21b 100644 --- a/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml +++ b/Documentation/devicetree/bindings/arm/arm,coresight-tmc.yaml @@ -86,6 +86,11 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 maximum: 15 + qcom,cpu-bound-components: + type: boolean + description: + indicates whether the TMC-ETF is located physically within cpu cluster. + in-ports: $ref: /schemas/graph.yaml#/properties/ports additionalProperties: false diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml index 6e2e0c5518411..5fdcbf331ea56 100644 --- a/Documentation/devicetree/bindings/arm/psci.yaml +++ b/Documentation/devicetree/bindings/arm/psci.yaml @@ -98,6 +98,26 @@ properties: [1] Kernel documentation - ARM idle states bindings Documentation/devicetree/bindings/cpu/idle-states.yaml + reboot-mode: + type: object + $ref: /schemas/power/reset/reboot-mode.yaml# + unevaluatedProperties: false + properties: + # "mode-normal" is just SYSTEM_RESET + mode-normal: false + patternProperties: + "^mode-.*$": + minItems: 1 + maxItems: 2 + description: | + Describes a vendor-specific reset type. The string after "mode-" + maps a reboot mode to the parameters in the PSCI SYSTEM_RESET2 call. + + Parameters are named mode-xxx = , where xxx is the + name of the magic reboot mode, type corresponds to the reset_type + and the values should be provided as per the PSCI SYSTEM_RESET2 + specs. The cookie value is optional and defaulted to zero. + patternProperties: "^power-domain-": $ref: /schemas/power/power-domain.yaml# @@ -137,6 +157,15 @@ allOf: required: - cpu_off - cpu_on + - if: + not: + properties: + compatible: + contains: + const: arm,psci-1.0 + then: + properties: + reboot-mode: false additionalProperties: false @@ -260,4 +289,17 @@ examples: domain-idle-states = <&cluster_ret>, <&cluster_pwrdn>; }; }; + + - |+ + + // Case 5: SYSTEM_RESET2 vendor resets + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + reboot-mode { + mode-edl = <0x80000000 1>; + mode-bootloader = <0x80010001 2>; + }; + }; ... diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml index e002f87361ad3..468da6439bbf9 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml @@ -29,7 +29,11 @@ properties: oneOf: - items: - enum: + - qcom,glymur-ctcu + - qcom,kaanapali-ctcu - qcom,qcs8300-ctcu + - qcom,sm8750-ctcu + - qcom,x1e80100-ctcu - const: qcom,sa8775p-ctcu - enum: - qcom,sa8775p-ctcu @@ -44,6 +48,11 @@ properties: items: - const: apb + interrupts: + items: + - description: Interrupt for the ETR device connected to in-port0. + - description: Interrupt for the ETR device connected to in-port1. + label: description: Description of a coresight device. @@ -65,6 +74,8 @@ additionalProperties: false examples: - | + #include + ctcu@1001000 { compatible = "qcom,sa8775p-ctcu"; reg = <0x1001000 0x1000>; @@ -72,6 +83,9 @@ examples: clocks = <&aoss_qmp>; clock-names = "apb"; + interrupts = , + ; + in-ports { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/arm/qcom,tgu.yaml b/Documentation/devicetree/bindings/arm/qcom,tgu.yaml new file mode 100644 index 0000000000000..76440f2497b97 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/qcom,tgu.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +# Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/qcom,tgu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Trigger Generation Unit - TGU + +description: | + The Trigger Generation Unit (TGU) is a Data Engine which can be utilized + to sense a plurality of signals and create a trigger into the CTI or + generate interrupts to processors. The TGU is like the trigger circuit + of a Logic Analyzer. The corresponding trigger logic can be realized by + configuring the conditions for each step after sensing the signal. + Once setup and enabled, it will observe sense inputs and based upon + the activity of those inputs, even over clock cycles, may detect a + preprogrammed state/sequence and then produce a trigger or interrupt. + + The primary use case of the TGU is to detect patterns or sequences on a + given set of signals within some region to identify the issue in time + once there is abnormal behavior in the subsystem. + +maintainers: + - Mao Jinlong + - Songwei Chai + +# Need a custom select here or 'arm,primecell' will match on lots of nodes +select: + properties: + compatible: + contains: + enum: + - qcom,tgu + required: + - compatible + +properties: + compatible: + items: + - const: qcom,tgu + - const: arm,primecell + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: apb_pclk + +required: + - compatible + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x10b0e000 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +... diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 50cc18a6ec5ed..de58e1ac0a16f 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -932,6 +932,7 @@ properties: - items: - enum: - arduino,monza + - qcom,monaco-ac-evk - qcom,monaco-evk - qcom,qcs8300-ride - const: qcom,qcs8300 @@ -968,6 +969,24 @@ properties: - const: qcom,qcs9100 - const: qcom,sa8775p + - items: + - enum: + - qcom,shikra-cqm-evk + - const: qcom,shikra-cqm-som + - const: qcom,shikra + + - items: + - enum: + - qcom,shikra-cqs-evk + - const: qcom,shikra-cqs-som + - const: qcom,shikra + + - items: + - enum: + - qcom,shikra-iqs-evk + - const: qcom,shikra-iqs-som + - const: qcom,shikra + - items: - enum: - google,blueline diff --git a/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml new file mode 100644 index 0000000000000..c1688bb3d68d8 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,clk-gp-mnd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Peripheral Web's PDM GP_MN Clock Divider + +maintainers: + - Taniya Das + +description: | + The Peripheral Web's PDM GP_MN clock divider receives an input clock + (TCXO4) with frequency Fin and generates an output clock with + frequency Fout = Fin * (M / N) and a duty cycle controlled by D + and routed over a gpio pin. + + The divider is configured using three registers: + + - GP_MN_CLK_MDIV: holds the M value. + - GP_MN_CLK_NDIV: holds the ones complement of (N - M). + - GP_MN_CLK_DUTY: holds the D value. + + For every N input clock cycles the GP_MN produces M output clock + cycles. D is the number of native clock cycles in which the GP_MN + output is low, counted over 2^13 native clock cycles. + + Hardware constraints: + + M <= 511 + N <= 8191 + N > 2 * M + M < D < (N - M) + M and N must be coprime (no common divisor) + +properties: + compatible: + const: qcom,clk-gp-mnd + + reg: + maxItems: 1 + + clocks: + items: + - description: PDM XO4 source clock + - description: PDM AHB bus clock for register access + + clock-names: + items: + - const: pdm_clk + - const: ahb_clk + + '#clock-cells': + const: 0 + + clock-output-names: + maxItems: 1 + + pinctrl-0: + description: Pin configuration for the GP_MN output in the active state. + + pinctrl-names: + items: + - const: active + + assigned-clocks: + maxItems: 1 + description: Parent clock phandle used to set the input frequency. + + assigned-clock-rates: + maxItems: 1 + description: | + Rate for the parent clock in Hz. + Supported rates: 19200000, 9600000, 6400000, 4800000. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - clock-output-names + - pinctrl-0 + - pinctrl-names + - assigned-clocks + - assigned-clock-rates + +additionalProperties: false + +examples: + - | + #include + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x88d3000 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + pinctrl-0 = <&gp_mn_pin_active>; + pinctrl-names = "active"; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + #clock-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/clock/qcom,glymur-evacc.yaml b/Documentation/devicetree/bindings/clock/qcom,glymur-evacc.yaml new file mode 100644 index 0000000000000..8315e3ce82ecf --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,glymur-evacc.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,glymur-evacc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm EVA Clock & Reset Controller on Glymur SoC + +maintainers: + - Taniya Das + +description: | + Qualcomm EVA clock control module which supports the clocks, resets and + power domains for the EVA instances on Glymur SoC. + + See also: + - include/dt-bindings/clock/qcom,glymur-evacc.h + +properties: + compatible: + const: qcom,glymur-evacc + + clocks: + items: + - description: Interface clock from GCC + - description: Board XO source + - description: Board XO_A source + - description: Sleep clock source + + power-domains: + description: + Power domains required for the clock controller to operate + items: + - description: MMCX power domain + - description: MXC power domain + + required-opps: + description: + Required OPP nodes for the MMCX and MXC power domains. + items: + - description: MMCX performance point + - description: MXC performance point + +required: + - compatible + - clocks + - power-domains + - required-opps + - '#power-domain-cells' + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + clock-controller@ab00000 { + compatible = "qcom,glymur-evacc"; + reg = <0x0ab00000 0x10000>; + clocks = <&gcc GCC_EVA_AHB_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, + <&sleep_clk>; + power-domains = <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml index 707b25d2c11e6..efafe86e1238d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,milos-camcc.yaml @@ -8,16 +8,23 @@ title: Qualcomm Camera Clock & Reset Controller on Milos maintainers: - Luca Weiss + - Taniya Das description: | Qualcomm camera clock control module provides the clocks, resets and power domains on Milos. - See also: include/dt-bindings/clock/qcom,milos-camcc.h + See also: + include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h + include/dt-bindings/clock/qcom,eliza-camcc.h + include/dt-bindings/clock/qcom,milos-camcc.h properties: compatible: - const: qcom,milos-camcc + enum: + - qcom,eliza-cambistmclkcc + - qcom,eliza-camcc + - qcom,milos-camcc clocks: items: @@ -32,6 +39,7 @@ properties: required: - compatible - clocks + - '#power-domain-cells' allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml index 14c31efe1308a..c0c9e450b8cda 100644 --- a/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,milos-videocc.yaml @@ -8,16 +8,21 @@ title: Qualcomm Video Clock & Reset Controller on Milos maintainers: - Luca Weiss + - Taniya Das description: | Qualcomm video clock control module provides the clocks, resets and power domains on Milos. - See also: include/dt-bindings/clock/qcom,milos-videocc.h + See also: + include/dt-bindings/clock/qcom,eliza-videocc.h + include/dt-bindings/clock/qcom,milos-videocc.h properties: compatible: - const: qcom,milos-videocc + enum: + - qcom,eliza-videocc + - qcom,milos-videocc clocks: items: @@ -29,6 +34,7 @@ properties: required: - compatible - clocks + - '#power-domain-cells' allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml index 4a533b45eec2d..5cee033f2115d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml @@ -17,7 +17,13 @@ description: | properties: compatible: - const: qcom,qcm2290-dispcc + oneOf: + - items: + - enum: + - qcom,shikra-dispcc + - const: qcom,qcm2290-dispcc + - enum: + - qcom,qcm2290-dispcc clocks: items: @@ -25,8 +31,11 @@ properties: - description: Board active-only XO source - description: GPLL0 source from GCC - description: GPLL0 div source from GCC - - description: Byte clock from DSI PHY - - description: Pixel clock from DSI PHY + - description: Byte clock from DSI PHY0 + - description: Pixel clock from DSI PHY0 + - description: Byte clock from DSI PHY1 + - description: Pixel clock from DSI PHY1 + - description: Board sleep clock clock-names: items: @@ -36,6 +45,9 @@ properties: - const: gcc_disp_gpll0_div_clk_src - const: dsi0_phy_pll_out_byteclk - const: dsi0_phy_pll_out_dsiclk + - const: dsi1_phy_pll_out_byteclk + - const: dsi1_phy_pll_out_dsiclk + - const: sleep_clk required: - compatible @@ -61,13 +73,19 @@ examples: <&gcc GCC_DISP_GPLL0_CLK_SRC>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, <&dsi0_phy 0>, - <&dsi0_phy 1>; + <&dsi0_phy 1>, + <&dsi1_phy 0>, + <&dsi1_phy 1>, + <&sleep_clk>; clock-names = "bi_tcxo", "bi_tcxo_ao", "gcc_disp_gpll0_clk_src", "gcc_disp_gpll0_div_clk_src", "dsi0_phy_pll_out_byteclk", - "dsi0_phy_pll_out_dsiclk"; + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "sleep_clk"; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml index 734880805c1b9..1bd70d091fcd7 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-gpucc.yaml @@ -18,7 +18,9 @@ description: | properties: compatible: - const: qcom,qcm2290-gpucc + enum: + - qcom,qcm2290-gpucc + - qcom,shikra-gpucc reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml index ab97d4b7dba8b..af9fc5b14a810 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml @@ -21,35 +21,41 @@ description: | properties: compatible: - items: - - enum: - - qcom,rpmcc-apq8060 - - qcom,rpmcc-apq8064 - - qcom,rpmcc-ipq806x - - qcom,rpmcc-mdm9607 - - qcom,rpmcc-msm8226 - - qcom,rpmcc-msm8660 - - qcom,rpmcc-msm8909 - - qcom,rpmcc-msm8916 - - qcom,rpmcc-msm8917 - - qcom,rpmcc-msm8936 - - qcom,rpmcc-msm8937 - - qcom,rpmcc-msm8940 - - qcom,rpmcc-msm8953 - - qcom,rpmcc-msm8974 - - qcom,rpmcc-msm8976 - - qcom,rpmcc-msm8992 - - qcom,rpmcc-msm8994 - - qcom,rpmcc-msm8996 - - qcom,rpmcc-msm8998 - - qcom,rpmcc-qcm2290 - - qcom,rpmcc-qcs404 - - qcom,rpmcc-sdm429 - - qcom,rpmcc-sdm660 - - qcom,rpmcc-sm6115 - - qcom,rpmcc-sm6125 - - qcom,rpmcc-sm6375 - - const: qcom,rpmcc + oneOf: + - items: + - enum: + - qcom,rpmcc-apq8060 + - qcom,rpmcc-apq8064 + - qcom,rpmcc-ipq806x + - qcom,rpmcc-mdm9607 + - qcom,rpmcc-msm8226 + - qcom,rpmcc-msm8660 + - qcom,rpmcc-msm8909 + - qcom,rpmcc-msm8916 + - qcom,rpmcc-msm8917 + - qcom,rpmcc-msm8936 + - qcom,rpmcc-msm8937 + - qcom,rpmcc-msm8940 + - qcom,rpmcc-msm8953 + - qcom,rpmcc-msm8974 + - qcom,rpmcc-msm8976 + - qcom,rpmcc-msm8992 + - qcom,rpmcc-msm8994 + - qcom,rpmcc-msm8996 + - qcom,rpmcc-msm8998 + - qcom,rpmcc-qcm2290 + - qcom,rpmcc-qcs404 + - qcom,rpmcc-sdm429 + - qcom,rpmcc-sdm660 + - qcom,rpmcc-sm6115 + - qcom,rpmcc-sm6125 + - qcom,rpmcc-sm6375 + - const: qcom,rpmcc + - items: + - enum: + - qcom,rpmcc-shikra + - const: qcom,rpmcc-qcm2290 + - const: qcom,rpmcc '#clock-cells': const: 1 @@ -126,6 +132,7 @@ allOf: - qcom,rpmcc-qcs404 - qcom,rpmcc-sdm429 - qcom,rpmcc-sdm660 + - qcom,rpmcc-shikra - qcom,rpmcc-sm6115 - qcom,rpmcc-sm6125 diff --git a/Documentation/devicetree/bindings/clock/qcom,shikra-audiocorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,shikra-audiocorecc.yaml new file mode 100644 index 0000000000000..2ed1d9d871175 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,shikra-audiocorecc.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,shikra-audiocorecc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Audio Core Clock & Reset Controller for Qualcomm Shikra SoC + +maintainers: + - Imran Shaik + +description: | + Audio core clock control module provides the clocks and resets + on Qualcomm Shikra SoC platform. + + See also: + - include/dt-bindings/clock/qcom,shikra-audiocorecc.h + +properties: + compatible: + enum: + - qcom,shikra-cqm-audiocorecc + - qcom,shikra-cqs-audiocorecc + + clocks: + items: + - description: Board XO source + - description: Board sleep clock + - description: Audio ref clock source + + reg: + maxItems: 2 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + #include + #include + clock-controller@a0a0000 { + compatible = "qcom,shikra-cqm-audiocorecc"; + reg = <0x0a0a0000 0x10000>, + <0x0a0b4000 0x1000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&aud_ref_clk_src>; + #clock-cells = <1>; + #reset-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml new file mode 100644 index 0000000000000..da6eebfa84c22 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,shikra-gcc.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,shikra-gcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Global Clock & Reset Controller on Qualcomm Shikra SoC + +maintainers: + - Imran Shaik + - Taniya Das + +description: | + Global clock control module provides the clocks, resets and power + domains on Qualcomm Shikra SoC platform. + + See also: include/dt-bindings/clock/qcom,shikra-gcc.h + +properties: + compatible: + const: qcom,shikra-gcc + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + - description: EMAC0 sgmiiphy mac rclk source + - description: EMAC0 sgmiiphy mac tclk source + - description: EMAC1 sgmiiphy mac rclk source + - description: EMAC1 sgmiiphy mac tclk source + - description: PCIE Pipe clock source + - description: USB3 phy wrapper pipe clock source + + power-domains: + items: + - description: CX domain + +required: + - compatible + - clocks + - power-domains + - '#power-domain-cells' + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + clock-controller@1400000 { + compatible = "qcom,shikra-gcc"; + reg = <0x01400000 0x1f0000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <&emac0_sgmiiphy_rclk>, + <&emac0_sgmiiphy_tclk>, + <&emac1_sgmiiphy_rclk>, + <&emac1_sgmiiphy_tclk>, + <&pcie_pipe_clk>, + <&usb3_phy_wrapper_gcc_usb30_pipe_clk>; + power-domains = <&rpmpd RPMPD_VDDCX>; + #clock-cells = <1>; + #power-domain-cells = <1>; + #reset-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml index 104ba10ca5737..21998c6bf5575 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm graphics clock control module provides clocks, resets and power domains on Qualcomm SoCs. - See also: include/dt-bindings/clock/qcom,sm6115-gpucc.h + See also: include/dt-bindings/clock/qcom,shikra-gpucc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml index fdbdf605ee695..734bab762a308 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml @@ -15,6 +15,7 @@ description: | domains on Qualcomm SoCs. See also: + include/dt-bindings/clock/qcom,eliza-gpucc.h include/dt-bindings/clock/qcom,glymur-gpucc.h include/dt-bindings/clock/qcom,kaanapali-gpucc.h include/dt-bindings/clock/qcom,milos-gpucc.h @@ -30,6 +31,7 @@ description: | properties: compatible: enum: + - qcom,eliza-gpucc - qcom,glymur-gpucc - qcom,kaanapali-gpucc - qcom,milos-gpucc @@ -71,6 +73,7 @@ allOf: compatible: contains: enum: + - qcom,eliza-gpucc - qcom,sm8750-gpucc then: required: diff --git a/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml index b28614186cc09..e7cb8cfa957a4 100644 --- a/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,x1e80100-camcc.yaml @@ -8,12 +8,14 @@ title: Qualcomm Camera Clock & Reset Controller on x1e80100 maintainers: - Bryan O'Donoghue + - Jagadeesh Kona description: | Qualcomm camera clock control module provides the clocks, resets and power domains on x1e80100. See also: + include/dt-bindings/clock/qcom,glymur-camcc.h include/dt-bindings/clock/qcom,x1e80100-camcc.h allOf: @@ -22,6 +24,7 @@ allOf: properties: compatible: enum: + - qcom,glymur-camcc - qcom,x1e80100-camcc - qcom,x1p42100-camcc diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml index 8ca0292490a2c..ecad7781644ce 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.yaml +++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml @@ -95,6 +95,14 @@ properties: - device - dual + usb-role-switch: + $ref: /schemas/types.yaml#/definitions/phandle + description: + A phandle to the USB role-switch provider. The provider is typically + a dual-role (DRD) USB controller node that declares the boolean + 'usb-role-switch' property. Use this when the connector is not + directly linked to the provider in the OF graph. + typec-power-opmode: description: Determines the power operation mode that the Type C connector will support and will advertise through CC pins when it has no power diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml index 98eb36bff1727..fa54fb7ef5246 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml @@ -54,6 +54,12 @@ properties: - qcom,sm8650-cpufreq-epss - const: qcom,cpufreq-epss + - description: RIMPS CPUFREQ HW + items: + - enum: + - qcom,shikra-cpufreq-rimps + - const: qcom,cpufreq-rimps + reg: minItems: 1 items: @@ -144,6 +150,7 @@ allOf: - qcom,sc8280xp-cpufreq-epss - qcom,sdm670-cpufreq-hw - qcom,sdm845-cpufreq-hw + - qcom,shikra-cpufreq-rimps - qcom,sm4450-cpufreq-epss - qcom,sm6115-cpufreq-hw - qcom,sm6350-cpufreq-hw diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml index db895c50e2d25..4d351b6c455da 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml @@ -21,6 +21,7 @@ properties: - qcom,sa8775p-inline-crypto-engine - qcom,sc7180-inline-crypto-engine - qcom,sc7280-inline-crypto-engine + - qcom,shikra-inline-crypto-engine - qcom,sm8450-inline-crypto-engine - qcom,sm8550-inline-crypto-engine - qcom,sm8650-inline-crypto-engine @@ -82,7 +83,7 @@ examples: compatible = "qcom,sm8550-inline-crypto-engine", "qcom,inline-crypto-engine"; reg = <0x01d88000 0x8000>; - clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, + clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>; <&gcc GCC_UFS_PHY_AHB_CLK>; clock-names = "core", "iface"; diff --git a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml index dc270c8aedf3a..5de52d7a745c3 100644 --- a/Documentation/devicetree/bindings/crypto/qcom,prng.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom,prng.yaml @@ -30,6 +30,7 @@ properties: - qcom,sa8255p-trng - qcom,sa8775p-trng - qcom,sc7280-trng + - qcom,shikra-trng - qcom,sm8450-trng - qcom,sm8550-trng - qcom,sm8650-trng diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index 08febd66c22ba..5a653757ee752 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -54,6 +54,7 @@ properties: - qcom,qcs8300-qce - qcom,sa8775p-qce - qcom,sc7280-qce + - qcom,shikra-qce - qcom,sm6350-qce - qcom,sm8250-qce - qcom,sm8350-qce diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml index 7cfe92a8bcd72..de61bda09db96 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml @@ -4,19 +4,20 @@ $id: http://devicetree.org/schemas/display/bridge/lontium,lt9211.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Lontium LT9211 DSI/LVDS/DPI to DSI/LVDS/DPI bridge. +title: Lontium LT9211/LT9211C DSI/LVDS/DPI to DSI/LVDS/DPI bridge. maintainers: - Marek Vasut description: | - The LT9211 are bridge devices which convert Single/Dual-Link DSI/LVDS + The LT9211 and LT9211C are bridge devices which convert Single/Dual-Link DSI/LVDS or Single DPI to Single/Dual-Link DSI/LVDS or Single DPI. properties: compatible: enum: - lontium,lt9211 + - lontium,lt9211c reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml index 429a06057ae85..77220f893bf83 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml @@ -4,19 +4,23 @@ $id: http://devicetree.org/schemas/display/bridge/lontium,lt9611.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Lontium LT9611(UXC) 2 Port MIPI to HDMI Bridge +title: Lontium LT9611(UXC/C/EX/UXD) 2 Port MIPI DSI to HDMI Bridge maintainers: - Vinod Koul description: | - The LT9611 and LT9611UXC are bridge devices which convert DSI to HDMI + The LT9611、LT9611UXC、LT9611C、LT9611EX and LT9611UXD + are bridge devices which convert DSI to HDMI properties: compatible: enum: - lontium,lt9611 + - lontium,lt9611c + - lontium,lt9611ex - lontium,lt9611uxc + - lontium,lt9611uxd reg: maxItems: 1 @@ -37,6 +41,17 @@ properties: vcc-supply: description: Regulator for 3.3V IO power. + lontium,port-select: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + default: 0 + description: | + Selects which DSI input port(s) the bridge uses. Only relevant for + the lontium,lt9611c compatible. + 0 = PORT_SELECT_A - single DSI port A (default) + 1 = PORT_SELECT_B - single DSI port B + 2 = PORT_SELECT_AB - dual DSI ports A and B + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -100,6 +115,8 @@ examples: vdd-supply = <<9611_1v8>; vcc-supply = <<9611_3v3>; + lontium,port-select = <1>; + ports { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index dbc0613e427ed..a2f3e91104af3 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -33,6 +33,7 @@ properties: - qcom,sdm660-dsi-ctrl - qcom,sdm670-dsi-ctrl - qcom,sdm845-dsi-ctrl + - qcom,shikra-dsi-ctrl - qcom,sm6115-dsi-ctrl - qcom,sm6125-dsi-ctrl - qcom,sm6150-dsi-ctrl diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml index be6cd8adb3b67..cc1f227ade2d3 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml @@ -13,7 +13,9 @@ $ref: /schemas/display/msm/dpu-common.yaml# properties: compatible: - const: qcom,qcm2290-dpu + enum: + - qcom,qcm2290-dpu + - qcom,shikra-dpu reg: items: diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml index bb09ecd1a5b4f..8271cb71bab8f 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml @@ -4,21 +4,35 @@ $id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Qualcomm QCM220 Display MDSS +title: Qualcomm QCM2290 and Shikra Display MDSS maintainers: - Loic Poulain + - Mahadevan P description: Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS - are mentioned for QCM2290 target. + are mentioned for QCM2290 and Shikra targets. Shikra uses the same MDSS/DPU/DSI + hardware as QCM2290 (DPU 6.5) and shares the same register layout. $ref: /schemas/display/msm/mdss-common.yaml# +select: + properties: + compatible: + contains: + enum: + - qcom,qcm2290-mdss + - qcom,shikra-mdss + required: + - compatible + properties: compatible: - const: qcom,qcm2290-mdss + enum: + - qcom,qcm2290-mdss + - qcom,shikra-mdss clocks: items: @@ -52,7 +66,9 @@ patternProperties: properties: compatible: - const: qcom,qcm2290-dpu + enum: + - qcom,qcm2290-dpu + - qcom,shikra-dpu "^dsi@[0-9a-f]+$": type: object @@ -60,9 +76,13 @@ patternProperties: properties: compatible: - items: - - const: qcom,qcm2290-dsi-ctrl - - const: qcom,mdss-dsi-ctrl + oneOf: + - items: + - const: qcom,qcm2290-dsi-ctrl + - const: qcom,mdss-dsi-ctrl + - items: + - const: qcom,shikra-dsi-ctrl + - const: qcom,mdss-dsi-ctrl "^phy@[0-9a-f]+$": type: object diff --git a/Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml b/Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml new file mode 100644 index 0000000000000..8ae72a8265e61 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/dlc,dlc0697.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DLC DLC0697 1080x1920 video-mode DSI panel + +maintainers: + - Arpit Saini + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: dlc,dlc0697 + + reg: + maxItems: 1 + description: DSI virtual channel + + reset-gpios: true + + enable-gpios: true + + vddio-supply: + description: I/O voltage supply (1.8V) + + bias-supply: + description: LCD bias supply (3.3V), typically a GPIO-controlled fixed regulator + + port: true + +required: + - compatible + - reg + - reset-gpios + - vddio-supply + - port + +additionalProperties: false + +examples: + - | + #include + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "dlc,dlc0697"; + reg = <0>; + + reset-gpios = <&tlmm 41 GPIO_ACTIVE_LOW>; + vddio-supply = <&vreg_l15>; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml b/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml index 0923fb189ada9..e72adc172af10 100644 --- a/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml +++ b/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml @@ -48,7 +48,7 @@ properties: iommus: minItems: 1 - maxItems: 6 + maxItems: 7 num-channels: $ref: /schemas/types.yaml#/definitions/uint32 diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml index 25f62bacbc919..9d64765416137 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml @@ -67,6 +67,7 @@ properties: - qcom,scm-sdx55 - qcom,scm-sdx65 - qcom,scm-sdx75 + - qcom,scm-shikra - qcom,scm-sm6115 - qcom,scm-sm6125 - qcom,scm-sm6350 @@ -148,6 +149,7 @@ allOf: - qcom,scm-msm8974 - qcom,scm-msm8976 - qcom,scm-qcm2290 + - qcom,scm-shikra - qcom,scm-sm6375 then: required: @@ -167,6 +169,7 @@ allOf: - qcom,scm-msm8660 - qcom,scm-msm8960 - qcom,scm-qcm2290 + - qcom,scm-shikra - qcom,scm-sm6375 then: properties: diff --git a/Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml b/Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml new file mode 100644 index 0000000000000..6ffadc4d28bcf --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml @@ -0,0 +1,128 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/qcom,bcl-hwmon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SPMI PMIC Battery Current Limiting (BCL) Hardware Monitor + +maintainers: + - Manaf Meethalavalappu Pallikunhi + +description: | + SPMI PMIC Battery Current Limiting (BCL) hardware provides monitoring and + alarm functionality for battery overcurrent and battery or system under + voltage conditions. It monitors battery voltage and current, and + can trigger interrupts when configurable thresholds are exceeded. + +properties: + compatible: + oneOf: + - description: v1 based BCL + items: + - enum: + - qcom,pm7250b-bcl + - qcom,pm8250b-bcl + - const: qcom,bcl-v1 + + - description: v2 based BCL + items: + - enum: + - qcom,pm8350b-bcl + - qcom,pm8350c-bcl + - const: qcom,bcl-v2 + + - description: v3 bmx based BCL + items: + - enum: + - qcom,pm8550b-bcl + - qcom,pm7550ba-bcl + - const: qcom,bcl-v3-bmx + + - description: v3 core based BCL + items: + - enum: + - qcom,pm8550-bc0l + - qcom,pm7550-bcl + - const: qcom,bcl-v3-core + + - description: v3 wb based BCL + items: + - enum: + - qcom,pmw5100-bcl + - const: qcom,bcl-v3-wb + + - description: v4 bmx based BCL + items: + - enum: + - qcom,pmih010-bcl + - const: qcom,bcl-v4-bmx + + - description: v4 bmx with different scale based BCL + items: + - enum: + - qcom,pmv010-bcl + - const: qcom,bcl-v4-pmv010 + + - description: v4 core based BCL + items: + - enum: + - qcom,pmh010-bcl + - const: qcom,bcl-v4-core + + - description: v4 wb based BCL + items: + - enum: + - qcom,pmw6100-bcl + - const: qcom,bcl-v4-wb + + reg: + maxItems: 1 + description: BCL base address in the SPMI PMIC register map + + interrupts: + minItems: 2 + maxItems: 2 + description: + BCL alarm interrupts for different threshold levels + + interrupt-names: + items: + - const: bcl-max-min + - const: bcl-critical + + overcurrent-thresholds-milliamp: + description: + Current thresholds in milliamperes for the two configurable current + alarm levels (max and critical). These values are used to override + default thresholds if a platform has different battery ocp specification. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 2 + +required: + - compatible + - reg + - interrupts + - interrupt-names + +unevaluatedProperties: false + +examples: + - | + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + sensor@1d00 { + compatible = "qcom,pm7250b-bcl", "qcom,bcl-v1"; + reg = <0x1d00>; + interrupts = <0x2 0x1d 0x0 IRQ_TYPE_EDGE_RISING>, + <0x2 0x1d 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "bcl-max-min", + "bcl-critical"; + overcurrent-thresholds-milliamp = <5500 6000>; + }; + }; diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml index 51534953a69cf..9401dc2d50522 100644 --- a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml @@ -60,6 +60,13 @@ properties: power-domains: maxItems: 1 + qcom,qup-multi-owner: + type: boolean + description: + Indicates that the QUP-based controller is shared with one or more + other system processors and must not be assumed to have exclusive + ownership by the operating system. + reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml index ff64225e82817..8f6c937e44cef 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml @@ -52,6 +52,7 @@ properties: - qcom,sa8775p-llcc-bwmon - qcom,sc7180-llcc-bwmon - qcom,sc8280xp-llcc-bwmon + - qcom,shikra-cpu-bwmon - qcom,sm6350-cpu-bwmon - qcom,sm8250-llcc-bwmon - qcom,sm8550-llcc-bwmon diff --git a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml index 41b9f758bf8b8..3b8ebe17a9760 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml @@ -17,6 +17,8 @@ description: properties: compatible: oneOf: + - enum: + - qcom,shikra-epss-l3 - items: - enum: - qcom,sc7180-osm-l3 diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml index 8162a49d49a66..040b8d4f8ee9c 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml @@ -58,6 +58,7 @@ properties: - qcom,sm8650-pdc - qcom,sm8750-pdc - qcom,x1e80100-pdc + - qcom,x1p42100-pdc - const: qcom,pdc reg: @@ -65,6 +66,7 @@ properties: items: - description: PDC base register region - description: Edge or Level config register for SPI interrupts + - description: PDC config for pass through or secondary IRQ mode for GPIOs '#interrupt-cells': const: 2 @@ -85,6 +87,10 @@ properties: The tuples indicates the valid mapping of valid PDC ports and their hwirq mapping. + qcom,qmp: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AOSS side-channel message RAM. + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml index a701dec2fa0a4..384c5a99ea71e 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml @@ -108,6 +108,7 @@ properties: - qcom,sc7280-smmu-500 - qcom,sc8180x-smmu-500 - qcom,sc8280xp-smmu-500 + - qcom,shikra-smmu-500 - qcom,sm6115-smmu-500 - qcom,sm6125-smmu-500 - qcom,sm8150-smmu-500 @@ -246,6 +247,13 @@ properties: minItems: 1 maxItems: 3 + interconnects: + maxItems: 1 + description: + Interconnect path to the SMMU register space. Required on SoCs + where the SMMU registers are only accessible after a bandwidth + vote has been placed on the interconnect fabric. + nvidia,memory-controller: description: | A phandle to the memory controller on NVIDIA Tegra186 and later SoCs. @@ -644,6 +652,26 @@ allOf: clock-names: false clocks: false + - if: + properties: + compatible: + items: + - enum: + - qcom,qcs615-smmu-500 + - qcom,qcs8300-smmu-500 + - qcom,sa8775p-smmu-500 + - qcom,sc7280-smmu-500 + - const: qcom,adreno-smmu + - const: qcom,smmu-500 + - const: arm,mmu-500 + then: + properties: + interconnects: + maxItems: 1 + else: + properties: + interconnects: false + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml index 1b4ef0688ca79..01d6eaefe165e 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml @@ -66,6 +66,7 @@ properties: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared + - qcom,shikra-apcs-hmss-global reg: maxItems: 1 @@ -239,6 +240,7 @@ allOf: - qcom,msm8996-apcs-hmss-global - qcom,qcm2290-apcs-hmss-global - qcom,sdm845-apss-shared + - qcom,shikra-apcs-hmss-global then: properties: clocks: false diff --git a/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml b/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml new file mode 100644 index 0000000000000..5596f3fb99003 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml @@ -0,0 +1,343 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,glymur-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Glymur Camera Subsystem (CAMSS) + +maintainers: + - Nihal Kumar Gupta + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,glymur-camss + + reg: + maxItems: 16 + + reg-names: + items: + - const: csid_wrapper + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy4 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 26 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: core_ahb + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy4 + - const: csiphy4_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 12 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy4 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller. + - description: IFE1 GDSC - Image Front End, Global Distributed Switch Controller. + - description: Titan Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: top + + vdd-csiphy-0p8-supply: + description: + Phandle to 0.8V regulator supply to CSI PHYs. + + vdd-csiphy-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSI PHYs pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-2]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + camss: isp@acb6000 { + compatible = "qcom,glymur-camss"; + + reg = <0x0 0x0acb6000 0x0 0x1000>, + <0x0 0x0acb7000 0x0 0x2000>, + <0x0 0x0acb9000 0x0 0x2000>, + <0x0 0x0acbb000 0x0 0x2000>, + <0x0 0x0acc6000 0x0 0x1000>, + <0x0 0x0acca000 0x0 0x1000>, + <0x0 0x0ace4000 0x0 0x2000>, + <0x0 0x0ace6000 0x0 0x2000>, + <0x0 0x0acec000 0x0 0x2000>, + <0x0 0x0acf6000 0x0 0x1000>, + <0x0 0x0acf7000 0x0 0x1000>, + <0x0 0x0acf8000 0x0 0x1000>, + <0x0 0x0ac62000 0x0 0xf000>, + <0x0 0x0ac71000 0x0 0xf000>, + <0x0 0x0acc7000 0x0 0x2000>, + <0x0 0x0accb000 0x0 0x2000>; + + reg-names = "csid_wrapper", + "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy4", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&hsc_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x00>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + + power-domain-names = "ife0", + "ife1", + "top"; + + vdd-csiphy-0p8-supply = <&csiphy_0p8_supply>; + vdd-csiphy-1p2-supply = <&csiphy_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + csiphy_ep0: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml new file mode 100644 index 0000000000000..3c5305b688ec7 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,glymur-iris.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Glymur SoC Iris video encoder and decoder + +maintainers: + - Vishnu Reddy + +description: + The Iris video processing unit on Qualcomm Glymur SoC is a video encode and + decode accelerator. + +properties: + compatible: + const: qcom,glymur-iris + + clocks: + maxItems: 9 + + clock-names: + items: + - const: iface + - const: core + - const: vcodec0_core + - const: iface1 + - const: core_freerun + - const: vcodec0_core_freerun + - const: iface2 + - const: vcodec1_core + - const: vcodec1_core_freerun + + dma-coherent: true + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: cpu-cfg + - const: video-mem + + iommus: + maxItems: 4 + + iommu-map: + maxItems: 1 + + operating-points-v2: true + opp-table: + type: object + + power-domains: + maxItems: 5 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: mxc + - const: mmcx + - const: vcodec1 + + resets: + maxItems: 6 + + reset-names: + items: + - const: bus0 + - const: bus1 + - const: core + - const: vcodec0_core + - const: bus2 + - const: vcodec1_core + +required: + - compatible + - reg + - clocks + - clock-names + - dma-coherent + - interconnects + - interconnect-names + - interrupts + - iommus + - memory-region + - power-domains + - power-domain-names + - resets + - reset-names + +allOf: + - $ref: qcom,venus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + video-codec@aa00000 { + compatible = "qcom,glymur-iris"; + reg = <0x0aa00000 0xf0000>; + + clocks = <&gcc_video_axi0_clk>, + <&videocc_mvs0c_clk>, + <&videocc_mvs0_clk>, + <&gcc_video_axi0c_clk>, + <&videocc_mvs0c_freerun_clk>, + <&videocc_mvs0_freerun_clk>, + <&gcc_video_axi1_clk>, + <&videocc_mvs1_clk>, + <&videocc_mvs1_freerun_clk>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "iface2", + "vcodec1_core", + "vcodec1_core_freerun"; + + dma-coherent; + + interconnects = <&hsc_noc_master_appss_proc &config_noc_slave_venus_cfg>, + <&mmss_noc_master_video &mc_virt_slave_ebi1>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + iommus = <&apps_smmu 0x1940 0x0>, + <&apps_smmu 0x1943 0x0>, + <&apps_smmu 0x1944 0x0>, + <&apps_smmu 0x19e0 0x0>; + + iommu-map = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&videocc_mvs0c_gdsc>, + <&videocc_mvs0_gdsc>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc_mvs1_gdsc>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vcodec1"; + + resets = <&gcc_video_axi0_clk_ares>, + <&gcc_video_axi0c_clk_ares>, + <&videocc_mvs0c_freerun_clk_ares>, + <&videocc_mvs0_freerun_clk_ares>, + <&gcc_video_axi1_clk_ares>, + <&videocc_mvs1_freerun_clk_ares>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core", + "bus2", + "vcodec1_core"; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-366000000 { + opp-hz = /bits/ 64 <366000000 366000000 549000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-533333334 { + opp-hz = /bits/ 64 <533333334 533333334 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-655000000 { + opp-hz = /bits/ 64 <655000000 655000000 982000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml new file mode 100644 index 0000000000000..2f2bb682f32f4 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,kaanapali-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,kaanapali-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@9253000 { + compatible = "qcom,kaanapali-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x09523000 0x0 0x2000>, + <0x0 0x09525000 0x0 0x2000>, + <0x0 0x09527000 0x0 0x2000>, + <0x0 0x09529000 0x0 0x2000>, + <0x0 0x0952b000 0x0 0x2000>, + <0x0 0x0952d000 0x0 0x2000>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x9000>, + <0x0 0x092f0000 0x0 0x9000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p8-supply = <&vreg_0p8_supply>; + vdd-csiphy0-1p2-supply = <&vreg_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml index 391d0f6f67ef5..7b1469d6a1601 100644 --- a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml @@ -8,13 +8,16 @@ title: Qualcomm QCM2290 Camera Subsystem (CAMSS) maintainers: - Loic Poulain + - Nihal Kumar Gupta description: The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. properties: compatible: - const: qcom,qcm2290-camss + enum: + - qcom,qcm2290-camss + - qcom,shikra-camss reg: maxItems: 9 @@ -76,6 +79,7 @@ properties: - const: sf_mnoc iommus: + minItems: 1 maxItems: 4 power-domains: diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml index 5977e7d0a71b4..770dd159c56d1 100644 --- a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml @@ -15,12 +15,27 @@ description: allOf: - $ref: qcom,venus-common.yaml# + - if: + properties: + compatible: + contains: + const: qcom,shikra-iris + then: + properties: + iommus: + maxItems: 1 + else: + properties: + iommus: + maxItems: 2 properties: compatible: oneOf: - items: - - const: qcom,sm6115-venus + - enum: + - const: qcom,shikra-iris + - const: qcom,sm6115-venus - const: qcom,qcm2290-venus - const: qcom,qcm2290-venus @@ -45,9 +60,6 @@ properties: - const: vcodec0_core - const: vcodec0_bus - iommus: - maxItems: 2 - interconnects: maxItems: 2 diff --git a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml index b21bed3148484..697cce56effaa 100644 --- a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml @@ -50,6 +50,9 @@ properties: iommus: maxItems: 1 + iommu-map: + maxItems: 1 + memory-region: maxItems: 1 @@ -116,6 +119,7 @@ unevaluatedProperties: false examples: - | #include + #include #include venus: video-codec@aa00000 { @@ -133,5 +137,6 @@ examples: clock-names = "core", "iface", "bus", "vcodec0_core", "vcodec0_bus"; iommus = <&apps_smmu 0x0c00 0x60>; + iommu-map = ; memory-region = <&venus_mem>; }; diff --git a/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml new file mode 100644 index 0000000000000..fc0550899c074 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,sm8750-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SM8750 Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,sm8750-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@ad27000 { + compatible = "qcom,sm8750-camss"; + + reg = <0x0 0x0ad27000 0x0 0x2b00>, + <0x0 0x0ad2a000 0x0 0x2b00>, + <0x0 0x0ad2d000 0x0 0x2b00>, + <0x0 0x0ad6d000 0x0 0xa00>, + <0x0 0x0ad72000 0x0 0xa00>, + <0x0 0x0ada9000 0x0 0x2000>, + <0x0 0x0adab000 0x0 0x2000>, + <0x0 0x0adad000 0x0 0x2000>, + <0x0 0x0adaf000 0x0 0x2000>, + <0x0 0x0adb1000 0x0 0x2000>, + <0x0 0x0adb3000 0x0 0x2000>, + <0x0 0x0ad8b000 0x0 0x400>, + <0x0 0x0ad8c000 0x0 0x400>, + <0x0 0x0ad8d000 0x0 0x400>, + <0x0 0x0ac86000 0x0 0x10000>, + <0x0 0x0ac96000 0x0 0x10000>, + <0x0 0x0aca6000 0x0 0x10000>, + <0x0 0x0ad6e000 0x0 0x3000>, + <0x0 0x0ad73000 0x0 0x3000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p9-supply = <&vreg_0p9_supply>; + vdd-csiphy0-1p2-supply = <&vreg_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml index 59a3fde846d21..10716a93dd359 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml +++ b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml @@ -20,11 +20,11 @@ properties: clocks: minItems: 3 - maxItems: 7 + maxItems: 9 clock-names: minItems: 3 - maxItems: 7 + maxItems: 9 firmware-name: maxItems: 1 @@ -41,11 +41,11 @@ properties: power-domains: minItems: 1 - maxItems: 4 + maxItems: 5 power-domain-names: minItems: 1 - maxItems: 4 + maxItems: 5 required: - reg diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index 2d1662ef522b7..d2763977a494d 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -39,6 +39,14 @@ properties: - const: vfe_lite0 - const: vfe_lite1 + '#address-cells': + const: 2 + + '#size-cells': + const: 2 + + ranges: true + clocks: maxItems: 29 @@ -104,7 +112,22 @@ properties: - const: sf_icp_mnoc iommus: - maxItems: 8 + oneOf: + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + - description: Legacy slot 0 - do not use + - description: Legacy slot 1 - do not use + - description: Legacy slot 2 - do not use + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected power-domains: items: @@ -126,11 +149,22 @@ properties: description: 1.2V supply to a PHY. + phys: + maxItems: 4 + + phy-names: + items: + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy4 + ports: $ref: /schemas/graph.yaml#/properties/ports description: - CSI input ports. + CSI input ports. Supports either standard single sensor mode or + Qualcomm's combo mode with one sensor in 2x1 + 1x1 data-lane, clock-lane mode. patternProperties: "^port@[0-3]$": @@ -138,26 +172,94 @@ properties: unevaluatedProperties: false description: - Input port for receiving CSI data from a CSIPHY. + Input port for receiving CSI data. properties: - endpoint: + endpoint@0: $ref: video-interfaces.yaml# unevaluatedProperties: false + description: + Endpoint for receiving a single sensor input (or first leg of combo). + properties: data-lanes: minItems: 1 - maxItems: 4 + maxItems: 4 # Base max allows 4 (for D-PHY) + + clock-lanes: + maxItems: 1 bus-type: enum: - 1 # MEDIA_BUS_TYPE_CSI2_CPHY - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + endpoint@1: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving the second leg of a combo sensor input. + + properties: + data-lanes: + maxItems: 1 + + clock-lanes: + maxItems: 1 + + bus-type: + const: 4 # Combo is D-PHY specific + required: - data-lanes + allOf: + # Case 1: Combo Mode (endpoint@1 is present) + # If endpoint@1 exists, we restrict endpoint@0 to 2 lanes (D-PHY split) + - if: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 2 + maxItems: 2 + bus-type: + const: 4 + endpoint@1: + properties: + data-lanes: + minItems: 1 + maxItems: 1 + bus-type: + const: 4 + + # Case 2: Single Mode (endpoint@1 is missing) + # We explicitly allow up to 4 lanes here to cover the D-PHY use case. + - if: + not: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 1 + maxItems: 4 + +patternProperties: + "^phy@[0-9a-f]+$": + $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml + unevaluatedProperties: false + + "^opp-table(-.*)?$": + type: object + required: - compatible - reg @@ -171,8 +273,6 @@ required: - iommus - power-domains - power-domain-names - - vdd-csiphy-0p8-supply - - vdd-csiphy-1p2-supply - ports additionalProperties: false @@ -184,6 +284,7 @@ examples: #include #include #include + #include #include soc { @@ -229,6 +330,10 @@ examples: "vfe_lite0", "vfe_lite1"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, <&camcc CAM_CC_CORE_AHB_CLK>, @@ -332,13 +437,10 @@ examples: "sf_icp_mnoc"; iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, <&apps_smmu 0x860 0x60>, - <&apps_smmu 0x1800 0x60>, - <&apps_smmu 0x1860 0x60>, - <&apps_smmu 0x18e0 0x00>, - <&apps_smmu 0x1980 0x20>, - <&apps_smmu 0x1900 0x00>, - <&apps_smmu 0x19a0 0x20>; + <&apps_smmu 0x18a0 0x0>; power-domains = <&camcc CAM_CC_IFE_0_GDSC>, <&camcc CAM_CC_IFE_1_GDSC>, diff --git a/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml new file mode 100644 index 0000000000000..8bfa7e616c3b6 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml @@ -0,0 +1,424 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,x1p42100-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm X1P42100 Camera Subsystem (CAMSS) + +maintainers: + - Wenmeng Liu + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,x1p42100-camss + + reg: + maxItems: 14 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_wrapper + - const: csiphy0 + - const: csiphy4 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + '#address-cells': + const: 2 + + '#size-cells': + const: 2 + + ranges: true + + clocks: + maxItems: 22 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: core_ahb + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe_lite + - const: cphy_rx_clk_src + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy4 + - const: csiphy4_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 10 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy4 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + oneOf: + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + - description: Legacy slot 0 - do not use + - description: Legacy slot 1 - do not use + - description: Legacy slot 2 - do not use + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + + power-domains: + items: + - description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller. + - description: Titan Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: top + + vdd-csiphy-0p8-supply: + description: + 0.8V supply to a PHY. + + vdd-csiphy-1p2-supply: + description: + 1.2V supply to a PHY. + + phys: + maxItems: 2 + + phy-names: + items: + - const: csiphy0 + - const: csiphy4 + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. Supports either standard single sensor mode or + Qualcomm's combo mode with one sensor in 2x1 + 1x1 data-lane, clock-lane mode. + + patternProperties: + "^port@[0-3]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint@0: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving a single sensor input (or first leg of combo). + + properties: + data-lanes: + minItems: 1 + maxItems: 4 # Base max allows 4 (for D-PHY) + + clock-lanes: + maxItems: 1 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + endpoint@1: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving the second leg of a combo sensor input. + + properties: + data-lanes: + maxItems: 1 + + clock-lanes: + maxItems: 1 + + bus-type: + const: 4 # Combo is D-PHY specific + + required: + - data-lanes + + allOf: + # Case 1: Combo Mode (endpoint@1 is present) + # If endpoint@1 exists, we restrict endpoint@0 to 2 lanes (D-PHY split) + - if: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 2 + maxItems: 2 + bus-type: + const: 4 + endpoint@1: + properties: + data-lanes: + minItems: 1 + maxItems: 1 + bus-type: + const: 4 + + # Case 2: Single Mode (endpoint@1 is missing) + # We explicitly allow up to 4 lanes here to cover the D-PHY use case. + - if: + not: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 1 + maxItems: 4 + +patternProperties: + "^phy@[0-9a-f]+$": + $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml + unevaluatedProperties: false + + "^opp-table(-.*)?$": + type: object + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + camss: isp@acb7000 { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0x4000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy4", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x18a0 0x0>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + + power-domain-names = "ife0", + "top"; + + vdd-csiphy-0p8-supply = <&csiphy_0p8_supply>; + vdd-csiphy-1p2-supply = <&csiphy_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 644c42b5e2e57..f6a4ee3a73d0e 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -146,7 +146,11 @@ patternProperties: "^audio-codec@[0-9a-f]+$": type: object - $ref: /schemas/sound/qcom,pm8916-wcd-analog-codec.yaml# + oneOf: + - $ref: /schemas/sound/qcom,pm8916-wcd-analog-codec.yaml# + - properties: + compatible: + const: qcom,pm4125-codec "^battery@[0-9a-f]+$": type: object @@ -189,10 +193,18 @@ patternProperties: type: object $ref: /schemas/rtc/qcom-pm8xxx-rtc.yaml# + "^sensor@[0-9a-f]+$": + type: object + $ref: /schemas/hwmon/qcom,bcl-hwmon.yaml# + "^temp-alarm@[0-9a-f]+$": type: object $ref: /schemas/thermal/qcom,spmi-temp-alarm.yaml# + "^temperature-sensor@[0-9a-f]+$": + type: object + $ref: /schemas/thermal/qcom-spmi-mbg-tm.yaml# + "^typec@[0-9a-f]+$": type: object $ref: /schemas/usb/qcom,pmic-typec.yaml# diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml index 7dd2fe035e6d3..fba5ff5283b15 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml @@ -34,6 +34,7 @@ properties: - qcom,sdx55-tcsr - qcom,sdx65-tcsr - qcom,sdx75-tcsr + - qcom,shikra-tcsr - qcom,sm4450-tcsr - qcom,sm6115-tcsr - qcom,sm8150-tcsr diff --git a/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml index bd558a11b7929..b3fcc1673c106 100644 --- a/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml @@ -145,6 +145,11 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 description: platform specific settings for DLL_CONFIG reg. + qcom,ice: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to the Inline Crypto Engine (ICE) hardware block for this controller. + iommus: minItems: 1 maxItems: 8 @@ -198,35 +203,69 @@ allOf: enum: - qcom,sdhci-msm-v4 then: - properties: - reg: - minItems: 2 - items: - - description: Host controller register map - - description: SD Core register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 2 - items: - - const: hc - - const: core - - const: cqhci - - const: ice + if: + required: + - qcom,ice + then: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + else: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + - const: ice else: - properties: - reg: - minItems: 1 - items: - - description: Host controller register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 1 - items: - - const: hc - - const: cqhci - - const: ice + if: + required: + - qcom,ice + then: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + else: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + - const: ice unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml new file mode 100644 index 0000000000000..8e2f15a75d620 --- /dev/null +++ b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/bluetooth/qcom,qcc2072-bt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm QCC2072 Bluetooth + +maintainers: + - Balakrishna Godavarthi + - Rocky Liao + +description: + Qualcomm QCC2072 is a UART-based Bluetooth controller. + +properties: + compatible: + enum: + - qcom,qcc2072-bt + +required: + - compatible + +allOf: + - $ref: bluetooth-controller.yaml# + - $ref: qcom,bluetooth-common.yaml# + - $ref: /schemas/serial/serial-peripheral-props.yaml# + +unevaluatedProperties: false + +examples: + - | + serial { + bluetooth { + compatible = "qcom,qcc2072-bt"; + max-speed = <3200000>; + }; + }; diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml index 28e494262cd92..3a4bcb3e56583 100644 --- a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml +++ b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml @@ -62,6 +62,12 @@ properties: "#gpio-cells": const: 2 +patternProperties: + "^.+-hog(-[0-9]+)?$": + type: object + required: + - gpio-hog + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml index 423959cb928d9..4528946856c8c 100644 --- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml +++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml @@ -32,6 +32,7 @@ properties: - qcom,qcs404-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos + - qcom,shikra-ethqos - qcom,sm8150-ethqos reg: @@ -57,16 +58,30 @@ properties: - const: sfty clocks: - maxItems: 4 + minItems: 4 + maxItems: 7 clock-names: - items: - - const: stmmaceth - - const: pclk - - const: ptp_ref - - enum: - - rgmii - - phyaux + oneOf: + - items: + - const: stmmaceth + - const: pclk + - const: ptp_ref + - enum: + - rgmii + - phyaux + - description: | + Extended clock list for platforms with AXI NOC clocks that require + explicit driver management (e.g. Shikra). GCC_EMAC0_AXI_CLK appears + as both "stmmaceth" and "axi"; CCF refcounting makes this safe. + items: + - const: stmmaceth + - const: pclk + - const: ptp_ref + - const: rgmii + - const: axi + - const: axi-noc + - const: pcie-tile-axi-noc iommus: maxItems: 1 diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml index 2ab047f2bb69d..52b86133ee00d 100644 --- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml +++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml @@ -48,6 +48,7 @@ properties: - qcom,sdm630-qfprom - qcom,sdm670-qfprom - qcom,sdm845-qfprom + - qcom,shikra-qfprom - qcom,sm6115-qfprom - qcom,sm6350-qfprom - qcom,sm6375-qfprom diff --git a/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml b/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml new file mode 100644 index 0000000000000..f9d1dba9dd2e8 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/qcom,shikra-pcie.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Shikra PCI Express Root Complex + +maintainers: + - Bjorn Andersson + - Manivannan Sadhasivam + +description: + Qualcomm Shikra SoC (and compatible) PCIe root complex controller is based on + the Synopsys DesignWare PCIe IP. + +properties: + compatible: + const: qcom,shikra-pcie + + reg: + minItems: 5 + maxItems: 6 + + reg-names: + minItems: 5 + items: + - const: parf # Qualcomm specific registers + - const: dbi # DesignWare PCIe registers + - const: elbi # External local bus interface registers + - const: atu # ATU address space + - const: config # PCIe configuration space + - const: mhi # MHI registers + + clocks: + minItems: 7 + maxItems: 9 + + clock-names: + minItems: 7 + items: + - const: aux # Auxiliary clock + - const: cfg # Configuration clock + - const: bus_master # Master AXI clock + - const: bus_slave # Slave AXI clock + - const: slave_q2a # Slave Q2A clock + - const: ddrss_memnoc_pcie # PCIe SF MEMNOC clock + - const: tile # PCIe tile SYS NoC clock + - const: qmip_pcie_ahb # QMIP PCIe AHB clock + + interrupts: + minItems: 8 + maxItems: 9 + + interrupt-names: + minItems: 8 + items: + - const: msi0 + - const: msi1 + - const: msi2 + - const: msi3 + - const: msi4 + - const: msi5 + - const: msi6 + - const: msi7 + - const: global + + resets: + minItems: 1 + maxItems: 2 + + reset-names: + minItems: 1 + items: + - const: pci # PCIe core reset + - const: link_down # PCIe link down reset + +required: + - power-domains + - resets + - reset-names + +allOf: + - $ref: qcom,pcie-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + pcie@45e8000 { + device_type = "pci"; + compatible = "qcom,shikra-pcie"; + reg = <0x0 0x045e8000 0x0 0x3000>, + <0x0 0x60000000 0x0 0xf1d>, + <0x0 0x60000f20 0x0 0xa8>, + <0x0 0x60001000 0x0 0x1000>, + <0x0 0x60100000 0x0 0x100000>, + <0x0 0x045eb000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>, + <0x03000000 0x4 0x00000000 0x4 0x00000000 0x3 0x0000000>; + bus-range = <0x00 0xff>; + + linux,pci-domain = <0>; + num-lanes = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + interrupt-map = <0 0 0 1 &intc 0 0 0 499 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 500 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 501 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 502 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_SLV_AXI_CLK>, + <&gcc GCC_PCIE_SLV_Q2A_AXI_CLK>, + <&gcc GCC_DDRSS_MEMNOC_PCIE_SF_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>, + <&gcc GCC_QMIP_PCIE_CFG_AHB_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ddrss_memnoc_pcie", + "tile", + "qmip_pcie_ahb"; + + assigned-clocks = <&gcc GCC_PCIE_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&system_noc MASTER_PCIE2_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_PCIE2_0 RPM_ACTIVE_TAG>; + + interconnect-names = "pcie-mem", + "cpu-pcie"; + + iommu-map = <0x0 &apps_smmu 0x800 0x1>, + <0x100 &apps_smmu 0x801 0x1>; + + resets = <&gcc GCC_PCIE_BCR>; + reset-names = "pci"; + + power-domains = <&gcc GCC_PCIE_GDSC>; + + max-link-speed = <2>; + + operating-points-v2 = <&pcie_opp_table>; + + status = "disabled"; + + pcie_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml index b3ad05d90201c..f9f71f28aa92b 100644 --- a/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml +++ b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml @@ -26,6 +26,11 @@ properties: reg: maxItems: 1 + gpio-controller: true + + '#gpio-cells': + const: 2 + resx-gpios: maxItems: 1 description: @@ -69,6 +74,17 @@ $defs: type: object properties: + reset-gpios: + description: + Specify the TC9563 GPIO used to reset the endpoint + connected to the particular TC9563 downstream port. + + ep-pwr-en-gpios: + description: + Specify the TC9563 GPIO used for enabling power to + the endpoint connected to the particular TC9563 + downstream port. + toshiba,tx-amplitude-microvolt: description: Change Tx Margin setting for low power consumption. @@ -104,7 +120,7 @@ examples: #address-cells = <3>; #size-cells = <2>; - pcie@0 { + tc9563: pcie@0 { device_type = "pci"; reg = <0x0 0x0 0x0 0x0 0x0>; @@ -120,6 +136,7 @@ examples: device_type = "pci"; #address-cells = <3>; #size-cells = <2>; + #gpio-cells = <2>; ranges; bus-range = <0x02 0xff>; @@ -154,6 +171,9 @@ examples: device_type = "pci"; ranges; bus-range = <0x04 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tc9563 5 GPIO_ACTIVE_LOW>; }; pcie@3,0 { diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml index 1636285fbe535..8402fe4a96e03 100644 --- a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml @@ -20,6 +20,7 @@ properties: - qcom,qcm2290-qmp-usb3-phy - qcom,qcs615-qmp-usb3-phy - qcom,sdm660-qmp-usb3-phy + - qcom,shikra-qmp-usb3-phy - qcom,sm6115-qmp-usb3-phy reg: @@ -116,6 +117,7 @@ allOf: contains: enum: - qcom,qcm2290-qmp-usb3-phy + - qcom,shikra-qmp-usb3-phy - qcom,sm6115-qmp-usb3-phy then: properties: diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml index 449c2a7e5fecf..001fd0ccc9852 100644 --- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml @@ -28,6 +28,7 @@ properties: - qcom,qcm2290-qusb2-phy - qcom,qcs615-qusb2-phy - qcom,sdm660-qusb2-phy + - qcom,shikra-qusb2-phy - qcom,sm4250-qusb2-phy - qcom,sm6115-qusb2-phy - items: diff --git a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml index 90fc8c039219c..0a1330b9118d6 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml @@ -36,6 +36,10 @@ properties: description: Phandle to a regulator that provides power to the PHY. + vdda-0p9-supply: + description: + Phandle to a 0.9V regulator supply to the PHY. + "#phy-cells": const: 0 diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml index 108cf9dc86ea0..1190588ff91f3 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml @@ -20,6 +20,7 @@ properties: - qcom,eliza-qmp-gen3x2-pcie-phy - qcom,glymur-qmp-gen4x2-pcie-phy - qcom,glymur-qmp-gen5x4-pcie-phy + - qcom,glymur-qmp-gen5x8-pcie-phy - qcom,kaanapali-qmp-gen3x2-pcie-phy - qcom,qcs615-qmp-gen3x1-pcie-phy - qcom,qcs8300-qmp-gen4x2-pcie-phy @@ -34,6 +35,7 @@ properties: - qcom,sdm845-qmp-pcie-phy - qcom,sdx55-qmp-pcie-phy - qcom,sdx65-qmp-gen4x2-pcie-phy + - qcom,shikra-qmp-gen2x1-pcie-phy - qcom,sm8150-qmp-gen3x1-pcie-phy - qcom,sm8150-qmp-gen3x2-pcie-phy - qcom,sm8250-qmp-gen3x1-pcie-phy @@ -70,20 +72,23 @@ properties: - const: ref - enum: [rchng, refgen] - const: pipe - - const: pipediv2 + - enum: [phy_b_aux, pipediv2] power-domains: - maxItems: 1 + minItems: 1 + maxItems: 2 resets: minItems: 1 - maxItems: 2 + maxItems: 4 reset-names: minItems: 1 items: - const: phy - const: phy_nocsr + - const: phy_b + - const: phy_b_nocsr vdda-phy-supply: true @@ -166,6 +171,7 @@ allOf: - qcom,sdm845-qhp-pcie-phy - qcom,sdm845-qmp-pcie-phy - qcom,sdx55-qmp-pcie-phy + - qcom,shikra-qmp-gen2x1-pcie-phy - qcom,sm8150-qmp-gen3x1-pcie-phy - qcom,sm8150-qmp-gen3x2-pcie-phy - qcom,sm8250-qmp-gen3x1-pcie-phy @@ -196,6 +202,7 @@ allOf: - qcom,eliza-qmp-gen3x2-pcie-phy - qcom,glymur-qmp-gen4x2-pcie-phy - qcom,glymur-qmp-gen5x4-pcie-phy + - qcom,glymur-qmp-gen5x8-pcie-phy - qcom,qcs8300-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x2-pcie-phy - qcom,sa8775p-qmp-gen4x4-pcie-phy @@ -214,6 +221,17 @@ allOf: clock-names: minItems: 6 + - if: + properties: + compatible: + contains: + enum: + - qcom,glymur-qmp-gen5x8-pcie-phy + then: + properties: + power-domains: + minItems: 2 + - if: properties: compatible: @@ -238,11 +256,24 @@ allOf: reset-names: minItems: 2 else: - properties: - resets: - maxItems: 1 - reset-names: - maxItems: 1 + if: + properties: + compatible: + contains: + enum: + - qcom,glymur-qmp-gen5x8-pcie-phy + then: + properties: + resets: + minItems: 4 + reset-names: + minItems: 4 + else: + properties: + resets: + maxItems: 1 + reset-names: + maxItems: 1 - if: properties: diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml new file mode 100644 index 0000000000000..63114151104b4 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm CSI2 PHY + +maintainers: + - Bryan O'Donoghue + +description: + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY + modes. + +properties: + compatible: + const: qcom,x1e80100-csi2-phy + + reg: + maxItems: 1 + + "#phy-cells": + const: 1 + description: + The single cell specifies the PHY operating mode. + See include/dt-bindings/phy/phy-qcom-mipi-csi2.h for valid values. + + clocks: + maxItems: 2 + + clock-names: + items: + - const: core + - const: timer + + interrupts: + maxItems: 1 + + operating-points-v2: + maxItems: 1 + + power-domains: + items: + - description: MXC or MXA voltage rail + - description: MMCX voltage rail + + power-domain-names: + items: + - const: mx + - const: mmcx + + vdda-0p9-supply: + description: Phandle to a 0.9V regulator supply to a PHY. + + vdda-1p2-supply: + description: Phandle to 1.2V regulator supply to a PHY. + +required: + - compatible + - reg + - "#phy-cells" + - clocks + - clock-names + - interrupts + - operating-points-v2 + - power-domains + - power-domain-names + - vdda-0p9-supply + - vdda-1p2-supply + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + csiphy4: csiphy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0x0ace4000 0x2000>; + #phy-cells = <1>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + }; + + csiphy_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + isp@acb7000 { + phys = <&csiphy4 PHY_QCOM_CSI2_MODE_DPHY>; + }; diff --git a/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml new file mode 100644 index 0000000000000..4c6e6cbfbfe40 --- /dev/null +++ b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/limits/qcom,spel.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SoC Power and Electrical Limits (SPEL) + +maintainers: + - Manaf Meethalavalappu Pallikunhi + +description: + The Qualcomm SPEL (SoC Power and Electrical Limits) provides hardware-based + power monitoring and limiting capabilities for various power domains in + Qualcomm SoCs. + +properties: + compatible: + const: qcom,glymur-spel + + reg: + maxItems: 3 + + reg-names: + items: + - const: config + - const: constraints + - const: nodes + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + power-limits@ef3b000 { + compatible = "qcom,glymur-spel"; + reg = <0x0ef3b000 0x1000>, + <0x0ef3d000 0x1000>, + <0x0ef3e000 0x1000>; + reg-names = "config", + "constraints", + "nodes"; + }; diff --git a/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml b/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml new file mode 100644 index 0000000000000..092e267e29da4 --- /dev/null +++ b/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ptp/qcom,tsc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Timestamp Counter Subsystem (TSCSS) + +maintainers: + - Imran Shaik + - Taniya Das + +description: + Qualcomm TSCSS is a time synchronization subsystem composed of two main + blocks - the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU). + + The TSC block is a timestamp generator that maintains a running counter used + for system timekeeping. The ETU block captures timestamps for external events + using one of the available timestamp sources. + +properties: + compatible: + enum: + - qcom,tsc + + reg: + maxItems: 2 + + reg-names: + items: + - const: tsc + - const: etu + + clocks: + items: + - description: TSC AHB clock + - description: TSC cntr clock + - description: TSC ETU clock + + clock-names: + items: + - const: cfg_ahb + - const: cntr + - const: etu + + interrupts: + maxItems: 1 + + interrupt-names: + items: + - const: etu_summary_irq + + qcom,tsc-nsec-update: + description: + Indicates the TSC counters have values in nanoseconds, rather than + in secs and nanoseconds. + type: boolean + + qcom,etu-slice: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of ETU slice numbers corresponding to the ETU sel. + In case this property is not defined the sel number will be + considered as the slice number for ETU offset calculation. + + qcom,etu-event-sel: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of ETU event sel numbers for the corresponding ETU slice + numbers. + + qcom,etu-event-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + ETU event sel names for the corresponding event sel numbers. + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + #include + tsc: tsc@1c80000 { + compatible = "qcom,tsc"; + reg = <0x01c80000 0x2000>, + <0x01ca0000 0x20000>; + reg-names = "tsc", "etu"; + clocks = <&tscss_ahb_clock>, <&tscss_cntr_clock>, + <&tscss_cntr_clock>; + clock-names = "cfg_ahb", "cntr", "etu"; + interrupts = ; + interrupt-names = "etu_summary_irq"; + qcom,etu-slice = <10 11>; + qcom,etu-event-sel = <10 11>; + qcom,etu-event-names = "gps_pps", "tod_pps"; + qcom,tsc-nsec-update; + }; diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml index fcefc722ee2a4..024b34d0eb1a6 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml @@ -14,17 +14,21 @@ description: | regulator will be enabled in situations where the device is required to provide power to the connected peripheral. -allOf: - - $ref: regulator.yaml# + The pm8150b variant uses an OTG current-limit selector, supporting limits + of 500 mA, 1000 mA, 1500 mA, 2000 mA, 2500 mA and 3000 mA. + + The pm4125 variant uses a different register layout with a 2-bit VBOOST + voltage selector supporting output voltages of 4.25 V, 4.5 V, 4.75 V + and 5.0 V. properties: compatible: oneOf: - enum: - qcom,pm8150b-vbus-reg + - qcom,pm4125-vbus-reg - items: - enum: - - qcom,pm4125-vbus-reg - qcom,pm6150-vbus-reg - qcom,pm7250b-vbus-reg - qcom,pmi632-vbus-reg @@ -34,11 +38,35 @@ properties: maxItems: 1 description: VBUS output base address +allOf: + - $ref: regulator.yaml# + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8150b-vbus-reg + - qcom,pm6150-vbus-reg + - qcom,pm7250b-vbus-reg + - qcom,pmi632-vbus-reg + then: + required: + - regulator-min-microamp + - regulator-max-microamp + + - if: + properties: + compatible: + contains: + const: qcom,pm4125-vbus-reg + then: + required: + - regulator-min-microvolt + - regulator-max-microvolt + required: - compatible - reg - - regulator-min-microamp - - regulator-max-microamp unevaluatedProperties: false @@ -55,4 +83,16 @@ examples: regulator-max-microamp = <3000000>; }; }; + - | + pmic { + #address-cells = <1>; + #size-cells = <0>; + + usb-vbus-regulator@1100 { + compatible = "qcom,pm4125-vbus-reg"; + reg = <0x1100>; + regulator-min-microvolt = <4250000>; + regulator-max-microvolt = <5000000>; + }; + }; ... diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 16a245fe2738d..7e8ecae8e6cb6 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -32,6 +32,14 @@ properties: reg: maxItems: 1 + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + cx-supply: true px-supply: @@ -49,6 +57,30 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + + interrupt-names: + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - memory-region @@ -57,56 +89,6 @@ unevaluatedProperties: false allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# - - if: - properties: - compatible: - contains: - enum: - - qcom,msm8226-adsp-pil - - qcom,msm8953-adsp-pil - - qcom,msm8974-adsp-pil - - qcom,msm8996-adsp-pil - - qcom,msm8996-slpi-pil - - qcom,msm8998-adsp-pas - - qcom,msm8998-slpi-pas - - qcom,sdm660-adsp-pas - - qcom,sdm660-cdsp-pas - - qcom,sdm845-adsp-pas - - qcom,sdm845-cdsp-pas - - qcom,sdm845-slpi-pas - then: - properties: - clocks: - items: - - description: XO clock - clock-names: - items: - - const: xo - - - if: - properties: - compatible: - contains: - enum: - - qcom,msm8226-adsp-pil - - qcom,msm8953-adsp-pil - - qcom,msm8974-adsp-pil - - qcom,msm8996-adsp-pil - - qcom,msm8996-slpi-pil - - qcom,msm8998-adsp-pas - - qcom,msm8998-slpi-pas - - qcom,sdm660-adsp-pas - - qcom,sdm660-cdsp-pas - - qcom,sdm845-adsp-pas - - qcom,sdm845-cdsp-pas - - qcom,sdm845-slpi-pas - then: - properties: - interrupts: - maxItems: 5 - interrupt-names: - maxItems: 5 - - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml new file mode 100644 index 0000000000000..ce18460a949fc --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/qcom,kaanapali-soccp-pas.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali SoCCP Peripheral Authentication Service + +maintainers: + - Jingyi Wang + +description: + The SoC Control Processor (SoCCP) is a small RISC-V MCU that controls USB + Type-C, battery charging and various other functions on Qualcomm SoCs, somewhat + analogous to traditional PC Embedded Controllers. This document describes + the Peripheral Authentication Service that loads and boots firmware for SoCCP. + +properties: + compatible: + oneOf: + - items: + - enum: + - qcom,glymur-soccp-pas + - const: qcom,kaanapali-soccp-pas + - enum: + - qcom,kaanapali-soccp-pas + + reg: + maxItems: 1 + + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + + power-domains: + items: + - description: CX power domain + - description: MX power domain + + power-domain-names: + items: + - const: cx + - const: mx + + firmware-name: + items: + - description: Firmware name of the SoC Control Processor + - description: Firmware name of the SoCCP Devicetree + + memory-region: + items: + - description: Memory region for main Firmware authentication + - description: Memory region for Devicetree Firmware authentication + + interrupts: + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Pong interrupt + + interrupt-names: + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: pong + + qcom,smem-states: + minItems: 2 + description: States used by the AP to signal the SoC Control Processor + + qcom,smem-state-names: + minItems: 2 + description: The names of the state bits used for SMP2P output + +required: + - compatible + - reg + - memory-region + - power-domains + - power-domain-names + +allOf: + - $ref: /schemas/remoteproc/qcom,pas-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #define IPCC_MPROC_SOCCP + + remoteproc@d00000 { + compatible = "qcom,kaanapali-soccp-pas"; + reg = <0x00d00000 0x200000>; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + interrupts-extended = <&intc GIC_SPI 167 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "pong"; + + memory-region = <&soccp_mem>, + <&soccp_dtb_mem_mem>; + + firmware-name = "qcom/kaanapali/soccp.mbn", + "qcom/kaanapali/soccp_dtb.mbn"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; + + qcom,smem-states = <&soccp_smp2p_out 0>, + <&soccp_smp2p_out 8>; + qcom,smem-state-names = "stop", + "ping"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "soccp"; + qcom,remote-pid = <19>; + + /* ... */ + }; + }; diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml index e5cce0d05fc69..99d7337e58ec5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml @@ -34,12 +34,22 @@ properties: - const: xo interrupts: - minItems: 6 - maxItems: 6 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt interrupt-names: - minItems: 6 - maxItems: 6 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack qcom,qmp: $ref: /schemas/types.yaml#/definitions/phandle @@ -59,6 +69,14 @@ properties: - description: Memory region for core Firmware authentication - description: Memory region for Devicetree Firmware authentication + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index 4607b459131b4..6e483b8b1f223 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -26,23 +26,11 @@ properties: interrupts: minItems: 5 - items: - - description: Watchdog interrupt - - description: Fatal interrupt - - description: Ready interrupt - - description: Handover interrupt - - description: Stop acknowledge interrupt - - description: Shutdown acknowledge interrupt + maxItems: 6 interrupt-names: minItems: 5 - items: - - const: wdog - - const: fatal - - const: ready - - const: handover - - const: stop-ack - - const: shutdown-ack + maxItems: 6 iommus: maxItems: 1 @@ -58,19 +46,23 @@ properties: qcom,smem-states: $ref: /schemas/types.yaml#/definitions/phandle-array description: States used by the AP to signal the Hexagon core + minItems: 1 items: - - description: Stop the modem + - description: Stop the remoteproc items: - description: Phandle to the Shared Memory Point 2 Point device handling the communication with a remote processor - description: Single bit index to toggle in the value sent to the remote processor maximum: 32 + - description: ping the remoteproc qcom,smem-state-names: description: The names of the state bits used for SMP2P output + minItems: 1 items: - const: stop + - const: ping smd-edge: $ref: /schemas/remoteproc/qcom,smd-edge.yaml# @@ -79,6 +71,20 @@ properties: channels and devices related to the ADSP. unevaluatedProperties: false + '#cooling-cells': + description: + Number of cooling cells; 2 for min/max cooling state and 3 when + selecting a thermal mitigation device index. + enum: [2, 3] + + tmd-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + Names of the thermal mitigation devices available in remote processor + subsystem. + minItems: 1 + maxItems: 5 + glink-edge: $ref: /schemas/remoteproc/qcom,glink-edge.yaml# description: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml index ad45fd00ae346..bf9bf1af9ff14 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml @@ -32,10 +32,20 @@ properties: - const: xo interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack power-domains: false power-domain-names: false @@ -49,6 +59,14 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml index bcd2bcf96e246..dda2d144b7206 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml @@ -59,10 +59,28 @@ properties: - description: Memory region for main Firmware authentication interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output required: - compatible diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml index 66b455d0a8e32..b20780e5e26bd 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml @@ -48,6 +48,34 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml index 8227527c1d770..4bbe4a986c7c5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml @@ -45,6 +45,34 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml index 8c4abde749150..8c16b01c53e42 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml @@ -30,10 +30,22 @@ properties: - const: xo interrupts: - minItems: 6 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt interrupt-names: - minItems: 6 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack power-domains: items: @@ -59,6 +71,14 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml index eeb6a8aafeb92..454ba82bd6f18 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml @@ -51,6 +51,34 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml index c1a3cc308bdb2..42e02c64347a0 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml @@ -45,6 +45,34 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml index 7286b2baa19f2..274f87880e2e6 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml @@ -39,8 +39,36 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + smd-edge: false + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index a8cddf7e2fe1a..5a7c5f8c92d17 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -61,6 +61,34 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml index 6d09823153fc8..72d0db5698c5c 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml @@ -55,6 +55,34 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 9f30a38152a38..faf7b2890de8d 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -75,6 +75,34 @@ properties: - description: DSM Memory region 2 - description: Memory region for Qlink Logging + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml index e51acdcaafaf6..01250b556985b 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml @@ -120,7 +120,9 @@ allOf: properties: qcom,glink-channels: items: - - const: adsp_apps + - enum: + - adsp_apps + - modem_apps power-domains: false else: properties: diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 84218636c0d8d..12560342f37fb 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -32,18 +32,27 @@ properties: ports: $ref: /schemas/graph.yaml#/properties/ports description: - These ports is to be attached to the endpoint of the DWC3 controller node - and type C connector node. The controller has the "usb-role-switch" - property. + These ports attach to endpoints of DWC3 controller nodes and Type-C + connector nodes. The controller has the "usb-role-switch" property. + EUD supports up to 2 USB ports. For single-port configurations, use + port@0 and port@1. For dual-port configurations, use all four ports. properties: port@0: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the DWC3 controller. + description: This port is to be attached to the primary DWC3 controller. port@1: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the type C connector. + description: This port is to be attached to the primary Type-C connector. + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the secondary DWC3 controller. + + port@3: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the secondary Type-C connector. required: - compatible diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index 270bcd079f886..bd1d32898461c 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -57,6 +57,7 @@ properties: - qcom,rpm-qcm2290 - qcom,rpm-qcs404 - qcom,rpm-sdm660 + - qcom,rpm-shikra - qcom,rpm-sm6115 - qcom,rpm-sm6125 - qcom,rpm-sm6375 diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 2eed2277511f8..07fe0dc51801b 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -19,6 +19,7 @@ properties: - qcom,sm8450-lpass-rx-macro - qcom,sm8550-lpass-rx-macro - qcom,sc8280xp-lpass-rx-macro + - qcom,shikra-lpass-rx-macro - items: - enum: - qcom,kaanapali-lpass-rx-macro diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index 5c42b2b323ee4..d43adaa2fbff9 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -19,6 +19,7 @@ properties: - qcom,sm8450-lpass-va-macro - qcom,sm8550-lpass-va-macro - qcom,sc8280xp-lpass-va-macro + - qcom,shikra-lpass-va-macro - items: - enum: - qcom,glymur-lpass-va-macro diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml index 9e5b30d9c6e62..4daa3d26b7ab6 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml @@ -17,12 +17,49 @@ properties: const: qcom,q6apm-dais iommus: + description: + IOMMU mappings for the PCM DMA window. Required on platforms where + audio buffers are HLOS-allocated and mapped through an IOMMU (ADSP/ + LPASS path). Omit on platforms where buffers are allocated from a + reserved memory carveout with no IOMMU mapping. minItems: 1 maxItems: 2 + memory-region: + description: + Optional reserved DMA pool for PCM buffers on platforms where the q6apm + DMA buffer must come from a predefined carveout. + maxItems: 1 + + qcom,src-vmid: + description: + Optional VMID that TrustZone currently tracks as the owner of the PCM + DMA buffer before qcom_scm_assign_mem() is called. When absent the + driver defaults to QCOM_SCM_VMID_HLOS (0x3), which is correct for + normal HLOS-allocated memory. Platforms where the buffer resides in + S2-only memory pre-owned by a non-HLOS VMID (e.g. QCOM_SCM_VMID_LPASS + on the mDSP audio path) must set this so the srcvm argument matches + what TZ tracks, otherwise the SCM call is rejected with -EINVAL. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 31 + + qcom,vmid: + description: + Optional list of destination VMIDs to share PCM DMA buffers with when + SCM memory reassignment is required. For reserved memory regions the + full region is reassigned to this destination VMID list. For non-reserved + DMA buffers, HLOS is also kept as a destination so the CPU retains RW + access. Do not list HLOS here. + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + minimum: 1 + maximum: 31 + minItems: 1 + maxItems: 8 + required: - compatible - - iommus additionalProperties: false @@ -32,3 +69,22 @@ examples: compatible = "qcom,q6apm-dais"; iommus = <&apps_smmu 0x1801 0x0>; }; + - | + /* Reserved-memory mDSP path: no IOMMU, carveout shared with DSP VMIDs */ + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + audio_carveout_mem: audio-carveout@86200000 { + compatible = "shared-dma-pool"; + no-map; + reg = <0x0 0x86200000 0x0 0x40000>; + }; + }; + + dais { + compatible = "qcom,q6apm-dais"; + memory-region = <&audio_carveout_mem>; + qcom,vmid = <0xf 0x16>; + }; diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml index 2fb95544db8b5..1a17930760804 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml @@ -21,15 +21,57 @@ properties: '#sound-dai-cells': const: 1 + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + +patternProperties: + '^dai@[0-9]+$': + type: object + description: + Optional per-DAI clock description for LPASS backends. + + properties: + reg: + description: + Digital Audio Interface ID. + + clocks: + minItems: 1 + maxItems: 3 + + clock-names: + description: + Supported names are `mclk`, `bclk` and `eclk` depending on the + interface clock required by the backend. + minItems: 1 + maxItems: 3 + + additionalProperties: false + required: - compatible - '#sound-dai-cells' +additionalProperties: false + unevaluatedProperties: false examples: - | + #include + dais { compatible = "qcom,q6apm-lpass-dais"; + #address-cells = <1>; + #size-cells = <0>; #sound-dai-cells = <1>; + + dai@0 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk"; + }; }; diff --git a/Documentation/devicetree/bindings/sound/qcom,shikra-qaif.yaml b/Documentation/devicetree/bindings/sound/qcom,shikra-qaif.yaml new file mode 100644 index 0000000000000..640dc5f86b198 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,shikra-qaif.yaml @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,shikra-qaif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Audio Interface on Shikra + +maintainers: + - Qualcomm Innovation Center, Inc. + +description: + Qualcomm Audio Interface CPU DAI controller used by the Shikra audio core. + +properties: + compatible: + const: qcom,shikra-qaif-cpu + + reg: + maxItems: 1 + + reg-names: + const: audio-qaif-core + + iommus: + maxItems: 1 + + clocks: + minItems: 15 + maxItems: 15 + + clock-names: + items: + - const: gcc_lpass_config_clk + - const: gcc_lpass_core_axim_clk + - const: audio_core_cc_aud_dma_clk + - const: audio_core_cc_aud_dma_mem_clk + - const: audio_core_cc_bus_clk + - const: audio_core_cc_aif_if0_ebit_clk + - const: audio_core_cc_aif_if0_ibit_clk + - const: audio_core_cc_aif_if1_ebit_clk + - const: audio_core_cc_aif_if1_ibit_clk + - const: audio_core_cc_aif_if2_ebit_clk + - const: audio_core_cc_aif_if2_ibit_clk + - const: audio_core_cc_aif_if3_ebit_clk + - const: audio_core_cc_aif_if3_ibit_clk + - const: audio_core_cc_ext_mclka_clk + - const: audio_core_cc_ext_mclkb_clk + + interrupts: + maxItems: 1 + + interrupt-names: + const: qaif-irq-audio-core + + '#sound-dai-cells': + const: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + aif-interface: + $ref: /schemas/types.yaml#/definitions/phandle + description: TDM/MI2S interface configuration referenced by this controller. + +required: + - compatible + - reg + - reg-names + - iommus + - clocks + - clock-names + - interrupts + - interrupt-names + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | + #include + #include + #include + + audio@a000000 { + compatible = "qcom,shikra-qaif-cpu"; + reg = <0x0a000000 0x20000>; + reg-names = "audio-qaif-core"; + iommus = <&apps_smmu 0x1c0 0x0>; + clocks = <&gcc 0>, <&gcc 1>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_MEM_CLK>, + <&audiocorecc AUDIO_CORE_CC_BUS_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK>; + clock-names = "gcc_lpass_config_clk", "gcc_lpass_core_axim_clk", + "audio_core_cc_aud_dma_clk", + "audio_core_cc_aud_dma_mem_clk", + "audio_core_cc_bus_clk", + "audio_core_cc_aif_if0_ebit_clk", + "audio_core_cc_aif_if0_ibit_clk", + "audio_core_cc_aif_if1_ebit_clk", + "audio_core_cc_aif_if1_ibit_clk", + "audio_core_cc_aif_if2_ebit_clk", + "audio_core_cc_aif_if2_ibit_clk", + "audio_core_cc_aif_if3_ebit_clk", + "audio_core_cc_aif_if3_ibit_clk", + "audio_core_cc_ext_mclka_clk", + "audio_core_cc_ext_mclkb_clk"; + interrupts = ; + interrupt-names = "qaif-irq-audio-core"; + #sound-dai-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 15f38622b98b9..f224e84919cdb 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -45,6 +45,7 @@ properties: - qcom,sc7180-qdsp6-sndcard - qcom,sc8280xp-sndcard - qcom,sdm845-sndcard + - qcom,shikra-sndcard - qcom,sm8250-sndcard - qcom,sm8450-sndcard - qcom,x1e80100-sndcard @@ -63,6 +64,11 @@ properties: List of phandles pointing to auxiliary devices, such as amplifiers, to be added to the sound card. + qcom,adsp-bypass-mode: + type: boolean + description: + Indicates the platform is configured for ADSP bypass mode. + model: $ref: /schemas/types.yaml#/definitions/string description: User visible long sound card name diff --git a/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml b/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml new file mode 100644 index 0000000000000..69af511a400ea --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,wsa885x-i2c.yaml @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,wsa885x-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm WSA885X I2C smart speaker amplifier + +maintainers: + - Srinivas Kandagatla + +allOf: + - $ref: dai-common.yaml# + +description: | + WSA885X is a Qualcomm smart speaker amplifier codec. + This binding describes the I2C control interface and + board-level resources required by the codec. + +properties: + compatible: + const: qcom,wsa885x-i2c + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + powerdown-gpios: + description: GPIO spec for the codec shutdown/powerdown pin. + maxItems: 1 + + interrupt-gpios: + description: GPIO spec for the codec interrupt pin. + maxItems: 1 + + vdd-io-supply: + description: 1.8V I/O supply. + + vdd-1p8-supply: + description: 1.8V analog/digital core supply. + + qcom,battery_config: + deprecated: true + description: Battery topology configuration. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2] + + qcom,battery-config: + description: Speaker battery configuration, 1 for 1S and 2S. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2] + + wsa885x-init-table: + description: Register/value initialization table as pairs. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 512 + + qcom,wsa885x-init-table: + description: Register/value initialization table as pairs. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 256 + +required: + - compatible + - reg + - '#sound-dai-cells' + - vdd-io-supply + - vdd-1p8-supply + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + speaker-codec@c { + compatible = "qcom,wsa885x-i2c"; + reg = <0x0c>; + #sound-dai-cells = <0>; + + qcom,battery_config = <1>; + + powerdown-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + interrupt-gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; + + vdd-io-supply = <&vreg_l15a_1p8>; + vdd-1p8-supply = <&vreg_l10a_1p8>; + + wsa885x-init-table = < + 0x800d 0x1c + 0x8090 0x1f + >; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml index 9447a2f371b56..5b06cc1a5f781 100644 --- a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml +++ b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml @@ -215,6 +215,12 @@ properties: maximum: 4 - const: 0xff + qcom,swr-master-ee-val: + $ref: /schemas/types.yaml#/definitions/uint8-array + description: + Execution-environment value used to route SoundWire master + interrupts to CPU0 or CPU1. + label: maxItems: 1 diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml index c63026904061d..2eb7566afef38 100644 --- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml +++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml @@ -36,6 +36,7 @@ properties: - qcom,sdx55-imem - qcom,sdx65-imem - qcom,sdx75-imem + - qcom,shikra-imem - qcom,sm6115-imem - qcom,sm6125-imem - qcom,sm6350-imem diff --git a/Documentation/devicetree/bindings/thermal/qcom-spmi-mbg-tm.yaml b/Documentation/devicetree/bindings/thermal/qcom-spmi-mbg-tm.yaml new file mode 100644 index 0000000000000..a0ecc9f35cf6e --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/qcom-spmi-mbg-tm.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/thermal/qcom-spmi-mbg-tm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm's SPMI PMIC MBG Thermal Monitoring + +maintainers: + - Jishnu Prakash + - Kamal Wadhwa + +description: + Qualcomm's MBG(Master Bandgap) temperature alarm monitors the die + temperature and generates an interrupt if the PMIC die temperature is + over a set of programmable temperature thresholds. It allows monitoring + for both hot and cold, LVL1 and LVL2 thresholds, which makes it different + from the existing temp alarm peripheral. The interrupt comes over SPMI + and the MBG's fault status register gives details to understand whether + it is a hot/cold and LVL1/LVL2 violation. + +properties: + compatible: + const: qcom,pm8775-mbg-tm + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + io-channels: + items: + - description: ADC channel, which reports chip die temperature. + + io-channel-names: + items: + - const: thermal + + '#thermal-sensor-cells': + const: 0 + +required: + - compatible + - reg + - interrupts + - io-channels + - io-channel-names + +allOf: + - $ref: thermal-sensor.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + temperature-sensor@d700 { + compatible = "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts = <0x1 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pm8775_adc 0x3>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml index e8b8c03f87a0e..eb51c35059dc9 100644 --- a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml +++ b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml @@ -87,6 +87,17 @@ allOf: peer-hub: true vdd-supply: true + - if: + properties: + compatible: + contains: + enum: + - usb5e3,625 + then: + properties: + peer-hub: true + vdd-supply: false + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index a7f58114c02e8..2e2d4562fb03c 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml @@ -227,6 +227,7 @@ allOf: - qcom,sdx65-dwc3 - qcom,sdx75-dwc3 - qcom,sm6350-dwc3 + - qcom,sm8750-dwc3 then: properties: clocks: @@ -366,7 +367,6 @@ allOf: - qcom,sm8450-dwc3 - qcom,sm8550-dwc3 - qcom,sm8650-dwc3 - - qcom,sm8750-dwc3 then: properties: clocks: diff --git a/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml index 8201656b41ed7..d5368b423a9ac 100644 --- a/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,snps-dwc3.yaml @@ -60,6 +60,7 @@ properties: - qcom,sdx55-dwc3 - qcom,sdx65-dwc3 - qcom,sdx75-dwc3 + - qcom,shikra-dwc3 - qcom,sm4250-dwc3 - qcom,sm6115-dwc3 - qcom,sm6125-dwc3 @@ -358,6 +359,7 @@ allOf: - qcom,sar2130p-dwc3 - qcom,sc8180x-dwc3 - qcom,sc8180x-dwc3-mp + - qcom,shikra-dwc3 - qcom,sm4250-dwc3 - qcom,sm6115-dwc3 - qcom,sm6125-dwc3 @@ -434,6 +436,7 @@ allOf: - qcom,ipq8074-dwc3 - qcom,msm8953-dwc3 - qcom,msm8998-dwc3 + - qcom,shikra-dwc3 then: properties: interrupts: diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index 5d9bf4694d5d0..9cd1e0b5af6da 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst @@ -72,6 +72,7 @@ interactions and system performance. intel_th stm sys-t + p_ost coresight/index rv/index hisi-ptt diff --git a/Documentation/trace/p_ost.rst b/Documentation/trace/p_ost.rst new file mode 100644 index 0000000000000..2b92e22296539 --- /dev/null +++ b/Documentation/trace/p_ost.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +MIPI OST over STP +=================== + +The OST (Open System Trace) driver is used with STM class devices to +generate standardized trace stream. Trace sources can be identified +by different entity IDs. + +CONFIG_STM_PROTO_OST is for p_ost driver enablement. Once this config +is enabled, you can select the p_ost protocol by command below: + +# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy + +The policy name format is extended like this: + + :. + +With a coresight-stm device, it will look like "stm0:p_ost.policy". + +With the MIPI OST protocol driver, the attributes for each protocol node are: + +# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy/default +# ls /sys/kernel/config/stp-policy/stm0:p_ost.policy/default +channels entity masters + +The entity here is the set of entities that p_ost supports. Currently +p_ost supports ftrace, console and diag entities. + +Set entity: +# echo 'ftrace' > /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity + +Get available and currently selected (shown in square brackets) entity: +# cat /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity +[ftrace] console diag + +See Documentation/ABI/testing/configfs-stp-policy-p_ost for more details. + diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a99..df8f45b22d4a5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -340,6 +340,17 @@ S: Maintained F: drivers/acpi/arm64 F: include/linux/acpi_iort.h +ACPI AEST +M: Ruidong Tian +L: linux-acpi@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org +S: Supported +F: Documentation/ABI/testing/debugfs-aest +F: arch/arm64/include/asm/ras.h +F: drivers/acpi/arm64/aest.c +F: drivers/ras/aest/ +F: include/linux/acpi_aest.h + ACPI FOR RISC-V (ACPI/riscv) M: Sunil V L L: linux-acpi@vger.kernel.org @@ -8024,6 +8035,13 @@ S: Maintained F: Documentation/devicetree/bindings/display/bridge/chipone,icn6211.yaml F: drivers/gpu/drm/bridge/chipone-icn6211.c +DRM DRIVER FOR DLC DLC0697 DSI PANEL +M: Arpit Saini +S: Maintained +T: git https://gitlab.freedesktop.org/drm/misc/kernel.git +F: Documentation/devicetree/bindings/display/panel/dlc,dlc0697.yaml +F: drivers/gpu/drm/panel/panel-dlc0697.c + DRM DRIVER FOR EBBG FT8719 PANEL M: Joel Selvaraj S: Maintained @@ -21899,6 +21917,16 @@ F: sound/soc/codecs/wcd93*.* F: sound/soc/codecs/wsa88*.* F: sound/soc/qcom/ +QCOM AUDIO INTERFACE (QAIF) DRIVER +M: Harendra Gautam +M: Srinivas Kandagatla +L: linux-sound@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/sound/qcom,qaif.yaml +F: include/dt-bindings/sound/qcom,qaif.h +F: sound/soc/qcom/qaif* + QCOM EMBEDDED USB DEBUGGER (EUD) M: Souradeep Chowdhury L: linux-arm-msm@vger.kernel.org @@ -22100,6 +22128,15 @@ S: Maintained F: Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml F: drivers/net/wwan/qcom_bam_dmux.c +QUALCOMM BCL HARDWARE MONITOR DRIVER +M: Manaf Meethalavalappu Pallikunhi +L: linux-hwmon@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/hwmon/qcom,bcl-hwmon.yaml +F: drivers/hwmon/qcom-bcl-hwmon.c +F: drivers/hwmon/qcom-bcl-hwmon.h + QUALCOMM BLUETOOTH DRIVER M: Bartosz Golaszewski L: linux-arm-msm@vger.kernel.org @@ -22296,6 +22333,17 @@ S: Maintained F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml F: drivers/media/platform/qcom/iris/ +QUALCOMM MIPI CSI2 PHY DRIVER +M: Bryan O'Donoghue +L: linux-phy@lists.infradead.org +L: linux-media@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h +F: include/dt-bindings/phy/phy-qcom-mipi-csi2* + QUALCOMM NAND CONTROLLER DRIVER M: Manivannan Sadhasivam L: linux-mtd@lists.infradead.org @@ -22322,6 +22370,13 @@ S: Maintained F: Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml F: drivers/power/supply/qcom_smbx.c +QUALCOMM SPEL POWERCAP DRIVER +M: Manaf Meethalavalappu Pallikunhi +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/power/limits/qcom,spel.yaml +F: drivers/powercap/qcom_spel.c + QUALCOMM PPE DRIVER M: Luo Jie L: netdev@vger.kernel.org @@ -22330,6 +22385,12 @@ F: Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst F: drivers/net/ethernet/qualcomm/ppe/ +QUALCOMM QMI (REMOTEPROC THERMAL MITIGATION) TMD +M: Gaurav Kohli +L: linux-arm-msm@vger.kernel.org +L: linux-pm@vger.kernel.org +F: drivers/soc/qcom/qmi_tmd.c + QUALCOMM QSEECOM DRIVER M: Maximilian Luz L: linux-arm-msm@vger.kernel.org diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6f33c4e2f09c3..16654473af958 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -7,7 +7,9 @@ apq8016-sbc-usb-host-dtbs := apq8016-sbc.dtb apq8016-sbc-usb-host.dtbo dtb-$(CONFIG_ARCH_QCOM) += sar2130p-qar2130p.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtbo dtb-$(CONFIG_ARCH_QCOM) += apq8016-schneider-hmibsc.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8039-t2.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony-xperia-kitakami-karin_windy.dtb @@ -17,9 +19,12 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb dtb-$(CONFIG_ARCH_QCOM) += eliza-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-camera-imx577.dtbo +hamoa-iot-evk-camera-imx577-dtbs := hamoa-iot-evk.dtb hamoa-iot-evk-camera-imx577.dtbo hamoa-iot-evk-el2-dtbs := hamoa-iot-evk.dtb x1-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-camera-imx577.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-lenovo-ideacentre-mini-01q8x10.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq5018-rdp432-c2.dtb @@ -44,31 +49,53 @@ dtb-$(CONFIG_ARCH_QCOM) += kaanapali-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk.dtb +lemans-evk-emmc-dtbs := lemans-evk.dtb lemans-evk-emmc.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-emmc.dtb + +lemans-evk-sd-card-dtbs := lemans-evk.dtb lemans-evk-sd-card.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-sd-card.dtb + lemans-evk-camera-csi1-imx577-dtbs := lemans-evk.dtb lemans-evk-camera-csi1-imx577.dtbo lemans-evk-camera-dtbs := lemans-evk.dtb lemans-evk-camera.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera-csi1-imx577.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera-csi1-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera.dtbo lemans-evk-el2-dtbs := lemans-evk.dtb lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-el2.dtb lemans-evk-ifp-mezzanine-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-nothing-asteroids.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk.dtb monaco-evk-camera-imx577-dtbs := monaco-evk.dtb monaco-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtbo monaco-evk-el2-dtbs := monaco-evk.dtb monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-el2.dtb + +monaco-ac-evk-ifp-mezzanine-dtbs := monaco-ac-evk.dtb monaco-evk-ifp-mezzanine.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb + +monaco-evk-sd-card-dtbs := monaco-evk.dtb monaco-evk-sd-card.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-sd-card.dtb + +monaco-evk-emmc-dtbs := monaco-evk.dtb monaco-evk-emmc.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-emmc.dtb + +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb @@ -164,7 +191,11 @@ purwa-iot-evk-el2-dtbs := purwa-iot-evk.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-iot-evk-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcm6490-fairphone-fp5.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp.dtb +qcm6490-idp-el2-dtbs := qcm6490-idp.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcm6490-particle-tachyon.dtb dtb-$(CONFIG_ARCH_QCOM) += qcm6490-shift-otter.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb @@ -174,21 +205,36 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride.dtb qcs615-ride-el2-dtbs := qcs615-ride.dtb talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-radxa-dragon-q6a.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb +qcs6490-rb3gen2-el2-dtbs := qcs6490-rb3gen2.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-el2.dtb qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo +qcs6490-rb3gen2-industrial-mezzanine-m2-cologne-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb +qcs6490-rb3gen2-industrial-mezzanine-el2-dtbs := qcs6490-rb3gen2-industrial-mezzanine.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-el2.dtb + +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb +qcs6490-rb3gen2-vision-mezzanine-el2-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-el2.dtb + +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-minipc-g1iot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-rubikpi3.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride.dtb qcs8300-ride-el2-dtbs := qcs8300-ride.dtb monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8550-aim300-aiot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3.dtb @@ -198,6 +244,7 @@ qcs9100-ride-r3-el2-dtbs := qcs9100-ride-r3.dtb lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb2210-arduino-imola.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb @@ -205,6 +252,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb qrb2210-rb1-vision-mezzanine-dtbs := qrb2210-rb1.dtb qrb2210-rb1-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb4210-rb2.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb @@ -212,6 +260,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb qrb5165-rb5-vision-mezzanine-dtbs := qrb5165-rb5.dtb qrb5165-rb5-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qru1000-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb @@ -222,6 +271,7 @@ sc7180-acer-aspire1-el2-dtbs := sc7180-acer-aspire1.dtb sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-acer-aspire1.dtb sc7180-acer-aspire1-el2.dtb sc7180-ecs-liva-qc710-el2-dtbs := sc7180-ecs-liva-qc710.dtb sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-ecs-liva-qc710.dtb sc7180-ecs-liva-qc710-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1-lte.dtb @@ -297,6 +347,7 @@ sc8280xp-microsoft-arcata-el2-dtbs := sc8280xp-microsoft-arcata.dtb sc8280xp-el2 dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-microsoft-arcata.dtb sc8280xp-microsoft-arcata-el2.dtb sc8280xp-microsoft-blackrock-el2-dtbs := sc8280xp-microsoft-blackrock.dtb sc8280xp-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-microsoft-blackrock.dtb sc8280xp-microsoft-blackrock-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sda660-inforce-ifc6560.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm450-lenovo-tbx605f.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm450-motorola-ali.dtb @@ -315,6 +366,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb sdm845-db845c-navigation-mezzanine-dtbs := sdm845-db845c.dtb sdm845-db845c-navigation-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-crosshatch.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-blueline.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-lg-judyln.dtb @@ -334,6 +386,17 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm850-huawei-matebook-e-2019.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-samsung-w737.dtb dtb-$(CONFIG_ARCH_QCOM) += sdx75-idp.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk.dtb + +shikra-cqm-evk-imx577-camera-dtbs := shikra-cqm-evk.dtb shikra-cqm-evk-imx577-camera.dtbo +shikra-cqs-evk-imx577-camera-dtbs := shikra-cqs-evk.dtb shikra-cqm-evk-imx577-camera.dtbo +shikra-iqs-evk-imx577-camera-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-imx577-camera.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-imx577-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-imx577-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6115-fxtec-pro1x.dtb @@ -380,7 +443,9 @@ sm8550-hdk-rear-camera-card-dtbs := sm8550-hdk.dtb sm8550-hdk-rear-camera-card.d dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card-rear-camera-card.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-rear-camera-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-rear-camera-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-qrd.dtb @@ -394,7 +459,9 @@ sm8650-hdk-rear-camera-card-dtbs := sm8650-hdk.dtb sm8650-hdk-rear-camera-card.d dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card-rear-camera-card.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-rear-camera-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-rear-camera-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-qrd.dtb @@ -403,12 +470,14 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8750-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-evk.dtb talos-evk-usb1-peripheral-dtbs := talos-evk.dtb talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtbo talos-evk-camera-imx577-dtbs := talos-evk.dtb talos-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtb talos-evk-lvds-auo,g133han01-dtbs := \ talos-evk.dtb talos-evk-lvds-auo,g133han01.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-lvds-auo,g133han01.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-lvds-auo,g133han01.dtbo x1e001de-devkit-el2-dtbs := x1e001de-devkit.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1e001de-devkit.dtb x1e001de-devkit-el2.dtb x1e78100-lenovo-thinkpad-t14s-el2-dtbs := x1e78100-lenovo-thinkpad-t14s.dtb x1-el2.dtbo @@ -457,3 +526,116 @@ x1p42100-lenovo-thinkbook-16-el2-dtbs := x1p42100-lenovo-thinkbook-16.dtb x1-el2 dtb-$(CONFIG_ARCH_QCOM) += x1p42100-lenovo-thinkbook-16.dtb x1p42100-lenovo-thinkbook-16-el2.dtb x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += x1-el2.dtbo + +glymur-crd-camx-dtbs := glymur-crd.dtb glymur-crd-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += glymur-crd-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += glymur-crd-camx.dtbo + +hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtbo + +hamoa-camx-el2-dtbs := hamoa-iot-evk-el2.dtb hamoa-evk-camx.dtbo hamoa-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-camx-el2.dtb + +lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtbo + +lemans-camx-el2-dtbs := lemans-evk-el2.dtb lemans-evk-camx.dtbo lemans-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-rtss-mb.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-staging.dtbo + +monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtbo + +monaco-camx-el2-dtbs := monaco-evk-el2.dtb monaco-evk-camx.dtbo monaco-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-rtss-mb.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo + +purwa-evk-camx-dtbs := purwa-iot-evk.dtb purwa-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtb + +purwa-camx-el2-dtbs := purwa-iot-evk-el2.dtb purwa-evk-camx.dtbo purwa-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += purwa-camx-el2.dtb + +qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb + +qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtbo + +qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ + qcs6490-rb3gen2-vision-mezzanine-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-staging.dtbo + +qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtbo + +qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-camx.dtb + +qcs9100-ride-r3-camx-dtbs:= qcs9100-ride-r3.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-camx.dtb + +sa8775p-ride-camx-dtbs:= sa8775p-ride.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtbo + +sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb + +talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += purwa-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += kaanapali-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/agatti.dtsi b/arch/arm64/boot/dts/qcom/agatti.dtsi index f0b6ae9b81528..47ced162150c5 100644 --- a/arch/arm64/boot/dts/qcom/agatti.dtsi +++ b/arch/arm64/boot/dts/qcom/agatti.dtsi @@ -770,6 +770,42 @@ drive-strength = <8>; }; }; + + lpass_tx_swr_active: lpass-tx-swr-active-state { + clk-pins { + pins = "gpio0"; + function = "swr_tx_clk"; + drive-strength = <10>; + slew-rate = <3>; + bias-disable; + }; + + data-pins { + pins = "gpio1", "gpio2"; + function = "swr_tx_data"; + drive-strength = <10>; + slew-rate = <3>; + bias-bus-hold; + }; + }; + + lpass_rx_swr_active: lpass-rx-swr-active-state { + clk-pins { + pins = "gpio3"; + function = "swr_rx_clk"; + drive-strength = <10>; + slew-rate = <3>; + bias-disable; + }; + + data-pins { + pins = "gpio4", "gpio5"; + function = "swr_rx_data"; + drive-strength = <10>; + slew-rate = <3>; + bias-bus-hold; + }; + }; }; gcc: clock-controller@1400000 { @@ -2190,13 +2226,19 @@ <&gcc GCC_DISP_GPLL0_CLK_SRC>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, - <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>; + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>, + <0>, + <0>, + <&sleep_clk>; clock-names = "bi_tcxo", "bi_tcxo_ao", "gcc_disp_gpll0_clk_src", "gcc_disp_gpll0_div_clk_src", "dsi0_phy_pll_out_byteclk", - "dsi0_phy_pll_out_dsiclk"; + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "sleep_clk"; #power-domain-cells = <1>; #clock-cells = <1>; #reset-cells = <1>; @@ -2239,6 +2281,159 @@ }; }; + rxmacro: codec@a600000 { + compatible = "qcom,sm6115-lpass-rx-macro"; + reg = <0x0 0xa600000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "dcodec", + "fsgen"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <22579200>, + <22579200>; + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr1: soundwire@a610000 { + compatible = "qcom,soundwire-v1.6.0"; + reg = <0x0 0x0a610000 0x0 0x2000>; + interrupts = ; + + clocks = <&rxmacro>; + clock-names = "iface"; + + resets = <&lpass_audiocc 0>; + reset-names = "swr_audio_cgcr"; + + label = "RX"; + qcom,din-ports = <0>; + qcom,dout-ports = <5>; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; + + status = "disabled"; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + + + txmacro: codec@a620000 { + compatible = "qcom,sm6115-lpass-tx-macro"; + reg = <0x0 0x0a620000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "dcodec", + "fsgen"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <19200000>, + <19200000>; + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + lpass_audiocc: clock-controller@a6a9000 { + compatible = "qcom,sm6115-lpassaudiocc"; + reg = <0x0 0x0a6a9000 0x0 0x1000>; + #reset-cells = <1>; + }; + + vamacro: codec@a730000 { + compatible = "qcom,sm6115-lpass-va-macro"; + reg = <0x0 0x0a730000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", + "dcodec", + "npl"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <19200000>, + <19200000>; + #clock-cells = <0>; + clock-output-names = "fsgen"; + #sound-dai-cells = <1>; + }; + + swr0: soundwire@a740000 { + compatible = "qcom,soundwire-v1.6.0"; + reg = <0x0 0x0a740000 0x0 0x2000>; + interrupts = , + ; + clocks = <&txmacro>; + clock-names = "iface"; + + resets = <&lpasscc 0>; + reset-names = "swr_audio_cgcr"; + + label = "VA_TX"; + qcom,din-ports = <3>; + qcom,dout-ports = <0>; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x03 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x00 0x00 0x00>; + + status = "disabled"; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + + lpasscc: clock-controller@a7ec000 { + compatible = "qcom,sm6115-lpasscc"; + reg = <0x0 0x0a7ec000 0x0 0x1000>; + #reset-cells = <1>; + }; + remoteproc_adsp: remoteproc@ab00000 { compatible = "qcom,qcm2290-adsp-pas", "qcom,sm6115-adsp-pas"; reg = <0x0 0x0ab00000 0x0 0x100>; diff --git a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi new file mode 100644 index 0000000000000..acf015644f483 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci1 { + /*cam0-ov08x*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4p>; + cam_vana-supply = <&vreg_l7p>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 2800000>; + rgltr-max-voltage = <1800000 2800000>; + rgltr-load-current = <204000 55000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 100 0>, + <&tlmm 239 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK4", + "CAMIF_RESET4"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi new file mode 100644 index 0000000000000..c2c6050a47add --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi @@ -0,0 +1,2454 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac00000 { + compatible = "qcom,cam-icp_v2_1"; + icp-version = <0x0201>; + reg = <0x0 0xac01000 0x0 0x1000>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_wd0"; + reg-cam-base = <0x1000 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk", + "camcc_debug_clk"; + clock-rates = <0 300000000 0 0>, + <0 400000000 0 0>, + <0 480000000 0 0>, + <0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/glymur/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&hsc_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy4", + "cci0", "cci1", "csid0", "csid1", "csid2", + "csid3", "ife0", "ife1", "ife2", "ife3", + "ipe0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "cam-cdm-intf0", "bps0", "icp0", + "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", + "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife1_linear_stats_wr: ife1-linear-stats-wr { + cell-index = <7>; + node-name = "ife1-linear-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife1_pdaf_wr: ife1-pdaf-wr { + cell-index = <8>; + node-name = "ife1-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <9>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife1_ubwc_wr: ife1-ubwc-wr { + cell-index = <10>; + node-name = "ife1-ubwc-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <11>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife3_rdi_stats_pixel_raw_wr: ife3-rdi-stats-pixel-raw-wr { + cell-index = <12>; + node-name = "ife3-rdi-stats-pixel-raw-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <13>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <14>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <15>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <16>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <17>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <18>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <19>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <20>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <21>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <22>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <23>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <24>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <25>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <26>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_rd0: level1-rt0-rd0 { + cell-index = <27>; + node-name = "level1-sfe-rd"; + parent-node = <&level2_rt0_rd>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <28>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <29>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <30>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <31>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <32>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <33>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <34>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <35>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <36>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <37>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <38>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <39>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <40>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + operating-points-v2 = <&cci1_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1@ac26000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x400>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <400000000 0>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table1>; + nrt-device; + cdm-client-names = "ife1", "dualife1"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <26>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1@ac71000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac71000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x71000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>; + clock-names = "ife_1_fast_ahb", + "ife_1_clk_src", + "ife_1_clk", + "cam_cc_cpas_ife_1_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <17 5 21 9>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1@acb9000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb9000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb9000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <3>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ace6000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy1_opp_table>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x14b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x14400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.7 GB */ + iova-region-name = "io"; + iova-region-start = <0x14c00000>; + iova-region-len = <0xeb300000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x4800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0820 0x0000>; + dma-coherent; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio239"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio239"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio239"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio239"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* mclk1 */ + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* mclk1 */ + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* mclk2 */ + config { + pins = "gpio98"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* mclk2 */ + config { + pins = "gpio98"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* mclk3 */ + config { + pins = "gpio99"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio99"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* mclk3 */ + config { + pins = "gpio99"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio99"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_asc_mclk4"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_asc_mclk4"; + }; + }; + + cci_i2c_sda0_active: cci_i2c_sda0_active { + mux { + /* CLK, DATA */ + pins = "gpio101"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio101"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci_i2c_sda0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio101"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio101"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_active: cci_i2c_scl0_active { + mux { + /* CLK, DATA */ + pins = "gpio102"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci_i2c_scl0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio102"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci_i2c_sda1_active { + mux { + /* CLK, DATA */ + pins = "gpio103"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio103"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci_i2c_sda1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio103"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio103"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci_i2c_scl1_active { + mux { + /* CLK, DATA */ + pins = "gpio104"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci_i2c_scl1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio104"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci_i2c_sda2_active { + mux { + /* CLK, DATA */ + pins = "gpio105"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio105"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda2_suspend: cci_i2c_sda2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio105"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio105"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci_i2c_scl2_active { + mux { + /* CLK, DATA */ + pins = "gpio106"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl2_suspend: cci_i2c_scl2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio106"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "asc_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "asc_cci"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso new file mode 100644 index 0000000000000..64cea8de94206 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "glymur-camera.dtsi" +#include "glymur-camera-sensor.dtsi" + +&cam_icp_firmware { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0000>; + }; +}; + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; + +&cci1_i2c1 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index e784b538f42e1..2a507d1692232 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -522,14 +522,14 @@ pinctrl-0 = <&pcie6_default>; pinctrl-names = "default"; - status = "okay"; + status = "disabled"; }; &pcie6_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p08>; - status = "okay"; + status = "disabled"; }; &pcie6_port0 { diff --git a/arch/arm64/boot/dts/qcom/glymur-staging.dtso b/arch/arm64/boot/dts/qcom/glymur-staging.dtso new file mode 100644 index 0000000000000..eb928fca1a371 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-staging.dtso @@ -0,0 +1,1449 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Glymur staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&{/} { + ete-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + ete-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + ete-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + ete-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + ete-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + ete-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + ete-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + ete-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + + ete-8 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu8>; + qcom,skip-power-up; + + out-ports { + port { + etm8_out: endpoint { + remote-endpoint = <&ncc1_2_rep_in>; + }; + }; + }; + }; + + ete-9 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu9>; + qcom,skip-power-up; + + out-ports { + port { + etm9_out: endpoint { + remote-endpoint = <&ncc1_3_rep_in>; + }; + }; + }; + }; + + ete-10 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu10>; + qcom,skip-power-up; + + out-ports { + port { + etm10_out: endpoint { + remote-endpoint = <&ncc1_4_rep_in>; + }; + }; + }; + }; + + ete-11 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu11>; + qcom,skip-power-up; + + out-ports { + port { + etm11_out: endpoint { + remote-endpoint = <&ncc1_5_rep_in>; + }; + }; + }; + }; + + ete-12 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu12>; + qcom,skip-power-up; + + out-ports { + port { + etm12_out: endpoint { + remote-endpoint = <&ncc2_0_rep_in>; + }; + }; + }; + }; + + ete-13 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu13>; + qcom,skip-power-up; + + out-ports { + port { + etm13_out: endpoint { + remote-endpoint = <&ncc2_1_rep_in>; + }; + }; + }; + }; + + ete-14 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu14>; + qcom,skip-power-up; + + out-ports { + port { + etm14_out: endpoint { + remote-endpoint = <&ncc2_2_rep_in>; + }; + }; + }; + }; + + ete-15 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu15>; + qcom,skip-power-up; + + out-ports { + port { + etm15_out: endpoint { + remote-endpoint = <&ncc2_3_rep_in>; + }; + }; + }; + }; + + ete-16 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu16>; + qcom,skip-power-up; + + out-ports { + port { + etm16_out: endpoint { + remote-endpoint = <&ncc2_4_rep_in>; + }; + }; + }; + }; + + ete-17 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu17>; + qcom,skip-power-up; + + out-ports { + port { + etm17_out: endpoint { + remote-endpoint = <&ncc2_5_rep_in>; + }; + }; + }; + }; + +}; + +&soc { + ctcu@10001000 { + compatible = "qcom,glymur-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&etr1_out>; + }; + }; + }; + }; + + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep_in: endpoint { + remote-endpoint = <&swao_rep_out0>; + }; + }; + }; + + out-ports { + port { + qdss_rep_out0: endpoint { + remote-endpoint = <&etr_rep_in>; + }; + }; + }; + }; + + tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x00e0 0x0000>; + + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&etr_rep_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_rep_in: endpoint { + remote-endpoint = <&qdss_rep_out0>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + etr_rep_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + etr_rep_out1: endpoint { + remote-endpoint = <&etr1_in>; + }; + }; + }; + }; + + tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0100 0x0000>; + + arm,scatter-gather; + + in-ports { + port { + etr1_in: endpoint { + remote-endpoint = <&etr_rep_out1>; + }; + }; + }; + + out-ports { + port { + etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + + tn@11200000 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@36 { + reg = <0x36>; + + tn_ag_in54: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + }; + }; + + tgu@11c02000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c02000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + replicator@11c06000 { + out-ports { + port@0 { + reg = <0>; + + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + }; + }; + + tgu@11c0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11c0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11c10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + + port@2 { + reg = <2>; + + apss_funnel_in2: endpoint { + remote-endpoint = <&ncc2_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in54>; + }; + }; + }; + }; + + funnel@1d021000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d021000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@1d029000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d029000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + funnel@1d081000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d081000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d090000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d090000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d0a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d0b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d0c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d0d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d0e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d121000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d121000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@1d129000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d129000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + funnel@1d181000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d181000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc1_1_funnel_in2: endpoint { + remote-endpoint = <&ncc1_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc1_1_funnel_in3: endpoint { + remote-endpoint = <&ncc1_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc1_1_funnel_in4: endpoint { + remote-endpoint = <&ncc1_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc1_1_funnel_in5: endpoint { + remote-endpoint = <&ncc1_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d190000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d190000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d1a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d1b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_2_rep_in: endpoint { + remote-endpoint = <&etm8_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d1c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_3_rep_in: endpoint { + remote-endpoint = <&etm9_out>; + }; + }; + }; + + out-ports { + port { + ncc1_3_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d1d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_4_rep_in: endpoint { + remote-endpoint = <&etm10_out>; + }; + }; + }; + + out-ports { + port { + ncc1_4_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d1e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_5_rep_in: endpoint { + remote-endpoint = <&etm11_out>; + }; + }; + }; + + out-ports { + port { + ncc1_5_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d221000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d221000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc2_2_funnel_in2: endpoint { + remote-endpoint = <&ncc2_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_funnel_out: endpoint { + remote-endpoint = <&ncc2_etf_in>; + }; + }; + }; + }; + + tmc@1d229000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d229000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_etf_in: endpoint { + remote-endpoint = <&ncc2_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in2>; + }; + }; + }; + }; + + funnel@1d281000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d281000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc2_1_funnel_in0: endpoint { + remote-endpoint = <&ncc2_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc2_1_funnel_in1: endpoint { + remote-endpoint = <&ncc2_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc2_1_funnel_in2: endpoint { + remote-endpoint = <&ncc2_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc2_1_funnel_in3: endpoint { + remote-endpoint = <&ncc2_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc2_1_funnel_in4: endpoint { + remote-endpoint = <&ncc2_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc2_1_funnel_in5: endpoint { + remote-endpoint = <&ncc2_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_funnel_out: endpoint { + remote-endpoint = <&ncc2_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d290000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d290000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_0_rep_in: endpoint { + remote-endpoint = <&etm12_out>; + }; + }; + }; + + out-ports { + port { + ncc2_0_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d2a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_1_rep_in: endpoint { + remote-endpoint = <&etm13_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d2b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_2_rep_in: endpoint { + remote-endpoint = <&etm14_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d2c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_3_rep_in: endpoint { + remote-endpoint = <&etm15_out>; + }; + }; + }; + + out-ports { + port { + ncc2_3_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d2d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_4_rep_in: endpoint { + remote-endpoint = <&etm16_out>; + }; + }; + }; + + out-ports { + port { + ncc2_4_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d2e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d2e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc2_5_rep_in: endpoint { + remote-endpoint = <&etm17_out>; + }; + }; + }; + + out-ports { + port { + ncc2_5_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in5>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi new file mode 100644 index 0000000000000..ac0f603a0ddad --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&apps_rsc { + /* PM8010_M */ + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l5-supply = <&vreg_bob1>; + vdd-l6-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p1: ldo1 { + regulator-name = "vreg_l1m_1p1"; + regulator-min-microvolt = <1056000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p15: ldo2 { + regulator-name = "vreg_l2m_1p15"; + regulator-min-microvolt = <1152000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l5m_3p0: ldo5 { + regulator-name = "vreg_l5m_3p0"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l6m_1p8: ldo6 { + regulator-name = "vreg_l6m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi new file mode 100644 index 0000000000000..a2f821a2b93ff --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /*cam0-cmk_imx577*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000>; + rgltr-max-voltage = <1808000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 97 0>, + <&tlmm 110 0>, + <&tlmm 19 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + /*cam1-og0a1b*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l7m_2p9>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 2912000>; + rgltr-max-voltage = <1808000 2912000>; + rgltr-load-current = <120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 96 0>, <&tlmm 109 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&cam_cci1 { + /*cam2-imx688*/ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l6m_1p8>; + cam_vdig-supply = <&vreg_l1m_1p1>; + cam_v_custom1-supply = <&vreg_l7b_2p8>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_v_custom1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-max-voltage = <1808000 1808000 1200000 2800000>; + rgltr-load-current = <120000 120000 120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + gpios = <&tlmm 100 0>, <&tlmm 237 0>, <&tlmm 233 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <4>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi new file mode 100644 index 0000000000000..94dd42b380f4e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi @@ -0,0 +1,2473 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac01000 { + compatible = "qcom,cam-icp_v2"; + icp-version = <0x0200>; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <0 300000000 0>, + <0 400000000 0>, + <0 480000000 0>, + <0 600000000 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/x1e80100/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy4", + "cci0", "cci1", "csid0", "csid1", "csid2", + "csid3", "ife0", "ife1", "ife2", "ife3", "sfe0", + "ipe0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "cam-cdm-intf0", "bps0", "icp0", + "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", + "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife1_linear_stats_wr: ife1-linear-stats-wr { + cell-index = <7>; + node-name = "ife1-linear-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife1_pdaf_wr: ife1-pdaf-wr { + cell-index = <8>; + node-name = "ife1-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <9>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife1_ubwc_wr: ife1-ubwc-wr { + cell-index = <10>; + node-name = "ife1-ubwc-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <11>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife3_rdi_stats_pixel_raw_wr: ife3-rdi-stats-pixel-raw-wr { + cell-index = <12>; + node-name = "ife3-rdi-stats-pixel-raw-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <13>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <14>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <15>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <16>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <17>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <18>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <19>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <20>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <21>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <22>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <23>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + sfe0_all_rd: sfe0-all-rd { + cell-index = <24>; + node-name = "sfe0-all-rd"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_rt0_rd>; + }; + + sfe0_rdi_stats_nrdi_wr: sfe0-rdi-stats-nrdi-wr { + cell-index = <25>; + node-name = "sfe0-rdi-stats-nrdi-wr"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <26>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <27>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <28>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_rd0: level1-rt0-rd0 { + cell-index = <29>; + node-name = "level1-sfe-rd"; + parent-node = <&level2_rt0_rd>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <30>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <31>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <32>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <33>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <34>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <35>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <36>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <37>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <38>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <39>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <40>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <41>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <42>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + operating-points-v2 = <&cci1_opp_table>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1@ac26000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x400>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <400000000 0>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table1>; + nrt-device; + cdm-client-names = "ife1", "dualife1"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <26>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1@ac71000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac71000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x71000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>; + clock-names = "ife_1_fast_ahb", + "ife_1_clk_src", + "ife_1_clk", + "cam_cc_cpas_ife_1_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <17 5 21 9>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe0: qcom,sfe0@ac9e000 { + compatible = "qcom,sfe680"; + reg = <0x0 0xac9e000 0x0 0x8000>; + reg-names = "sfe0"; + reg-cam-base = <0x9e000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "sfe"; + power-domains = <&camcc CAM_CC_SFE_0_GDSC>; + clocks = <&camcc CAM_CC_SFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_0_CLK_SRC>, + <&camcc CAM_CC_SFE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_0_CLK>; + clock-names = "sfe_0_fast_ahb", + "sfe_0_clk_src", + "sfe_0_clk", + "cam_cc_cpas_sfe_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "sfe_0_clk_src"; + operating-points-v2 = <&sfe0_opp_table>; + cam_hw_pid = <10 2>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + sfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1@acb9000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb9000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb9000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <3>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ace6000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy1_opp_table>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@ace8000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace8000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe8000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy2_opp_table>; + cell-index = <2>; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x0060>, + <&apps_smmu 0x0820 0x0060>, + <&apps_smmu 0x0840 0x0060>, + <&apps_smmu 0x0860 0x0060>; + dma-coherent; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_int: cam-sensor-active-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_suspend_int: cam-sensor-suspend-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cci0_active: cci0-active { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci0_suspend: cci0-suspend { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + function = "cci_i2c"; + }; + }; + + cci1_active: cci1-active { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci1_suspend: cci1-suspend { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + function = "cci_i2c"; + }; + }; + + cci2_active: cci2-active { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci2_suspend: cci2-suspend { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + function = "cci_i2c"; + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso b/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso new file mode 100644 index 0000000000000..5584660dbcfd6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso new file mode 100644 index 0000000000000..df773142192eb --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hamoa-camera-regulators.dtsi" +#include "hamoa-camera.dtsi" +#include "hamoa-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso b/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso new file mode 100644 index 0000000000000..f45a7fbd14b1f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&{/} { + vreg_cam1_1p8: regulator-cam1 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam1"; + startup-delay-us = <1000>; + enable-active-high; + gpio = <&tlmm 19 GPIO_ACTIVE_HIGH>; + }; +}; + +&camss { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + csiphy1_ep: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&imx577_ep>; + }; + }; + }; +}; + +&cci0 { + status = "okay"; +}; + +&cci0_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx577"; + reg = <0x1a>; + + reset-gpios = <&tlmm 110 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam1_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK1_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK1_CLK>; + assigned-clock-rates = <24000000>; + + dvdd-supply = <&vreg_cam1_1p8>; + dovdd-supply = <&vreg_l4m_1p8>; + + port { + imx577_ep: endpoint { + link-frequencies = /bits/ 64 <600000000>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&csiphy1_ep>; + }; + }; + }; +}; + +&csiphy1 { + vdda-0p8-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index c7ba4b353ddd2..27bec1a8496dd 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -522,6 +522,23 @@ regulator-boot-on; }; + vreg_wcn_bt_en: regulator-wcn-bt-en { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_BT_EN"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + gpio = <&tlmm 116 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wcn_bt_en>; + pinctrl-names = "default"; + + regulator-always-on; + regulator-boot-on; + }; + vreg_wwan: regulator-wwan { compatible = "regulator-fixed"; @@ -687,10 +704,9 @@ vddrfa1p2-supply = <&vreg_wcn_1p9>; vddrfa1p8-supply = <&vreg_wcn_1p9>; - bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>; wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&wcn_bt_en>, <&wcn_wlan_en>; + pinctrl-0 = <&wcn_wlan_en>; pinctrl-names = "default"; regulators { @@ -839,6 +855,16 @@ pinctrl-0 = <&eusb6_reset_n>; pinctrl-names = "default"; }; + + embedded-controller@76 { + compatible = "qcom,hamoa-iot-evk-ec", "qcom,hamoa-crd-ec"; + reg = <0x76>; + + interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&ec_int_n_default>; + pinctrl-names = "default"; + }; }; &i2c7 { @@ -1341,6 +1367,28 @@ }; &tlmm { + cam1_default: cam1-default-state { + mclk-pins { + pins = "gpio97"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + rst-pins { + pins = "gpio110"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + + ec_int_n_default: ec-int-n-state { + pins = "gpio66"; + function = "gpio"; + bias-disable; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; @@ -1519,13 +1567,13 @@ compatible = "qcom,wcn7850-bt"; max-speed = <3200000>; - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddrfacmn-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddwlcx-supply = <&vreg_wcn_3p3>; + vddwlmx-supply = <&vreg_wcn_3p3>; + vddrfa0p8-supply = <&vreg_wcn_3p3>; + vddrfa1p2-supply = <&vreg_wcn_3p3>; + vddrfa1p8-supply = <&vreg_wcn_3p3>; }; }; diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi index 9c5e77df00547..6187c8cdf6b34 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi @@ -376,6 +376,21 @@ regulator-initial-mode = ; }; }; + + /* PM8010_M */ + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vrer_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + }; }; &iris { @@ -400,6 +415,7 @@ &pcie3_phy { vdda-phy-supply = <&vreg_l3c_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; @@ -414,6 +430,7 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; @@ -428,6 +445,7 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; @@ -442,6 +460,7 @@ &pcie6a_phy { vdda-phy-supply = <&vreg_l1d_0p8>; vdda-pll-supply = <&vreg_l2j_1p2>; + vdda-qref-supply = <&vreg_l3j_0p8>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi b/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi index 6a31a0adf8be4..2e746ede850f8 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include "qcom-adc5-gen3.h" / { thermal-zones { @@ -189,6 +191,90 @@ }; }; }; + + sys-0-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX1_GPIO_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-1-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX2_GPIO_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX1_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX2_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-4-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX3_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-5-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX4_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-6-thermal { + polling-delay-passive = <0>; + thermal-sensors = <&pmk8550_vadc ADC5_GEN3_AMUX5_THM_100K_PU(1)>; + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; }; }; @@ -277,6 +363,142 @@ status = "disabled"; }; + + pmk8550_vadc: adc@9000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x9000>, <0x9100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x90 0x1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x91 0x1 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <1>; + #io-channel-cells = <1>; + pinctrl-0 = <&sys_therm_0_gpio3>, <&sys_therm_1_gpio4>; + pinctrl-names = "default"; + + channel@3 { + reg = ; + label = "pmk8550_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@103 { + reg = ; + label = "pm8550_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@18e { + reg = ; + label = "pm8550_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + + channel@14a { + reg = ; + label = "pm8550_gpio_01"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@14b { + reg = ; + label = "pm8550_gpio_02"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@144 { + reg = ; + label = "pm8550_therm_2"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@145 { + reg = ; + label = "pm8550_therm_3"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@146 { + reg = ; + label = "pm8550_therm_4"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@147 { + reg = ; + label = "pm8550_therm_5"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@148 { + reg = ; + label = "pm8550_therm_6"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + qcom,adc-tm; + }; + + channel@203 { + reg = ; + label = "pm8550ve_2_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@303 { + reg = ; + label = "pmc8380_3_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@403 { + reg = ; + label = "pmc8380_4_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@503 { + reg = ; + label = "pmc8380_5_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@603 { + reg = ; + label = "pmc8380_6_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@803 { + reg = ; + label = "pm8550ve_8_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@903 { + reg = ; + label = "pm8550ve_9_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; }; /* PMC8380C */ @@ -291,6 +513,8 @@ reg = <0xa00>; interrupts = <0x1 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(1)>; + io-channel-names = "thermal"; }; pm8550_gpios: gpio@8800 { @@ -301,6 +525,18 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + + sys_therm_0_gpio3: sys-therm_0-gpio3-state { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + sys_therm_1_gpio4: sys-therm-1-gpio4-state { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; }; pm8550_flash: led-controller@ee00 { @@ -329,6 +565,8 @@ reg = <0xa00>; interrupts = <0x2 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(2)>; + io-channel-names = "thermal"; }; pm8550ve_2_gpios: gpio@8800 { @@ -354,6 +592,8 @@ reg = <0xa00>; interrupts = <0x3 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(3)>; + io-channel-names = "thermal"; }; pmc8380_3_gpios: gpio@8800 { @@ -378,6 +618,8 @@ reg = <0xa00>; interrupts = <0x4 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(4)>; + io-channel-names = "thermal"; }; pmc8380_4_gpios: gpio@8800 { @@ -402,6 +644,8 @@ reg = <0xa00>; interrupts = <0x5 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(5)>; + io-channel-names = "thermal"; }; pmc8380_5_gpios: gpio@8800 { @@ -426,6 +670,8 @@ reg = <0xa00>; interrupts = <0x6 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(6)>; + io-channel-names = "thermal"; }; pmc8380_6_gpios: gpio@8800 { @@ -451,6 +697,8 @@ reg = <0xa00>; interrupts = <0x8 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(8)>; + io-channel-names = "thermal"; }; pm8550ve_8_gpios: gpio@8800 { @@ -476,6 +724,8 @@ reg = <0xa00>; interrupts = <0x9 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmk8550_vadc ADC5_GEN3_DIE_TEMP(9)>; + io-channel-names = "thermal"; }; pm8550ve_9_gpios: gpio@8800 { diff --git a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso new file mode 100644 index 0000000000000..465e521384842 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Hamoa staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +#include "x1-staging.dtsi" diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 4ba751a65142b..99631cde48e83 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -302,6 +306,14 @@ exit-latency-us = <4000>; min-residency-us = <7000>; }; + + domain_ss3: domain-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x0200c354>; + entry-latency-us = <2800>; + exit-latency-us = <4400>; + min-residency-us = <9000>; + }; }; }; @@ -317,11 +329,214 @@ }; }; + etm-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + etm-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + etm-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + etm-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + etm-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + etm-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + + etm-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_2_rep_in>; + }; + }; + }; + }; + + etm-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_3_rep_in>; + }; + }; + }; + }; + + etm8: etm-8 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu8>; + qcom,skip-power-up; + + out-ports { + port { + etm8_out: endpoint { + remote-endpoint = <&ncc2_0_rep_in>; + }; + }; + }; + }; + + etm9: etm-9 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu9>; + qcom,skip-power-up; + + out-ports { + port { + etm9_out: endpoint { + remote-endpoint = <&ncc2_1_rep_in>; + }; + }; + }; + }; + + etm10: etm-10 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu10>; + qcom,skip-power-up; + + out-ports { + port { + etm10_out: endpoint { + remote-endpoint = <&ncc2_2_rep_in>; + }; + }; + }; + }; + + etm11: etm-11 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu11>; + qcom,skip-power-up; + + out-ports { + port { + etm11_out: endpoint { + remote-endpoint = <&ncc2_3_rep_in>; + }; + }; + }; + }; + firmware { scm: scm { compatible = "qcom,scm-x1e80100", "qcom,scm"; - interconnects = <&aggre2_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + /* TODO: add interconnects */ qcom,dload-mode = <&tcsr 0x19000>; }; @@ -338,6 +553,10 @@ reg = <0x13>; #power-domain-cells = <1>; }; + + scmi_vendor: protocol@80 { + reg = <0x80>; + }; }; }; @@ -460,7 +679,12 @@ system_pd: power-domain-system { #power-domain-cells = <0>; - /* TODO: system-wide idle states */ + domain-idle-states = <&domain_ss3>; + }; + + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; }; }; @@ -5484,8 +5708,8 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x1940 0>, - <&apps_smmu 0x1947 0>; + iommu-map = , + ; dma-coherent; /* @@ -5550,138 +5774,578 @@ #power-domain-cells = <1>; }; - mdss: display-subsystem@ae00000 { - compatible = "qcom,x1e80100-mdss"; - reg = <0 0x0ae00000 0 0x1000>; - reg-names = "mdss"; - - interrupts = ; + cci0: cci@ac15000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac15000 0 0x1000>; - clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, - <&gcc GCC_DISP_HF_AXI_CLK>, - <&dispcc DISP_CC_MDSS_MDP_CLK>; + interrupts = ; - resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; - interconnects = <&mmss_noc MASTER_MDP QCOM_ICC_TAG_ALWAYS - &gem_noc SLAVE_LLCC QCOM_ICC_TAG_ALWAYS>, - <&mc_virt MASTER_LLCC QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, - <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY - &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; - interconnect-names = "mdp0-mem", - "mdp1-mem", - "cpu-cfg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - power-domains = <&dispcc MDSS_GDSC>; + pinctrl-0 = <&cci0_default>; + pinctrl-1 = <&cci0_sleep>; + pinctrl-names = "default", "sleep"; - iommus = <&apps_smmu 0x1c00 0x2>; + #address-cells = <1>; + #size-cells = <0>; - interrupt-controller; - #interrupt-cells = <1>; + status = "disabled"; - #address-cells = <2>; - #size-cells = <2>; - ranges; + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; - status = "disabled"; + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; - mdss_mdp: display-controller@ae01000 { - compatible = "qcom,x1e80100-dpu"; - reg = <0 0x0ae01000 0 0x8f000>, - <0 0x0aeb0000 0 0x2008>; - reg-names = "mdp", - "vbif"; + cci1: cci@ac16000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac16000 0 0x1000>; - interrupts-extended = <&mdss 0>; + interrupts = ; - clocks = <&gcc GCC_DISP_HF_AXI_CLK>, - <&dispcc DISP_CC_MDSS_AHB_CLK>, - <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, - <&dispcc DISP_CC_MDSS_MDP_CLK>, - <&dispcc DISP_CC_MDSS_VSYNC_CLK>; - clock-names = "nrt_bus", - "iface", - "lut", - "core", - "vsync"; + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; - operating-points-v2 = <&mdp_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - power-domains = <&rpmhpd RPMHPD_MMCX>; + pinctrl-0 = <&cci1_default>; + pinctrl-1 = <&cci1_sleep>; + pinctrl-names = "default", "sleep"; - ports { - #address-cells = <1>; - #size-cells = <0>; + #address-cells = <1>; + #size-cells = <0>; - port@0 { - reg = <0>; + status = "disabled"; - mdss_intf0_out: endpoint { - remote-endpoint = <&mdss_dp0_in>; - }; - }; + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; - port@4 { - reg = <4>; + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; - mdss_intf4_out: endpoint { - remote-endpoint = <&mdss_dp1_in>; - }; - }; + camss: isp@acb7000 { + compatible = "qcom,x1e80100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0ace6000 0 0x1000>, + <0 0x0ace8000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0xf000>, + <0 0x0ac71000 0 0xf000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; - port@5 { - reg = <5>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; - mdss_intf5_out: endpoint { - remote-endpoint = <&mdss_dp3_in>; - }; - }; + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x18a0 0x0>; - port@6 { - reg = <6>; + #address-cells = <2>; + #size-cells = <2>; + ranges; - mdss_intf6_out: endpoint { - remote-endpoint = <&mdss_dp2_in>; - }; - }; - }; + phys = <&csiphy0 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy1 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy2 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy4 PHY_QCOM_CSI2_MODE_DPHY>; + phy-names = "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4"; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "top"; - mdp_opp_table: opp-table { - compatible = "operating-points-v2"; + status = "disabled"; - opp-200000000 { - opp-hz = /bits/ 64 <200000000>; - required-opps = <&rpmhpd_opp_low_svs>; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; - opp-325000000 { - opp-hz = /bits/ 64 <325000000>; - required-opps = <&rpmhpd_opp_svs>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy0_inep0: endpoint@0 { + reg = <0>; }; + }; - opp-375000000 { - opp-hz = /bits/ 64 <375000000>; - required-opps = <&rpmhpd_opp_svs_l1>; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy1_inep0: endpoint@0 { + reg = <0>; }; + }; - opp-514000000 { - opp-hz = /bits/ 64 <514000000>; - required-opps = <&rpmhpd_opp_nom>; + port@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy2_inep0: endpoint@0 { + reg = <0>; }; + }; - opp-575000000 { - opp-hz = /bits/ 64 <575000000>; - required-opps = <&rpmhpd_opp_nom_l1>; + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy4_inep0: endpoint@0 { + reg = <0>; }; }; }; - mdss_dp0: displayport-controller@ae90000 { - compatible = "qcom,x1e80100-dp"; - reg = <0 0x0ae90000 0 0x200>, - <0 0x0ae90200 0 0x200>, - <0 0x0ae90400 0 0xc00>, + csiphy0: phy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace4000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy1: phy@ace6000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace6000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy2: phy@ace8000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace8000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy4: phy@acec000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0acec000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxa_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy_mxc_opp_table: opp-table-mxc { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + csiphy_mxa_opp_table: opp-table-mxa { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + }; + + camcc: clock-controller@ade0000 { + compatible = "qcom,x1e80100-camcc"; + reg = <0 0x0ade0000 0 0x20000>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&bi_tcxo_div2>, + <&bi_tcxo_ao_div2>, + <&sleep_clk>; + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + mdss: display-subsystem@ae00000 { + compatible = "qcom,x1e80100-mdss"; + reg = <0 0x0ae00000 0 0x1000>; + reg-names = "mdss"; + + interrupts = ; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + + interconnects = <&mmss_noc MASTER_MDP QCOM_ICC_TAG_ALWAYS + &gem_noc SLAVE_LLCC QCOM_ICC_TAG_ALWAYS>, + <&mc_virt MASTER_LLCC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "mdp0-mem", + "mdp1-mem", + "cpu-cfg"; + + power-domains = <&dispcc MDSS_GDSC>; + + iommus = <&apps_smmu 0x1c00 0x2>; + + interrupt-controller; + #interrupt-cells = <1>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdss_mdp: display-controller@ae01000 { + compatible = "qcom,x1e80100-dpu"; + reg = <0 0x0ae01000 0 0x8f000>, + <0 0x0aeb0000 0 0x2008>; + reg-names = "mdp", + "vbif"; + + interrupts-extended = <&mdss 0>; + + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "nrt_bus", + "iface", + "lut", + "core", + "vsync"; + + operating-points-v2 = <&mdp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss_intf0_out: endpoint { + remote-endpoint = <&mdss_dp0_in>; + }; + }; + + port@4 { + reg = <4>; + + mdss_intf4_out: endpoint { + remote-endpoint = <&mdss_dp1_in>; + }; + }; + + port@5 { + reg = <5>; + + mdss_intf5_out: endpoint { + remote-endpoint = <&mdss_dp3_in>; + }; + }; + + port@6 { + reg = <6>; + + mdss_intf6_out: endpoint { + remote-endpoint = <&mdss_dp2_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-325000000 { + opp-hz = /bits/ 64 <325000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-375000000 { + opp-hz = /bits/ 64 <375000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-514000000 { + opp-hz = /bits/ 64 <514000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-575000000 { + opp-hz = /bits/ 64 <575000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + }; + }; + + mdss_dp0: displayport-controller@ae90000 { + compatible = "qcom,x1e80100-dp"; + reg = <0 0x0ae90000 0 0x200>, + <0 0x0ae90200 0 0x200>, + <0 0x0ae90400 0 0xc00>, <0 0x0ae91000 0 0x400>, <0 0x0ae91400 0 0x400>; @@ -6047,8 +6711,10 @@ pdc: interrupt-controller@b220000 { compatible = "qcom,x1e80100-pdc", "qcom,pdc"; - reg = <0 0x0b220000 0 0x30000>, <0 0x174000f0 0 0x64>; - + reg = <0 0x0b220000 0 0x30000>, + <0 0x174000f0 0 0x64>, + <0 0x0b2045e8 0 0x4>; + qcom,qmp = <&aoss_qmp>; qcom,pdc-ranges = <0 480 42>, <42 251 5>, <47 522 52>, <99 609 32>, <131 717 12>, <143 816 19>; @@ -6131,6 +6797,78 @@ gpio-ranges = <&tlmm 0 0 239>; wakeup-parent = <&pdc>; + cci0_default: cci0-default-state { + cci0_i2c0_default: cci0-i2c0-default-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci0_i2c1_default: cci0-i2c1-default-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_sleep: cci0-sleep-state { + cci0_i2c0_sleep: cci0-i2c0-sleep-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci0_i2c1_sleep: cci0-i2c1-sleep-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_default: cci1-default-state { + cci1_i2c0_default: cci1-i2c0-default-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci1_i2c1_default: cci1-i2c1-default-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_sleep: cci1-sleep-state { + cci1_i2c0_sleep: cci1-i2c0-sleep-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci1_i2c1_sleep: cci1-i2c1-sleep-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-down; + }; + }; + edp0_hpd_default: edp0-hpd-default-state { pins = "gpio119"; function = "edp0_hot"; @@ -6804,23 +7542,52 @@ }; }; - stm@10002000 { - compatible = "arm,coresight-stm", "arm,primecell"; - reg = <0x0 0x10002000 0x0 0x1000>, - <0x0 0x16280000 0x0 0x180000>; - reg-names = "stm-base", - "stm-stimulus-base"; + ctcu@10001000 { + compatible = "qcom,x1e80100-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; + clock-names = "apb"; - out-ports { - port { - stm_out: endpoint { - remote-endpoint = <&funnel0_in7>; - }; - }; - }; + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&etr1_out>; + }; + }; + }; + }; + + stm@10002000 { + compatible = "arm,coresight-stm", "arm,primecell"; + reg = <0x0 0x10002000 0x0 0x1000>, + <0x0 0x16280000 0x0 0x180000>; + reg-names = "stm-base", + "stm-stimulus-base"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + stm_out: endpoint { + remote-endpoint = <&funnel0_in7>; + }; + }; + }; }; tpdm@10003000 { @@ -6829,6 +7596,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dcc"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -6886,6 +7654,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -6955,6 +7724,14 @@ }; }; + port@4 { + reg = <4>; + + funnel1_in4: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + port@5 { reg = <5>; @@ -7018,12 +7795,129 @@ }; }; + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep_in: endpoint { + remote-endpoint = <&swao_rep_out0>; + }; + }; + }; + + out-ports { + port { + qdss_rep_out0: endpoint { + remote-endpoint = <&etr_rep_in>; + }; + }; + }; + }; + + tmc_etr: tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + iommus = <&apps_smmu 0x04e0 0x0>; + + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&etr_rep_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_rep_in: endpoint { + remote-endpoint = <&qdss_rep_out0>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + etr_rep_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + etr_rep_out1: endpoint { + remote-endpoint = <&etr1_in>; + }; + }; + }; + }; + + tmc_etr1: tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + iommus = <&apps_smmu 0x0500 0x0>; + + arm,scatter-gather; + arm,buffer-size = <0x400000>; + + in-ports { + port { + etr1_in: endpoint { + remote-endpoint = <&etr_rep_out1>; + }; + }; + }; + + out-ports { + port { + etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + tpdm@10800000 { compatible = "qcom,coresight-tpdm", "arm,primecell"; reg = <0x0 0x10800000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_rpdm_mxa"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7043,6 +7937,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_gcc"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7062,6 +7957,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_prng"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -7081,6 +7977,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_lpass"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7124,6 +8021,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_cdsp_cscti"; }; tpdm@109d0000 { @@ -7132,6 +8030,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_qm"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7152,6 +8051,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_south_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7172,6 +8072,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_south_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7331,7 +8232,20 @@ }; out-ports { - port { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + + port@1 { + reg = <1>; + swao_rep_out1: endpoint { remote-endpoint = <&eud_in>; }; @@ -7406,6 +8320,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7425,6 +8340,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7444,6 +8360,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7463,6 +8380,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7482,6 +8400,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7501,6 +8420,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr_lpi"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7571,6 +8491,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dlmm"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7619,6 +8540,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dlct"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -7638,6 +8560,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ipcc"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7771,6 +8694,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_rdpm"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7790,6 +8714,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_rdpm_mx"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7886,6 +8811,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_tmess_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -7924,224 +8850,1002 @@ out-ports { port { - tmess_tpda_out: endpoint { - remote-endpoint = <&tmess_funnel_in0>; + tmess_tpda_out: endpoint { + remote-endpoint = <&tmess_funnel_in0>; + }; + }; + }; + }; + + funnel@10cc5000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x10cc5000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + tmess_funnel_in0: endpoint { + remote-endpoint = <&tmess_tpda_out>; + }; + }; + }; + + out-ports { + port { + tmess_funnel_out: endpoint { + remote-endpoint = <&funnel1_in2>; + }; + }; + }; + }; + + funnel@10d04000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x10d04000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@6 { + reg = <6>; + + ddr_funnel0_in6: endpoint { + remote-endpoint = <&ddr_funnel1_out>; + }; + }; + }; + + out-ports { + port { + ddr_funnel0_out: endpoint { + remote-endpoint = <&dlct1_funnel_in5>; + }; + }; + }; + }; + + tpdm@10d08000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d08000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_0"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc0_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in0>; + }; + }; + }; + }; + + tpdm@10d09000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d09000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_1"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc1_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in1>; + }; + }; + }; + }; + + tpdm@10d0a000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d0a000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_2"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc2_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in2>; + }; + }; + }; + }; + + tpdm@10d0b000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d0b000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_3"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc3_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in3>; + }; + }; + }; + }; + + tpdm@10d0c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d0c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_4"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc4_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in4>; + }; + }; + }; + }; + + tpdm@10d0d000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d0d000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_5"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc5_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in5>; + }; + }; + }; + }; + + tpdm@10d0e000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_6"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc6_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in6>; + }; + }; + }; + }; + + tpdm@10d0f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x10d0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_llcc_7"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + llcc7_tpdm_out: endpoint { + remote-endpoint = <&llcc_tpda_in7>; + }; + }; + }; + }; + + tpda@10d12000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x10d12000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + llcc_tpda_in0: endpoint { + remote-endpoint = <&llcc0_tpdm_out>; + }; + }; + + port@1 { + reg = <1>; + + llcc_tpda_in1: endpoint { + remote-endpoint = <&llcc1_tpdm_out>; + }; + }; + + port@2 { + reg = <2>; + + llcc_tpda_in2: endpoint { + remote-endpoint = <&llcc2_tpdm_out>; + }; + }; + + port@3 { + reg = <3>; + + llcc_tpda_in3: endpoint { + remote-endpoint = <&llcc3_tpdm_out>; + }; + }; + + port@4 { + reg = <4>; + + llcc_tpda_in4: endpoint { + remote-endpoint = <&llcc4_tpdm_out>; + }; + }; + + port@5 { + reg = <5>; + + llcc_tpda_in5: endpoint { + remote-endpoint = <&llcc5_tpdm_out>; + }; + }; + + port@6 { + reg = <6>; + + llcc_tpda_in6: endpoint { + remote-endpoint = <&llcc6_tpdm_out>; + }; + }; + + port@7 { + reg = <7>; + + llcc_tpda_in7: endpoint { + remote-endpoint = <&llcc7_tpdm_out>; + }; + }; + }; + + out-ports { + port { + llcc_tpda_out: endpoint { + remote-endpoint = <&ddr_funnel1_in0>; + }; + }; + }; + }; + + funnel@10d13000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x10d13000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + ddr_funnel1_in0: endpoint { + remote-endpoint = <&llcc_tpda_out>; + }; + }; + }; + + out-ports { + port { + ddr_funnel1_out: endpoint { + remote-endpoint = <&ddr_funnel0_in6>; + }; + }; + }; + }; + + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + + port@2 { + reg = <2>; + + apss_funnel_in2: endpoint { + remote-endpoint = <&ncc2_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&funnel1_in4>; + }; + }; + }; + }; + + funnel@13401000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13401000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@13409000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13409000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + replicator@13490000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13490000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@134a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@134b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@134c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + funnel@134d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x134d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + funnel@13901000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13901000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@13909000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13909000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + replicator@13990000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13990000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@139a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x139a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + replicator@139b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x139b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_2_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in2>; }; }; }; }; - funnel@10cc5000 { - compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; - reg = <0x0 0x10cc5000 0x0 0x1000>; + replicator@139c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x139c0000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; in-ports { port { - tmess_funnel_in0: endpoint { - remote-endpoint = <&tmess_tpda_out>; + ncc1_3_rep_in: endpoint { + remote-endpoint = <&etm7_out>; }; }; }; out-ports { port { - tmess_funnel_out: endpoint { - remote-endpoint = <&funnel1_in2>; + ncc1_3_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in3>; }; }; }; }; - funnel@10d04000 { - compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; - reg = <0x0 0x10d04000 0x0 0x1000>; + funnel@139d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x139d0000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + qcom,cpu-bound-components; in-ports { #address-cells = <1>; #size-cells = <0>; - port@6 { - reg = <6>; + port@0 { + reg = <0>; - ddr_funnel0_in6: endpoint { - remote-endpoint = <&ddr_funnel1_out>; + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; }; }; - }; - out-ports { - port { - ddr_funnel0_out: endpoint { - remote-endpoint = <&dlct1_funnel_in5>; + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; }; }; - }; - }; - tpdm@10d08000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d08000 0x0 0x1000>; + port@2 { + reg = <2>; - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; + ncc1_1_funnel_in2: endpoint { + remote-endpoint = <&ncc1_2_rep_out>; + }; + }; - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; + port@3 { + reg = <3>; - out-ports { - port { - llcc0_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in0>; + ncc1_1_funnel_in3: endpoint { + remote-endpoint = <&ncc1_3_rep_out>; }; }; }; - }; - - tpdm@10d09000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d09000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; out-ports { port { - llcc1_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in1>; + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; }; }; }; }; - tpdm@10d0a000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d0a000 0x0 0x1000>; + cluster2_funnel_l2: funnel@13e01000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13e01000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc2_2_funnel_in2: endpoint { + remote-endpoint = <&ncc2_1_funnel_out>; + }; + }; + }; out-ports { port { - llcc2_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in2>; + ncc2_2_funnel_out: endpoint { + remote-endpoint = <&ncc2_etf_in>; }; }; }; }; - tpdm@10d0b000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d0b000 0x0 0x1000>; + cluster2_etf: tmc@13e09000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13e09000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; + in-ports { + port { + ncc2_etf_in: endpoint { + remote-endpoint = <&ncc2_2_funnel_out>; + }; + }; + }; out-ports { port { - llcc3_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in3>; + ncc2_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in2>; }; }; }; }; - tpdm@10d0c000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d0c000 0x0 0x1000>; + cluster2_rep_2_0: replicator@13e90000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13e90000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; + in-ports { + port { + ncc2_0_rep_in: endpoint { + remote-endpoint = <&etm8_out>; + }; + }; + }; out-ports { port { - llcc4_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in4>; + ncc2_0_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in0>; }; }; }; }; - tpdm@10d0d000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d0d000 0x0 0x1000>; + cluster2_rep_2_1: replicator@13ea0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13ea0000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; + in-ports { + port { + ncc2_1_rep_in: endpoint { + remote-endpoint = <&etm9_out>; + }; + }; + }; out-ports { port { - llcc5_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in5>; + ncc2_1_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in1>; }; }; }; }; - tpdm@10d0e000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d0e000 0x0 0x1000>; + cluster2_rep_2_2: replicator@13eb0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13eb0000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; + in-ports { + port { + ncc2_2_rep_in: endpoint { + remote-endpoint = <&etm10_out>; + }; + }; + }; out-ports { port { - llcc6_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in6>; + ncc2_2_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in2>; }; }; }; }; - tpdm@10d0f000 { - compatible = "qcom,coresight-tpdm", "arm,primecell"; - reg = <0x0 0x10d0f000 0x0 0x1000>; + cluster2_rep_2_3: replicator@13ec0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13ec0000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; - qcom,cmb-element-bits = <32>; - qcom,cmb-msrs-num = <32>; + in-ports { + port { + ncc2_3_rep_in: endpoint { + remote-endpoint = <&etm11_out>; + }; + }; + }; out-ports { port { - llcc7_tpdm_out: endpoint { - remote-endpoint = <&llcc_tpda_in7>; + ncc2_3_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in3>; }; }; }; }; - tpda@10d12000 { - compatible = "qcom,coresight-tpda", "arm,primecell"; - reg = <0x0 0x10d12000 0x0 0x1000>; + cluster2_funnel_l1: funnel@13ed0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13ed0000 0x0 0x1000>; clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + qcom,cpu-bound-components; in-ports { #address-cells = <1>; @@ -8150,96 +9854,40 @@ port@0 { reg = <0>; - llcc_tpda_in0: endpoint { - remote-endpoint = <&llcc0_tpdm_out>; + ncc2_1_funnel_in0: endpoint { + remote-endpoint = <&ncc2_0_rep_out>; }; }; port@1 { reg = <1>; - llcc_tpda_in1: endpoint { - remote-endpoint = <&llcc1_tpdm_out>; + ncc2_1_funnel_in1: endpoint { + remote-endpoint = <&ncc2_1_rep_out>; }; }; port@2 { reg = <2>; - llcc_tpda_in2: endpoint { - remote-endpoint = <&llcc2_tpdm_out>; + ncc2_1_funnel_in2: endpoint { + remote-endpoint = <&ncc2_2_rep_out>; }; }; port@3 { reg = <3>; - llcc_tpda_in3: endpoint { - remote-endpoint = <&llcc3_tpdm_out>; - }; - }; - - port@4 { - reg = <4>; - - llcc_tpda_in4: endpoint { - remote-endpoint = <&llcc4_tpdm_out>; - }; - }; - - port@5 { - reg = <5>; - - llcc_tpda_in5: endpoint { - remote-endpoint = <&llcc5_tpdm_out>; - }; - }; - - port@6 { - reg = <6>; - - llcc_tpda_in6: endpoint { - remote-endpoint = <&llcc6_tpdm_out>; - }; - }; - - port@7 { - reg = <7>; - - llcc_tpda_in7: endpoint { - remote-endpoint = <&llcc7_tpdm_out>; - }; - }; - }; - - out-ports { - port { - llcc_tpda_out: endpoint { - remote-endpoint = <&ddr_funnel1_in0>; - }; - }; - }; - }; - - funnel@10d13000 { - compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; - reg = <0x0 0x10d13000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - - in-ports { - port { - ddr_funnel1_in0: endpoint { - remote-endpoint = <&llcc_tpda_out>; + ncc2_1_funnel_in3: endpoint { + remote-endpoint = <&ncc2_3_rep_out>; }; }; }; out-ports { port { - ddr_funnel1_out: endpoint { - remote-endpoint = <&ddr_funnel0_in6>; + ncc2_1_funnel_out: endpoint { + remote-endpoint = <&ncc2_2_funnel_in2>; }; }; }; @@ -8815,6 +10463,9 @@ status = "disabled"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + glink-edge { interrupts-extended = <&ipcc IPCC_CLIENT_CDSP IPCC_MPROC_SIGNAL_GLINK_QMP @@ -9402,6 +11053,7 @@ }; thermal_nsp0: nsp0-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 1>; trips { @@ -9411,15 +11063,30 @@ type = "hot"; }; + nsp0_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp0-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp1: nsp1-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 2>; trips { @@ -9429,15 +11096,30 @@ type = "hot"; }; + nsp1_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp1-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp2: nsp2-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 3>; trips { @@ -9447,15 +11129,30 @@ type = "hot"; }; + nsp2_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp2-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp3: nsp3-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 4>; trips { @@ -9465,12 +11162,26 @@ type = "hot"; }; + nsp3_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp3-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_gpuss_0: gpuss-0-thermal { diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index f9b5b5718b904..e11096fc641aa 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -82,6 +82,11 @@ }; }; + pmih0108_e1_eusb2_repeater { + vdd18-supply = <&vreg_l15b_1p8>; + vdd3-supply = <&vreg_l5b_3p1>; + }; + sound { compatible = "qcom,kaanapali-sndcard", "qcom,sm8450-sndcard"; model = "Kaanapali-MTP"; @@ -865,6 +870,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/kaanapali/gen80200_zap.mbn"; +}; + &lpass_vamacro { pinctrl-0 = <&dmic01_default>, <&dmic23_default>; pinctrl-names = "default"; @@ -1076,6 +1089,11 @@ status = "okay"; }; +&remoteproc_soccp { + firmware-name = "qcom/kaanapali/soccp.mbn", + "qcom/kaanapali/soccp_dtb.mbn"; +}; + &sdhc_2 { cd-gpios = <&tlmm 55 GPIO_ACTIVE_LOW>; @@ -1348,3 +1366,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index 55d02219ef4e9..7d3604ea0ec2a 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -80,6 +80,11 @@ wakeup-source; }; }; + + pmih0108_e1_eusb2_repeater { + vdd18-supply = <&vreg_l15b_1p8>; + vdd3-supply = <&vreg_l5b_3p1>; + }; }; &apps_rsc { @@ -693,6 +698,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/kaanapali/gen80200_zap.mbn"; +}; + &pmh0101_flash { status = "okay"; @@ -786,6 +799,11 @@ status = "okay"; }; +&remoteproc_soccp { + firmware-name = "qcom/kaanapali/soccp.mbn", + "qcom/kaanapali/soccp_dtb.mbn"; +}; + &tlmm { gpio-reserved-ranges = <36 4>, /* NFC eSE SPI */ <74 1>, /* eSE */ @@ -843,3 +861,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso new file mode 100644 index 0000000000000..f6d7ef82d6e39 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso @@ -0,0 +1,838 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kaanapali staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&{/} { + ete-0 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + ete-1 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + ete-2 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + ete-3 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + ete-4 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + ete-5 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + ete-6 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + ete-7 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; +}; + +&soc { + ctcu: ctcu@10001000 { + compatible = "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&tmc_etr_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&tmc_etr1_out>; + }; + }; + }; + }; + + replicator_qdss: replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_qdss_in: endpoint { + remote-endpoint = <&replicator_swao_out0>; + }; + }; + }; + + out-ports { + port { + replicator_qdss_out: endpoint { + remote-endpoint = <&replicator_etr_in>; + }; + }; + }; + }; + + tmc_etr: tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x04e0 0x0>; + arm,scatter-gather; + + in-ports { + port { + tmc_etr_in: endpoint { + remote-endpoint = <&replicator_etr_out0>; + }; + }; + }; + + out-ports { + port { + tmc_etr_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator_etr: replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_etr_in: endpoint { + remote-endpoint = <&replicator_qdss_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + replicator_etr_out0: endpoint { + remote-endpoint = <&tmc_etr_in>; + }; + }; + + port@1 { + reg = <1>; + + replicator_etr_out1: endpoint { + remote-endpoint = <&tmc_etr1_in>; + }; + }; + }; + }; + + tmc_etr1: tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0500 0x0>; + arm,scatter-gather; + + in-ports { + port { + tmc_etr1_in: endpoint { + remote-endpoint = <&replicator_etr_out1>; + }; + }; + }; + + out-ports { + port { + tmc_etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + + tgu@11301000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11301000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tmc@11305000 { + out-ports { + port { + tmc_etf_out: endpoint { + remote-endpoint = <&replicator_swao_in>; + }; + }; + }; + }; + + replicator_swao: replicator@11306000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x11306000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_swao_in: endpoint { + remote-endpoint = <&tmc_etf_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + replicator_swao_out0: endpoint { + remote-endpoint = <&replicator_qdss_in>; + }; + }; + }; + }; + + tgu@1130e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x1130e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@1130f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x1130f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11310000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11310000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + replicator@1d090000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d090000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d0a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d0b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d0c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d0d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d0e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d0e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d081000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d081000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + funnel@1d021000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d021000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@1d029000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d029000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + replicator@1d190000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d190000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d1a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x1d1a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + funnel@1d181000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d181000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + funnel@1d121000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x1d121000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@1d129000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x1d129000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in54>; + }; + }; + }; + }; + + tn@111b8000 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@36 { + reg = <0x36>; + + tn_ag_in54: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 7aa9653bd456e..192a5caa6ccea 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -26,6 +26,7 @@ #include #include #include +#include #include "kaanapali-ipcc.h" @@ -48,6 +49,7 @@ power-domains = <&cpu_pd0>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; l2_0: l2-cache { compatible = "cache"; @@ -65,6 +67,7 @@ power-domains = <&cpu_pd1>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu2: cpu@200 { @@ -76,6 +79,7 @@ power-domains = <&cpu_pd2>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu3: cpu@300 { @@ -87,6 +91,7 @@ power-domains = <&cpu_pd3>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu4: cpu@400 { @@ -98,6 +103,7 @@ power-domains = <&cpu_pd4>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu5: cpu@500 { @@ -109,6 +115,7 @@ power-domains = <&cpu_pd5>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 0>; + #cooling-cells = <2>; }; cpu6: cpu@10000 { @@ -120,6 +127,7 @@ power-domains = <&cpu_pd6>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 1>; + #cooling-cells = <2>; l2_1: l2-cache { compatible = "cache"; @@ -137,6 +145,7 @@ power-domains = <&cpu_pd7>; power-domain-names = "psci"; clocks = <&pdp_scmi_perf 1>; + #cooling-cells = <2>; }; cpu-map { @@ -265,7 +274,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -504,6 +513,32 @@ }; }; + smp2p-soccp { + compatible = "qcom,smp2p"; + + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,smem = <617>, <616>; + qcom,local-pid = <0>; + qcom,remote-pid = <19>; + + soccp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + soccp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; @@ -1513,6 +1548,57 @@ }; }; + remoteproc_soccp: remoteproc-soccp@d00000 { + compatible = "qcom,kaanapali-soccp-pas"; + reg = <0x0 0x00d00000 0x0 0x200000>; + + interrupts-extended = <&intc GIC_SPI 167 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "pong"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; + + memory-region = <&soccp_mem>, + <&soccp_dtb_mem>; + + qcom,smem-states = <&soccp_smp2p_out 0>, + <&soccp_smp2p_out 8>; + qcom,smem-state-names = "stop", + "ping"; + + status = "okay"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <19>; + label = "soccp"; + }; + }; + + rng: rng@10c3000 { + compatible = "qcom,kaanapali-trng", "qcom,trng"; + reg = <0x0 0x010c3000 0x0 0x1000>; + }; + ipcc: mailbox@1106000 { compatible = "qcom,kaanapali-ipcc", "qcom,ipcc"; reg = <0x0 0x01106000 0x0 0x1000>; @@ -2545,6 +2631,31 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; + cryptobam: dma-controller@1dc4000 { + compatible = "qcom,bam-v2.0.0"; + reg = <0x0 0x01dc4000 0x0 0x22000>; + interrupts = ; + #dma-cells = <1>; + iommus = <&apps_smmu 0xc0 0x0>, + <&apps_smmu 0xc1 0x0>; + qcom,ee = <0>; + qcom,num-ees = <4>; + num-channels = <20>; + qcom,controlled-remotely; + }; + + crypto: crypto@1dfa000 { + compatible = "qcom,kaanapali-qce", "qcom,sm8150-qce", "qcom,qce"; + reg = <0x0 0x01dfa000 0x0 0x6000>; + interconnects = <&aggre_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "memory"; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0xc0 0x0>, + <&apps_smmu 0xc1 0x0>; + }; + tcsr_mutex: hwlock@1f40000 { compatible = "qcom,tcsr-mutex"; reg = <0x0 0x01f40000 0x0 0x20000>; @@ -2577,6 +2688,238 @@ #power-domain-cells = <1>; }; + gpu: gpu@3d00000 { + compatible = "qcom,adreno-44050a01", "qcom,adreno"; + reg = <0x0 0x03d00000 0x0 0x6c000>, + <0x0 0x03d9e000 0x0 0x2000>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem"; + + interrupts = ; + + iommus = <&adreno_smmu 0 0x0>, + <&adreno_smmu 1 0x0>; + + operating-points-v2 = <&gpu_opp_table>; + + qcom,gmu = <&gmu>; + #cooling-cells = <2>; + + nvmem-cells = <&gpu_speed_bin>; + nvmem-cell-names = "speed_bin"; + + interconnects = <&gem_noc MASTER_GFX3D QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "gfx-mem"; + + gpu_zap_shader: zap-shader { + memory-region = <&gpu_microcode_mem>; + }; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2-adreno", + "operating-points-v2"; + + opp-222000000 { + opp-hz = /bits/ 64 <222000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + /* ACD is disabled */ + }; + + opp-282000000 { + opp-hz = /bits/ 64 <282000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xca2e5ffd>; + }; + + opp-342000000 { + opp-hz = /bits/ 64 <342000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe22a5ffd>; + }; + + opp-382000000 { + opp-hz = /bits/ 64 <382000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa22c5ffd>; + }; + + opp-422000000 { + opp-hz = /bits/ 64 <422000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa22c5ffd>; + }; + + opp-461000000 { + opp-hz = /bits/ 64 <461000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82e5ffd>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82c5ffd>; + }; + + opp-539000000 { + opp-hz = /bits/ 64 <539000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc82b5ffd>; + }; + + opp-578000000 { + opp-hz = /bits/ 64 <578000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02c5ffd>; + }; + + opp-646000000 { + opp-hz = /bits/ 64 <646000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02c5ffd>; + }; + + opp-726000000 { + opp-hz = /bits/ 64 <726000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882f5ffd>; + }; + + opp-826000000 { + opp-hz = /bits/ 64 <826000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82c5ffd>; + }; + + opp-902000000 { + opp-hz = /bits/ 64 <902000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-967000000 { + opp-hz = /bits/ 64 <967000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882a5ffd>; + }; + + opp-1050000000 { + opp-hz = /bits/ 64 <1050000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x88295ffd>; + }; + + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x07>; + qcom,opp-acd-level = <0xa02e5ffd>; + }; + + opp-1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x03>; + qcom,opp-acd-level = <0x802d5ffd>; + }; + }; + }; + + gmu: gmu@3d6c000 { + compatible = "qcom,adreno-gmu-840.1", "qcom,adreno-gmu"; + + reg = <0x0 0x03d6c000 0x0 0x68000>; + reg-names = "gmu"; + + interrupts = , + ; + interrupt-names = "hfi", "gmu"; + + clocks = <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>, + <&gcc GCC_GPU_GEMNOC_GFX_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>; + clock-names = "ahb", + "gmu", + "cxo", + "memnoc", + "hub"; + + power-domains = <&gpucc GPU_CC_CX_GDSC>, + <&gxclkctl GX_CLKCTL_GX_GDSC>; + power-domain-names = "cx", + "gx"; + + iommus = <&adreno_smmu 5 0x0>; + + qcom,qmp = <&aoss_qmp>; + + operating-points-v2 = <&gmu_opp_table>; + + gmu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-475000000 { + opp-hz = /bits/ 64 <475000000>; + opp-level = ; + }; + + opp-575000000 { + opp-hz = /bits/ 64 <575000000>; + opp-level = ; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-level = ; + }; + + opp-725000000 { + opp-hz = /bits/ 64 <725000000>; + opp-level = ; + }; + + opp-750000000 { + opp-hz = /bits/ 64 <750000000>; + opp-level = ; + }; + }; + }; + gxclkctl: clock-controller@3d64000 { compatible = "qcom,kaanapali-gxclkctl"; reg = <0x0 0x03d64000 0x0 0x6000>; @@ -2601,6 +2944,47 @@ #power-domain-cells = <1>; }; + adreno_smmu: iommu@3da0000 { + compatible = "qcom,kaanapali-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x3da0000 0x0 0x40000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + dma-coherent; + + power-domains = <&gpucc GPU_CC_CX_GDSC>; + + clocks = <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>; + clock-names = "hlos"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + remoteproc_adsp: remoteproc@6800000 { compatible = "qcom,kaanapali-adsp-pas", "qcom,sm8550-adsp-pas"; reg = <0x0 0x06800000 0x0 0x10000>; @@ -3142,47 +3526,175 @@ }; }; - usb_hsphy: phy@88e3000 { - compatible = "qcom,kaanapali-m31-eusb2-phy", - "qcom,sm8750-m31-eusb2-phy"; - reg = <0x0 0x88e3000 0x0 0x29c>; - - clocks = <&tcsr TCSR_USB2_CLKREF_EN>; - clock-names = "ref"; - - resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; - - #phy-cells = <0>; - - status = "disabled"; - }; - - usb_dp_qmpphy: phy@88e8000 { - compatible = "qcom,kaanapali-qmp-usb3-dp-phy", - "qcom,sm8750-qmp-usb3-dp-phy"; - reg = <0x0 0x088e8000 0x0 0x4000>; - - clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, - <&tcsr TCSR_USB3_CLKREF_EN>, - <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, - <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; - clock-names = "aux", - "ref", - "com_aux", - "usb3_pipe"; - - resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, - <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; - reset-names = "phy", - "common"; - - power-domains = <&gcc GCC_USB3_PHY_GDSC>; - - #clock-cells = <1>; - #phy-cells = <1>; - - orientation-switch; + camss: isp@9253000 { + compatible = "qcom,kaanapali-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x09523000 0x0 0x2000>, + <0x0 0x09525000 0x0 0x2000>, + <0x0 0x09527000 0x0 0x2000>, + <0x0 0x09529000 0x0 0x2000>, + <0x0 0x0952b000 0x0 0x2000>, + <0x0 0x0952d000 0x0 0x2000>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x1300>, + <0x0 0x092f0000 0x0 0x1300>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; status = "disabled"; ports { @@ -3191,28 +3703,120 @@ port@0 { reg = <0>; - - usb_dp_qmpphy_out: endpoint { - }; }; port@1 { reg = <1>; - - usb_dp_qmpphy_usb_ss_in: endpoint { - remote-endpoint = <&usb_dwc3_ss>; - }; }; port@2 { reg = <2>; + }; - usb_dp_qmpphy_dp_in: endpoint { - }; + port@3 { + reg = <3>; + }; + + port@4 { + reg = <4>; + }; + + port@5 { + reg = <5>; }; }; }; + cci0: cci@941b000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941b000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@941c000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941c000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci1_0_default &cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep &cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@941d000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941d000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@956d000 { compatible = "qcom,kaanapali-camcc"; reg = <0x0 0x0956d000 0x0 0x80000>; @@ -3770,36 +4374,284 @@ #interrupt-cells = <2>; wakeup-parent = <&pdc>; - hub_i2c0_data_clk: hub-i2c0-data-clk-state { - /* SDA, SCL */ - pins = "gpio66", "gpio67"; - function = "i2chub0_se0"; + cam0_default: cam0-default-state { + pins = "gpio89"; + function = "cam_mclk"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; - hub_i2c1_data_clk: hub-i2c1-data-clk-state { - /* SDA, SCL */ - pins = "gpio78", "gpio79"; - function = "i2chub0_se1"; + cam1_default: cam1-default-state { + pins = "gpio90"; + function = "cam_mclk"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; - hub_i2c2_data_clk: hub-i2c2-data-clk-state { - /* SDA, SCL */ - pins = "gpio68", "gpio69"; - function = "i2chub0_se2"; + cam2_default: cam2-default-state { + pins = "gpio91"; + function = "cam_asc_mclk2"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; - hub_i2c3_data_clk: hub-i2c3-data-clk-state { - /* SDA, SCL */ - pins = "gpio70", "gpio71"; - function = "i2chub0_se3"; + cam3_default: cam3-default-state { + pins = "gpio92"; + function = "cam_mclk"; drive-strength = <2>; - bias-pull-up; + bias-disable; + }; + + cam4_default: cam4-default-state { + pins = "gpio93"; + function = "cam_asc_mclk4"; + drive-strength = <2>; + bias-disable; + }; + + cam5_default: cam5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam6_default: cam6-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam7_default: cam7-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio109"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio110"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio109"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio110"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio112"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio112"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio107"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio160"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio107"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio160"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio108"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio149"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio108"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio149"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + hub_i2c0_data_clk: hub-i2c0-data-clk-state { + /* SDA, SCL */ + pins = "gpio66", "gpio67"; + function = "i2chub0_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + hub_i2c1_data_clk: hub-i2c1-data-clk-state { + /* SDA, SCL */ + pins = "gpio78", "gpio79"; + function = "i2chub0_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + hub_i2c2_data_clk: hub-i2c2-data-clk-state { + /* SDA, SCL */ + pins = "gpio68", "gpio69"; + function = "i2chub0_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + hub_i2c3_data_clk: hub-i2c3-data-clk-state { + /* SDA, SCL */ + pins = "gpio70", "gpio71"; + function = "i2chub0_se3"; + drive-strength = <2>; + bias-pull-up; }; hub_i2c4_data_clk: hub-i2c4-data-clk-state { @@ -4377,6 +5229,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + arm,primecell-periphid = <0x000f0c00>; in-ports { #address-cells = <1>; @@ -5831,6 +6684,18 @@ }; }; + efuse@221c8000 { + compatible = "qcom,kaanapali-qfprom", "qcom,qfprom"; + reg = <0x0 0x221c8000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + gpu_speed_bin: gpu-speed-bin@142 { + reg = <0x142 0x2>; + bits = <3 9>; + }; + }; + nsp_noc: interconnect@260c0000 { compatible = "qcom,kaanapali-nsp-noc"; reg = <0x0 0x260c0000 0x0 0x21280>; @@ -6112,6 +6977,160 @@ reg = <0x100 0x80>; }; }; + + usb_hsphy: phy@88e3000 { + compatible = "qcom,kaanapali-m31-eusb2-phy", + "qcom,sm8750-m31-eusb2-phy"; + reg = <0x0 0x88e3000 0x0 0x29c>; + + clocks = <&tcsr TCSR_USB2_CLKREF_EN>; + clock-names = "ref"; + + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_dp_qmpphy: phy@88e8000 { + compatible = "qcom,kaanapali-qmp-usb3-dp-phy", + "qcom,sm8750-qmp-usb3-dp-phy"; + reg = <0x0 0x088e8000 0x0 0x4000>; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, + <&tcsr TCSR_USB3_CLKREF_EN>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "usb3_pipe"; + + resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, + <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; + reset-names = "phy", + "common"; + + power-domains = <&gcc GCC_USB3_PHY_GDSC>; + + #clock-cells = <1>; + #phy-cells = <1>; + + orientation-switch; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_dp_qmpphy_out: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_dp_qmpphy_usb_ss_in: endpoint { + remote-endpoint = <&usb_dwc3_ss>; + }; + }; + + port@2 { + reg = <2>; + + usb_dp_qmpphy_dp_in: endpoint { + }; + }; + }; + }; + + usb: usb@a600000 { + compatible = "qcom,kaanapali-dwc3", "qcom,snps-dwc3"; + reg = <0x0 0x0a600000 0x0 0xfc100>; + + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interrupts-extended = <&intc GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 14 IRQ_TYPE_EDGE_BOTH>, + <&pdc 15 IRQ_TYPE_EDGE_BOTH>, + <&pdc 17 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dwc_usb3", + "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; + + power-domains = <&gcc GCC_USB30_PRIM_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&gcc GCC_USB30_PRIM_BCR>; + + interconnects = <&aggre_noc MASTER_USB3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_USB3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "usb-ddr", "apps-usb"; + iommus = <&apps_smmu 0x40 0x0>; + + phys = <&usb_hsphy>, <&usb_dp_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", "usb3-phy"; + + snps,hird-threshold = /bits/ 8 <0x0>; + snps,usb2-gadget-lpm-disable; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,is-utmi-l1-suspend; + snps,usb3_lpm_capable; + snps,usb2-lpm-disable; + snps,has-lpm-erratum; + tx-fifo-resize; + dma-coherent; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_dwc3_hs: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_dwc3_ss: endpoint { + remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; + }; + }; + }; + }; }; thermal-zones { @@ -6764,13 +7783,15 @@ }; gpuss-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 0>; trips { - gpuss-0-hot { - temperature = <120000>; + gpuss_0_alert0: gpuss-0-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-0-critical { @@ -6779,16 +7800,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_0_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 1>; trips { - gpuss-1-hot { - temperature = <120000>; + gpuss_1_alert0: gpuss-1-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-1-critical { @@ -6797,16 +7827,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_1_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-2-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 2>; trips { - gpuss-2-hot { - temperature = <120000>; + gpuss_2_alert0: gpuss-2-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-2-critical { @@ -6815,16 +7854,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_2_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-3-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 3>; trips { - gpuss-3-hot { - temperature = <120000>; + gpuss_3_alert0: gpuss-3-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-3-critical { @@ -6833,16 +7881,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_3_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-4-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 4>; trips { - gpuss-4-hot { - temperature = <120000>; + gpuss_4_alert0: gpuss-4-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-4-critical { @@ -6851,16 +7908,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_4_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-5-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 5>; trips { - gpuss-5-hot { - temperature = <120000>; + gpuss_5_alert0: gpuss-5-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-5-critical { @@ -6869,16 +7935,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_5_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-6-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 6>; trips { - gpuss-6-hot { - temperature = <120000>; + gpuss_6_alert0: gpuss-6-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-6-critical { @@ -6887,16 +7962,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_6_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-7-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 7>; trips { - gpuss-7-hot { - temperature = <120000>; + gpuss_7_alert0: gpuss-7-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-7-critical { @@ -6905,16 +7989,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_7_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-8-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 8>; trips { - gpuss-8-hot { - temperature = <120000>; + gpuss_8_alert0: gpuss-8-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-8-critical { @@ -6923,16 +8016,25 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_8_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-9-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 9>; trips { - gpuss-9-hot { - temperature = <120000>; + gpuss_9_alert0: gpuss-9-alert0 { + temperature = <105000>; hysteresis = <5000>; - type = "hot"; + type = "passive"; }; gpuss-9-critical { @@ -6941,12 +8043,26 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_9_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-10-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens5 10>; trips { + gpuss_10_alert0: gpuss-10-alert0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; gpuss-10-hot { temperature = <120000>; hysteresis = <5000>; @@ -6959,6 +8075,13 @@ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_10_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddr-thermal { diff --git a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso new file mode 100644 index 0000000000000..91e4cda45b491 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kodiak specific modifications required to boot in EL2. + */ + +/dts-v1/; +/plugin/; + +&gpu_zap_shader { + status = "disabled"; +}; + +&remoteproc_adsp { + iommus = <&apps_smmu 0x1800 0x0>; +}; + +&remoteproc_cdsp { + iommus = <&apps_smmu 0x11a0 0x0400>; +}; + +&remoteproc_mpss { + status = "disabled"; +}; + +&reserved_memory { + #address-cells = <2>; + #size-cells = <2>; + + wlan_ce_mem: wlan-ce@4cd000 { + no-map; + reg = <0x0 0x004cd000 0x0 0x1000>; + }; +}; + +&venus { + status = "disabled"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + memory-region = <&wlan_fw_mem>, <&wlan_ce_mem>; + status = "okay"; + + wifi-firmware { + iommus = <&apps_smmu 0x1c02 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kodiak-staging.dtso b/arch/arm64/boot/dts/qcom/kodiak-staging.dtso new file mode 100644 index 0000000000000..1d4c6d7d39dd0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kodiak-staging.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kodiak staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@6b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x6b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..db84a8d70818f 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -91,7 +91,7 @@ }; }; - reserved-memory { + reserved_memory: reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; @@ -191,9 +191,12 @@ qcom,vmid = ; }; - adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap@9cb80000 { - reg = <0x0 0x9cb80000 0x0 0x800000>; - no-map; + adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap { + compatible = "shared-dma-pool"; + alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; + reusable; + alignment = <0x0 0x400000>; + size = <0x0 0x800000>; }; }; @@ -863,7 +866,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -1050,6 +1053,8 @@ qcom,dll-config = <0x0007642c>; qcom,ddr-config = <0x80040868>; + qcom,ice = <&sdhc_ice>; + mmc-ddr-1_8v; mmc-hs200-1_8v; mmc-hs400-1_8v; @@ -1076,6 +1081,17 @@ }; }; + sdhc_ice: crypto@7c8000 { + compatible = "qcom,sc7280-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x007c8000 0x0 0x18000>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>, + <&gcc GCC_SDCC1_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&rpmhpd SC7280_CX>; + }; + gpi_dma0: dma-controller@900000 { #dma-cells = <3>; compatible = "qcom,sc7280-gpi-dma", "qcom,sm6350-gpi-dma"; @@ -3386,6 +3402,8 @@ power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; gfx_0_tbu: tbu@3dd9000 { @@ -3427,6 +3445,9 @@ qcom,smem-states = <&modem_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + tmd-names = "pa", "modem"; + status = "disabled"; glink-edge { @@ -3517,6 +3538,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3536,6 +3558,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss"; }; funnel@6041000 { @@ -3685,6 +3708,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao"; }; cti@6b01000 { @@ -3693,6 +3717,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_1"; }; cti@6b02000 { @@ -3701,6 +3726,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_2"; }; cti@6b03000 { @@ -3709,6 +3735,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_3"; }; funnel@6b04000 { @@ -3863,6 +3890,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3882,6 +3910,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3901,6 +3930,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3920,6 +3950,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3939,6 +3970,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3958,6 +3990,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aoss"; }; etm@7040000 { @@ -4404,12 +4437,20 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; + }; - port { - usb2_role_switch: endpoint { - remote-endpoint = <&eud_ep>; - }; - }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; }; qspi: spi@88dc000 { @@ -4578,6 +4619,7 @@ compatible = "qcom,fastrpc-compute-cb"; reg = <5>; iommus = <&apps_smmu 0x1805 0x0>; + qcom,nsessions = <5>; dma-coherent; }; }; @@ -4736,16 +4778,22 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; - status = "disabled"; - ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; + eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + eud_con: endpoint { }; }; }; @@ -4787,6 +4835,9 @@ qcom,smem-states = <&cdsp_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -4906,6 +4957,7 @@ }; }; }; + }; usb_1: usb@a600000 { @@ -4972,6 +5024,7 @@ reg = <0>; usb_1_dwc3_hs: endpoint { + remote-endpoint = <&eud_ep>; }; }; @@ -5908,6 +5961,13 @@ function = "edp_hot"; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio35"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + mi2s0_data0: mi2s0-data0-state { pins = "gpio98"; function = "mi2s0_data0"; @@ -5948,6 +6008,11 @@ function = "mi2s1_ws"; }; + mi2s1_mclk: mi2s1-mclk-state { + pins = "gpio105"; + function = "sec_mi2s"; + }; + pcie0_clkreq_n: pcie0-clkreq-n-state { pins = "gpio88"; function = "pcie0_clkreqn"; @@ -7716,6 +7781,8 @@ }; nspss0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 3>; trips { @@ -7725,15 +7792,31 @@ type = "hot"; }; + nspss0_alert1: trip-point1 { + temperature = <100000>; + hysteresis = <5000>; + type = "passive"; + }; + nspss0_crit: nspss0-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nspss0_alert1>; + cooling-device = <&remoteproc_cdsp THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nspss1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 4>; trips { @@ -7743,12 +7826,26 @@ type = "hot"; }; + nspss1_alert1: trip-point1 { + temperature = <100000>; + hysteresis = <5000>; + type = "passive"; + }; + nspss1_crit: nspss1-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nspss1_alert1>; + cooling-device = <&remoteproc_cdsp THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; video-thermal { @@ -7787,7 +7884,9 @@ }; }; - mdmss0-thermal { + mdmss0_thermal: mdmss0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 7>; trips { @@ -7797,15 +7896,35 @@ type = "hot"; }; + mdmss0_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss0_crit: mdmss0-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; - mdmss1-thermal { + mdmss1_thermal: mdmss1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 8>; trips { @@ -7815,15 +7934,35 @@ type = "hot"; }; + mdmss1_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss1_crit: mdmss1-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; - mdmss2-thermal { + mdmss2_thermal: mdmss2-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 9>; trips { @@ -7833,15 +7972,35 @@ type = "hot"; }; + mdmss2_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss2_crit: mdmss2-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss2_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss2_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; - mdmss3-thermal { + mdmss3_thermal: mdmss3-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 10>; trips { @@ -7851,12 +8010,30 @@ type = "hot"; }; + mdmss3_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss3_crit: mdmss3-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss3_alert1>; + cooling-device = <&remoteproc_mpss 0 0 2>; + }; + + map1 { + trip = <&mdmss3_alert1>; + cooling-device = <&remoteproc_mpss 1 0 2>; + }; + }; }; camera0-thermal { diff --git a/arch/arm64/boot/dts/qcom/lemans-auto.dtsi b/arch/arm64/boot/dts/qcom/lemans-auto.dtsi index 8db958d60fd1d..07fa9cb148ae6 100644 --- a/arch/arm64/boot/dts/qcom/lemans-auto.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-auto.dtsi @@ -102,3 +102,7 @@ }; }; }; + +&iris { + firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi new file mode 100644 index 0000000000000..d531f89dda08e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 8 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; +}; + +&cam_cci3 { + /* GMSL deserializer 3 */ + qcom,cam-gmsl-deserializer3 { + cell-index = <3>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET3"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser3_port0: endpoint { + remote-endpoint = <&gmsl_sensor12_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser3_port1: endpoint { + remote-endpoint = <&gmsl_sensor13_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser3_port2: endpoint { + remote-endpoint = <&gmsl_sensor14_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser3_port3: endpoint { + remote-endpoint = <&gmsl_sensor15_ep>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 0 */ + qcom,cam-gmsl-sensor12 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor12_ep: endpoint { + remote-endpoint = <&deser3_port0>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 1 */ + qcom,cam-gmsl-sensor13 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor13_ep: endpoint { + remote-endpoint = <&deser3_port1>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 2 */ + qcom,cam-gmsl-sensor14 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor14_ep: endpoint { + remote-endpoint = <&deser3_port2>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 3 */ + qcom,cam-gmsl-sensor15 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <15>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor15_ep: endpoint { + remote-endpoint = <&deser3_port3>; + }; + }; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi new file mode 100644 index 0000000000000..d6cce86922c26 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -0,0 +1,2552 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cci0: qcom,cci0@ac13000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac13000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x13000>; + interrupts = ; + interrupt-names = "CCI0"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1@ac14000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac14000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x14000>; + interrupts = ; + interrupt-names = "CCI1"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci2: qcom,cci2@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "CCI2"; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "cci_2_clk_src", + "cci_2_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci4_active>; + pinctrl-1 = <&cci4_suspend>; + pinctrl-2 = <&cci5_active>; + pinctrl-3 = <&cci5_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <2>; + status = "ok"; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci2: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci2: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci3: qcom,cci3@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "CCI3"; + operating-points-v2 = <&cci3_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_3_CLK_SRC>, + <&camcc CAM_CC_CCI_3_CLK>; + clock-names = "cci_3_clk_src", + "cci_3_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_3_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci6_active>; + pinctrl-1 = <&cci6_suspend>; + pinctrl-2 = <&cci7_active>; + pinctrl-3 = <&cci7_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <3>; + status = "ok"; + + cci3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci3: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci3: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci3: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci3: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_csiphy0: qcom,csiphy0@ac9c000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9c000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x9c000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + aggregator-rx; + cell-index = <0>; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ac9e000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xac9e000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x9e000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <1>; + aggregator-rx; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@aca0000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca0000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0xa0000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <2>; + aggregator-rx; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy3: qcom,csiphy3@aca2000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca2000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy3_opp_table>; + reg-cam-base = <0xa2000>; + interrupts = ; + interrupt-names = "CSIPHY3"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy3_clk", + "csi3phytimer_clk_src", + "csi3phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <3>; + aggregator-rx; + status = "ok"; + + csiphy3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg17: qcom,tpg17@acac000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacac000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xac000 0x11000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <17>; + phy-id = <0>; + status = "ok"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg18: qcom,tpg18@acad000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacad000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xad000 0x11000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <18>; + phy-id = <1>; + status = "ok"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg19: qcom,tpg19@acae000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacae000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xae000 0x11000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <19>; + phy-id = <2>; + status = "ok"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "ok"; + }; + + cam_cpas: qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac11000 0x0 0x1000>, + <0x0 0xac1A000 0x0 0x9400>, + <0x0 0xbbf0000 0x0 0x1f00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x11000 0x1A000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + clock-cntl-level = "suspend", "svs_l1", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <480000000>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "cci0", "cci1", "cci2", "cci3","csid0", "csid1", + "csid2", "csid3", "csid4", "csid5", "csid6", + "ife0", "ife1", "ife2", "ife3", "ife4", + "ife5", "ife6", "ipe0", "sfe0", "sfe1", + "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "icp0", "tpg17", "tpg18", "tpg19"; + enable-secure-qos-update = <1>; + cell-index = <0>; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + icp_all_rd: icp-all-rd { + cell-index = <0>; + node-name = "icp-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + ife_0_wr_0: ife-0-wr-0 { + cell-index = <1>; + node-name = "ife-0-wr-0"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_0_wr_1: ife-0-wr-1 { + cell-index = <2>; + node-name = "ife-0-wr-1"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_1_wr_0: ife-1-wr-0 { + cell-index = <3>; + node-name = "ife-1-wr-0"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_1_wr_1: ife-1-wr-1 { + cell-index = <4>; + node-name = "ife-1-wr-1"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_lite_0_wr_0: ife-lite-0-wr-0 { + cell-index = <5>; + node-name = "ife-lite-0-wr-0"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_1_wr_0: ife-lite-1-wr-0 { + cell-index = <6>; + node-name = "ife-lite-1-wr-0"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_2_wr_0: ife-lite-2-wr-0 { + cell-index = <7>; + node-name = "ife-lite-2-wr-0"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_3_wr_0: ife-lite-3-wr-0 { + cell-index = <8>; + node-name = "ife-lite-3-wr-0"; + client-name = "ife5"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_4_wr_0: ife-lite-4-wr-0 { + cell-index = <9>; + node-name = "ife-lite-4-wr-0"; + client-name = "ife6"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ipe_0_rd_all: ipe-0-rd-all { + cell-index = <10>; + node-name = "ipe-0-rd-all"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd1>; + }; + + ipe_0_wr_2: ipe-0-wr-2 { + cell-index = <11>; + node-name = "ipe-0-wr-2"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr2>; + }; + + ipe_cdm0_all_rd: ipe-cdm0-all-rd { + cell-index = <12>; + node-name = "ipe-cdm0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { + cell-index = <13>; + node-name = "rt-cdm0-all-rd-2"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { + cell-index = <14>; + node-name = "rt-cdm1-all-rd-2"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { + cell-index = <15>; + node-name = "rt-cdm2-all-rd-2"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { + cell-index = <16>; + node-name = "rt-cdm3-all-rd-2"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + sfe_0_rd_0: sfe-0-rd-0 { + cell-index = <17>; + node-name = "sfe-0-rd-0"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_1_rd_0: sfe-1-rd-0 { + cell-index = <18>; + node-name = "sfe-1-rd-0"; + client-name = "sfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt_rd2: level1-nrt-rd2 { + cell-index = <19>; + node-name = "level1-nrt-rd2"; + parent-node = <&level2_nrt_rd2>; + traffic-merge-type = ; + }; + + level1_rt_rd0: level1-rt-read0 { + cell-index = <20>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd0>; + traffic-merge-type = ; + }; + + level1_rt_wr0: level1-rt-wr0 { + cell-index = <21>; + node-name = "level1-rt-wr0"; + parent-node = <&level2_rt_wr0>; + traffic-merge-type = ; + }; + + level1_rt_wr1: level1-rt-wr1 { + cell-index = <22>; + node-name = "level1-rt-wr1"; + parent-node = <&level2_rt_wr1>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_icp_rd: level2-icp-rd { + cell-index = <23>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd1: level2-nrt-rd1 { + cell-index = <24>; + node-name = "level2-nrt-rd1"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd2: level2-nrt-rd2 { + cell-index = <25>; + node-name = "level2-nrt-rd2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_wr2: level2-nrt-wr2 { + cell-index = <26>; + node-name = "level2-nrt-wr2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_rd0: level2-rt-read0 { + cell-index = <27>; + node-name = "level2-rt-rd0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr0: level2-rt-wr0 { + cell-index = <28>; + node-name = "level2-rt-wr0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr1: level2-rt-wr1 { + cell-index = <29>; + node-name = "level2-rt-wr1"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_use_pil; + status = "ok"; + }; + + qcom,cam-i3c-id-table { + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,camera-main { + compatible = "qcom,camera"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-smmu-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0860 0x400>, + <&apps_smmu 0x0C60 0x400>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x400>, + <&apps_smmu 0x0840 0x480>, + <&apps_smmu 0x08C0 0x480>, + <&apps_smmu 0x0C00 0x400>, + <&apps_smmu 0x0C40 0x480>, + <&apps_smmu 0x0CC0 0x480>; + cam-smmu-label = "icp"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + subregion_support; + status = "ok"; + + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x10400000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xfc00000>; + iova-region-id = <0x1>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x3400 0x0020>, + <&apps_smmu 0x3420 0x0020>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 64 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xfffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid690"; + reg = <0x0 0xac7a000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid0", "csid_top"; + reg-cam-base = <0x7a000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid690"; + reg = <0x0 0xac7c000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid1", "csid_top"; + reg-cam-base = <0x7c000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac84000 0x0 0xf01>; + reg-names = "csid-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac88000 0x0 0xf01>; + reg-names = "csid-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-names = "csid-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + clock-control-debugfs = "true"; + cell-index = <4>; + status = "ok"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-names = "csid-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + clock-control-debugfs = "true"; + cell-index = <5>; + status = "ok"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac94000 0x0 0xf01>; + reg-names = "csid-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + clock-control-debugfs = "true"; + cell-index = <6>; + status = "ok"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp: qcom,icp { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0xac04000 0x0 0x1000>; + reg-names ="icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&pil_camera_mem>; + src-clock-name = "cam_cc_icp_clk_src"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "cam_cc_soc_fast_ahb_clk_src", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk_src", + "cam_cc_icp_clk"; + clock-rates = <300000000 0 480000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + nrt-device; + fw_name = "qcom/sa8775p/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <12>; + cell-index = <0>; + status = "ok"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0 { + compatible = "qcom,vfe690"; + reg = <0x0 0xac4d000 0x0 0xd000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0x4d000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_0_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_ife_0_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1 { + compatible = "qcom,vfe690"; + reg = <0x0 0xac5a000 0x0 0xd000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0x5a000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_1_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_ife_1_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac84000 0x0 0x1d00>; + reg-names = "ife-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <2>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac88000 0x0 0x1d00>; + reg-names = "ife-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <3>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac8c000 0x0 0x1d00>; + reg-names = "ife-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <4>; + status = "ok"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac90000 0x0 0x1d00>; + reg-names = "ife-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <5>; + status = "ok"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac94000 0x0 0x1d00>; + reg-names = "ife-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <6>; + status = "ok"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac2d000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x2d000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + src-clock-name = "cam_cc_ipe_clk_src"; + clocks = <&camcc CAM_CC_CPAS_IPE_CLK>, + <&camcc CAM_CC_IPE_AHB_CLK>, + <&camcc CAM_CC_IPE_CLK>, + <&camcc CAM_CC_IPE_CLK_SRC>, + <&camcc CAM_CC_IPE_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_cpas_ipe_clk", + "cam_cc_ipe_ahb_clk", + "cam_cc_ipe_clk", + "cam_cc_ipe_clk_src", + "cam_cc_ipe_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 480000000 0 300000000>, + <0 0 0 600000000 0 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <14 15>; + cell-index = <0>; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm0 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "dualife0"; + single-context-cdm; + cell-index = <0>; + status = "ok"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm1 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac27000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x27000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife1", "dualife1"; + single-context-cdm; + cell-index = <1>; + status = "ok"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm2 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac28000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x28000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <2>; + status = "ok"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm3 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac29000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x29000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <3>; + status = "ok"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0xac74000 0x0 0x1000>; + reg-names = "sfe-lite0"; + reg-cam-base = <0x74000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0xac75000 0x0 0x1000>; + reg-names = "sfe-lite1"; + reg-cam-base = <0x75000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_1_CLK>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_cpas_sfe_1_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci0_active: cci0-active { + mux { + /* CLK, DATA */ + pins = "gpio61","gpio60"; + function = "cci_i2c"; + }; + + config { + pins = "gpio61","gpio60"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci0_suspend: cci0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio61","gpio60"; + function = "cci_i2c"; + }; + + config { + pins = "gpio61","gpio60"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_active: cci1-active { + mux { + /* CLK, DATA */ + pins = "gpio53","gpio52"; + function = "cci_i2c"; + }; + + config { + pins = "gpio53","gpio52"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci1_suspend: cci1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio53","gpio52"; + function = "cci_i2c"; + }; + + config { + pins = "gpio53","gpio52"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_active: cci2-active { + mux { + /* CLK, DATA */ + pins = "gpio63","gpio62"; + function = "cci_i2c"; + }; + + config { + pins = "gpio63","gpio62"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci2_suspend: cci2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio63","gpio62"; + function = "cci_i2c"; + }; + + config { + pins = "gpio63","gpio62"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + mux { + /* CLK, DATA */ + pins = "gpio55","gpio54"; + function = "cci_i2c"; + }; + + config { + pins = "gpio55","gpio54"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci3_suspend: cci3-suspend { + mux { + /* CLK, DATA */ + pins = "gpio55","gpio54"; + function = "cci_i2c"; + }; + + config { + pins = "gpio55","gpio54"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci4_active: cci4-active { + mux { + /* CLK, DATA */ + pins = "gpio65","gpio64"; + function = "cci_i2c"; + }; + + config { + pins = "gpio65","gpio64"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci4_suspend: cci4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio65","gpio64"; + function = "cci_i2c"; + }; + + config { + pins = "gpio65","gpio64"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci5_active: cci5-active { + mux { + /* CLK, DATA */ + pins = "gpio57","gpio56"; + function = "cci_i2c"; + }; + + config { + pins = "gpio57","gpio56"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci5_suspend: cci5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio57","gpio56"; + function = "cci_i2c"; + }; + + config { + pins = "gpio57","gpio56"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci6_active: cci6-active { + mux { + /* CLK, DATA */ + pins = "gpio67","gpio66"; + function = "cci_i2c"; + }; + + config { + pins = "gpio67","gpio66"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci6_suspend: cci6-suspend { + mux { + /* CLK, DATA */ + pins = "gpio67","gpio66"; + function = "cci_i2c"; + }; + + config { + pins = "gpio67","gpio66"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci7_active: cci7-active { + mux { + /* CLK, DATA */ + pins = "gpio59","gpio58"; + function = "cci_i2c"; + }; + + config { + pins = "gpio59","gpio58"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci7_suspend: cci7-suspend { + mux { + /* CLK, DATA */ + pins = "gpio59","gpio58"; + function = "cci_i2c"; + }; + + config { + pins = "gpio59","gpio58"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso new file mode 100644 index 0000000000000..c7ddbc01a0070 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-cpas"; + __overlay__ { + enable-secure-qos-update = <0>; + }; + }; + + fragment@1 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x08c1 0x0400>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-el2.dtso index 621ad930cf547..3efbdda9348b3 100644 --- a/arch/arm64/boot/dts/qcom/lemans-el2.dtso +++ b/arch/arm64/boot/dts/qcom/lemans-el2.dtso @@ -15,7 +15,9 @@ }; &iris { - status = "disabled"; + video-firmware { + iommus = <&apps_smmu 0x0882 0x0400>; + }; }; &remoteproc_adsp { diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi new file mode 100644 index 0000000000000..f7005902a98a2 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -0,0 +1,1025 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; + + /*cam0a-ov9282*/ + rb8_slot0: qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios =<&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <20>; + status = "ok"; + }; + + /*cam24-ov13858*/ + qcom,cam-sensor24 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam24>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios =<&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <24>; + status = "ok"; + }; + + /*cam0-cmk_imx577*/ + qcom,cam-sensor27 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam27>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios =<&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <27>; + status = "ok"; + }; + + eeprom_cam24: qcom,eeprom24 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios =<&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <24>; + status = "ok"; + }; + + eeprom_cam27: qcom,eeprom27 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios =<&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <27>; + status = "ok"; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 8 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; + + /*cam1-ov9282*/ + rb8_slot1: qcom,cam-sensor21 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <21>; + status = "ok"; + }; + + /*cam1-cmk_imx577*/ + qcom,cam-sensor28 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam28>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <28>; + status = "ok"; + }; + + /*cam1-ov9282*/ + qcom,cam-sensor31 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 73 0>, + <&expander2 2 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <31>; + status = "ok"; + }; + + eeprom_cam28: qcom,eeprom28 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <28>; + status = "ok"; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; + + /*cam2-ov9282*/ + rb8_slot2: qcom,cam-sensor22 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <22>; + status = "ok"; + }; + + /*cam2-cmk_imx577*/ + qcom,cam-sensor29 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam29>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <29>; + status = "ok"; + }; + + eeprom_cam29: qcom,eeprom29 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <29>; + status = "ok"; + }; +}; + +&cam_cci3 { + /* GMSL deserializer 3 */ + qcom,cam-gmsl-deserializer3 { + cell-index = <3>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET3"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser3_port0: endpoint { + remote-endpoint = <&gmsl_sensor12_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser3_port1: endpoint { + remote-endpoint = <&gmsl_sensor13_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser3_port2: endpoint { + remote-endpoint = <&gmsl_sensor14_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser3_port3: endpoint { + remote-endpoint = <&gmsl_sensor15_ep>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 0 */ + qcom,cam-gmsl-sensor12 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor12_ep: endpoint { + remote-endpoint = <&deser3_port0>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 1 */ + qcom,cam-gmsl-sensor13 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor13_ep: endpoint { + remote-endpoint = <&deser3_port1>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 2 */ + qcom,cam-gmsl-sensor14 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor14_ep: endpoint { + remote-endpoint = <&deser3_port2>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 3 */ + qcom,cam-gmsl-sensor15 { + cell-index = <15>; + compatible = "qcom,cam-gmsl-sensor"; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor15_ep: endpoint { + remote-endpoint = <&deser3_port3>; + }; + }; + }; + + /*cam3-ov9282*/ + rb8_slot3: qcom,cam-sensor23 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <23>; + status = "ok"; + }; + + /*cam3-cmk_imx577*/ + qcom,cam-sensor30 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam30>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <30>; + status = "ok"; + }; + + eeprom_cam30: qcom,eeprom30 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <30>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + gpios-shared-pinctrl = <633>; + shared-pctrl-gpio-names = "mclk1"; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "mclk1_active", "mclk1_suspend"; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso new file mode 100644 index 0000000000000..520fb14660142 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "lemans-camera.dtsi" +#include "lemans-evk-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio132"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst3: cam-sensor-active-rst3 { + /* RESET */ + mux { + pins = "gpio135"; + function = "gpio"; + }; + + config { + pins = "gpio135"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio132"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst3: cam-sensor-suspend-rst3 { + /* RESET */ + mux { + pins = "gpio135"; + function = "gpio"; + }; + + config { + pins = "gpio135"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso new file mode 100644 index 0000000000000..52739d39a1ff8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +/ { + vmmc_sdc1: regulator-l8c { + compatible = "regulator-fixed"; + regulator-name = "vreg-sdc1"; + + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + }; + + vqmmc_sdc1: regulator-s4a { + compatible = "regulator-fixed"; + regulator-name = "vqmmc-sdc1"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&sdhc { + vmmc-supply = <&vmmc_sdc1>; + vqmmc-supply = <&vqmmc_sdc1>; + + pinctrl-0 = <&sdc_default>, <&sdc_rclk>; + pinctrl-1 = <&sdc_sleep>, <&sdc_rclk_sleep>; + + pinctrl-names = "default", "sleep"; + + supports-cqe; + non-removable; + + qcom,dll-config = <0x000F64EC>; + max-frequency = <50000000>; + + bus-width = <8>; + no-sd; + no-sdio; + + status = "okay"; +}; + +&tlmm { + sdc_rclk: sdc1-rclk-state { + pins = "sdc1_rclk"; + bias-pull-down; + }; + + sdc_rclk_sleep: sdc1-rclk-sleep-state { + pins = "sdc1_rclk"; + drive-strength = <2>; + bias-bus-hold; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso new file mode 100644 index 0000000000000..007ab63473495 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&sdhc { + vmmc-supply = <&vmmc_sdc>; + vqmmc-supply = <&vreg_sdc>; + + pinctrl-0 = <&sdc_default>, <&sd_cd>; + pinctrl-1 = <&sdc_sleep>, <&sd_cd>; + pinctrl-names = "default", "sleep"; + + bus-width = <4>; + cd-gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + no-mmc; + no-sdio; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso new file mode 100644 index 0000000000000..cf345ec5d06c9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&i2c18 { + eeprom@52 { + nvmem-layout { + mac_addr2: mac-addr@6 { + reg = <0x6 0x6>; + }; + mac_addr3: mac-addr@c { + reg = <0xc 0x6>; + }; + }; + }; +}; + +&pcieport0 { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 56 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr2>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 57 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr3>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&tlmm 77 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr-intn-wol-sig { + pins = "gpio56"; + function = "gpio"; + input-enable; + bias-disable; + }; + napa_intn_wol_sig: napa-intn-wol-sig { + pins = "gpio57"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 34dfc8d22b6a5..cc66193025c6a 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -21,6 +21,7 @@ ethernet0 = ðernet0; mmc1 = &sdhc; serial0 = &uart10; + serial1 = &uart17; serial2 = &uart0; }; @@ -63,12 +64,43 @@ reg = <1>; usb0_con_ss_ep: endpoint { - remote-endpoint = <&hd3ss3220_in_ep>; + remote-endpoint = <&hd3ss3220_0_in_ep>; }; }; }; }; + connector-1 { + compatible = "usb-c-connector"; + label = "USB1-Type-C"; + data-role = "host"; + power-role = "source"; + + vbus-supply = <&usb1_vbus>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb1_con_hs_ep: endpoint { + remote-endpoint = <&usb_hub_2_1>; + }; + }; + + port@1 { + reg = <1>; + + usb1_con_ss_ep: endpoint { + remote-endpoint = <&hd3ss3220_1_in_ep>; + }; + + }; + }; + }; + connector-2 { compatible = "gpio-usb-b-connector", "usb-b-connector"; label = "micro-USB"; @@ -88,6 +120,57 @@ }; }; + connector-2 { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + id-gpios = <&pmm8654au_2_gpios 11 GPIO_ACTIVE_HIGH>; + vbus-gpios = <&expander3 3 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb2_vbus>; + + pinctrl-0 = <&usb2_id>; + pinctrl-names = "default"; + + port { + usb2_con_hs_ep: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + + connector-3 { + compatible = "pcie-m2-e-connector"; + vpcie3v3-supply = <&vreg_wcn_3p3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcieport0_ep>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&uart17_ep>; + }; + }; + }; + }; + edp0-connector { compatible = "dp-connector"; label = "EDP0"; @@ -150,6 +233,22 @@ sound-dai = <&q6apm>; }; }; + + dp0-dai-link { + link-name = "DisplayPort0 Playback"; + + codec { + sound-dai = <&mdss0_dp0>; + }; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; usb0_vbus: regulator-usb0-vbus { @@ -161,6 +260,24 @@ enable-active-high; }; + usb1_vbus: regulator-usb1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb1_vbus"; + gpio = <&expander1 3 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + + usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&pmm8654au_1_gpios 9 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + usb2_vbus: regulator-usb2-vbus { compatible = "regulator-fixed"; regulator-name = "usb2_vbus"; @@ -178,6 +295,17 @@ regulator-max-microvolt = <2950000>; }; + vreg_dcin_12v: regulator-dcin-12v { + compatible = "regulator-fixed"; + + regulator-name = "VREG_DCIN_12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + + regulator-always-on; + regulator-boot-on; + }; + vreg_sdc: regulator-vreg-sdc { compatible = "regulator-gpio"; @@ -191,6 +319,19 @@ startup-delay-us = <100>; }; + + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + vin-supply = <&vreg_dcin_12v>; + + regulator-always-on; + regulator-boot-on; + }; }; &apps_rsc { @@ -544,6 +685,8 @@ pinctrl-0 = <&usb_id>, <&usb0_intr_state>; pinctrl-names = "default"; + wakeup-source; + ports { #address-cells = <1>; #size-cells = <0>; @@ -551,7 +694,7 @@ port@0 { reg = <0>; - hd3ss3220_in_ep: endpoint { + hd3ss3220_0_in_ep: endpoint { remote-endpoint = <&usb0_con_ss_ep>; }; }; @@ -559,12 +702,45 @@ port@1 { reg = <1>; - hd3ss3220_out_ep: endpoint { + hd3ss3220_0_out_ep: endpoint { remote-endpoint = <&usb_0_dwc3_ss>; }; }; }; }; + + usb-typec@47 { + compatible = "ti,hd3ss3220"; + reg = <0x47>; + + interrupts-extended = <&pmm8654au_2_gpios 6 IRQ_TYPE_EDGE_FALLING>; + + id-gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&usb1_id>, <&usb1_intr>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hd3ss3220_1_in_ep: endpoint { + remote-endpoint = <&usb1_con_ss_ep>; + }; + }; + + port@1 { + reg = <1>; + + hd3ss3220_1_out_ep: endpoint { + remote-endpoint = <&usb_hub_3_1>; + }; + }; + }; + }; }; &i2c18 { @@ -742,6 +918,14 @@ status = "okay"; }; +&pcieport0 { + port { + pcieport0_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; +}; + &pmm8654au_0_pon_resin { linux,code = ; status = "okay"; @@ -756,6 +940,22 @@ power-source = <0>; }; + usb1_intr: usb1-intr-state { + pins = "gpio6"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; + + usb2_id: usb2-id-state { + pins = "gpio11"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; + usb2_id: usb2-id-state { pins = "gpio11"; function = "normal"; @@ -815,24 +1015,9 @@ status = "okay"; }; -&sdhc { - vmmc-supply = <&vmmc_sdc>; - vqmmc-supply = <&vreg_sdc>; - - pinctrl-0 = <&sdc_default>, <&sd_cd>; - pinctrl-1 = <&sdc_sleep>, <&sd_cd>; - pinctrl-names = "default", "sleep"; - - bus-width = <4>; - cd-gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; - no-mmc; - no-sdio; - - status = "okay"; -}; - &serdes0 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; status = "okay"; }; @@ -956,6 +1141,12 @@ function = "gpio"; bias-pull-up; }; + + usb1_id: usb1-id-state { + pins = "gpio51"; + function = "gpio"; + bias-pull-up; + }; }; &uart0 { @@ -970,6 +1161,16 @@ status = "okay"; }; +&uart17 { + status = "okay"; + + port { + uart17_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; + }; +}; + &ufs_mem_hc { reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; vcc-supply = <&vreg_l8a>; @@ -996,7 +1197,7 @@ }; &usb_0_dwc3_ss { - remote-endpoint = <&hd3ss3220_out_ep>; + remote-endpoint = <&hd3ss3220_0_out_ep>; }; &usb_0_hsphy { @@ -1014,6 +1215,103 @@ status = "okay"; }; +&usb_1 { + dr_mode = "host"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + usb_hub_2_x: hub@1 { + compatible = "usb5e3,610"; + reg = <1>; + + peer-hub = <&usb_hub_3_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_2_1: endpoint { + remote-endpoint = <&usb1_con_hs_ep>; + }; + }; + + /* + * Port-4 is connected to M.2 E key connector on corekit. + */ + port@4 { + reg = <4>; + + usb_hub_2_4: endpoint { + }; + }; + }; + }; + + usb_hub_3_x: hub@2 { + compatible = "usb5e3,625"; + reg = <2>; + + peer-hub = <&usb_hub_2_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_3_1: endpoint { + remote-endpoint = <&hd3ss3220_1_out_ep>; + }; + }; + + port@4 { + reg = <4>; + + usb_hub_3_4: endpoint { + }; + }; + }; + }; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_1_qmpphy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l7a>; + + status = "okay"; +}; + +&usb_2 { + status = "okay"; +}; + +&usb_2_dwc3_hs { + remote-endpoint = <&usb2_con_hs_ep>; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + &usb_2 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi b/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi index 341119fc82440..6caec3e4df4bb 100644 --- a/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi @@ -5,6 +5,7 @@ #include #include +#include "qcom-adc5-gen3.h" / { thermal-zones { @@ -110,6 +111,8 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x0 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_0_adc ADC5_GEN3_DIE_TEMP(0)>; + io-channel-names = "thermal"; }; pmm8654au_0_pon: pon@1200 { @@ -141,6 +144,27 @@ interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; }; + pmm8654au_0_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@3 { + reg = ; + label = "pmm8654au_0_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@8e { + reg = ; + label = "pmm8654au_0_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + }; + pmm8654au_0_gpios: gpio@8800 { compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; reg = <0x8800>; @@ -176,6 +200,29 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x2 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_1_adc ADC5_GEN3_DIE_TEMP(2)>; + io-channel-names = "thermal"; + }; + + pmm8654au_1_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x2 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@203 { + reg = ; + label = "pmm8654au_1_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@28e { + reg = ; + label = "pmm8654au_1_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; }; pmm8654au_1_gpios: gpio@8800 { @@ -200,6 +247,29 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x4 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_2_adc ADC5_GEN3_DIE_TEMP(4)>; + io-channel-names = "thermal"; + }; + + pmm8654au_2_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x4 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@403 { + reg = ; + label = "pmm8654au_2_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@48e { + reg = ; + label = "pmm8654au_2_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; }; pmm8654au_2_gpios: gpio@8800 { @@ -224,6 +294,29 @@ reg = <0xa00>; interrupts-extended = <&spmi_bus 0x6 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; #thermal-sensor-cells = <0>; + io-channels = <&pmm8654au_3_adc ADC5_GEN3_DIE_TEMP(6)>; + io-channel-names = "thermal"; + }; + + pmm8654au_3_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x6 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@603 { + reg = ; + label = "pmm8654au_3_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@68e { + reg = ; + label = "pmm8654au_3_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; }; pmm8654au_3_gpios: gpio@8800 { diff --git a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi index 40f88498999bd..f02aa10762c8f 100644 --- a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi @@ -582,8 +582,6 @@ }; &iris { - firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; - status = "okay"; }; @@ -857,11 +855,15 @@ &serdes0 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; + status = "okay"; }; &serdes1 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; + status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso b/arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso new file mode 100644 index 0000000000000..b1d8996c9ea8b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-rtss-mb.dtso @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&soc { + ipcc_computeL1: qcom,ipcc@488000 { + compatible = "qcom,ipcc"; + reg = <0x0 0x00488000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + num_mbox_chans = <5>; + }; + + rtss_mailbox: rtss-mailbox@1ffe02c { + compatible = "qcom,rtss-mailbox"; + reg = <0x0 0x01ffe02c 0x0 0x10>, + <0x0 0x01ffd018 0x0 0x10>, + <0x0 0x17c0000c 0x0 0x04>; + mboxes = <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x2>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x3>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x4>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x5>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x6>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x7>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0x8>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x9>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xa>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xb>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xc>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xd>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xe>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xf>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS3 0x10>; + memory-region = <&sail_mailbox_mem>, + <&sail_ota_mem>; + interrupt-parent = <&ipcc_computeL1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + rtss-handshake-delay = <50000>; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-staging.dtso b/arch/arm64/boot/dts/qcom/lemans-staging.dtso new file mode 100644 index 0000000000000..ad919bfb6b19a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-staging.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Lemans staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@4b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@4b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 353a6e6fd3acb..7bba89aa4b923 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4,6 +4,7 @@ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +31,46 @@ #address-cells = <2>; #size-cells = <2>; + aest { + compatible = "arm,aest"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + aest-processor-0 { + compatible = "arm,aest-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x0>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster0 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster1 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + }; + clocks { xo_board_clk: xo-board-clk { compatible = "fixed-clock"; @@ -635,6 +677,11 @@ #power-domain-cells = <0>; domain-idle-states = <&cluster_sleep_apss_rsc_pc>; }; + + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; }; reserved-memory { @@ -2779,6 +2826,7 @@ status = "disabled"; pcieport0: pcie@0 { + compatible = "pciclass,0604"; device_type = "pci"; reg = <0x0 0x0 0x0 0x0 0x0>; bus-range = <0x01 0xff>; @@ -2897,7 +2945,6 @@ , , , - ; interrupt-names = "msi0", "msi1", "msi2", @@ -2906,7 +2953,6 @@ "msi5", "msi6", "msi7", - "global"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, @@ -3109,6 +3155,32 @@ clock-names = "core", "iface"; power-domains = <&gcc UFS_PHY_GDSC>; + + operating-points-v2 = <&ice_opp_table>; + + ice_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-75000000 { + opp-hz = /bits/ 64 <75000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; }; cryptobam: dma-controller@1dc4000 { @@ -3197,6 +3269,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dcc"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3256,6 +3329,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3724,6 +3798,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3744,6 +3819,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3764,6 +3840,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3784,6 +3861,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3804,6 +3882,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3824,6 +3903,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aoss"; }; funnel@4b83000 { @@ -4145,6 +4225,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_actpm"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -4165,6 +4246,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_apss"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4247,6 +4329,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_silver"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4267,6 +4350,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_gold"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4287,6 +4371,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_ext"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4303,7 +4388,9 @@ sdhc: mmc@87c4000 { compatible = "qcom,sa8775p-sdhci", "qcom,sdhci-msm-v5"; - reg = <0x0 0x087c4000 0x0 0x1000>; + reg = <0x0 0x87C4000 0x0 0x1000>, + <0x0 0x87C5000 0x0 0x1000>; + reg-names = "hc", "cqhci"; interrupts = , ; @@ -4311,9 +4398,11 @@ "pwr_irq"; clocks = <&gcc GCC_SDCC1_AHB_CLK>, - <&gcc GCC_SDCC1_APPS_CLK>; + <&gcc GCC_SDCC1_APPS_CLK>, + <&rpmhcc RPMH_CXO_CLK>; clock-names = "iface", - "core"; + "core", + "xo"; interconnects = <&aggre1_noc MASTER_SDC QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, @@ -4353,6 +4442,20 @@ }; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + usb_0_hsphy: phy@88e4000 { compatible = "qcom,sa8775p-usb-hs-phy", "qcom,usb-snps-hs-5nm-phy"; @@ -4796,6 +4899,8 @@ , , ; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; serdes0: phy@8901000 { @@ -4962,11 +5067,13 @@ memory-region = <&pil_video_mem>; + firmware-name = "qcom/vpu/vpu30_p4_s6_16mb.mbn"; + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x0880 0x0400>, - <&apps_smmu 0x0887 0x0400>; + iommu-map = , + ; dma-coherent; status = "disabled"; @@ -6022,6 +6129,13 @@ bias-disable; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio35"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + hs0_mi2s_active: hs0-mi2s-active-state { pins = "gpio114", "gpio115", "gpio116", "gpio117"; function = "hs0_mi2s"; @@ -7777,6 +7891,9 @@ qcom,smem-states = <&smp2p_cdsp0_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -7916,6 +8033,9 @@ qcom,smem-states = <&smp2p_cdsp1_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -8764,7 +8884,7 @@ thermal-sensors = <&tsens2 5>; trips { - trip-point0 { + nsp_0_0_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8776,6 +8896,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_0_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-0-thermal { @@ -8784,7 +8912,7 @@ thermal-sensors = <&tsens2 6>; trips { - trip-point0 { + nsp_0_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8796,6 +8924,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_0_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-0-thermal { @@ -8804,7 +8940,7 @@ thermal-sensors = <&tsens2 7>; trips { - trip-point0 { + nsp_0_2_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8816,6 +8952,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_0_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-0-0-thermal { @@ -8824,7 +8968,7 @@ thermal-sensors = <&tsens2 8>; trips { - trip-point0 { + nsp_1_0_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8836,6 +8980,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_0_0_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-1-0-thermal { @@ -8844,7 +8996,7 @@ thermal-sensors = <&tsens2 9>; trips { - trip-point0 { + nsp_1_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8856,6 +9008,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_1_0_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-2-0-thermal { @@ -8864,7 +9024,7 @@ thermal-sensors = <&tsens2 10>; trips { - trip-point0 { + nsp_1_2_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8876,6 +9036,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_2_0_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; ddrss-0-thermal { @@ -9018,7 +9186,7 @@ thermal-sensors = <&tsens3 5>; trips { - trip-point0 { + nsp_0_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9030,6 +9198,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_1_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-1-thermal { @@ -9038,7 +9214,7 @@ thermal-sensors = <&tsens3 6>; trips { - trip-point0 { + nsp_0_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9050,6 +9226,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_1_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-1-thermal { @@ -9058,7 +9242,7 @@ thermal-sensors = <&tsens3 7>; trips { - trip-point0 { + nsp_0_2_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9070,6 +9254,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_1_alert0>; + cooling-device = <&remoteproc_cdsp0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-0-1-thermal { @@ -9078,7 +9270,7 @@ thermal-sensors = <&tsens3 8>; trips { - trip-point0 { + nsp_1_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9090,6 +9282,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_0_1_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-1-1-thermal { @@ -9098,7 +9298,7 @@ thermal-sensors = <&tsens3 9>; trips { - trip-point0 { + nsp_1_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9110,6 +9310,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_1_1_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-2-1-thermal { @@ -9118,7 +9326,7 @@ thermal-sensors = <&tsens3 10>; trips { - trip-point0 { + nsp_1_2_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9130,6 +9338,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_2_1_alert0>; + cooling-device = <&remoteproc_cdsp1 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; ddrss-1-thermal { @@ -9179,6 +9395,7 @@ turing-llm-tpdm { compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_cdsp_llm_0"; qcom,cmb-element-bits = <32>; diff --git a/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts b/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts new file mode 100644 index 0000000000000..6f3c3ffefe340 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts @@ -0,0 +1,938 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include +#include +#include +#include + +#include "monaco.dtsi" +#include "monaco-pmics.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Monaco-ac EVK"; + compatible = "qcom,monaco-evk", "qcom,qcs8300"; + + aliases { + ethernet0 = ðernet0; + i2c1 = &i2c1; + serial0 = &uart7; + serial2 = &uart6; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector-2 { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + id-gpios = <&pmm8620au_0_gpios 9 GPIO_ACTIVE_HIGH>; + vbus-gpios = <&expander6 7 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb2_vbus>; + + pinctrl-0 = <&usb2_id>; + pinctrl-names = "default"; + + port { + usb2_con_hs_ep: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + + dmic: audio-codec-0 { + compatible = "dmic-codec"; + #sound-dai-cells = <0>; + num-channels = <1>; + }; + + max98357a: audio-codec-1 { + compatible = "maxim,max98357a"; + #sound-dai-cells = <0>; + }; + + dp-connector-0 { + compatible = "dp-connector"; + label = "DP0"; + type = "mini"; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <<8713sx_dp0_out>; + }; + }; + }; + + dp-connector-1 { + compatible = "dp-connector"; + label = "DP1"; + type = "mini"; + + port { + dp1_connector_in: endpoint { + remote-endpoint = <<8713sx_dp1_out>; + }; + }; + }; + + usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&pmm8650au_1_gpios 7 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + + sound { + compatible = "qcom,qcs8275-sndcard"; + model = "MONACO-EVK"; + + pinctrl-0 = <&hs0_mi2s_active>, <&mi2s1_active>; + pinctrl-names = "default"; + + hs0-mi2s-playback-dai-link { + link-name = "HS0 MI2S Playback"; + + codec { + sound-dai = <&max98357a>; + }; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + sec-mi2s-capture-dai-link { + link-name = "Secondary MI2S Capture"; + + codec { + sound-dai = <&dmic>; + }; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_TX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + vreg_cam0_2p8: vreg-cam0-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam0_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam0_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam1_2p8: vreg-cam1-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam1_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam1_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam2_2p8: vreg-cam2-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam2_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 75 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam2_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + /* This comes from a PMIC handled within the SAIL domain */ + vreg_s2s: vreg-s2s { + compatible = "regulator-fixed"; + regulator-name = "vreg_s2s"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "a"; + + vreg_l3a: ldo3 { + regulator-name = "vreg_l3a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4a: ldo4 { + regulator-name = "vreg_l4a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5a: ldo5 { + regulator-name = "vreg_l5a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6a: ldo6 { + regulator-name = "vreg_l6a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7a: ldo7 { + regulator-name = "vreg_l7a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8a: ldo8 { + regulator-name = "vreg_l8a"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9a: ldo9 { + regulator-name = "vreg_l9a"; + regulator-min-microvolt = <2970000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + vreg_s4a: smps4 { + regulator-name = "vreg_s4a"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_s9a: smps9 { + regulator-name = "vreg_s9a"; + regulator-min-microvolt = <1352000>; + regulator-max-microvolt = <1352000>; + regulator-initial-mode = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "c"; + + vreg_s5c: smps5 { + regulator-name = "vreg_s5c"; + regulator-min-microvolt = <1104000>; + regulator-max-microvolt = <1104000>; + regulator-initial-mode = ; + }; + + vreg_l1c: ldo1 { + regulator-name = "vreg_l1c"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <512000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2c: ldo2 { + regulator-name = "vreg_l2c"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <904000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4c: ldo4 { + regulator-name = "vreg_l4c"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7c: ldo7 { + regulator-name = "vreg_l7c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8c: ldo8 { + regulator-name = "vreg_l8c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9c: ldo9 { + regulator-name = "vreg_l9c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; +}; + +ðernet0 { + phy-mode = "2500base-x"; + phy-handle = <&hsgmii_phy0>; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + nvmem-cells = <&mac_addr0>; + nvmem-cell-names = "mac-address"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + hsgmii_phy0: ethernet-phy@1c { + compatible = "ethernet-phy-id004d.d101"; + reg = <0x1c>; + reset-gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&gpi_dma0 { + status = "okay"; +}; + +&gpi_dma1 { + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcs8300/a623_zap.mbn"; +}; + +&i2c0 { + status = "okay"; + + bridge@4f { + compatible = "lontium,lt8713sx"; + reg = <0x4f>; + reset-gpios = <&expander5 6 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt8713sx_dp_in: endpoint { + remote-endpoint = <&mdss_dp0_out>; + }; + }; + + port@1 { + reg = <1>; + + lt8713sx_dp0_out: endpoint { + remote-endpoint = <&dp0_connector_in>; + }; + }; + + port@2 { + reg = <2>; + + lt8713sx_dp1_out: endpoint { + remote-endpoint = <&dp1_connector_in>; + }; + }; + }; + }; +}; + +&i2c1 { + pinctrl-0 = <&qup_i2c1_default>; + pinctrl-names = "default"; + + status = "okay"; + + fan_controller: fan@18 { + compatible = "ti,amc6821"; + reg = <0x18>; + #pwm-cells = <2>; + + fan { + pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; + }; + }; + + eeprom0: eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + pagesize = <64>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + mac_addr0: mac-addr@0 { + reg = <0x0 0x6>; + }; + }; + }; +}; + +&i2c15 { + pinctrl-0 = <&qup_i2c15_default>; + pinctrl-names = "default"; + + status = "okay"; + + expander0: gpio@38 { + compatible = "ti,tca9538"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 56 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander0_int>; + pinctrl-names = "default"; + }; + + expander1: gpio@39 { + compatible = "ti,tca9538"; + reg = <0x39>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 16 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander1_int>; + pinctrl-names = "default"; + }; + + expander2: gpio@3a { + compatible = "ti,tca9538"; + reg = <0x3a>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 95 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander2_int>; + pinctrl-names = "default"; + }; + + expander3: gpio@3b { + compatible = "ti,tca9538"; + reg = <0x3b>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander3_int>; + pinctrl-names = "default"; + }; + + expander4: gpio@3c { + compatible = "ti,tca9538"; + reg = <0x3c>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 96 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander4_int>; + pinctrl-names = "default"; + }; + + expander5: gpio@3d { + compatible = "ti,tca9538"; + reg = <0x3d>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander5_int>; + pinctrl-names = "default"; + }; + + expander6: gpio@3e { + compatible = "ti,tca9538"; + reg = <0x3e>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander6_int>; + pinctrl-names = "default"; + }; +}; + +&iris { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dp0 { + pinctrl-0 = <&dp_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <<8713sx_dp_in>; +}; + +&mdss_dp0_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&pcie0 { + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie0_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcie1 { + pinctrl-0 = <&pcie1_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcieport0 { + reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; +}; + +&pcieport1 { + reset-gpios = <&tlmm 23 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; +}; + +&pmm8620au_0_gpios { + usb2_id: usb2-id-state { + pins = "gpio9"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&qup_i2c0_data_clk { + drive-strength = <2>; + bias-pull-up; +}; + +&qupv3_id_0 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&qupv3_id_1 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/qcs8300/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/qcs8300/cdsp0.mbn"; + + status = "okay"; +}; + +&remoteproc_gpdsp { + firmware-name = "qcom/qcs8300/gpdsp0.mbn"; + + status = "okay"; +}; + +&sdhc_1 { + vmmc-supply = <&vreg_l8a>; + vqmmc-supply = <&vreg_s2s>; + + no-sd; + no-sdio; + non-removable; + + status = "okay"; +}; + +&serdes0 { + phy-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&spi10 { + status = "okay"; + + tpm@0 { + compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + }; +}; + +&tlmm { + pcie0_default_state: pcie0-default-state { + wake-pins { + pins = "gpio0"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio1"; + function = "pcie0_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio2"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + ethernet0_default: ethernet0-default-state { + ethernet0_mdc: ethernet0-mdc-pins { + pins = "gpio5"; + function = "emac0_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + ethernet0_mdio: ethernet0-mdio-pins { + pins = "gpio6"; + function = "emac0_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + expander5_int: expander5-int-state { + pins = "gpio3"; + function = "gpio"; + bias-pull-up; + }; + + expander1_int: expander1-int-state { + pins = "gpio16"; + function = "gpio"; + bias-pull-up; + }; + + qup_i2c1_default: qup-i2c1-state { + pins = "gpio19", "gpio20"; + function = "qup0_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + pcie1_default_state: pcie1-default-state { + wake-pins { + pins = "gpio21"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio22"; + function = "pcie1_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + expander3_int: expander3-int-state { + pins = "gpio24"; + function = "gpio"; + bias-pull-up; + }; + + expander6_int: expander6-int-state { + pins = "gpio52"; + function = "gpio"; + bias-pull-up; + }; + + expander0_int: expander0-int-state { + pins = "gpio56"; + function = "gpio"; + bias-pull-up; + }; + + cam0_avdd_2v8_en_default: cam0-avdd-2v8-en-state { + pins = "gpio73"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam1_avdd_2v8_en_default: cam1-avdd-2v8-en-state { + pins = "gpio74"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam2_avdd_2v8_en_default: cam2-avdd-2v8-en-state { + pins = "gpio75"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + qup_i2c15_default: qup-i2c15-state { + pins = "gpio91", "gpio92"; + function = "qup1_se7"; + drive-strength = <2>; + bias-pull-up; + }; + + expander2_int: expander2-int-state { + pins = "gpio95"; + function = "gpio"; + bias-pull-up; + }; + + expander4_int: expander4-int-state { + pins = "gpio96"; + function = "gpio"; + bias-pull-up; + }; +}; + +&uart6 { + status = "okay"; +}; + +&uart7 { + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l8a>; + vcc-max-microamp = <1100000>; + vccq-supply = <&vreg_l4c>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l4a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&vreg_l7a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_2 { + status = "okay"; +}; + +&usb_2_dwc3_hs { + remote-endpoint = <&usb2_con_hs_ep>; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi new file mode 100644 index 0000000000000..a2a2cd0a27a3a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <609 610 611>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi new file mode 100644 index 0000000000000..8250f66c34526 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -0,0 +1,2499 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cci0: qcom,cci0@ac13000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac13000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x13000>; + interrupts = ; + interrupt-names = "CCI0"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1@ac14000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac14000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x14000>; + interrupts = ; + interrupt-names = "CCI1"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci_i2c_scl3_active &cci_i2c_sda3_active>; + pinctrl-3 = <&cci_i2c_scl3_suspend &cci_i2c_sda3_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci2: qcom,cci2@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "CCI2"; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "cci_2_clk_src", + "cci_2_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl4_active &cci_i2c_sda4_active>; + pinctrl-1 = <&cci_i2c_scl4_suspend &cci_i2c_sda4_suspend>; + pinctrl-2 = <&cci_i2c_scl5_active &cci_i2c_sda5_active>; + pinctrl-3 = <&cci_i2c_scl5_suspend &cci_i2c_sda5_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <2>; + status = "ok"; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci2: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci2: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_csiphy0: qcom,csiphy0@ac9c000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9c000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x9c000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <0>; + aggregator-rx; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ac9e000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xac9e000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x9e000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <1>; + aggregator-rx; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@aca0000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca0000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0xa0000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <2>; + aggregator-rx; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acac000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacac000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xac000 0x11000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <13>; + phy-id = <0>; + status = "ok"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acad000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacad000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xad000 0x11000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <14>; + phy-id = <1>; + status = "ok"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acae000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacae000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xae000 0x11000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <15>; + phy-id = <2>; + status = "ok"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "ok"; + }; + + cam_cpas: qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac11000 0x0 0x1000>, + <0x0 0xac1A000 0x0 0x9400>, + <0x0 0xbbf0000 0x0 0x1f00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x11000 0x1A000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + clock-cntl-level = "suspend", "svs_l1", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <480000000>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", + "cci0", "cci1", "cci2", + "csid0", "csid1", "csid2", "csid3", + "csid4", "csid5", "csid6", "ife0", + "ife1", "ife2", "ife3", "ife4", + "ife5", "ife6", "ipe0", "sfe0", "sfe1", + "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "icp0", "tpg13", "tpg14", "tpg15"; + enable-secure-qos-update = <1>; + cell-index = <0>; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + icp_all_rd: icp-all-rd { + cell-index = <0>; + node-name = "icp-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + ife_0_wr_0: ife-0-wr-0 { + cell-index = <1>; + node-name = "ife-0-wr-0"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_0_wr_1: ife-0-wr-1 { + cell-index = <2>; + node-name = "ife-0-wr-1"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_1_wr_0: ife-1-wr-0 { + cell-index = <3>; + node-name = "ife-1-wr-0"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_1_wr_1: ife-1-wr-1 { + cell-index = <4>; + node-name = "ife-1-wr-1"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_lite_0_wr_0: ife-lite-0-wr-0 { + cell-index = <5>; + node-name = "ife-lite-0-wr-0"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_1_wr_0: ife-lite-1-wr-0 { + cell-index = <6>; + node-name = "ife-lite-1-wr-0"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_2_wr_0: ife-lite-2-wr-0 { + cell-index = <7>; + node-name = "ife-lite-2-wr-0"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_3_wr_0: ife-lite-3-wr-0 { + cell-index = <8>; + node-name = "ife-lite-3-wr-0"; + client-name = "ife5"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_4_wr_0: ife-lite-4-wr-0 { + cell-index = <9>; + node-name = "ife-lite-4-wr-0"; + client-name = "ife6"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ipe_0_rd_all: ipe-0-rd-all { + cell-index = <10>; + node-name = "ipe-0-rd-all"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd1>; + }; + + ipe_0_wr_2: ipe-0-wr-2 { + cell-index = <11>; + node-name = "ipe-0-wr-2"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr2>; + }; + + ipe_cdm0_all_rd: ipe-cdm0-all-rd { + cell-index = <12>; + node-name = "ipe-cdm0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { + cell-index = <13>; + node-name = "rt-cdm0-all-rd-2"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { + cell-index = <14>; + node-name = "rt-cdm1-all-rd-2"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { + cell-index = <15>; + node-name = "rt-cdm2-all-rd-2"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { + cell-index = <16>; + node-name = "rt-cdm3-all-rd-2"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + sfe_0_rd_0: sfe-0-rd-0 { + cell-index = <17>; + node-name = "sfe-0-rd-0"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_1_rd_0: sfe-1-rd-0 { + cell-index = <18>; + node-name = "sfe-1-rd-0"; + client-name = "sfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt_rd2: level1-nrt-rd2 { + cell-index = <19>; + node-name = "level1-nrt-rd2"; + parent-node = <&level2_nrt_rd2>; + traffic-merge-type = ; + }; + + level1_rt_rd0: level1-rt-read0 { + cell-index = <20>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd0>; + traffic-merge-type = ; + }; + + level1_rt_wr0: level1-rt-wr0 { + cell-index = <21>; + node-name = "level1-rt-wr0"; + parent-node = <&level2_rt_wr0>; + traffic-merge-type = ; + }; + + level1_rt_wr1: level1-rt-wr1 { + cell-index = <22>; + node-name = "level1-rt-wr1"; + parent-node = <&level2_rt_wr1>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_icp_rd: level2-icp-rd { + cell-index = <23>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd1: level2-nrt-rd1 { + cell-index = <24>; + node-name = "level2-nrt-rd1"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd2: level2-nrt-rd2 { + cell-index = <25>; + node-name = "level2-nrt-rd2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_wr2: level2-nrt-wr2 { + cell-index = <26>; + node-name = "level2-nrt-wr2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_rd0: level2-rt-read0 { + cell-index = <27>; + node-name = "level2-rt-rd0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr0: level2-rt-wr0 { + cell-index = <28>; + node-name = "level2-rt-wr0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr1: level2-rt-wr1 { + cell-index = <29>; + node-name = "level2-rt-wr1"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_use_pil; + status = "ok"; + }; + + qcom,cam-i3c-id-table { + compatible = "qcom,cam-i3c-id-table"; + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,camera-main { + compatible = "qcom,camera"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-smmu-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0860 0x400>, + <&apps_smmu 0x0C60 0x400>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x400>, + <&apps_smmu 0x0840 0x480>, + <&apps_smmu 0x08C0 0x480>, + <&apps_smmu 0x0C00 0x400>, + <&apps_smmu 0x0C40 0x480>, + <&apps_smmu 0x0CC0 0x480>; + cam-smmu-label = "icp"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + subregion_support; + status = "ok"; + + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x10400000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xfc00000>; + iova-region-id = <0x1>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2400 0x0020>, + <&apps_smmu 0x2420 0x0020>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 64 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xfffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid692"; + reg = <0x0 0xac7a000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid0", "csid_top"; + reg-cam-base = <0x7a000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid692"; + reg = <0x0 0xac7c000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid1", "csid_top"; + reg-cam-base = <0x7c000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac84000 0x0 0xf01>; + reg-names = "csid-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac88000 0x0 0xf01>; + reg-names = "csid-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-names = "csid-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + clock-control-debugfs = "true"; + cell-index = <4>; + status = "ok"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-names = "csid-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + clock-control-debugfs = "true"; + cell-index = <5>; + status = "ok"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac94000 0x0 0xf01>; + reg-names = "csid-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + clock-control-debugfs = "true"; + cell-index = <6>; + status = "ok"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp: qcom,icp { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0xac04000 0x0 0x1000>; + reg-names ="icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + src-clock-name = "cam_cc_icp_clk_src"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "cam_cc_soc_fast_ahb_clk_src", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk_src", + "cam_cc_icp_clk"; + clock-rates = <300000000 0 480000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + nrt-device; + fw_name = "qcom/qcs8300/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <12>; + cell-index = <0>; + status = "ok"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0 { + compatible = "qcom,vfe692"; + reg = <0x0 0xac4d000 0x0 0xf000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0x4d000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_0_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_ife_0_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1 { + compatible = "qcom,vfe692"; + reg = <0x0 0xac60000 0x0 0xf000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0x60000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_1_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_ife_1_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac84000 0x0 0x1d00>; + reg-names = "ife-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <2>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac88000 0x0 0x1d00>; + reg-names = "ife-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <3>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac8c000 0x0 0x1d00>; + reg-names = "ife-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <4>; + status = "ok"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac90000 0x0 0x1d00>; + reg-names = "ife-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <5>; + status = "ok"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac94000 0x0 0x1d00>; + reg-names = "ife-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <6>; + status = "ok"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac2d000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x2d000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + src-clock-name = "cam_cc_ipe_clk_src"; + clocks = <&camcc CAM_CC_CPAS_IPE_CLK>, + <&camcc CAM_CC_IPE_AHB_CLK>, + <&camcc CAM_CC_IPE_CLK>, + <&camcc CAM_CC_IPE_CLK_SRC>, + <&camcc CAM_CC_IPE_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_cpas_ipe_clk", + "cam_cc_ipe_ahb_clk", + "cam_cc_ipe_clk", + "cam_cc_ipe_clk_src", + "cam_cc_ipe_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 480000000 0 300000000>, + <0 0 0 600000000 0 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <14 15>; + cell-index = <0>; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm0 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "dualife0"; + single-context-cdm; + cell-index = <0>; + status = "ok"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm1 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac27000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x27000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife1", "dualife1"; + single-context-cdm; + cell-index = <1>; + status = "ok"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm2 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac28000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x28000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <2>; + status = "ok"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm3 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac29000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x29000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <3>; + status = "ok"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0 { + compatible = "qcom,sfe-lite692"; + reg = <0x0 0xac74000 0x0 0x1000>; + reg-names = "sfe-lite0"; + reg-cam-base = <0x74000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1 { + compatible = "qcom,sfe-lite692"; + reg = <0x0 0xac75000 0x0 0x1000>; + reg-names = "sfe-lite1"; + reg-cam-base = <0x75000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_1_CLK>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_cpas_sfe_1_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio69"; + function = "cam_mclk"; + }; + + config { + pins = "gpio69"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio69"; + function = "cam_mclk"; + }; + + config { + pins = "gpio69"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci-i2c-scl2-active { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl2_suspend: cci-i2c-scl2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl3_active: cci-i2c-scl3-active { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl3_suspend: cci-i2c-scl3-suspend { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl4_active: cci-i2c-scl4-active { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl4_suspend: cci-i2c-scl4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl5_active: cci-i2c-scl5-active { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl5_suspend: cci-i2c-scl5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci-i2c-sda2-active { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda2_suspend: cci-i2c-sda2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda3_active: cci-i2c-sda3-active { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda3_suspend: cci-i2c-sda3-suspend { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda4_active: cci-i2c-sda4-active { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda4_suspend: cci-i2c-sda4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda5_active: cci-i2c-sda5-active { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda5_suspend: cci-i2c-sda5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso new file mode 100644 index 0000000000000..c7ddbc01a0070 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-cpas"; + __overlay__ { + enable-secure-qos-update = <0>; + }; + }; + + fragment@1 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x08c1 0x0400>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-el2.dtso index a7e3270f86090..7cae65ae499c3 100644 --- a/arch/arm64/boot/dts/qcom/monaco-el2.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-el2.dtso @@ -13,7 +13,10 @@ }; &iris { - status = "disabled"; + status = "okay"; + video-firmware { + iommus = <&apps_smmu 0x0882 0x0400>; + }; }; &remoteproc_adsp { diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi new file mode 100644 index 0000000000000..167b85c0e8844 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi @@ -0,0 +1,794 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; + + /*cam0-ov9282*/ + rb4_slot0: qcom,cam-sensor16 { + compatible = "qcom,cam-sensor"; + cell-index = <16>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor20 { + compatible = "qcom,cam-sensor"; + cell-index = <20>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam20>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam20: qcom,eeprom20 { + cell-index = <20>; + compatible = "qcom,eeprom"; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + status = "ok"; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; + + /*cam1-ov9282*/ + rb4_slot1: qcom,cam-sensor17 { + compatible = "qcom,cam-sensor"; + cell-index = <17>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor19 { + compatible = "qcom,cam-sensor"; + cell-index = <19>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam19>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor21 { + compatible = "qcom,cam-sensor"; + cell-index = <21>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam21>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam19: qcom,eeprom19 { + compatible = "qcom,eeprom"; + cell-index = <19>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam21: qcom,eeprom21 { + compatible = "qcom,eeprom"; + cell-index = <21>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; + + /*cam2-ov9282*/ + rb4_slot2: qcom,cam-sensor18 { + compatible = "qcom,cam-sensor"; + cell-index = <18>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam2-imx577*/ + qcom,cam-sensor22 { + compatible = "qcom,cam-sensor"; + cell-index = <22>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam22>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam22: qcom,eeprom22 { + compatible = "qcom,eeprom"; + cell-index = <22>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + gpios-shared = <609 610 611>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso new file mode 100644 index 0000000000000..0a5265e178feb --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-camera.dtsi" +#include "monaco-evk-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio73"; + function = "gpio"; + }; + + config { + pins = "gpio73"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio74"; + function = "gpio"; + }; + + config { + pins = "gpio74"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio73"; + function = "gpio"; + }; + + config { + pins = "gpio73"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio74"; + function = "gpio"; + }; + config { + pins = "gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; + +&vreg_cam0_2p8 { + status = "disabled"; +}; + +&vreg_cam1_2p8 { + status = "disabled"; +}; + +&vreg_cam2_2p8 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi new file mode 100644 index 0000000000000..45f814f059ec5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-common.dtsi @@ -0,0 +1,900 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +#include "monaco.dtsi" +#include "monaco-pmics.dtsi" + +/ { + aliases { + ethernet0 = ðernet0; + i2c1 = &i2c1; + serial0 = &uart7; + serial2 = &uart6; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector-2 { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + + id-gpios = <&pmm8620au_0_gpios 9 GPIO_ACTIVE_HIGH>; + vbus-gpios = <&expander6 7 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb2_vbus>; + + pinctrl-0 = <&usb2_id>; + pinctrl-names = "default"; + + port { + usb2_con_hs_ep: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + + dmic: audio-codec-0 { + compatible = "dmic-codec"; + #sound-dai-cells = <0>; + num-channels = <1>; + }; + + max98357a: audio-codec-1 { + compatible = "maxim,max98357a"; + #sound-dai-cells = <0>; + }; + + dp-connector-0 { + compatible = "dp-connector"; + label = "DP0"; + type = "mini"; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <<8713sx_dp0_out>; + }; + }; + }; + + dp-connector-1 { + compatible = "dp-connector"; + label = "DP1"; + type = "mini"; + + port { + dp1_connector_in: endpoint { + remote-endpoint = <<8713sx_dp1_out>; + }; + }; + }; + + usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + gpio = <&pmm8650au_1_gpios 7 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + + sound { + compatible = "qcom,qcs8275-sndcard"; + model = "MONACO-EVK"; + + pinctrl-0 = <&hs0_mi2s_active>, <&mi2s1_active>; + pinctrl-names = "default"; + + hs0-mi2s-playback-dai-link { + link-name = "HS0 MI2S Playback"; + + codec { + sound-dai = <&max98357a>; + }; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + sec-mi2s-capture-dai-link { + link-name = "Secondary MI2S Capture"; + + codec { + sound-dai = <&dmic>; + }; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_TX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + vreg_cam0_2p8: vreg-cam0-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam0_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam0_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam1_2p8: vreg-cam1-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam1_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam1_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; + + vreg_cam2_2p8: vreg-cam2-2p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam2_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + startup-delay-us = <10000>; + + gpio = <&tlmm 75 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&cam2_avdd_2v8_en_default>; + pinctrl-names = "default"; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "a"; + + vreg_l3a: ldo3 { + regulator-name = "vreg_l3a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4a: ldo4 { + regulator-name = "vreg_l4a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5a: ldo5 { + regulator-name = "vreg_l5a"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6a: ldo6 { + regulator-name = "vreg_l6a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7a: ldo7 { + regulator-name = "vreg_l7a"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8a: ldo8 { + regulator-name = "vreg_l8a"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9a: ldo9 { + regulator-name = "vreg_l9a"; + regulator-min-microvolt = <2970000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "c"; + + vreg_s5c: smps5 { + regulator-name = "vreg_s5c"; + regulator-min-microvolt = <1104000>; + regulator-max-microvolt = <1104000>; + regulator-initial-mode = ; + }; + + vreg_l1c: ldo1 { + regulator-name = "vreg_l1c"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <512000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2c: ldo2 { + regulator-name = "vreg_l2c"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <904000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4c: ldo4 { + regulator-name = "vreg_l4c"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7c: ldo7 { + regulator-name = "vreg_l7c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8c: ldo8 { + regulator-name = "vreg_l8c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9c: ldo9 { + regulator-name = "vreg_l9c"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; +}; + +ðernet0 { + phy-mode = "2500base-x"; + phy-handle = <&hsgmii_phy0>; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + nvmem-cells = <&mac_addr0>; + nvmem-cell-names = "mac-address"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + hsgmii_phy0: ethernet-phy@1c { + compatible = "ethernet-phy-id004d.d101"; + reg = <0x1c>; + reset-gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&gpi_dma0 { + status = "okay"; +}; + +&gpi_dma1 { + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcs8300/a623_zap.mbn"; +}; + +&i2c0 { + status = "okay"; + + bridge@4f { + compatible = "lontium,lt8713sx"; + reg = <0x4f>; + reset-gpios = <&expander5 6 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt8713sx_dp_in: endpoint { + remote-endpoint = <&mdss_dp0_out>; + }; + }; + + port@1 { + reg = <1>; + + lt8713sx_dp0_out: endpoint { + remote-endpoint = <&dp0_connector_in>; + }; + }; + + port@2 { + reg = <2>; + + lt8713sx_dp1_out: endpoint { + remote-endpoint = <&dp1_connector_in>; + }; + }; + }; + }; +}; + +&i2c1 { + pinctrl-0 = <&qup_i2c1_default>; + pinctrl-names = "default"; + + status = "okay"; + + fan_controller: fan@18 { + compatible = "ti,amc6821"; + reg = <0x18>; + #pwm-cells = <2>; + + fan { + pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; + }; + }; + + eeprom0: eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + pagesize = <64>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + mac_addr0: mac-addr@0 { + reg = <0x0 0x6>; + }; + }; + }; +}; + +&i2c15 { + pinctrl-0 = <&qup_i2c15_default>; + pinctrl-names = "default"; + + status = "okay"; + + expander0: gpio@38 { + compatible = "ti,tca9538"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 56 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander0_int>; + pinctrl-names = "default"; + }; + + expander1: gpio@39 { + compatible = "ti,tca9538"; + reg = <0x39>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 16 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander1_int>; + pinctrl-names = "default"; + }; + + expander2: gpio@3a { + compatible = "ti,tca9538"; + reg = <0x3a>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 95 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander2_int>; + pinctrl-names = "default"; + }; + + expander3: gpio@3b { + compatible = "ti,tca9538"; + reg = <0x3b>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander3_int>; + pinctrl-names = "default"; + }; + + expander4: gpio@3c { + compatible = "ti,tca9538"; + reg = <0x3c>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 96 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander4_int>; + pinctrl-names = "default"; + }; + + expander5: gpio@3d { + compatible = "ti,tca9538"; + reg = <0x3d>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander5_int>; + pinctrl-names = "default"; + }; + + expander6: gpio@3e { + compatible = "ti,tca9538"; + reg = <0x3e>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&expander6_int>; + pinctrl-names = "default"; + }; +}; + +&iris { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dp0 { + pinctrl-0 = <&dp_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <<8713sx_dp_in>; +}; + +&mdss_dp0_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&pcie0 { + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie0_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcie1 { + pinctrl-0 = <&pcie1_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l6a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&pcieport0 { + reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; +}; + +&pcieport1 { + reset-gpios = <&tlmm 23 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; +}; + +&pmm8620au_0_gpios { + usb2_id: usb2-id-state { + pins = "gpio9"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&qup_i2c0_data_clk { + drive-strength = <2>; + bias-pull-up; +}; + +&qupv3_id_0 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&qupv3_id_1 { + firmware-name = "qcom/qcs8300/qupv3fw.elf"; + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/qcs8300/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/qcs8300/cdsp0.mbn"; + + status = "okay"; +}; + +&remoteproc_gpdsp { + firmware-name = "qcom/qcs8300/gpdsp0.mbn"; + + status = "okay"; +}; + +&serdes0 { + phy-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&spi10 { + status = "okay"; + + tpm@0 { + compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + }; +}; + +&tlmm { + pcie0_default_state: pcie0-default-state { + wake-pins { + pins = "gpio0"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio1"; + function = "pcie0_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio2"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + ethernet0_default: ethernet0-default-state { + ethernet0_mdc: ethernet0-mdc-pins { + pins = "gpio5"; + function = "emac0_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + ethernet0_mdio: ethernet0-mdio-pins { + pins = "gpio6"; + function = "emac0_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + expander5_int: expander5-int-state { + pins = "gpio3"; + function = "gpio"; + bias-pull-up; + }; + + expander1_int: expander1-int-state { + pins = "gpio16"; + function = "gpio"; + bias-pull-up; + }; + + qup_i2c1_default: qup-i2c1-state { + pins = "gpio19", "gpio20"; + function = "qup0_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + pcie1_default_state: pcie1-default-state { + wake-pins { + pins = "gpio21"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio22"; + function = "pcie1_clkreq"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + expander3_int: expander3-int-state { + pins = "gpio24"; + function = "gpio"; + bias-pull-up; + }; + + expander6_int: expander6-int-state { + pins = "gpio52"; + function = "gpio"; + bias-pull-up; + }; + + expander0_int: expander0-int-state { + pins = "gpio56"; + function = "gpio"; + bias-pull-up; + }; + + cam0_avdd_2v8_en_default: cam0-avdd-2v8-en-state { + pins = "gpio73"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam1_avdd_2v8_en_default: cam1-avdd-2v8-en-state { + pins = "gpio74"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + cam2_avdd_2v8_en_default: cam2-avdd-2v8-en-state { + pins = "gpio75"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + qup_i2c15_default: qup-i2c15-state { + pins = "gpio91", "gpio92"; + function = "qup1_se7"; + drive-strength = <2>; + bias-pull-up; + }; + + expander2_int: expander2-int-state { + pins = "gpio95"; + function = "gpio"; + bias-pull-up; + }; + + expander4_int: expander4-int-state { + pins = "gpio96"; + function = "gpio"; + bias-pull-up; + }; +}; + +&uart6 { + status = "okay"; +}; + +&uart7 { + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l8a>; + vcc-max-microamp = <1100000>; + vccq-supply = <&vreg_l4c>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l4a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&vreg_l7a>; + vdda-pll-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&usb_2 { + status = "okay"; +}; + +&usb_2_dwc3_hs { + remote-endpoint = <&usb2_con_hs_ep>; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&refgen>; + vdda18-supply = <&vreg_l7c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso new file mode 100644 index 0000000000000..cb2566ac6923c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + vreg_s2s: regulator-vreg-s2s { + compatible = "regulator-fixed"; + regulator-name = "regulator-s2s"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&sdhc_1 { + vmmc-supply = <&vreg_l8a>; + vqmmc-supply = <&vreg_s2s>; + + supports-cqe; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + + pinctrl-names = "default", "sleep"; + + non-removable; + + bus-width = <8>; + no-sd; + no-sdio; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso new file mode 100644 index 0000000000000..bc4ea12587a2e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + vmmc_sdc: regulator-mmc-sdc { + compatible = "regulator-fixed"; + + regulator-name = "vmmc_sdc"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + }; + + vreg_sdc: regulator-sdc { + compatible = "regulator-gpio"; + + regulator-name = "vreg_sdc"; + regulator-type = "voltage"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + + gpios = <&expander1 7 GPIO_ACTIVE_HIGH>; + states = <1800000 1>, <2950000 0>; + + startup-delay-us = <100>; + }; +}; + +&sdhc_1 { + vmmc-supply = <&vmmc_sdc>; + vqmmc-supply = <&vreg_sdc>; + + pinctrl-0 = <&sdc1_state_on>, <&sd_cd>; + pinctrl-1 = <&sdc1_state_off>, <&sd_cd>; + pinctrl-names = "default", "sleep"; + + cap-sd-highspeed; + no-1-8-v; + + bus-width = <4>; + cd-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; + no-mmc; + no-sdio; + + status = "okay"; +}; + +&sdhc1_opp_table { + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; +}; + +&tlmm { + sd_cd: sd-cd-state { + pins = "gpio11"; + function = "gpio"; + bias-pull-up; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso new file mode 100644 index 0000000000000..a646b28f6f9d0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&eeprom1 { + nvmem-layout { + mac_addr1: mac-addr@0 { + reg = <0x0 0x6>; + }; + + mac_addr2: mac-addr@6 { + reg = <0x6 0x6>; + }; + }; +}; + +&pcieport0 { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 40 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr1>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 39 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr2>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&expander5 0 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr-intn-wol-sig { + pins = "gpio40"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_intn_wol_sig: napa-intn-wol-sig { + pins = "gpio39"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 9d17ef7d2caf1..87a172a25e2bc 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -5,174 +5,12 @@ /dts-v1/; -#include -#include -#include -#include - -#include "monaco.dtsi" -#include "monaco-pmics.dtsi" +#include "monaco-evk-common.dtsi" / { model = "Qualcomm Technologies, Inc. Monaco EVK"; compatible = "qcom,monaco-evk", "qcom,qcs8300"; - aliases { - ethernet0 = ðernet0; - i2c1 = &i2c1; - serial0 = &uart7; - serial2 = &uart6; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - connector-2 { - compatible = "gpio-usb-b-connector", "usb-b-connector"; - label = "micro-USB"; - type = "micro"; - - id-gpios = <&pmm8620au_0_gpios 9 GPIO_ACTIVE_HIGH>; - vbus-gpios = <&expander6 7 GPIO_ACTIVE_HIGH>; - vbus-supply = <&usb2_vbus>; - - pinctrl-0 = <&usb2_id>; - pinctrl-names = "default"; - - port { - usb2_con_hs_ep: endpoint { - remote-endpoint = <&usb_2_dwc3_hs>; - }; - }; - }; - - dmic: audio-codec-0 { - compatible = "dmic-codec"; - #sound-dai-cells = <0>; - num-channels = <1>; - }; - - max98357a: audio-codec-1 { - compatible = "maxim,max98357a"; - #sound-dai-cells = <0>; - }; - - dp-connector-0 { - compatible = "dp-connector"; - label = "DP0"; - type = "mini"; - - port { - dp0_connector_in: endpoint { - remote-endpoint = <<8713sx_dp0_out>; - }; - }; - }; - - dp-connector-1 { - compatible = "dp-connector"; - label = "DP1"; - type = "mini"; - - port { - dp1_connector_in: endpoint { - remote-endpoint = <<8713sx_dp1_out>; - }; - }; - }; - - usb2_vbus: regulator-usb2-vbus { - compatible = "regulator-fixed"; - regulator-name = "usb2_vbus"; - gpio = <&pmm8650au_1_gpios 7 GPIO_ACTIVE_HIGH>; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - }; - - sound { - compatible = "qcom,qcs8275-sndcard"; - model = "MONACO-EVK"; - - pinctrl-0 = <&hs0_mi2s_active>, <&mi2s1_active>; - pinctrl-names = "default"; - - hs0-mi2s-playback-dai-link { - link-name = "HS0 MI2S Playback"; - - codec { - sound-dai = <&max98357a>; - }; - - cpu { - sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; - }; - - platform { - sound-dai = <&q6apm>; - }; - }; - - sec-mi2s-capture-dai-link { - link-name = "Secondary MI2S Capture"; - - codec { - sound-dai = <&dmic>; - }; - - cpu { - sound-dai = <&q6apmbedai SECONDARY_MI2S_TX>; - }; - - platform { - sound-dai = <&q6apm>; - }; - }; - }; - - vreg_cam0_2p8: vreg-cam0-2p8 { - compatible = "regulator-fixed"; - regulator-name = "vreg_cam0_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - startup-delay-us = <10000>; - - gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&cam0_avdd_2v8_en_default>; - pinctrl-names = "default"; - }; - - vreg_cam1_2p8: vreg-cam1-2p8 { - compatible = "regulator-fixed"; - regulator-name = "vreg_cam1_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - startup-delay-us = <10000>; - - gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&cam1_avdd_2v8_en_default>; - pinctrl-names = "default"; - }; - - vreg_cam2_2p8: vreg-cam2-2p8 { - compatible = "regulator-fixed"; - regulator-name = "vreg_cam2_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - startup-delay-us = <10000>; - - gpio = <&tlmm 75 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&cam2_avdd_2v8_en_default>; - pinctrl-names = "default"; - }; - /* This comes from a PMIC handled within the SAIL domain */ vreg_s2s: vreg-s2s { compatible = "regulator-fixed"; @@ -181,519 +19,31 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; -}; - -&apps_rsc { - regulators-0 { - compatible = "qcom,pmm8654au-rpmh-regulators"; - qcom,pmic-id = "a"; - - vreg_l3a: ldo3 { - regulator-name = "vreg_l3a"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l4a: ldo4 { - regulator-name = "vreg_l4a"; - regulator-min-microvolt = <880000>; - regulator-max-microvolt = <912000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l5a: ldo5 { - regulator-name = "vreg_l5a"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l6a: ldo6 { - regulator-name = "vreg_l6a"; - regulator-min-microvolt = <880000>; - regulator-max-microvolt = <912000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l7a: ldo7 { - regulator-name = "vreg_l7a"; - regulator-min-microvolt = <880000>; - regulator-max-microvolt = <912000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l8a: ldo8 { - regulator-name = "vreg_l8a"; - regulator-min-microvolt = <2504000>; - regulator-max-microvolt = <2960000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l9a: ldo9 { - regulator-name = "vreg_l9a"; - regulator-min-microvolt = <2970000>; - regulator-max-microvolt = <3072000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - }; - - regulators-1 { - compatible = "qcom,pmm8654au-rpmh-regulators"; - qcom,pmic-id = "c"; - - vreg_s5c: smps5 { - regulator-name = "vreg_s5c"; - regulator-min-microvolt = <1104000>; - regulator-max-microvolt = <1104000>; - regulator-initial-mode = ; - }; - - vreg_l1c: ldo1 { - regulator-name = "vreg_l1c"; - regulator-min-microvolt = <300000>; - regulator-max-microvolt = <512000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l2c: ldo2 { - regulator-name = "vreg_l2c"; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <904000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l4c: ldo4 { - regulator-name = "vreg_l4c"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l7c: ldo7 { - regulator-name = "vreg_l7c"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l8c: ldo8 { - regulator-name = "vreg_l8c"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - - vreg_l9c: ldo9 { - regulator-name = "vreg_l9c"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - regulator-allow-set-load; - regulator-allowed-modes = ; - }; - }; -}; -ðernet0 { - phy-mode = "2500base-x"; - phy-handle = <&hsgmii_phy0>; - - pinctrl-0 = <ðernet0_default>; - pinctrl-names = "default"; - - snps,mtl-rx-config = <&mtl_rx_setup>; - snps,mtl-tx-config = <&mtl_tx_setup>; - nvmem-cells = <&mac_addr0>; - nvmem-cell-names = "mac-address"; - - status = "okay"; - - mdio { - compatible = "snps,dwmac-mdio"; - #address-cells = <1>; - #size-cells = <0>; - - hsgmii_phy0: ethernet-phy@1c { - compatible = "ethernet-phy-id004d.d101"; - reg = <0x1c>; - reset-gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; - reset-assert-us = <11000>; - reset-deassert-us = <70000>; - }; - }; - - mtl_rx_setup: rx-queues-config { - snps,rx-queues-to-use = <4>; - snps,rx-sched-sp; - - queue0 { - snps,dcb-algorithm; - snps,map-to-dma-channel = <0x0>; - snps,route-up; - snps,priority = <0x1>; - }; - - queue1 { - snps,dcb-algorithm; - snps,map-to-dma-channel = <0x1>; - snps,route-ptp; - }; - - queue2 { - snps,avb-algorithm; - snps,map-to-dma-channel = <0x2>; - snps,route-avcp; - }; - - queue3 { - snps,avb-algorithm; - snps,map-to-dma-channel = <0x3>; - snps,priority = <0xc>; - }; - }; - - mtl_tx_setup: tx-queues-config { - snps,tx-queues-to-use = <4>; - - queue0 { - snps,dcb-algorithm; - }; - - queue1 { - snps,dcb-algorithm; - }; - - queue2 { - snps,avb-algorithm; - snps,send_slope = <0x1000>; - snps,idle_slope = <0x1000>; - snps,high_credit = <0x3e800>; - snps,low_credit = <0xffc18000>; - }; - - queue3 { - snps,avb-algorithm; - snps,send_slope = <0x1000>; - snps,idle_slope = <0x1000>; - snps,high_credit = <0x3e800>; - snps,low_credit = <0xffc18000>; - }; - }; -}; - -&gpi_dma0 { - status = "okay"; -}; - -&gpi_dma1 { - status = "okay"; -}; - -&gpu { - status = "okay"; -}; - -&gpu_zap_shader { - firmware-name = "qcom/qcs8300/a623_zap.mbn"; -}; - -&i2c0 { - status = "okay"; - - bridge@4f { - compatible = "lontium,lt8713sx"; - reg = <0x4f>; - reset-gpios = <&expander5 6 GPIO_ACTIVE_LOW>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lt8713sx_dp_in: endpoint { - remote-endpoint = <&mdss_dp0_out>; - }; - }; - - port@1 { - reg = <1>; - - lt8713sx_dp0_out: endpoint { - remote-endpoint = <&dp0_connector_in>; - }; - }; - - port@2 { - reg = <2>; - - lt8713sx_dp1_out: endpoint { - remote-endpoint = <&dp1_connector_in>; - }; - }; - }; - }; -}; - -&i2c1 { - pinctrl-0 = <&qup_i2c1_default>; - pinctrl-names = "default"; - - status = "okay"; - - fan_controller: fan@18 { - compatible = "ti,amc6821"; - reg = <0x18>; - #pwm-cells = <2>; - - fan { - pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; - }; - }; - - eeprom0: eeprom@50 { - compatible = "atmel,24c256"; - reg = <0x50>; - pagesize = <64>; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - mac_addr0: mac-addr@0 { - reg = <0x0 0x6>; - }; - }; - }; -}; - -&i2c15 { - pinctrl-0 = <&qup_i2c15_default>; - pinctrl-names = "default"; - - status = "okay"; - - expander0: gpio@38 { - compatible = "ti,tca9538"; - reg = <0x38>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 56 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander0_int>; - pinctrl-names = "default"; - }; - - expander1: gpio@39 { - compatible = "ti,tca9538"; - reg = <0x39>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 16 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander1_int>; - pinctrl-names = "default"; - }; - - expander2: gpio@3a { - compatible = "ti,tca9538"; - reg = <0x3a>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 95 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander2_int>; - pinctrl-names = "default"; - }; - - expander3: gpio@3b { - compatible = "ti,tca9538"; - reg = <0x3b>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 24 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander3_int>; - pinctrl-names = "default"; - }; + vreg_dcin_12v: regulator-dcin-12v { + compatible = "regulator-fixed"; - expander4: gpio@3c { - compatible = "ti,tca9538"; - reg = <0x3c>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 96 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander4_int>; - pinctrl-names = "default"; - }; + regulator-name = "VREG_DCIN_12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; - expander5: gpio@3d { - compatible = "ti,tca9538"; - reg = <0x3d>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander5_int>; - pinctrl-names = "default"; + regulator-boot-on; + regulator-always-on; }; - expander6: gpio@3e { - compatible = "ti,tca9538"; - reg = <0x3e>; - #gpio-cells = <2>; - gpio-controller; - #interrupt-cells = <2>; - interrupt-controller; - interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&expander6_int>; - pinctrl-names = "default"; - }; -}; - -&iris { - status = "okay"; -}; - -&mdss { - status = "okay"; -}; - -&mdss_dp0 { - pinctrl-0 = <&dp_hot_plug_det>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&mdss_dp0_out { - data-lanes = <0 1 2 3>; - link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; - remote-endpoint = <<8713sx_dp_in>; -}; - -&mdss_dp0_phy { - vdda-phy-supply = <&vreg_l5a>; - vdda-pll-supply = <&vreg_l4a>; - - status = "okay"; -}; - -&pcie0 { - pinctrl-0 = <&pcie0_default_state>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pcie0_phy { - vdda-phy-supply = <&vreg_l6a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; - -&pcie1 { - pinctrl-0 = <&pcie1_default_state>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pcie1_phy { - vdda-phy-supply = <&vreg_l6a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; -&pcieport0 { - reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; -}; + regulator-name = "VREG_WCN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; -&pcieport1 { - reset-gpios = <&tlmm 23 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; -}; + vin-supply = <&vreg_dcin_12v>; -&pmm8620au_0_gpios { - usb2_id: usb2-id-state { - pins = "gpio9"; - function = "normal"; - input-enable; - bias-pull-up; - power-source = <0>; + regulator-boot-on; }; }; -&qup_i2c0_data_clk { - drive-strength = <2>; - bias-pull-up; -}; - -&qupv3_id_0 { - firmware-name = "qcom/qcs8300/qupv3fw.elf"; - status = "okay"; -}; - -&qupv3_id_1 { - firmware-name = "qcom/qcs8300/qupv3fw.elf"; - status = "okay"; -}; - -&remoteproc_adsp { - firmware-name = "qcom/qcs8300/adsp.mbn"; - - status = "okay"; -}; - -&remoteproc_cdsp { - firmware-name = "qcom/qcs8300/cdsp0.mbn"; - - status = "okay"; -}; - -&remoteproc_gpdsp { - firmware-name = "qcom/qcs8300/gpdsp0.mbn"; - - status = "okay"; -}; - &sdhc_1 { vmmc-supply = <&vreg_l8a>; vqmmc-supply = <&vreg_s2s>; @@ -704,222 +54,3 @@ status = "okay"; }; - -&serdes0 { - phy-supply = <&vreg_l4a>; - - status = "okay"; -}; - -&spi10 { - status = "okay"; - - tpm@0 { - compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; - reg = <0>; - spi-max-frequency = <20000000>; - }; -}; - -&tlmm { - pcie0_default_state: pcie0-default-state { - wake-pins { - pins = "gpio0"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - - clkreq-pins { - pins = "gpio1"; - function = "pcie0_clkreq"; - drive-strength = <2>; - bias-pull-up; - }; - - perst-pins { - pins = "gpio2"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - ethernet0_default: ethernet0-default-state { - ethernet0_mdc: ethernet0-mdc-pins { - pins = "gpio5"; - function = "emac0_mdc"; - drive-strength = <16>; - bias-pull-up; - }; - - ethernet0_mdio: ethernet0-mdio-pins { - pins = "gpio6"; - function = "emac0_mdio"; - drive-strength = <16>; - bias-pull-up; - }; - }; - - expander5_int: expander5-int-state { - pins = "gpio3"; - function = "gpio"; - bias-pull-up; - }; - - expander1_int: expander1-int-state { - pins = "gpio16"; - function = "gpio"; - bias-pull-up; - }; - - qup_i2c1_default: qup-i2c1-state { - pins = "gpio19", "gpio20"; - function = "qup0_se1"; - drive-strength = <2>; - bias-pull-up; - }; - - pcie1_default_state: pcie1-default-state { - wake-pins { - pins = "gpio21"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - - clkreq-pins { - pins = "gpio22"; - function = "pcie1_clkreq"; - drive-strength = <2>; - bias-pull-up; - }; - - perst-pins { - pins = "gpio23"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - expander3_int: expander3-int-state { - pins = "gpio24"; - function = "gpio"; - bias-pull-up; - }; - - expander6_int: expander6-int-state { - pins = "gpio52"; - function = "gpio"; - bias-pull-up; - }; - - expander0_int: expander0-int-state { - pins = "gpio56"; - function = "gpio"; - bias-pull-up; - }; - - cam0_avdd_2v8_en_default: cam0-avdd-2v8-en-state { - pins = "gpio73"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - cam1_avdd_2v8_en_default: cam1-avdd-2v8-en-state { - pins = "gpio74"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - cam2_avdd_2v8_en_default: cam2-avdd-2v8-en-state { - pins = "gpio75"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - qup_i2c15_default: qup-i2c15-state { - pins = "gpio91", "gpio92"; - function = "qup1_se7"; - drive-strength = <2>; - bias-pull-up; - }; - - expander2_int: expander2-int-state { - pins = "gpio95"; - function = "gpio"; - bias-pull-up; - }; - - expander4_int: expander4-int-state { - pins = "gpio96"; - function = "gpio"; - bias-pull-up; - }; -}; - -&uart6 { - status = "okay"; -}; - -&uart7 { - status = "okay"; -}; - -&ufs_mem_hc { - reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; - vcc-supply = <&vreg_l8a>; - vcc-max-microamp = <1100000>; - vccq-supply = <&vreg_l4c>; - vccq-max-microamp = <1200000>; - - status = "okay"; -}; - -&ufs_mem_phy { - vdda-phy-supply = <&vreg_l4a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; - -&usb_1 { - dr_mode = "peripheral"; - - status = "okay"; -}; - -&usb_1_hsphy { - vdda-pll-supply = <&vreg_l7a>; - vdda18-supply = <&vreg_l7c>; - vdda33-supply = <&vreg_l9a>; - - status = "okay"; -}; - -&usb_qmpphy { - vdda-phy-supply = <&vreg_l7a>; - vdda-pll-supply = <&vreg_l5a>; - - status = "okay"; -}; - -&usb_2 { - status = "okay"; -}; - -&usb_2_dwc3_hs { - remote-endpoint = <&usb2_con_hs_ep>; -}; - -&usb_2_hsphy { - vdda-pll-supply = <&vreg_l7a>; - vdda18-supply = <&vreg_l7c>; - vdda33-supply = <&vreg_l9a>; - - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi index 9b5ed55939b86..6b146fdd6ebca 100644 --- a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi @@ -275,6 +275,7 @@ mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; + supports-cqe; no-sd; no-sdio; non-removable; diff --git a/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi b/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi index e990d7367719b..232bcb942b54c 100644 --- a/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi @@ -5,6 +5,7 @@ #include #include +#include "qcom-adc5-gen3.h" &spmi_bus { pmm8620au_0: pmic@0 { @@ -20,6 +21,27 @@ interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; }; + pmm8620au_0_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@3 { + reg = ; + label = "pmm8620au_0_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@8e { + reg = ; + label = "pmm8620au_0_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + }; + pmm8620au_0_gpios: gpio@8800 { compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; reg = <0x8800>; @@ -37,6 +59,27 @@ #address-cells = <1>; #size-cells = <0>; + pmm8650au_1_adc: adc@8000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x8000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x2 0x80 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@203 { + reg = ; + label = "pmm8650au_1_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@28e { + reg = ; + label = "pmm8650au_1_vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + }; + pmm8650au_1_gpios: gpio@8800 { compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; reg = <0x8800>; diff --git a/arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso b/arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso new file mode 100644 index 0000000000000..b1d8996c9ea8b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-rtss-mb.dtso @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&soc { + ipcc_computeL1: qcom,ipcc@488000 { + compatible = "qcom,ipcc"; + reg = <0x0 0x00488000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + num_mbox_chans = <5>; + }; + + rtss_mailbox: rtss-mailbox@1ffe02c { + compatible = "qcom,rtss-mailbox"; + reg = <0x0 0x01ffe02c 0x0 0x10>, + <0x0 0x01ffd018 0x0 0x10>, + <0x0 0x17c0000c 0x0 0x04>; + mboxes = <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x2>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x3>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x4>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x5>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x6>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0x7>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0x8>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0x9>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xa>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xb>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xc>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS0 0xd>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS1 0xe>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS2 0xf>, + <&ipcc_computeL1 IPCC_CLIENT_RTSS3 0x10>; + memory-region = <&sail_mailbox_mem>, + <&sail_ota_mem>; + interrupt-parent = <&ipcc_computeL1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + rtss-handshake-delay = <50000>; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-staging.dtso new file mode 100644 index 0000000000000..fc44741b8caab --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-staging.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Monaco staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@4b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@4b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index e4c8466f941bd..b77bf8f1dc86e 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -3,6 +3,7 @@ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include #include @@ -29,6 +30,46 @@ #address-cells = <2>; #size-cells = <2>; + aest { + compatible = "arm,aest"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + aest-processor-0 { + compatible = "arm,aest-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x0>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster0 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + + aest-l3-cluster1 { + compatible = "arm,aest-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,addressing-mode = /bits/ 64 <0x0>; + arm,processor-flags = ; + interrupts = ; + interrupt-names = "fhi"; + }; + }; + clocks { xo_board_clk: xo-board-clk { compatible = "fixed-clock"; @@ -742,6 +783,11 @@ #power-domain-cells = <0>; domain-idle-states = <&system_sleep>; }; + + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; }; reserved-memory { @@ -783,7 +829,7 @@ }; camera_mem: camera-region@95200000 { - reg = <0x0 0x95200000 0x0 0x500000>; + reg = <0x0 0x95200000 0x0 0x700000>; no-map; }; @@ -2488,8 +2534,7 @@ , , , - , - ; + ; interrupt-names = "msi0", "msi1", "msi2", @@ -2497,8 +2542,7 @@ "msi4", "msi5", "msi6", - "msi7", - "global"; + "msi7"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, @@ -3017,14 +3061,6 @@ #address-cells = <1>; #size-cells = <0>; - port@0 { - reg = <0>; - - swao_rep_out0: endpoint { - remote-endpoint = <&qdss_rep_in>; - }; - }; - port@1 { reg = <1>; @@ -3049,6 +3085,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_spdm"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3311,6 +3348,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_prng"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3330,6 +3368,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_pimem"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3351,6 +3390,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_ch_south"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3444,6 +3484,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_cdsp"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3487,6 +3528,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_mmnoc_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3559,6 +3601,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dlct"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3734,6 +3777,14 @@ #address-cells = <1>; #size-cells = <0>; + port@0 { + reg = <0>; + + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + port@1 { reg = <1>; @@ -3811,6 +3862,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3830,6 +3882,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3849,6 +3902,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3868,6 +3922,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3887,6 +3942,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3906,6 +3962,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aoss"; }; tpdm@4b80000 { @@ -3914,6 +3971,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_cdsp_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3981,6 +4039,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_cdsp_1"; }; tpdm@4c40000 { @@ -3989,6 +4048,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_gpdsp_0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4082,6 +4142,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dl_south"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4154,6 +4215,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4244,6 +4306,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr_ch0"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4287,6 +4350,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr_ch1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4612,6 +4676,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss"; }; tpdm@6860000 { @@ -4620,6 +4685,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_actpm"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -4639,6 +4705,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_apss"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4719,6 +4786,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_gold"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4738,6 +4806,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_silver"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -4757,6 +4826,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ext_dsb"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -4776,6 +4846,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_llm_gold"; }; cti@68f0000 { @@ -4784,6 +4855,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_llm_silver"; }; cti@6900000 { @@ -4792,6 +4864,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ext_dsb"; }; sdhc_1: mmc@87c4000 { @@ -4832,13 +4905,13 @@ qcom,dll-config = <0x000f64ee>; qcom,ddr-config = <0x80040868>; bus-width = <8>; - supports-cqe; dma-coherent; mmc-ddr-1_8v; mmc-hs200-1_8v; mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; + qcom,ice = <&sdhc_ice>; status = "disabled"; @@ -4867,6 +4940,31 @@ }; }; + sdhc_ice: crypto@87c8000 { + compatible = "qcom,qcs8300-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x087c8000 0x0 0x18000>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>, + <&gcc GCC_SDCC1_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&rpmhpd RPMHPD_CX>; + }; + + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + #clock-cells = <0>; + pinctrl-names = "active"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + }; + usb_1_hsphy: phy@8904000 { compatible = "qcom,qcs8300-usb-hs-phy", "qcom,usb-snps-hs-7nm-phy"; @@ -5088,6 +5186,8 @@ "gpu_cc_hub_aon_clk"; power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; pmu@9091000 { @@ -6433,6 +6533,13 @@ bias-disable; }; + gp_mn_active: gp_mn_active-state { + pins = "gpio32"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + hs0_mi2s_active: hs0-mi2s-active-state { pins = "gpio106", "gpio107", "gpio108", "gpio109"; function = "hs0_mi2s"; @@ -7728,6 +7835,9 @@ qcom,smem-states = <&smp2p_cdsp_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -8160,39 +8270,87 @@ }; nsp-0-0-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 5>; trips { + nsp_0_0_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 6>; trips { + nsp_0_1_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 7>; trips { + nsp_0_2_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_0_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-0-thermal { @@ -8280,39 +8438,87 @@ }; nsp-0-0-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 5>; trips { + nsp_0_0_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 6>; trips { + nsp_0_1_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 7>; trips { + nsp_0_2_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_1_alert0>; + cooling-device = <&remoteproc_cdsp + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-1-thermal { diff --git a/arch/arm64/boot/dts/qcom/pm4125.dtsi b/arch/arm64/boot/dts/qcom/pm4125.dtsi index 542e8fe030da4..829a77fb1e5cb 100644 --- a/arch/arm64/boot/dts/qcom/pm4125.dtsi +++ b/arch/arm64/boot/dts/qcom/pm4125.dtsi @@ -37,7 +37,7 @@ }; pm4125_vbus: usb-vbus-regulator@1100 { - compatible = "qcom,pm4125-vbus-reg", "qcom,pm8150b-vbus-reg"; + compatible = "qcom,pm4125-vbus-reg"; reg = <0x1100>; status = "disabled"; }; @@ -65,6 +65,83 @@ status = "disabled"; }; + pm4125_tz: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_BOTH>; + io-channels = <&pm4125_adc ADC5_DIE_TEMP>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + status = "disabled"; + }; + + pm4125_adc: adc@3100 { + compatible = "qcom,spmi-adc5"; + reg = <0x3100>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + + /* Channel nodes */ + channel@0 { + reg = ; + label = "ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@1 { + reg = ; + label = "vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@6 { + reg = ; + label = "die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@7 { + reg = ; + label = "usb_in_i_uv"; + qcom,pre-scaling = <1 1>; + }; + + channel@8 { + reg = ; + label = "usb_in_v_div_16"; + qcom,pre-scaling = <1 16>; + }; + + channel@9 { + reg = ; + label = "chg_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@4b { + reg = ; + label = "bat_id"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@83 { + reg = ; + label = "vph_pwr"; + qcom,pre-scaling = <1 3>; + }; + + channel@84 { + reg = ; + label = "vbat_sns"; + qcom,pre-scaling = <1 3>; + }; + }; + rtc@6000 { compatible = "qcom,pm8941-rtc"; reg = <0x6000>, <0x6100>; diff --git a/arch/arm64/boot/dts/qcom/pm7250b.dtsi b/arch/arm64/boot/dts/qcom/pm7250b.dtsi index 43cab07126c5c..363a1d6769c63 100644 --- a/arch/arm64/boot/dts/qcom/pm7250b.dtsi +++ b/arch/arm64/boot/dts/qcom/pm7250b.dtsi @@ -201,6 +201,16 @@ interrupt-controller; #interrupt-cells = <2>; }; + + sensor@1d00 { + compatible = "qcom,pm7250b-bcl", "qcom,bcl-v1"; + reg = <0x1d00>; + interrupts = , + ; + interrupt-names = "bcl-max-min", + "bcl-critical"; + overcurrent-thresholds-milliamp = <5500 6000>; + }; }; pmic@PM7250B_SID1 { diff --git a/arch/arm64/boot/dts/qcom/pm8005.dtsi b/arch/arm64/boot/dts/qcom/pm8005.dtsi index 0f0ab2da83055..2867ace2fa1ce 100644 --- a/arch/arm64/boot/dts/qcom/pm8005.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8005.dtsi @@ -11,6 +11,13 @@ #address-cells = <1>; #size-cells = <0>; + pm8005_tz: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x4 0x24 0x0 IRQ_TYPE_EDGE_BOTH>; + #thermal-sensor-cells = <0>; + }; + pm8005_gpios: gpio@c000 { compatible = "qcom,pm8005-gpio", "qcom,spmi-gpio"; reg = <0xc000>; diff --git a/arch/arm64/boot/dts/qcom/pm8350c.dtsi b/arch/arm64/boot/dts/qcom/pm8350c.dtsi index 1a24e6439e36d..f0cf55a7fc9e5 100644 --- a/arch/arm64/boot/dts/qcom/pm8350c.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8350c.dtsi @@ -41,6 +41,15 @@ #pwm-cells = <2>; status = "disabled"; }; + + sensor@4700 { + compatible = "qcom,pm8350c-bcl", "qcom,bcl-v2"; + reg = <0x4700>; + interrupts = <0x2 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x2 0x47 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "bcl-max-min", + "bcl-critical"; + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi new file mode 100644 index 0000000000000..ffd6b1c4d570f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + + /*cam1-og0a1b*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l7m_2p9>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 2912000>; + rgltr-max-voltage = <1808000 2912000>; + rgltr-load-current = <120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 96 0>, <&tlmm 109 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&cam_cci1 { + /*cam2-imx688*/ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l6m_1p8>; + cam_vdig-supply = <&vreg_l1m_1p1>; + cam_v_custom1-supply = <&vreg_l7b_2p8>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_v_custom1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-max-voltage = <1808000 1808000 1200000 2800000>; + rgltr-load-current = <120000 120000 120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + gpios = <&tlmm 100 0>, <&tlmm 237 0>, <&tlmm 233 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <4>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi new file mode 100644 index 0000000000000..cbc9ec0f83aad --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -0,0 +1,2086 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac01000 { + compatible = "qcom,cam-icp_v2"; + icp-version = <0x0200>; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <0 300000000 0>, + <0 400000000 0>, + <0 480000000 0>, + <0 600000000 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/x1p42100/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy4", "cci0", "cci1", "csid0", + "csid1", "csid2", "ife0", "ife1", "ife2", "ipe0", + "rt-cdm0", "rt-cdm1", "rt-cdm2", "cam-cdm-intf0", + "bps0", "icp0", "jpeg-dma0", + "jpeg-enc0", "tpg13", "tpg14", "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife1_rdi_stats_pixel_raw_wr: ife1-rdi-stats-pixel-raw-wr { + cell-index = <7>; + node-name = "ife1-rdi-stats-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <8>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <9>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <10>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <11>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <12>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <13>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <14>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <15>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <16>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <17>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <18>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <19>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <20>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <21>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <22>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <23>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <24>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <25>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <26>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <27>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <28>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <29>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <30>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <31>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <32>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <33>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <34>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + operating-points-v2 = <&cci1_opp_table>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <1>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <2>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm1"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x0060>, + <&apps_smmu 0x0820 0x0060>, + <&apps_smmu 0x0840 0x0060>, + <&apps_smmu 0x0860 0x0060>; + dma-coherent; + cam-smmu-label = "ife"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_int: cam-sensor-active-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_suspend_int: cam-sensor-suspend-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cci0_active: cci0-active { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci0_suspend: cci0-suspend { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + function = "cci_i2c"; + }; + }; + + cci1_active: cci1-active { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci1_suspend: cci1-suspend { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + function = "cci_i2c"; + }; + }; + + cci2_active: cci2-active { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci2_suspend: cci2-suspend { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + function = "cci_i2c"; + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso b/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso new file mode 100644 index 0000000000000..5584660dbcfd6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso new file mode 100644 index 0000000000000..27d1ff2fc2fea --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hamoa-camera-regulators.dtsi" +#include "purwa-camera.dtsi" +#include "purwa-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index ad503beec1d3d..2f55f27196f31 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -514,6 +514,23 @@ regulator-boot-on; }; + vreg_wcn_bt_en: regulator-wcn-bt-en { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_BT_EN"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + gpio = <&tlmm 116 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wcn_bt_en>; + pinctrl-names = "default"; + + regulator-always-on; + regulator-boot-on; + }; + vreg_wwan: regulator-wwan { compatible = "regulator-fixed"; @@ -628,10 +645,9 @@ vddrfa1p2-supply = <&vreg_wcn_1p9>; vddrfa1p8-supply = <&vreg_wcn_1p9>; - bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>; wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&wcn_bt_en>, <&wcn_wlan_en>; + pinctrl-0 = <&wcn_wlan_en>; pinctrl-names = "default"; regulators { @@ -734,6 +750,10 @@ }; }; +&camss { + status = "okay"; +}; + &i2c3 { clock-frequency = <400000>; @@ -1325,6 +1345,38 @@ }; }; +&thermal_gpuss_0 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + +&thermal_gpuss_1 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + +&thermal_gpuss_2 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + +&thermal_gpuss_3 { + trips { + trip-point0 { + temperature = <105000>; + }; + }; +}; + &tlmm { edp_reg_en: edp-reg-en-state { pins = "gpio70"; @@ -1504,13 +1556,13 @@ compatible = "qcom,wcn7850-bt"; max-speed = <3200000>; - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddaon-supply = <&vreg_wcn_3p3>; + vddwlcx-supply = <&vreg_wcn_3p3>; + vddwlmx-supply = <&vreg_wcn_3p3>; + vddrfacmn-supply = <&vreg_wcn_3p3>; + vddrfa0p8-supply = <&vreg_wcn_3p3>; + vddrfa1p2-supply = <&vreg_wcn_3p3>; + vddrfa1p8-supply = <&vreg_wcn_3p3>; }; }; diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi b/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi index 394e65518ac50..ff8621f875058 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-iot-som.dtsi @@ -389,6 +389,10 @@ firmware-name = "qcom/x1p42100/gen71500_zap.mbn"; }; +&iris { + status = "okay"; +}; + &pcie3 { pinctrl-0 = <&pcie3_default>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/qcom/purwa-staging.dtso b/arch/arm64/boot/dts/qcom/purwa-staging.dtso new file mode 100644 index 0000000000000..5ab12052dd80f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-staging.dtso @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Purwa staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +#include "x1-staging.dtsi" diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 9ab4f26b35f29..2b6106c15aee2 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -6,6 +6,8 @@ /* X1P42100 is heavily based on hamoa, with some meaningful differences */ #include "hamoa.dtsi" +#include + /delete-node/ &bwmon_cluster0; /delete-node/ &cluster_pd2; /delete-node/ &cpu_map_cluster2; @@ -17,8 +19,11 @@ /delete-node/ &cpu_pd9; /delete-node/ &cpu_pd10; /delete-node/ &cpu_pd11; +/delete-node/ &csiphy1; +/delete-node/ &csiphy2; /delete-node/ &gpu_opp_table; /delete-node/ &gpu_speed_bin; +/delete-node/ &iris_opp_table; /delete-node/ &pcie3_phy; /delete-node/ &thermal_aoss3; /delete-node/ &thermal_cpu2_0_btm; @@ -35,11 +40,187 @@ /delete-node/ &thermal_gpuss_5; /delete-node/ &thermal_gpuss_6; /delete-node/ &thermal_gpuss_7; +/delete-node/ &etm8; +/delete-node/ &etm9; +/delete-node/ &etm10; +/delete-node/ &etm11; +/delete-node/ &cluster2_funnel_l1; +/delete-node/ &cluster2_funnel_l2; +/delete-node/ &cluster2_etf; +/delete-node/ &cluster2_rep_2_0; +/delete-node/ &cluster2_rep_2_1; +/delete-node/ &cluster2_rep_2_2; +/delete-node/ &cluster2_rep_2_3; +/delete-node/ &apss_funnel_in2; + +&camss { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0x4000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy4", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x1860 0x60>, + <&apps_smmu 0x18e0 0x00>, + <&apps_smmu 0x19a0 0x20>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "top"; + + phys = <&csiphy0 PHY_TYPE_DPHY>, + <&csiphy4 PHY_TYPE_DPHY>; + phy-names = "csiphy0", + "csiphy4"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy0_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy4_inep0: endpoint@0 { + reg = <0>; + }; + }; + }; +}; + +&camcc { + compatible = "qcom,x1p42100-camcc"; +}; &gcc { compatible = "qcom,x1p42100-gcc", "qcom,x1e80100-gcc"; }; +&videocc { + compatible = "qcom,x1p42100-videocc"; +}; + &gmu { compatible = "qcom,adreno-gmu-x145.0", "qcom,adreno-gmu"; }; @@ -47,6 +228,8 @@ &gpu { compatible = "qcom,adreno-43030c00", "qcom,adreno"; + iommus = <&adreno_smmu 0 0x0>; + nvmem-cells = <&gpu_speed_bin>; nvmem-cell-names = "speed_bin"; @@ -157,6 +340,55 @@ compatible = "qcom,x1p42100-gpucc"; }; +&iris { + compatible = "qcom,x1p42100-iris"; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&videocc VIDEO_CC_MVS0_BSE_CLK>; + clock-names = "iface", + "core", + "vcodec0_core", + "vcodec0_bse"; + + operating-points-v2 = <&iris_opp_table_x1p42100>; + + iris_opp_table_x1p42100: opp-table { + compatible = "operating-points-v2"; + + opp-210000000 { + opp-hz = /bits/ 64 <210000000 105000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000 150000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_svs>; + }; + + opp-335000000 { + opp-hz = /bits/ 64 <335000000 167500000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-424000000 { + opp-hz = /bits/ 64 <424000000 212000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_nom>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000 250000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_turbo>; + }; + }; +}; + /* PCIe3 has half the lanes compared to X1E80100 */ &pcie3 { num-lanes = <4>; @@ -166,6 +398,10 @@ compatible = "qcom,x1p42100-qmp-gen4x4-pcie-phy"; }; +&pdc { + compatible = "qcom,x1p42100-pdc", "qcom,pdc"; +}; + &qfprom { gpu_speed_bin: gpu-speed-bin@119 { reg = <0x119 0x2>; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts index 04cb9230d29fd..9f0cfd0b5005e 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts @@ -89,6 +89,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -98,7 +99,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1478,10 +1479,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c>; vdda18-supply = <&vreg_l1c>; @@ -1521,3 +1518,7 @@ qcom,calibration-variant = "Fairphone_5"; status = "okay"; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index bdc02260f902b..999862932e3ed 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -591,12 +591,7 @@ }; &gcc { - protected-clocks = ,, - , , - , , - , , - , , - , , + protected-clocks = , , ,, , , , @@ -619,6 +614,13 @@ firmware-name = "qcom/qcm6490/a660_zap.mbn"; }; +&ipa { + qcom,gsi-loader = "self"; + memory-region = <&ipa_fw_mem>; + firmware-name = "qcom/qcm6490/ipa_fws.mbn"; + status = "okay"; +}; + &lpass_rx_macro { status = "okay"; }; @@ -673,6 +675,22 @@ status = "okay"; }; +&pcie1 { + perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie1_reset_n>, <&pcie1_wake_n>, <&pcie1_clkreq_n>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l10c_0p88>; + vdda-pll-supply = <&vreg_l6b_1p2>; + + status = "okay"; +}; + &pm7250b_gpios { lcd_disp_bias_en: lcd-disp-bias-en-state { pins = "gpio2"; @@ -786,6 +804,46 @@ bias-disable; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + +&qup_uart7_cts { + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; +}; + +&qup_uart7_rts { + /* We'll drive RTS, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&qup_uart7_rx { + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module is + * in tri-state (module powered off or not driving the + * signal yet). + */ + bias-pull-up; +}; + +&qup_uart7_tx { + /* We'll drive TX, so no pull */ + drive-strength = <2>; + bias-disable; +}; + &qupv3_id_0 { status = "okay"; }; @@ -1064,6 +1122,22 @@ bias-pull-up; }; + pcie1_reset_n: pcie1-reset-n-state { + pins = "gpio2"; + function = "gpio"; + drive-strength = <16>; + output-low; + bias-disable; + }; + + pcie1_wake_n: pcie1-wake-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + sd_cd: sd-cd-state { pins = "gpio91"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts index bf18c48520813..ca9c1a09ca733 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts @@ -65,6 +65,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -74,7 +75,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -826,10 +827,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; @@ -862,3 +859,7 @@ &usb_dp_qmpphy_out { remote-endpoint = <&pmic_glink_ss_in>; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts index 797f37596bf19..eb7e228787c24 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts @@ -75,6 +75,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -84,7 +85,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -952,10 +953,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c>; vdda18-supply = <&vreg_l1c>; @@ -986,6 +983,10 @@ remote-endpoint = <&pmic_glink_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &venus { firmware-name = "qcom/qcm6490/SHIFT/otter/venus.mbn"; diff --git a/arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h b/arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h new file mode 100644 index 0000000000000..aa8e54d7e786a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcom-adc5-gen3.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DTS_ARM64_QCOM_ADC5_GEN3_H__ +#define __DTS_ARM64_QCOM_ADC5_GEN3_H__ + +/* ADC channels for PMIC5 Gen3 */ + +#define VIRT_CHAN(sid, chan) ((sid) << 8 | (chan)) + +#define ADC5_GEN3_REF_GND(sid) VIRT_CHAN(sid, 0x00) +#define ADC5_GEN3_1P25VREF(sid) VIRT_CHAN(sid, 0x01) +#define ADC5_GEN3_VREF_VADC(sid) VIRT_CHAN(sid, 0x02) +#define ADC5_GEN3_DIE_TEMP(sid) VIRT_CHAN(sid, 0x03) + +#define ADC5_GEN3_AMUX1_THM(sid) VIRT_CHAN(sid, 0x04) +#define ADC5_GEN3_AMUX2_THM(sid) VIRT_CHAN(sid, 0x05) +#define ADC5_GEN3_AMUX3_THM(sid) VIRT_CHAN(sid, 0x06) +#define ADC5_GEN3_AMUX4_THM(sid) VIRT_CHAN(sid, 0x07) +#define ADC5_GEN3_AMUX5_THM(sid) VIRT_CHAN(sid, 0x08) +#define ADC5_GEN3_AMUX6_THM(sid) VIRT_CHAN(sid, 0x09) +#define ADC5_GEN3_AMUX1_GPIO(sid) VIRT_CHAN(sid, 0x0a) +#define ADC5_GEN3_AMUX2_GPIO(sid) VIRT_CHAN(sid, 0x0b) +#define ADC5_GEN3_AMUX3_GPIO(sid) VIRT_CHAN(sid, 0x0c) +#define ADC5_GEN3_AMUX4_GPIO(sid) VIRT_CHAN(sid, 0x0d) + +#define ADC5_GEN3_CHG_TEMP(sid) VIRT_CHAN(sid, 0x10) +#define ADC5_GEN3_USB_SNS_V_16(sid) VIRT_CHAN(sid, 0x11) +#define ADC5_GEN3_VIN_DIV16_MUX(sid) VIRT_CHAN(sid, 0x12) +#define ADC5_GEN3_VREF_BAT_THERM(sid) VIRT_CHAN(sid, 0x15) +#define ADC5_GEN3_IIN_FB(sid) VIRT_CHAN(sid, 0x17) +#define ADC5_GEN3_TEMP_ALARM_LITE(sid) VIRT_CHAN(sid, 0x18) +#define ADC5_GEN3_IIN_SMB(sid) VIRT_CHAN(sid, 0x19) +#define ADC5_GEN3_ICHG_SMB(sid) VIRT_CHAN(sid, 0x1b) +#define ADC5_GEN3_ICHG_FB(sid) VIRT_CHAN(sid, 0xa1) + +/* 30k pull-up */ +#define ADC5_GEN3_AMUX1_THM_30K_PU(sid) VIRT_CHAN(sid, 0x24) +#define ADC5_GEN3_AMUX2_THM_30K_PU(sid) VIRT_CHAN(sid, 0x25) +#define ADC5_GEN3_AMUX3_THM_30K_PU(sid) VIRT_CHAN(sid, 0x26) +#define ADC5_GEN3_AMUX4_THM_30K_PU(sid) VIRT_CHAN(sid, 0x27) +#define ADC5_GEN3_AMUX5_THM_30K_PU(sid) VIRT_CHAN(sid, 0x28) +#define ADC5_GEN3_AMUX6_THM_30K_PU(sid) VIRT_CHAN(sid, 0x29) +#define ADC5_GEN3_AMUX1_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2a) +#define ADC5_GEN3_AMUX2_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2b) +#define ADC5_GEN3_AMUX3_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2c) +#define ADC5_GEN3_AMUX4_GPIO_30K_PU(sid) VIRT_CHAN(sid, 0x2d) + +/* 100k pull-up */ +#define ADC5_GEN3_AMUX1_THM_100K_PU(sid) VIRT_CHAN(sid, 0x44) +#define ADC5_GEN3_AMUX2_THM_100K_PU(sid) VIRT_CHAN(sid, 0x45) +#define ADC5_GEN3_AMUX3_THM_100K_PU(sid) VIRT_CHAN(sid, 0x46) +#define ADC5_GEN3_AMUX4_THM_100K_PU(sid) VIRT_CHAN(sid, 0x47) +#define ADC5_GEN3_AMUX5_THM_100K_PU(sid) VIRT_CHAN(sid, 0x48) +#define ADC5_GEN3_AMUX6_THM_100K_PU(sid) VIRT_CHAN(sid, 0x49) +#define ADC5_GEN3_AMUX1_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4a) +#define ADC5_GEN3_AMUX2_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4b) +#define ADC5_GEN3_AMUX3_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4c) +#define ADC5_GEN3_AMUX4_GPIO_100K_PU(sid) VIRT_CHAN(sid, 0x4d) + +/* 400k pull-up */ +#define ADC5_GEN3_AMUX1_THM_400K_PU(sid) VIRT_CHAN(sid, 0x64) +#define ADC5_GEN3_AMUX2_THM_400K_PU(sid) VIRT_CHAN(sid, 0x65) +#define ADC5_GEN3_AMUX3_THM_400K_PU(sid) VIRT_CHAN(sid, 0x66) +#define ADC5_GEN3_AMUX4_THM_400K_PU(sid) VIRT_CHAN(sid, 0x67) +#define ADC5_GEN3_AMUX5_THM_400K_PU(sid) VIRT_CHAN(sid, 0x68) +#define ADC5_GEN3_AMUX6_THM_400K_PU(sid) VIRT_CHAN(sid, 0x69) +#define ADC5_GEN3_AMUX1_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6a) +#define ADC5_GEN3_AMUX2_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6b) +#define ADC5_GEN3_AMUX3_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6c) +#define ADC5_GEN3_AMUX4_GPIO_400K_PU(sid) VIRT_CHAN(sid, 0x6d) + +/* 1/3 Divider */ +#define ADC5_GEN3_AMUX1_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8a) +#define ADC5_GEN3_AMUX2_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8b) +#define ADC5_GEN3_AMUX3_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8c) +#define ADC5_GEN3_AMUX4_GPIO_DIV3(sid) VIRT_CHAN(sid, 0x8d) + +#define ADC5_GEN3_VPH_PWR(sid) VIRT_CHAN(sid, 0x8e) +#define ADC5_GEN3_VBAT_SNS_QBG(sid) VIRT_CHAN(sid, 0x8f) + +#define ADC5_GEN3_VBAT_SNS_CHGR(sid) VIRT_CHAN(sid, 0x94) +#define ADC5_GEN3_VBAT_2S_MID_QBG(sid) VIRT_CHAN(sid, 0x96) +#define ADC5_GEN3_VBAT_2S_MID_CHGR(sid) VIRT_CHAN(sid, 0x9d) + +#endif /* __DTS_ARM64_QCOM_ADC5_GEN3_H__ */ diff --git a/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso b/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso new file mode 100644 index 0000000000000..4255147f00ef9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* +* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +*/ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "qcs6490-camera.dtsi" +#include "qcs6490-rb3gen2-camera-sensor.dtsi" + +&cam_csid2 { + status = "disabled"; +}; + +&cam_vfe2 { + status = "disabled"; +}; + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso b/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso new file mode 100644 index 0000000000000..a40d8817a7a20 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "talos-camera.dtsi" +#include "talos-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 51b13b492472f..6bd07c323a439 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -232,8 +232,8 @@ vreg_l2a: ldo2 { regulator-name = "vreg_l2a"; - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <3100000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; regulator-initial-mode = ; regulator-allow-set-load; regulator-allowed-modes = ; + mode-edl = <0x80000000 0x1>; + }; +}; + +&qspi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <25000000>; + spi-tx-bus-width = <2>; + spi-rx-bus-width = <2>; + }; +}; + &qupv3_id_0 { status = "okay"; }; @@ -599,7 +618,7 @@ cd-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>; vmmc-supply = <&vreg_l10a>; - vqmmc-supply = <&vreg_s4a>; + vqmmc-supply = <&vreg_l2a>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi new file mode 100644 index 0000000000000..2fadfb9de1fee --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -0,0 +1,2471 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_a5: qcom,a5 { + compatible = "qcom,cam-a5"; + cell-index = <0>; + reg = <0x0 0xac00000 0x0 0x6000>, + <0x0 0xac10000 0x0 0x8000>, + <0x0 0xac18000 0x0 0x3000>; + reg-names = "a5_qgic", "a5_sierra", "a5_csr"; + reg-cam-base = <0x00000 0x10000 0x18000>; + interrupts = ; + interrupt-names = "a5"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "soc_fast_ahb", + "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <100000000 0 400000000 0>, + <200000000 0 400000000 0>, + <300000000 0 600000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "soc_fast_ahb"; + operating-points-v2 = <&a5_opp_table>; + fw_name = "qcom/qcm6490/CAMERA_ICP_170.elf"; + ubwc-ipe-fetch-cfg = <0x7073 0x707b>; + ubwc-ipe-write-cfg = <0x161cf 0x161ef>; + ubwc-bps-fetch-cfg = <0x7073 0x707b>; + ubwc-bps-write-cfg = <0x161cf 0x161ef>; + qos-val = <0x00000A0A>; + status = "ok"; + + a5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps { + compatible = "qcom,cam-bps"; + cell-index = <0>; + reg = <0x0 0xac6f000 0x0 0x8000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_AREG_CLK>, + <&camcc CAM_CC_BPS_AXI_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_areg_clk", + "bps_axi_clk", + "bps_clk_src", + "bps_clk"; + clock-rates = <0 0 0 200000000 0>, + <0 0 0 400000000 0>, + <0 0 0 480000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc", + "lrmecdm"; + status = "ok"; + }; + + qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + cell-index = <0>; + label = "cpas"; + arch-compat = "cpas_top"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0x0ac40000 0x0 0x1000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg-cam-base = <0x40000 0x9f000>; + cam_hw_fuse = , + , + , + , + , + ; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk"; + src-clock-name = "cam_cc_camnoc_axi_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0>, + <0 0 80000000 0 150000000 0 0 0>, + <0 0 80000000 0 240000000 0 0 0>, + <0 0 80000000 0 320000000 0 0 0>, + <0 0 80000000 0 400000000 0 0 0>, + <0 0 80000000 0 480000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "csiphy4", "cci0", "cci1", "csid0", "csid1", + "csid2", "csid3", "csid4", "ife0", "ife1", + "ife2", "ife3", "ife4", "ipe0", "cam-cdm-intf0", + "cpas-cdm0", "bps0", "icp0", "jpeg-dma0", "jpeg-enc0", + "lrmecpas0"; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + cpas_cdm0_all_rd: cpas-cdm0-all-rd { + cell-index = <2>; + node-name = "cpas-cdm0-all-rd"; + client-name = "cpas-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_read0>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <3>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_read0>; + }; + + ife0_pixelall_wr: ife0-pixelall-wr { + cell-index = <4>; + node-name = "ife0-pixelall-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife0_rdi_wr: ife0-rdi-wr { + cell-index = <5>; + node-name = "ife0-rdi-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife1_pixelall_wr: ife1-pixelall-wr { + cell-index = <6>; + node-name = "ife1-pixelall-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_rdi_wr: ife1-rdi-wr { + cell-index = <7>; + node-name = "ife1-rdi-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife2_pixelall_wr: ife2-pixelall-wr { + cell-index = <8>; + node-name = "ife2-pixelall-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write1>; + }; + + ife2_rdi_wr: ife2-rdi-wr { + cell-index = <9>; + node-name = "ife2-rdi-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife3_rdi_wr: ife3-rdi-wr { + cell-index = <10>; + node-name = "ife3-rdi-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife4_rdi_wr: ife4-rdi-wr { + cell-index = <11>; + node-name = "ife4-rdi-wr"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ipe0_all_rd: ipe0-all-rd { + cell-index = <12>; + node-name = "ipe0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_read0>; + }; + + ipe0_ref_wr: ipe0-ref-wr { + cell-index = <13>; + node-name = "ipe0-ref-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + ipe0_viddisp_wr: ipe0-viddisp-wr { + cell-index = <14>; + node-name = "ipe0-viddisp-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_write0>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <15>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_read0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <16>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_write0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <17>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_read0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <18>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_write0>; + }; + + lrme0_all_rd: lrme0-all-rd { + cell-index = <19>; + node-name = "lrme0-all-rd"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + lrme0_all_wr: lrme0-all-wr { + cell-index = <20>; + node-name = "lrme0-all-wr"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_write0: level1-nrt0-write0 { + cell-index = <21>; + node-name = "level1-nrt0-write0"; + parent-node = <&level2_nrt0_write0>; + traffic-merge-type = ; + }; + + level1_nrt0_read0: level1-nrt0-read0 { + cell-index = <22>; + node-name = "level1-nrt0-read0"; + parent-node = <&level2_nrt0_read0>; + traffic-merge-type = ; + }; + + level1_nrt1_write0: level1-nrt1-write0 { + cell-index = <23>; + node-name = "level1-nrt1-write0"; + parent-node = <&level2_nrt0_write0>; + traffic-merge-type = ; + }; + + level1_nrt1_read0: level1-nrt1-read0 { + cell-index = <24>; + node-name = "level1-nrt1-read0"; + parent-node = <&level2_nrt0_read0>; + traffic-merge-type = ; + }; + + level1_rt0_write0: level1-rt0-write0 { + cell-index = <25>; + node-name = "level1-rt0-write0"; + parent-node = <&level2_rt0_write0>; + traffic-merge-type = ; + }; + + level1_rt1_write0: level1-rt1-write0 { + cell-index = <26>; + node-name = "level1-rt1-write0"; + parent-node = <&level2_rt1_write0>; + traffic-merge-type = ; + }; + + level1_rt1_write1: level1-rt1-write1 { + cell-index = <27>; + node-name = "level1-rt1-write1"; + parent-node = <&level2_rt1_write0>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <3>; + camnoc-max-needed; + + level2_nrt0_write0: level2-nrt0-write0 { + cell-index = <28>; + node-name = "level2-nrt0-write0"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt0_read0: level2-nrt0-read0 { + cell-index = <29>; + node-name = "level2-nrt0-read0"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt1_read0: level2-nrt1-read0 { + cell-index = <30>; + node-name = "level2-nrt1-read0"; + parent-node = <&level3_nrt1_rd_sum>; + traffic-merge-type = + ; + bus-width-factor = <4>; + }; + + level2_rt0_write0: level2-rt0-write0 { + cell-index = <31>; + node-name = "level2-rt0-write0"; + parent-node = <&level3_rt0_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt1_write0: level2-rt1-write0 { + cell-index = <32>; + node-name = "level2-rt1-write0"; + parent-node = <&level3_rt0_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <33>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + interconnect-names = "cam_sf_0"; + interconnects = + <&mmss_noc MASTER_CAMNOC_SF 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + + level3_nrt1_rd_sum: level3-nrt1-rd-sum { + cell-index = <34>; + node-name = "level3-nrt1-rd-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + interconnect-names = "cam_sf_icp"; + interconnects = + <&mmss_noc MASTER_CAMNOC_ICP 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + + level3_rt0_wr_sum: level3-rt0-wr-sum { + cell-index = <35>; + node-name = "level3-rt0-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + interconnect-names = "cam_hf_0"; + interconnects = + <&mmss_noc MASTER_CAMNOC_HF 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + }; + }; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,a5", + "qcom,ipe0", + "qcom,bps"; + num-a5 = <1>; + num-ipe = <1>; + num-bps = <1>; + icp_pc_en; + status = "ok"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "ok"; + }; + + qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + arch-compat = "lrme"; + status = "ok"; + }; + + qcom,camera-main { + compatible = "qcom,camera_kt"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-icp-fw { + compatible = "qcom,msm-cam-smmu-fw-dev"; + label="icp"; + memory-region = <&camera_mem>; + }; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2040 0x0>; + cam-smmu-label = "cpas-cdm"; + dma-coherent; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm_cam_smmu_icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2000 0x20>, + <&apps_smmu 0x2020 0x20>, + <&apps_smmu 0x2062 0x0>, + <&apps_smmu 0x2080 0x20>, + <&apps_smmu 0x20A0 0x20>, + <&apps_smmu 0x2140 0x0>; + cam-smmu-label = "icp"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 5MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x500000>; + iova-region-id = <0x0>; + status = "ok"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.7 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xcf300000>; + iova-region-id = <0x3>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-secondary-heap { + /* Secondary heap region is 1MB long */ + iova-region-name = "secheap"; + iova-region-start = <0x10a00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x4>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is 150MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x9600000>; + iova-region-id = <0x1>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x800 0x4E0>, + <&apps_smmu 0x820 0x4E0>, + <&apps_smmu 0x840 0x4E0>, + <&apps_smmu 0x860 0x4E0>, + <&apps_smmu 0x880 0x4E0>, + <&apps_smmu 0x8A0 0x4E0>, + <&apps_smmu 0x8C0 0x4E0>, + <&apps_smmu 0x8E0 0x4E0>, + <&apps_smmu 0xC00 0x4E0>, + <&apps_smmu 0xC20 0x4E0>, + <&apps_smmu 0xC40 0x4E0>, + <&apps_smmu 0xC60 0x4E0>, + <&apps_smmu 0xC80 0x4E0>, + <&apps_smmu 0xCA0 0x4E0>, + <&apps_smmu 0xCC0 0x4E0>, + <&apps_smmu 0xCE0 0x4E0>; + cam-smmu-label = "ife"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x20C0 0x20>, + <&apps_smmu 0x20E0 0x20>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-lrme { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2100 0x20>, + <&apps_smmu 0x2120 0x20>; + cam-smmu-label = "lrme"; + dma-coherent; + + lrme_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "ok"; + }; + + /* IO region is approximately 3.3 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + cam_cci0: qcom,cci0 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4a000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x4a000>; + interrupts = ; + interrupt-names = "cci"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pinctrl-0 = <&cci0_active &cci1_active>; + pinctrl-1 = <&cci0_suspend &cci1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 70 0>, + <&tlmm 71 0>, + <&tlmm 72 0>; + gpio-req-tbl-num = <0 1 2 3>; + gpio-req-tbl-flags = <1 1 1 1>; + gpio-req-tbl-label = "CCI_I2C_DATA0", + "CCI_I2C_CLK0", + "CCI_I2C_DATA1", + "CCI_I2C_CLK1"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4b000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x4b000>; + interrupts = ; + interrupt-names = "cci"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pinctrl-0 = <&cci2_active &cci3_active>; + pinctrl-1 = <&cci2_suspend &cci3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 74 0>, + <&tlmm 75 0>, + <&tlmm 76 0>; + gpio-req-tbl-num = <0 1 2 3>; + gpio-req-tbl-flags = <1 1 1 1>; + gpio-req-tbl-label = "CCI_I2C_DATA2", + "CCI_I2C_CLK2", + "CCI_I2C_DATA3", + "CCI_I2C_CLK3"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + qcom,cpas-cdm0 { + compatible = "qcom,cam170-cpas-cdm0"; + cell-index = <0>; + label = "cpas-cdm"; + reg = <0x0 0xac48000 0x0 0x1000>; + reg-names = "cpas-cdm"; + reg-cam-base = <0x48000>; + interrupts = ; + interrupt-names = "cpas-cdm"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <80000000 0>; + clock-cntl-level = "svs"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + operating-points-v2 = <&cdm_cpas_opp_table>; + cdm-client-names = "ife0", "ife1", "ife2", + "ife3", "ife4", "dualife"; + status = "ok"; + + cdm_cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid165_204"; + cell-index = <0>; + reg = <0x0 0xacb3000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xb3000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid165_204"; + cell-index = <1>; + reg = <0x0 0xacba000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xba000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid2: qcom,csid2 { + compatible = "qcom,csid165_204"; + cell-index = <2>; + reg = <0x0 0x0acc1000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xc1000>; + interrupts = ; + interrupt-names = "csid2"; + power-domains = <&camcc CAM_CC_IFE_2_GDSC>; + clocks = <&camcc CAM_CC_IFE_2_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CSID_CLK>, + <&camcc CAM_CC_IFE_2_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_2_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CLK>, + <&camcc CAM_CC_IFE_2_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid2_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite165"; + cell-index = <3>; + reg = <0x0 0xacc8000 0x0 0x1000>; + reg-names = "csid-lite"; + reg-cam-base = <0xc8000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk"; + clock-rates = <300000000 0 0 320000000 0>, + <400000000 0 0 400000000 0>, + <400000000 0 0 480000000 0>, + <400000000 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite165"; + cell-index = <4>; + reg = <0x0 0x0accf000 0x0 0x1000>; + reg-names = "csid-lite"; + reg-cam-base = <0xcf000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk"; + clock-rates = <300000000 0 0 320000000 0>, + <400000000 0 0 400000000 0>, + <400000000 0 0 480000000 0>, + <400000000 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0 { + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + cell-index = <0>; + reg = <0x0 0x0ace0000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe0000>; + interrupts = ; + interrupt-names = "csiphy0"; + operating-points-v2 = <&csiphy0_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + clock-cntl-level = "lowsvs", "svs"; + src-clock-name = "csi0phytimer_clk_src"; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1 { + cell-index = <1>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace2000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe2000>; + interrupts = ; + interrupt-names = "csiphy1"; + operating-points-v2 = <&csiphy1_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2 { + cell-index = <2>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "csiphy2"; + operating-points-v2 = <&csiphy2_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy3: qcom,csiphy3 { + cell-index = <3>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "csiphy3"; + operating-points-v2 = <&csiphy3_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy3_clk", + "csi3phytimer_clk_src", + "csi3phytimer_clk"; + src-clock-name = "csi3phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4 { + cell-index = <4>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace8000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe8000>; + interrupts = ; + interrupt-names = "csiphy4"; + operating-points-v2 = <&csiphy4_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + cell-index = <0>; + reg = <0x0 0xac87000 0x0 0xa000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, + <&camcc CAM_CC_IPE_0_AREG_CLK>, + <&camcc CAM_CC_IPE_0_AXI_CLK>, + <&camcc CAM_CC_IPE_0_CLK_SRC>, + <&camcc CAM_CC_IPE_0_CLK>; + clock-names = "ipe_0_ahb_clk", + "ipe_0_areg_clk", + "ipe_0_axi_clk", + "ipe_0_clk_src", + "ipe_0_clk"; + clock-rates = <0 0 0 300000000 0>, + <0 0 0 430000000 0>, + <0 0 0 520000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + src-clock-name = "ipe_0_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-430000000 { + opp-hz = /bits/ 64 <430000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-520000000 { + opp-hz = /bits/ 64 <520000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma { + compatible = "qcom,cam_jpeg_dma_165"; + cell-index = <0>; + reg = <0x0 0xac52000 0x0 0x4000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x52000 0x9f000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <600000000 0>; + clock-cntl-level = "nominal"; + src-clock-name = "jpegdma_clk_src"; + operating-points-v2 = <&jpeg_dma_opp_table>; + cam_hw_pid = <20 21>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <2>; + status = "ok"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc { + compatible = "qcom,cam_jpeg_enc_165"; + cell-index = <0>; + reg = <0x0 0xac4e000 0x0 0x4000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "jpege_hw", "cam_camnoc"; + reg-cam-base = <0x4e000 0x9f000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <600000000 0>; + clock-cntl-level = "nominal"; + src-clock-name = "jpegenc_clk_src"; + operating-points-v2 = <&jpeg_enc_opp_table>; + cam_hw_pid = <22 23>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <2>; + status = "ok"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_lrme: qcom,lrme { + compatible = "qcom,lrme"; + cell-index = <0>; + reg = <0x0 0xac6b000 0x0 0x1000>; + reg-names = "lrme"; + reg-cam-base = <0x6b000>; + interrupts = ; + interrupt-names = "lrme"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_LRME_CLK_SRC>, + <&camcc CAM_CC_LRME_CLK>; + clock-names = "lrme_clk_src", + "lrme_clk"; + clock-rates = <240000000 0>, + <300000000 0>, + <320000000 0>, + <400000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "lrme_clk_src"; + operating-points-v2 = <&lrme_opp_table>; + status = "ok"; + + lrme_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,vfe0 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0xacaf000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xaf000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <24 8>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,vfe1 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0xacb6000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xb6000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <25 9>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + + cam_vfe2: qcom,vfe2 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0x0acbd000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xbd000>; + interrupts = ; + interrupt-names = "ife2"; + power-domains = <&camcc CAM_CC_IFE_2_GDSC>; + clocks = <&camcc CAM_CC_IFE_2_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CLK>, + <&camcc CAM_CC_IFE_2_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe2_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_2_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <3 10>; + cell-index = <2>; + status = "ok"; + + vfe2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,vfe-lite0 { + compatible = "qcom,vfe-lite165"; + cell-index = <3>; + reg = <0x0 0xacc4000 0x0 0x5000>; + reg-names = "ife-lite"; + reg-cam-base = <0xc4000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CLK>; + clock-names = "ife_clk_src", + "ife_clk"; + clock-rates = <320000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <11>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,vfe-lite1 { + compatible = "qcom,vfe-lite165"; + reg = <0x0 0x0accb000 0x0 0x5000>; + reg-names = "ife-lite"; + reg-cam-base = <0xcb000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CLK>; + clock-names = "ife_clk_src", + "ife_clk"; + clock-rates = <320000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <12>; + cell-index = <4>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_active_mux: cam-sensor-active-mux { + /* GC630 bypass mux */ + mux { + pins = "gpio1"; + function = "gpio"; + }; + + config { + pins = "gpio1"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + mux { + pins = "gpio20"; + function = "gpio"; + }; + + config { + pins = "gpio20"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET REARAUX */ + mux { + pins = "gpio21"; + function = "gpio"; + }; + + config { + pins = "gpio21"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET 2 */ + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst3: cam-sensor-active-rst3 { + /* RESET 3 */ + mux { + pins = "gpio78"; + function = "gpio"; + }; + + config { + pins = "gpio78"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET 4 */ + mux { + pins = "gpio79"; + function = "gpio"; + }; + + config { + pins = "gpio79"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_active: cam_sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio64"; + function = "cam_mclk"; + }; + + config { + pins = "gpio64"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio64"; + function = "cam_mclk"; + }; + + config { + pins = "gpio64"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio65"; + function = "cam_mclk"; + }; + + config { + pins = "gpio65"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio65"; + function = "cam_mclk"; + }; + + config { + pins = "gpio65"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio66"; + function = "cam_mclk"; + }; + + config { + pins = "gpio66"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio66"; + function = "cam_mclk"; + }; + + config { + pins = "gpio66"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* MCLK4 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* MCLK4 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk5_active: cam-sensor-mclk5-active { + /* MCLK5 */ + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk5_suspend: cam-sensor-mclk5-suspend { + /* MCLK5 */ + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_mux: cam-sensor-suspend-mux { + /* GC630 bypass mux */ + mux { + pins = "gpio1"; + function = "gpio"; + }; + + config { + pins = "gpio1"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst0: cam_sensor-suspend-rst0 { + /* RESET REAR */ + mux { + pins = "gpio20"; + function = "gpio"; + }; + + config { + pins = "gpio20"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET REARAUX */ + mux { + pins = "gpio21"; + function = "gpio"; + }; + + config { + pins = "gpio21"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET 2 */ + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst3: cam-sensor-suspend-rst3 { + /* RESET 3 */ + mux { + pins = "gpio78"; + function = "gpio"; + }; + + config { + pins = "gpio78"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET 4 */ + mux { + pins = "gpio79"; + function = "gpio"; + }; + + config { + pins = "gpio79"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cci0_active: cci0-active { + mux { + /* DATA, CLK */ + pins = "gpio69","gpio70"; // Only 2 + function = "cci_i2c"; + }; + + config { + pins = "gpio69","gpio70"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci0_suspend: cci0-suspend { + mux { + /* DATA, CLK */ + pins = "gpio69","gpio70"; + function = "cci_i2c"; + }; + + config { + pins = "gpio69","gpio70"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_active: cci1-active { + mux { + /* DATA, CLK */ + pins = "gpio71","gpio72"; + function = "cci_i2c"; + }; + + config { + pins = "gpio71","gpio72"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_suspend: cci1-suspend { + mux { + /* DATA, CLK */ + pins = "gpio71","gpio72"; + function = "cci_i2c"; + }; + + config { + pins = "gpio71","gpio72"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_active: cci2-active { + mux { + /* DATA, CLK */ + pins = "gpio73","gpio74"; + function = "cci_i2c"; + }; + + config { + pins = "gpio73","gpio74"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_suspend: cci2-suspend { + mux { + /* DATA, CLK */ + pins = "gpio73","gpio74"; + function = "cci_i2c"; + }; + + config { + pins = "gpio73","gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + mux { + /* DATA, CLK */ + pins = "gpio75","gpio76"; + function = "cci_i2c"; + }; + + config { + pins = "gpio75","gpio76"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_suspend: cci3-suspend { + mux { + /* DATA, CLK */ + pins = "gpio75","gpio76"; + function = "cci_i2c"; + }; + + config { + pins = "gpio75","gpio76"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts index bb5a42b038f19..400d128132fcb 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts @@ -24,6 +24,23 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; + +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi new file mode 100644 index 0000000000000..026b97b58377d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi @@ -0,0 +1,551 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + //cam1 interpose on dk csi0 + actuator_rear_cam11: qcom,actuator11 { + compatible = "qcom,actuator"; + cell-index = <11>; + cci-master = <1>; + regulator-names = "cam_vaf"; + rgltr-cntrl-support; + rgltr-min-voltage = <2856000>; + rgltr-max-voltage = <3104000>; + rgltr-load-current = <100000>; + }; + + eeprom_rear_cam11: qcom,eeprom11 { + compatible = "qcom,eeprom"; + cell-index = <11>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio", "cam_clk"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 0>; + rgltr-max-voltage = <1800000 0>; + rgltr-load-current = <120000 0>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0a-ov9282*/ + rb3_slot0a: qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 64 0>, + <&tlmm 20 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam1-ov9282*/ + rb3_slot1: qcom,cam-sensor6 { + compatible = "qcom,cam-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam1-imx586/imx686*/ + qcom,cam-sensor11 { + compatible = "qcom,cam-sensor"; + cell-index = <11>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + actuator-src = <&actuator_rear_cam11>; + eeprom-src = <&eeprom_rear_cam11>; + cam_vio-supply = <&vreg_l18b_1p8>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "cam_vio", "cam_clk"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 0>; + rgltr-max-voltage = <1800000 0>; + rgltr-load-current = <120000 0>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + +}; + +&cam_cci1 { + eeprom_cam2: qcom,eeprom0 { + compatible = "qcom,eeprom"; + cell-index = <8>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 66 0>, + <&tlmm 77 0>, + <&pm7250b_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam3: qcom,eeprom3 { + compatible = "qcom,eeprom"; + cell-index = <0>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 78 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-position = <1>; + sensor-mode = <0>; + cci-master = <1>; + qcom,cam-power-seq-type ="cam_reset","cam_vio", + "cam_clk","cam_reset"; + qcom,cam-power-seq-val = "cam_reset","cam_vio", + "cam_mclk","cam_reset"; + qcom,cam-power-seq-cfg-val = <0 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 1 18>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam3-imx577*/ + rb3_slot3: qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + cell-index = <0>; + csiphy-sd-index = <3>; + eeprom-src = <&eeprom_cam3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 78 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /* GMSL 1 */ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + cell-index = <4>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_4"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /* GMSL 2 */ + qcom,cam-sensor5 { + compatible = "qcom,cam-sensor"; + cell-index = <5>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_5"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /*cam0b-ov9282*/ + rb3_slot0b: qcom,cam-sensor7 { + compatible = "qcom,cam-sensor"; + cell-index = <7>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk4_active + &cam_sensor_active_rst5>; + pinctrl-1 = <&cam_sensor_mclk4_suspend + &cam_sensor_suspend_rst5>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 149 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK4", + "CAM_RESET5"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam2-imx577*/ + rb3_slot2: qcom,cam-sensor8 { + compatible = "qcom,cam-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam2>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 66 0>, + <&tlmm 77 0>, + <&pm7250b_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /* GMSL 3 */ + qcom,cam-sensor9 { + compatible = "qcom,cam-sensor"; + cell-index = <9>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_9"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /* GMSL 4 */ + qcom,cam-sensor10 { + compatible = "qcom,cam-sensor"; + cell-index = <10>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_10"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared-pinctrl = <640>; + shared-pctrl-gpio-names = "gmsl"; + pinctrl-0 = <&cam_sensor_active_gmsl>; + pinctrl-1 = <&cam_sensor_suspend_gmsl>; + pinctrl-names = "gmsl_active", "gmsl_suspend"; + status = "ok"; + }; +}; + +&tlmm { + cam_sensor_active_gmsl: cam-sensor-active-gmsl { + /* GMSL_ENABLE */ + mux { + pins = "gpio93"; + function = "gpio"; + }; + + config { + pins = "gpio93"; + bias-pull-up; + drive-strength = <2>; /* 2 MA */ + output-high; + }; + }; + + cam_sensor_active_rst5: cam-sensor-active-rst5 { + /* RESET 5 */ + mux { + pins = "gpio115"; + function = "gpio"; + }; + + config { + pins = "gpio115"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_gmsl: cam-sensor-suspend-gmsl { + /* GMSL_ENABLE */ + mux { + pins = "gpio93"; + function = "gpio"; + }; + + config { + pins = "gpio93"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst5: cam-sensor-suspend-rst5 { + /* RESET 5 */ + mux { + pins = "gpio115"; + function = "gpio"; + }; + + config { + pins = "gpio115"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtso new file mode 100644 index 0000000000000..905a40f4b938f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-m2-cologne.dtso @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved. +*/ + +/dts-v1/; +/plugin/; +#include + +&tlmm { + qup_uart4_sleep_cts: qup-uart4-sleep-cts-state { + pins = "gpio16"; + function = "gpio"; + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; + }; + + qup_uart4_sleep_rts: qup-uart4-sleep-rts-state { + pins = "gpio17"; + function = "gpio"; + /* + * Configure pull-down on RTS. As RTS is active low + * signal, pull it low to indicate the BT SoC that it + * can wakeup the system anytime from suspend state by + * pulling RX low (by sending wakeup bytes). + */ + bias-pull-down; + }; + + qup_uart4_sleep_rx: qup-uart4-sleep-rx-state { + pins = "gpio19"; + function = "gpio"; + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module + * is floating which may cause spurious wakeups. + */ + bias-pull-up; + }; + + qup_uart4_sleep_tx: qup-uart4-sleep-tx-state { + pins = "gpio18"; + function = "gpio"; + /* + * Configure pull-up on TX when it isn't actively driven + * to prevent BT SoC from receiving garbage during sleep. + */ + bias-pull-up; + }; + + sw_ctrl: sw-ctrl-state { + pins = "gpio86"; + function = "gpio"; + bias-pull-down; + }; +}; + +&qup_uart4_cts { + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; +}; + +&qup_uart4_rts { + /* We'll drive RTS, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&qup_uart4_rx { + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module is + * in tri-state (module powered off or not driving the + * signal yet). + */ + bias-pull-up; +}; + +&qup_uart4_tx { + /* We'll drive TX, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&uart4 { + status = "okay"; + /delete-property/ interrupts; + interrupts-extended = <&intc GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>, + <&tlmm 19 IRQ_TYPE_EDGE_FALLING>; + pinctrl-names = "default", "sleep"; + pinctrl-1 = <&qup_uart4_sleep_cts>, <&qup_uart4_sleep_rts>, + <&qup_uart4_sleep_tx>, <&qup_uart4_sleep_rx>; + + bluetooth: bluetooth { + compatible = "qcom,qcc2072-bt"; + max-speed = <3200000>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso new file mode 100644 index 0000000000000..edb284558b5a6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&{/} { + qep_vreg: qep_vreg { + compatible = "regulator-fixed"; + regulator-name = "qep_vreg"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pm7325_gpios 8 0>; + enable-active-high; + }; + + aqr_vreg: aqr_vreg { + compatible = "regulator-fixed"; + regulator-name = "aqr_vreg"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pm7250b_gpios 4 0>; + enable-active-high; + }; +}; + +&pcie1_port0 { + pcie@0,0 { + pcie@3,0 { + qps615: pci@0,0 { + compatible = "pci1179,0220"; + interrupts-extended = <&tlmm 141 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + phy-supply = <&aqr_vreg>; + reset-deassert-us = <221000>; + + gpio-controller; + #gpio-cells = <2>; + }; + + pci@0,1 { + compatible = "pci1179,0220"; + interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + phy-supply = <&qep_vreg>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&pcie0_port { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 136 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&rtl_rc0_intn_wol_sig>; + phy-mode = "sgmii"; + phy-reset-gpios = <&tlmm 90 GPIO_ACTIVE_LOW>; + reset-deassert-us = <75000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 142 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_rc0_intn_wol_sig>; + phy-reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; + phy-supply = <&qep_vreg>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr_intn_wol_sig { + pins = "gpio141"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_intn_wol_sig: napa_intn_wol_sig { + pins = "gpio101"; + function = "gpio"; + input-enable; + bias-disable; + }; + + rtl_rc0_intn_wol_sig: rtl_rc0_intn_wol_sig { + pins = "gpio136"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_rc0_intn_wol_sig: napa_rc0_intn_wol_sig { + pins = "gpio142"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso index 83908db335afa..d8e02a0f521b8 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso @@ -6,6 +6,7 @@ /dts-v1/; /plugin/; #include +#include #include #include @@ -34,6 +35,143 @@ &remoteproc_wpss { status = "disabled"; + +}; +/ { + wcd9370: audio-codec { + compatible = "qcom,wcd9370-codec"; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>; + vdd-buck-supply = <&vph_pwr>; + vdd-rxtx-supply = <&vph_pwr>; + vdd-px-supply = <&vph_pwr>; + vdd-mic-bias-supply = <&vph_pwr>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,hphl-jack-type-normally-closed = <1>; + qcom,ground-jack-type-normally-closed = <1>; + qcom,rx-device = <&wcd937x_rx>; + qcom,tx-device = <&wcd937x_tx>; + + #sound-dai-cells = <1>; + }; + + + hdmi-connector { + status = "disabled"; + }; + + panel_lvds: panel-lvds@0 { + compatible = "panel-lvds"; + data-mapping = "vesa-24"; + width-mm = <476>; + height-mm = <268>; + + status = "okay"; + + panel-timing { + clock-frequency = <148500000>; + hactive = <1920>; + vactive = <1080>; + hfront-porch = <88>; + hback-porch = <148>; + hsync-len = <44>; + vfront-porch = <4>; + vback-porch = <36>; + vsync-len = <5>; + de-active = <1>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dual-lvds-odd-pixels; + panel_in_lvds_odd: endpoint { + remote-endpoint = <<9211c_out_odd>; + }; + }; + + port@1 { + reg = <1>; + + dual-lvds-even-pixels; + panel_in_lvds_even: endpoint { + remote-endpoint = <<9211c_out_even>; + }; + + }; + }; + }; + +}; + +&i2c1 { + status = "okay"; + + lvds_bridge: lvds-bridge@29 { + compatible = "lontium,lt9211c"; + reg = <0x29>; + reset-gpios = <&tlmm 117 1>; + + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9211c_in: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9211c_out_odd: endpoint { + remote-endpoint = <&panel_in_lvds_odd>; + }; + }; + + port@3 { + reg = <3>; + + lt9211c_out_even: endpoint { + remote-endpoint = <&panel_in_lvds_even>; + }; + }; + }; + }; + + +}; + +<9611_codec { + status = "disabled"; +}; + +&lpass_rx_macro { + status = "okay"; +}; + +&lpass_tx_macro { + status = "okay"; +}; + +&mdss_dsi0_out { + remote-endpoint = <<9211c_in>; }; &spi11 { @@ -244,6 +382,101 @@ }; }; +&sound { + model = "qcs6490-rb3gen2-ia-snd-card"; + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", + "SpkrRight IN", "WSA_SPK2 OUT", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "TX SWR_ADC1", "ADC2_OUTPUT", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + codec { + sound-dai = <&wcd9370 1>, <&swr1 0>, <&lpass_tx_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + codec { + sound-dai = <&wcd9370 0>, <&swr0 0>, <&lpass_rx_macro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; +}; + +&swr0 { + status = "okay"; + + wcd937x_rx: codec@0,4 { + compatible = "sdw20217010a00"; + reg = <0 4>; + + /* + * WCD9370 RX Port 1 (HPH_L/R) <==> SWR1 Port 1 (HPH_L/R) + * WCD9370 RX Port 2 (CLSH) <==> SWR1 Port 2 (CLSH) + * WCD9370 RX Port 3 (COMP_L/R) <==> SWR1 Port 3 (COMP_L/R) + * WCD9370 RX Port 4 (LO) <==> SWR1 Port 4 (LO) + * WCD9370 RX Port 5 (DSD_L/R) <==> SWR1 Port 5 (DSD) + */ + qcom,rx-port-mapping = <1 2 3 4 5>; + + /* + * Static channels mapping between slave and master rx port channels. + * In the order of slave port channels, which is + * hph_l, hph_r, clsh, comp_l, comp_r, lo, dsd_r, dsd_l. + */ + qcom,rx-channel-mapping = /bits/ 8 <1 2 1 1 2 1 1 2>; + }; +}; + +&swr1 { + status = "okay"; + wcd937x_tx: codec@0,3 { + compatible = "sdw20217010a00"; + reg = <0 3>; + + /* + * WCD9370 TX Port 1 (ADC1) <=> SWR2 Port 2 + * WCD9370 TX Port 2 (ADC2, 3) <=> SWR2 Port 2 + * WCD9370 TX Port 3 (DMIC0,1,2,3 & MBHC) <=> SWR2 Port 3 + * WCD9370 TX Port 4 (DMIC4,5,6,7) <=> SWR2 Port 4 + */ + qcom,tx-port-mapping = <1 1 2 3>; + + /* + * Static channel mapping between slave and master tx port channels. + * In the order of slave port channels which is adc1, adc2, adc3, + * mic0, dmic1, mbhc, dmic2, dmic3, dmci4, dmic5, dmic6, dmic7. + */ + qcom,tx-channel-mapping = /bits/ 8 <1 2 1 1 2 3 3 4 1 2 3 4>; + }; +}; + + &tlmm { pcie0_tc9563_resx_n: pcie0-tc9563-resx-state { pins = "gpio78"; @@ -283,8 +516,18 @@ output-enable; }; + wcd_default: wcd-reset-n-active-state { + pins = "gpio83"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; }; &wifi { status = "disabled"; }; + +&uart7 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso new file mode 100644 index 0000000000000..6c112224f0ce9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&{/} { + qep_vreg: qep_vreg { + compatible = "regulator-fixed"; + regulator-name = "qep_vreg"; + gpio = <&pm7325_gpios 8 0>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + }; + + aqr_vreg: aqr_vreg { + compatible = "regulator-fixed"; + regulator-name = "aqr_vreg"; + gpio = <&pm7250b_gpios 4 0>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + }; +}; + +&pcie1_port0 { + pcie@0,0 { + pcie@3,0 { + /* + * PF0: also acts as the QPS615 GPIO controller. + * gpio-controller / #gpio-cells expose the TC956X + * internal GPIO lines (hardware numbers 0-13) so that + * phy-reset-gpios can reference them. + */ + qps615: pci@0,0 { + interrupts-extended = <&tlmm 141 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + phy-supply = <&aqr_vreg>; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + reset-deassert-us = <221000>; + + gpio-controller; + #gpio-cells = <2>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + phy-supply = <&qep_vreg>; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr_intn_wol_sig { + mux { + pins = "gpio141"; + function = "gpio"; + }; + + config { + pins = "gpio141"; + input-enable; + bias-disable; + }; + }; + + napa_intn_wol_sig: napa_intn_wol_sig { + mux { + pins = "gpio101"; + function = "gpio"; + }; + + config { + pins = "gpio101"; + input-enable; + bias-disable; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso new file mode 100644 index 0000000000000..eb183d7dbd3d5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "qcs6490-camera.dtsi" +#include "qcs6490-rb3gen2-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 37a3b51323ce5..52329aa75cce7 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -57,8 +57,6 @@ label = "DP"; type = "mini"; - hpd-gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; - port { dp_connector_in: endpoint { remote-endpoint = <&mdss_edp_out>; @@ -202,6 +200,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -211,7 +210,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -711,6 +710,7 @@ lt9611_codec: hdmi-bridge@2b { compatible = "lontium,lt9611uxc"; reg = <0x2b>; + #sound-dai-cells = <1>; interrupts-extended = <&tlmm 24 IRQ_TYPE_EDGE_FALLING>; reset-gpios = <&pm7250b_gpios 2 GPIO_ACTIVE_HIGH>; @@ -806,7 +806,7 @@ }; &mdss_dp_out { - data-lanes = <0 1>; + data-lanes = <0 1 2 3>; remote-endpoint = <&usb_dp_qmpphy_dp_in>; }; @@ -1105,6 +1105,13 @@ status = "okay"; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qup_uart7_cts { /* * Configure a bias-bus-hold on CTS to lower power @@ -1184,6 +1191,9 @@ compatible = "qcom,qcs6490-rb3gen2-sndcard"; model = "QCS6490-RB3Gen2"; + pinctrl-0 = <&mi2s1_data0>, <&mi2s1_mclk>, <&mi2s1_sclk>, <&mi2s1_ws>; + pinctrl-names = "default"; + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", "SpkrRight IN", "WSA_SPK2 OUT", "VA DMIC0", "vdd-micb", @@ -1223,6 +1233,38 @@ sound-dai = <&q6apm>; }; }; + + mi2s1-playback-dai-link { + link-name = "Secondary MI2S Playback"; + + codec { + sound-dai = <<9611_codec 0>; + }; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_RX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + dp-dai-link { + link-name = "DisplayPort0 Playback"; + + codec { + sound-dai = <&mdss_dp>; + }; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; &spi3 { @@ -1402,14 +1444,14 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_dwc3_ss { remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; @@ -1422,6 +1464,7 @@ vdda-phy-supply = <&vreg_l6b_1p2>; vdda-pll-supply = <&vreg_l1b_0p912>; + mode-switch; orientation-switch; status = "okay"; @@ -1472,7 +1515,6 @@ /* PINCTRL - ADDITIONS TO NODES IN PARENT DEVICE TREE FILES */ &edp_hot_plug_det { - function = "gpio"; bias-disable; }; @@ -1561,3 +1603,26 @@ compatible = "qcom,qcm6490-lpassaudiocc"; /delete-property/ power-domains; }; + +&mi2s1_data0 { + drive-strength = <8>; + bias-disable; +}; + +&mi2s1_mclk { + drive-strength = <8>; + bias-disable; + output-high; +}; + +&mi2s1_sclk { + drive-strength = <8>; + bias-disable; + output-high; +}; + +&mi2s1_ws { + drive-strength = <8>; + bias-disable; + output-high; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts index a5ad796cb65d0..1e190ed18ae5a 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts @@ -22,6 +22,23 @@ /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; /delete-node/ &mpss_mem; + +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; /delete-node/ &rmtfs_mem; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts index f47efca42d48d..085f819fabcbd 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts @@ -23,6 +23,23 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; + +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; @@ -84,6 +101,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -93,7 +111,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1090,10 +1108,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; @@ -1127,6 +1141,10 @@ remote-endpoint = <&pmic_glink_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &ufs_mem_hc { reset-gpios = <&tlmm 175 GPIO_ACTIVE_LOW>; vcc-supply = <&vreg_l7b_2p952>; diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso b/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso new file mode 100644 index 0000000000000..8f26e6dc070b0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-camera.dtsi" +#include "monaco-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index e9a8553a8d821..7f9c9b958706d 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -637,7 +637,9 @@ &pcie0_phy { vdda-phy-supply = <&vreg_l6a>; - vdda-pll-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l4a>; + vdda-qref-supply = <&vreg_l7a>; + vdda-refgen-supply = <&refgen>; status = "okay"; }; @@ -657,6 +659,8 @@ &pcie1_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l7a>; + vdda-refgen-supply = <&refgen>; status = "okay"; }; @@ -703,6 +707,8 @@ &serdes0 { phy-supply = <&vreg_l5a>; + vdda-0p9-supply = <&vreg_l4a>; + status = "okay"; }; @@ -719,6 +725,7 @@ vmmc-supply = <&vreg_l8a>; vqmmc-supply = <&vreg_s4a>; + supports-cqe; non-removable; no-sd; no-sdio; diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts index bf088fa9807f0..5266f89feaaf2 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts @@ -110,6 +110,98 @@ leds = <&ledr>, <&ledg>, <&ledb>; }; + sound { + compatible = "qcom,qrb2210-sndcard"; + model = "Arduino-Imola-HPH-LOUT"; + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2"; + + mm1-dai-link { + link-name = "MultiMedia1"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + }; + + mm2-dai-link { + link-name = "MultiMedia2"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>; + }; + }; + + mm3-dai-link { + link-name = "MultiMedia3"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>; + }; + }; + + hph-playback-dai-link { + link-name = "HPH Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + lo-playback-dai-link { + link-name = "LO Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + ear-playback-dai-link { + link-name = "Ear Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + hph-capture-dai-link { + link-name = "HP Capture"; + cpu { + sound-dai = <&q6afedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 1>, <&swr0 0>, <&txmacro 0>; + }; + }; + }; + vreg_anx_30: regulator-anx-30 { compatible = "regulator-fixed"; regulator-name = "anx30"; @@ -421,6 +513,51 @@ }; }; +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000{ + compatible = "qcom,pm4125-codec"; + reg =<0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s4>; + vdd-pa-vpos-supply = <&pm4125_s4>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + }; + }; +}; + +&swr0 { + pinctrl-0 = <&lpass_tx_swr_active>; + pinctrl-names = "default"; + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <1 1 2 3>; + }; +}; + +&swr1 { + pinctrl-0 = <&lpass_rx_swr_active>; + pinctrl-names = "default"; + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + &tlmm { jmisc_gpio18: jmisc-gpio18-state { pins = "gpio18"; diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso b/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso new file mode 100644 index 0000000000000..f81fa6565f281 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "lemans-camera.dtsi" +#include "lemans-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi index b721a8546800c..e2c0a317ecb81 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi @@ -26,8 +26,26 @@ status = "okay"; }; +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + &remoteproc_mpss { compatible = "qcom,sc7280-mss-pil"; + /delete-property/ tmd-names; + /delete-property/ #cooling-cells; reg = <0 0x04080000 0 0x10000>, <0 0x04180000 0 0x48>; reg-names = "qdsp6", "rmb"; diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi index 3ebc915f0dc2f..6642076f62c49 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi @@ -7,6 +7,22 @@ /* WIFI SKUs save 256M by not having modem/mba/rmtfs memory regions defined. */ +&mdmss0_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss1_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss2_thermal { + /delete-node/ cooling-maps; +}; + +&mdmss3_thermal { + /delete-node/ cooling-maps; +}; + /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &rmtfs_mem; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso new file mode 100644 index 0000000000000..a42a034b92adf --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&camss { + vdd-csiphy-1p2-supply = <&pm4125_l5>; + vdd-csiphy-1p8-supply = <&pm4125_l13>; + + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + csiphy1_ep: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&imx577_ep1>; + }; + }; + }; +}; + +&cci { + status = "okay"; +}; + +&cci_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx577"; + reg = <0x1a>; + + reset-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&mclk1_default>; + pinctrl-names = "default"; + + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clock-rates = <24000000>; + + avdd-supply = <&pm4125_l15>; + + port { + imx577_ep1: endpoint { + link-frequencies = /bits/ 64 <600000000>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&csiphy1_ep>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts new file mode 100644 index 0000000000000..01464ef826d98 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -0,0 +1,813 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "shikra-cqm-som.dtsi" +#include "shikra-evk.dtsi" +#include +#include +#include + +/ { + model = "Qualcomm Technologies, Inc. Shikra CQM EVK"; + compatible = "qcom,shikra-cqm-evk", "qcom,shikra-cqm-som", "qcom,shikra"; + chassis-type = "embedded"; + + aliases { + i2c3 = &i2c3; + mmc0 = &sdhc_1; + mmc1 = &sdhc_2; /* SDC2 SD card slot */ + serial0 = &uart0; + serial1 = &uart8; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&pm4125_l17>; + gpio = <&tlmm 151 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; + + mi2s_tdm_sen: mi2s-tdm-sen-qaif-aif { + qcom,qaif-aif-bits-per-lane = <2>; + qcom,qaif-aif-ctrl-data-oe = <1>; + qcom,qaif-aif-full-cycle-en = <0>; + qcom,qaif-aif-invert-sync = <0>; + qcom,qaif-aif-lane-config = <1 1>, <1 0>; + qcom,qaif-aif-loopback-en = <0>; + qcom,qaif-aif-mono-mode-tx = <0>; + qcom,qaif-aif-mono-mode-rx = <0>; + qcom,qaif-aif-sample-width-rx = <16>; + qcom,qaif-aif-sample-width-tx = <16>; + qcom,qaif-aif-slot-width-rx = <32>; + qcom,qaif-aif-slot-width-tx = <32>; + qcom,qaif-aif-slot-en-rx-mask = <0x3>; + qcom,qaif-aif-slot-en-tx-mask = <0x3>; + qcom,qaif-aif-sync-delay = <1>; + qcom,qaif-aif-sync-mode = <1>; + qcom,qaif-aif-sync-src = <1>; + qcom,qaif-intf-dai-id = <34>; + }; + + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + sound: sound { + compatible = "qcom,shikra-sndcard"; + model = "shikra-cqm-evk"; + + qcom,adsp-bypass-mode; + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb", + "VA SWR_MIC0", "ADC2_OUTPUT"; + + pinctrl-0 = <&i2s2_default>, <&dmic_eldo_en_defualt>; + pinctrl-names = "default"; + + headset-capture-dai-link { + link-name = "Headphones Capture"; + + codec { + sound-dai = <&pmic4125_codec 1>, + <&swr1 0>, + <&vamacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu LPASS_CDC_DMA_VA_TX1>; + }; + }; + + headset-playback-dai-link { + link-name = "Headphones Playback"; + + codec { + sound-dai = <&pmic4125_codec 0>, + <&swr0 0>, + <&rxmacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu LPASS_CDC_DMA_RX0>; + }; + }; + + wsa-speaker-dai-link { + link-name = "WSA Speaker Playback"; + + codec { + sound-dai = <&wsa885x_i2c>; + }; + + cpu { + sound-dai = <&qaif_cpu MI2S_SENARY>; + }; + }; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + codec { + sound-dai = <&vamacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu LPASS_CDC_DMA_VA_TX0>; + }; + }; + }; + + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + + vddio-supply = <&pm4125_l7>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; + }; + }; +}; + +ðernet0 { + status = "okay"; + phy-handle = <ðphy0>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet0_defaults>; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&i2c3 { + status = "okay"; + + wsa885x_i2c: wsa885x-i2c-codec@c { + compatible = "qcom,wsa885x-i2c"; + reg = <0x0c>; + + pinctrl-names = "default"; + pinctrl-0 = <&wsa885x_i2c_spkr_sd_n>; + + interrupt-gpios = <&tlmm 77 GPIO_ACTIVE_HIGH>; + powerdown-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + vdd-1p8-supply = <&pm4125_l15>; + vdd-io-supply = <&pm4125_l15>; + qcom,battery_config = <2>; + + wsa885x-init-table = + <0x8470 0x2 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(1) */ + 0x8470 0x0 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(0) */ + 0x8470 0x1 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_EN(1) */ + 0x0004 0x1 /* SMP_AMP_CTRL_STEREO_CMT_GRP_MASK - CMT_GRP_MASK(1) */ + 0x8602 0x60 /* CDC_RX0_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8622 0x60 /* CDC_RX1_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8458 0x79 /* PANDEIRO_DIG_CTRL0_VBAT_THRM_FLT_CTL - VBAT_COEF_SEL */ + 0x810B 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3 */ + 0x8111 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3 */ + 0x813C 0x08 /* SPK_TOP_COMMON_CTRL4 - override_ctl*/ + 0x8102 0x04 /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP*/ + 0x811C 0x29 /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.SPK_TOP_LF_CH1_CTRL11.*/ + 0x811D 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH1_TUNE1 - HIZ_DELAY_PROG*/ + 0x8129 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH2_TUNE1 - HIZ_DELAY_PROG*/ + 0x811A 0x80 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH1_CTRL9 */ + 0x8126 0x80 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH2_CTRL9 */ + 0x8103 0x6 /* PANDEIRO_ANA_TOP_SPK_TOP_COMMON_TUNE1 - GAIN_TUNE */ + 0x80CA 0x85 /* PANDEIRO_ANA_TOP_IVSENSE_ADC_MODE_CTL2 */ + 0x80CB 0xE /* PANDEIRO_ANA_TOP_IVSENSE_ADC_MODE_CTL3 */ + 0x80CC 0xC /* PANDEIRO_ANA_TOP_IVSENSE_ADC_REF_CTL */ + 0x80D0 0x80 /* PANDEIRO_ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2 */ + 0x80BA 0xC0 /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.SPK_TOP_SPARE3 */ + 0x841C 0x4E /* PANDEIROI2S.TOP.PANDEIRO_DIG_CTRL */ + 0x8435 0x47 /* PANDEIRO_DIG_CTRL0_PA1_FSM_CTL1 - SILENT_STATE_IVS_EN */ + 0x86CE 0x09 /* PANDEIROI2S.TOP.CDC_CLSH_CDC_CLSH.V1P8_BP_CTL2.BP_CNT */ + 0x8667 0x34 /* CDC_COMPANDER1_CTL7 - AGAIN_DELAY */ + 0x800D 0x08>; /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.PON_CKSK_CTL_0 */ + #sound-dai-cells = <0>; + }; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/shikra/a704_zap.mbn"; +}; + +&i2c3 { + status = "okay"; +}; + +&mdss { + status = "okay"; +}; + +&pm4125_l5 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + +&mdss_dsi0 { + vdda-supply = <&pm4125_l5>; + status = "okay"; + + panel@0 { + compatible = "dlc,dlc0697"; + reg = <0>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + enable-gpios = <&tlmm 91 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&pm4125_l15>; + bias-supply = <&lcd_bias>; + + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pcie { + wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + + iommu-map = <0x0 &apps_smmu 0x0800 0x1>, + <0x100 &apps_smmu 0x0801 0x1>, + <0x208 &apps_smmu 0x0802 0x1>, + <0x210 &apps_smmu 0x0803 0x1>, + <0x218 &apps_smmu 0x0804 0x1>, + <0x300 &apps_smmu 0x0805 0x1>, + <0x400 &apps_smmu 0x0806 0x1>, + <0x500 &apps_smmu 0x0807 0x1>, + <0x501 &apps_smmu 0x0808 0x1>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_port0 { + #address-cells = <3>; + #size-cells = <2>; + + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c3 0x77>; + + resx-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_n>; + pinctrl-names = "default"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x3 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpio = <&tc9563 4 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 3 GPIO_ACTIVE_HIGH>; + }; + + pcie@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + + pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + }; + }; +}; + +&pcie_phy { + vdda-phy-supply = <&pm4125_l13>; + vdda-pll-supply = <&pm4125_l9>; + + status = "okay"; +}; + +&pm4125_hs_in { + remote-endpoint = <&usb_1_dwc3_hs>; +}; + +&pm4125_ss_in { + remote-endpoint = <&usb_qmpphy_out>; +}; + +&qaif_cpu { + aif-interface = <&mi2s_tdm_sen>; + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/shikra/cdsp.mbn"; + + status = "okay"; +}; + +&remoteproc_lpaicp { + firmware-name = "qcom/shikra/lpaicp.mbn", + "qcom/shikra/lpaicp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/shikra/cqm/qdsp6sw.mbn"; + + status = "okay"; +}; + +&rxmacro { + status = "okay"; +}; + +&sdhc_1 { + vmmc-supply = <&pm4125_l20>; + vqmmc-supply = <&pm4125_l14>; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + +&sdhc_2 { + vmmc-supply = <&pm4125_l21>; + vqmmc-supply = <&pm4125_l4>; + + no-sdio; + no-mmc; + + pinctrl-0 = <&sdc2_default &sdc2_card_det_n>; + pinctrl-1 = <&sdc2_sleep &sdc2_card_det_n>; + pinctrl-names = "default", "sleep"; + + cd-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000 { + compatible = "qcom,pm4125-codec"; + reg = <0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s1>; + vdd-pa-vpos-supply = <&pm4125_s1>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 + 500000 500000 500000 500000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + + status = "okay"; + }; + }; +}; + +&swr0 { + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + +&swr1 { + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 3>; + }; +}; + +&tlmm { + gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio96"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio97"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio98"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio99"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic_eldo_en_defualt: dmic_eldo_en_default { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; /* 8 mA */ + bias-disable; + output-high; + }; + + ethernet0_defaults: ethernet0-defaults-state { + rgmii-rx-pins { + pins = "gpio121", "gpio122", "gpio123", + "gpio124", "gpio125", "gpio126"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio127", "gpio128", "gpio129", + "gpio130", "gpio131", "gpio132"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio133", "gpio134"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac0_phy_en_hog: emac0-phy-en-hog { + gpio-hog; + gpios = <149 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac0-phy-en"; + }; + + i2s2_default: i2s2-default-active-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <8>; + output-high; + bias-disable; + }; + + lcd_bias_en: lcd-bias-en-state { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; + + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio117"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-pins { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; + + tc9563_resx_n: tc9563-resx-state { + pins = "gpio118"; + function = "gpio"; + bias-disable; + /* Reset pin of tc9563 is active low hence set default + * state of this pin to output-high. + */ + output-high; + }; + + wsa885x_i2c_spkr_sd_n: wsa885x-i2c-spkr-sd-n-active-state { + pins = "gpio2"; + function = "gpio"; + input-disable; + output-enable; + }; +}; + +&uart8 { + status = "okay"; + + bluetooth { + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; + }; +}; + +&usb_1 { + dr_mode = "otg"; + + status = "okay"; +}; + +&usb_1_dwc3_hs { + remote-endpoint = <&pm4125_hs_in>; +}; + +&usb_1_hsphy { + vdd-supply = <&pm4125_l12>; + vdda-pll-supply = <&pm4125_l13>; + vdda-phy-dpdm-supply = <&pm4125_l21>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&pm4125_l8>; + vdda-pll-supply = <&pm4125_l13>; + + status = "okay"; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm4125_l7>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "shikra"; + + status = "okay"; +}; + +&usb_qmpphy_out { + remote-endpoint = <&pm4125_ss_in>; +}; + +&vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&swr_tx_clk>, <&swr_tx_data0>; + pinctrl-names = "default"; + + qcom,dmic-sample-rate = <4800000>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi new file mode 100644 index 0000000000000..1bf69cb7d1058 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +#include "shikra.dtsi" +#include "pm4125.dtsi" +#include "pm8005.dtsi" + +/* Modem, Cocos + Kunlun PMIC */ +/ { + gpio-key { + compatible = "gpio-keys"; + label = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&vol_up_n>; + + key-volume-up { + label = "Volume Up"; + gpios = <&pm4125_gpios 9 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + linux,code = ; + wakeup-source; + debounce-interval = <15>; + linux,can-disable; + }; + }; + + pm4125_msm_therm_bridge: pm4125-msm-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM3_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_pa_therm_bridge: pm4125-pa-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM1_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_quiet_therm_bridge: pm4125-quiet-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM2_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; +}; + +&audiocorecc { + status = "okay"; +}; + +&pm4125_adc { + pinctrl-0 = <&pm4125_adc_gpio5_default>, <&pm4125_adc_gpio6_default>; + pinctrl-names = "default"; + status = "okay"; + + channel@4d { + reg = ; + label = "pa_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4e { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4f { + reg = ; + label = "msm_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@54 { + reg = ; + label = "chgr_skin"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@55 { + reg = ; + label = "gnss_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; +}; + +&pm4125_gpios { + pm4125_adc_gpio5_default: pm4125-adc-gpio5-state { + pins = "gpio5"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + pm4125_adc_gpio6_default: pm4125-adc-gpio6-state { + pins = "gpio6"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + vol_up_n: vol-up-n-state { + pins = "gpio9"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&pm4125_resin { + linux,code = ; + status = "okay"; +}; + +&pm4125_typec { + status = "okay"; + + connector { + compatible = "usb-c-connector"; + + power-role = "dual"; + data-role = "dual"; + self-powered; + + typec-power-opmode = "default"; + pd-disable; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pm4125_hs_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + pm4125_ss_in: endpoint { + }; + }; + }; + }; +}; + +&pm4125_tz { + status = "okay"; +}; + +&pm4125_vbus { + regulator-min-microvolt = <4250000>; + regulator-max-microvolt = <5000000>; + status = "okay"; +}; + +&pm8005_regulators { + status = "disabled"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-pm2250-regulators"; + + pm4125_s1: s1 { + regulator-min-microvolt = <1396000>; + regulator-max-microvolt = <1396000>; + }; + + pm4125_s2: s2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm4125_l3: l3 { + regulator-min-microvolt = <624000>; + regulator-max-microvolt = <650000>; + }; + + pm4125_l4: l4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + }; + + pm4125_l5: l5 { + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l6: l6 { + regulator-min-microvolt = <788000>; + regulator-max-microvolt = <1050000>; + }; + + pm4125_l7: l7 { + regulator-min-microvolt = <664000>; + regulator-max-microvolt = <664000>; + }; + + pm4125_l8: l8 { + regulator-min-microvolt = <928000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l9: l9 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l10: l10 { + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l12: l12 { + regulator-min-microvolt = <928000>; + regulator-max-microvolt = <975000>; + }; + + pm4125_l13: l13 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l14: l14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l15: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l16: l16 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l17: l17 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l18: l18 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + }; + + pm4125_l19: l19 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + }; + + pm4125_l20: l20 { + regulator-min-microvolt = <2952000>; + regulator-max-microvolt = <2952000>; + }; + + pm4125_l21: l21 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3056000>; + }; + + pm4125_l22: l22 { + regulator-min-microvolt = <3304000>; + regulator-max-microvolt = <3304000>; + }; + }; +}; + +&thermal_zones { + pm4125-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&pm4125_tz>; + + trips { + pm4125_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm4125_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "hot"; + }; + + pm4125_trip2: trip2 { + temperature = <155000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + pm8005-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&pm8005_tz>; + + trips { + pm8005_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip2: trip2 { + temperature = <145000>; + hysteresis = <0>; + type = "passive"; + }; + }; + }; + + sys-1-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_pa_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_quiet_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_msm_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts new file mode 100644 index 0000000000000..5ea41a9f8241e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -0,0 +1,804 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "shikra-cqs-som.dtsi" +#include "shikra-evk.dtsi" +#include +#include + +/ { + model = "Qualcomm Technologies, Inc. Shikra CQS EVK"; + compatible = "qcom,shikra-cqs-evk", "qcom,shikra-cqs-som", "qcom,shikra"; + chassis-type = "embedded"; + + aliases { + i2c3 = &i2c3; + mmc0 = &sdhc_1; + mmc1 = &sdhc_2; /* SDC2 SD card slot */ + serial0 = &uart0; + serial1 = &uart8; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + sound { + compatible = "qcom,shikra-sndcard"; + model = "shikra-cqs-evk"; + qcom,tdm-slots = <2>; + qcom,tdm-slot-width = <32>; + qcom,tdm-codec-slot-mask = <0x03>; + + clocks = <&q6prmcc LPASS_CLK_ID_AUD_INTF2_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "aud-intf2-ibit"; + + pinctrl-0 = <&i2s2_default>, <&dmic_eldo_en_default>; + pinctrl-names = "default"; + + audio-routing = "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + codec { + sound-dai = <&vamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-playback-dai-link { + link-name = "WSA Playback"; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_TDM_RX_0>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + codec { + sound-dai = <&wsa885x_i2c>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&pm4125_l17>; + gpio = <&tlmm 151 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; + + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + + vddio-supply = <&pm4125_l7>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; + }; + }; +}; + +&audiocorecc { + compatible = "qcom,shikra-cqs-audiocorecc"; +}; + +ðernet0 { + status = "okay"; + phy-handle = <ðphy0>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet0_defaults>; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/shikra/a704_zap.mbn"; +}; + +&i2c3 { + status = "okay"; + + wsa885x_i2c: wsa885x-i2c-codec@c { + compatible = "qcom,wsa885x-i2c"; + reg = <0x0c>; + + pinctrl-names = "default"; + pinctrl-0 = <&wsa885x_i2c_spkr_sd_n>; + + interrupt-gpios = <&tlmm 77 GPIO_ACTIVE_HIGH>; + powerdown-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + vdd-1p8-supply = <&pm4125_l15>; + vdd-io-supply = <&pm4125_l15>; + qcom,battery_config = <2>; + + wsa885x-init-table = + <0x8470 0x2 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(1) */ + 0x8470 0x0 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_CLR(0) */ + 0x8470 0x1 /* DIG_CTRL0_CDC_RXTX_FSCNT_CTL - FS_CNT_EN(1) */ + 0x0004 0x1 /* SMP_AMP_CTRL_STEREO_CMT_GRP_MASK - CMT_GRP_MASK(1) */ + 0x8602 0x60 /* CDC_RX0_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8622 0x60 /* CDC_RX1_RX_PATH_CFG1 - HPF_EN(0) */ + 0x8458 0x79 /* PANDEIRO_DIG_CTRL0_VBAT_THRM_FLT_CTL - VBAT_COEF_SEL */ + 0x810B 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3 */ + 0x8111 0xD9 /* PANDEIRO_ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3 */ + 0x813C 0x08 /* SPK_TOP_COMMON_CTRL4 - override_ctl*/ + 0x8102 0x04 /* SPK_TOP_COMMON_CTRL2 - LDO_PROG */ + 0x811C 0x29 /* SPK_TOP_LF_CH1_CTRL11 - PHASE90 */ + 0x811D 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH1_TUNE1 - HIZ_DELAY_PROG*/ + 0x8129 0x40 /* PANDEIRO_ANA_TOP_SPK_TOP_LF_CH2_TUNE1 - HIZ_DELAY_PROG*/ + 0x811A 0x80 /* SPK_TOP_LF_CH1_CTRL9 - OCP_CLIP_T_CTRL_EXT */ + 0x8126 0x80 /* SPK_TOP_LF_CH2_CTRL9 - OCP_CLIP_T_CTRL_EXT */ + 0x8103 0x6 /* PANDEIRO_ANA_TOP_SPK_TOP_COMMON_TUNE1 - GAIN_TUNE */ + 0x80CA 0x85 /* IVSENSE_ADC_MODE_CTL2 - SPARE_BITS_0 */ + 0x80CB 0xE /* IVSENSE_ADC_MODE_CTL3 - ADC_VREF_VCTL_I */ + 0x80CC 0xC /* IVSENSE_ADC_REF_CTL - ADC_VREF_VCTL_V */ + 0x80D0 0x80 /* PANDEIRO_ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2 */ + 0x80BA 0xC0 /* SPK_TOP_SPARE3 - force VDDSPK_LV_READY high */ + 0x841C 0x4E /* CDC_CLK_CTL - FSM_INTP_CG_DISABLE */ + 0x8435 0x47 /* PANDEIRO_DIG_CTRL0_PA1_FSM_CTL1 - SILENT_STATE_IVS_EN */ + 0x86CE 0x09 /* PANDEIROI2S.TOP.CDC_CLSH_CDC_CLSH.V1P8_BP_CTL2.BP_CNT */ + 0x8667 0x34 /* CDC_COMPANDER1_CTL7 - AGAIN_DELAY */ + 0x800D 0x08>; /* PANDEIROI2S.TOP.PANDEIRO_ANA_TOP.PON_CKSK_CTL_0 */ + + #sound-dai-cells = <0>; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm4125_l5>; + status = "okay"; + + panel@0 { + compatible = "dlc,dlc0697"; + reg = <0>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + enable-gpios = <&tlmm 91 GPIO_ACTIVE_HIGH>; + + vddio-supply = <&pm4125_l15>; + bias-supply = <&lcd_bias>; + + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pcie { + wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + + iommu-map = <0x0 &apps_smmu 0x0800 0x1>, + <0x100 &apps_smmu 0x0801 0x1>, + <0x208 &apps_smmu 0x0802 0x1>, + <0x210 &apps_smmu 0x0803 0x1>, + <0x218 &apps_smmu 0x0804 0x1>, + <0x300 &apps_smmu 0x0805 0x1>, + <0x400 &apps_smmu 0x0806 0x1>, + <0x500 &apps_smmu 0x0807 0x1>, + <0x501 &apps_smmu 0x0808 0x1>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_port0 { + #address-cells = <3>; + #size-cells = <2>; + + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c3 0x77>; + + resx-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_n>; + pinctrl-names = "default"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x3 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpio = <&tc9563 4 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 3 GPIO_ACTIVE_HIGH>; + }; + + pcie@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + + pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + }; + }; +}; + +&pcie_phy { + vdda-phy-supply = <&pm4125_l13>; + vdda-pll-supply = <&pm4125_l9>; + + status = "okay"; +}; + +&pm4125_hs_in { + remote-endpoint = <&usb_1_dwc3_hs>; +}; + +&pm4125_l5 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + +&pm4125_ss_in { + remote-endpoint = <&usb_qmpphy_out>; +}; + +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + dai@40 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_AUD_INTF2_IBIT + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/shikra/cdsp.mbn"; + + status = "okay"; +}; + +&remoteproc_lpaicp { + firmware-name = "qcom/shikra/lpaicp.mbn", + "qcom/shikra/lpaicp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/shikra/cqs/qdsp6sw.mbn"; + + status = "okay"; +}; + +&rxmacro { + clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_RX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "fsgen"; + + status = "okay"; +}; + +&sdhc_1 { + vmmc-supply = <&pm4125_l20>; + vqmmc-supply = <&pm4125_l14>; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + +&sdhc_2 { + vmmc-supply = <&pm4125_l21>; + vqmmc-supply = <&pm4125_l4>; + + no-sdio; + no-mmc; + + pinctrl-0 = <&sdc2_default &sdc2_card_det_n>; + pinctrl-1 = <&sdc2_sleep &sdc2_card_det_n>; + pinctrl-names = "default", "sleep"; + + cd-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000 { + compatible = "qcom,pm4125-codec"; + reg = <0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s1>; + vdd-pa-vpos-supply = <&pm4125_s1>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 + 500000 500000 500000 + 500000 500000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + + status = "okay"; + }; + }; +}; + +&swr0 { + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5 >; + }; +}; + +&swr1 { + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 2 3 4>; + }; +}; + +&tlmm { + gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio96"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio97"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio98"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio99"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic_eldo_en_default: dmic-eldo-en-default-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + ethernet0_defaults: ethernet0-defaults-state { + rgmii-rx-pins { + pins = "gpio121", "gpio122", "gpio123", + "gpio124", "gpio125", "gpio126"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio127", "gpio128", "gpio129", + "gpio130", "gpio131", "gpio132"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio133", "gpio134"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac0_phy_en_hog: emac0-phy-en-hog { + gpio-hog; + gpios = <149 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac0-phy-en"; + }; + + i2s2_default: i2s2-default-active-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <8>; + bias-disable; + }; + + i2s2_sleep: i2s2-sleep-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <2>; + bias-disable; + }; + + wsa885x_i2c_spkr_sd_n: wsa885x-i2c-spkr-sd-n-active-state { + pins = "gpio2"; + function = "gpio"; + drive-strength = <8>; + input-disable; + output-enable; + }; + lcd_bias_en: lcd-bias-en-state { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; + + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio117"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-pins { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; + + tc9563_resx_n: tc9563-resx-state { + pins = "gpio118"; + function = "gpio"; + bias-disable; + /* Reset pin of tc9563 is active low hence set default + * state of this pin to output-high. + */ + output-high; + }; + +}; + +&uart8 { + status = "okay"; + + bluetooth { + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; + }; +}; + +&usb_1 { + dr_mode = "otg"; + + status = "okay"; +}; + +&usb_1_dwc3_hs { + remote-endpoint = <&pm4125_hs_in>; +}; + +&usb_1_hsphy { + vdd-supply = <&pm4125_l12>; + vdda-pll-supply = <&pm4125_l13>; + vdda-phy-dpdm-supply = <&pm4125_l21>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&pm4125_l8>; + vdda-pll-supply = <&pm4125_l13>; + + status = "okay"; +}; + +&usb_qmpphy_out { + remote-endpoint = <&pm4125_ss_in>; +}; + +&vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&swr_tx_clk>, <&swr_tx_data0>; + pinctrl-names = "default"; + + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", "npl"; + + qcom,dmic-sample-rate = <4800000>; + status = "okay"; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm4125_l7>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "shikra"; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi new file mode 100644 index 0000000000000..e46dcf401d7c5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-som.dtsi @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +#include "shikra.dtsi" +#include "pm4125.dtsi" +#include "pm8005.dtsi" + +/* APQ (No Modem), Cocos + Kunlun PMIC */ + +/ { + gpio-key { + compatible = "gpio-keys"; + label = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&vol_up_n>; + + key-volume-up { + label = "Volume Up"; + gpios = <&pm4125_gpios 9 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + linux,code = ; + wakeup-source; + debounce-interval = <15>; + linux,can-disable; + }; + }; + + pm4125_msm_therm_bridge: pm4125-msm-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM3_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_pa_therm_bridge: pm4125-pa-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM1_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + pm4125_quiet_therm_bridge: pm4125-quiet-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM2_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; +}; + +&audiocorecc { + compatible = "qcom,shikra-cqs-audiocorecc"; + status = "okay"; +}; + +&pm4125_adc { + pinctrl-0 = <&pm4125_adc_gpio5_default>, <&pm4125_adc_gpio6_default>; + pinctrl-names = "default"; + status = "okay"; + + channel@4d { + reg = ; + label = "pa_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4e { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4f { + reg = ; + label = "msm_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@54 { + reg = ; + label = "chgr_skin"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@55 { + reg = ; + label = "gnss_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; +}; + +&pm4125_gpios { + pm4125_adc_gpio5_default: pm4125-adc-gpio5-state { + pins = "gpio5"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + pm4125_adc_gpio6_default: pm4125-adc-gpio6-state { + pins = "gpio6"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + vol_up_n: vol-up-n-state { + pins = "gpio9"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + +&pm4125_resin { + linux,code = ; + status = "okay"; +}; + +&pm4125_typec { + status = "okay"; + + connector { + compatible = "usb-c-connector"; + + power-role = "dual"; + data-role = "dual"; + self-powered; + + typec-power-opmode = "default"; + pd-disable; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pm4125_hs_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + pm4125_ss_in: endpoint { + }; + }; + }; + }; +}; + +&pm4125_tz { + status = "okay"; +}; + +&pm4125_vbus { + regulator-min-microvolt = <4250000>; + regulator-max-microvolt = <5000000>; + status = "okay"; +}; + +&pm8005_regulators { + status = "disabled"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-pm2250-regulators"; + + pm4125_s1: s1 { + regulator-min-microvolt = <1396000>; + regulator-max-microvolt = <1396000>; + }; + + pm4125_s2: s2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm4125_l3: l3 { + regulator-min-microvolt = <624000>; + regulator-max-microvolt = <650000>; + }; + + pm4125_l4: l4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + }; + + pm4125_l5: l5 { + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l6: l6 { + regulator-min-microvolt = <788000>; + regulator-max-microvolt = <1050000>; + }; + + pm4125_l7: l7 { + regulator-min-microvolt = <664000>; + regulator-max-microvolt = <664000>; + }; + + pm4125_l8: l8 { + regulator-min-microvolt = <928000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l9: l9 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm4125_l10: l10 { + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l12: l12 { + regulator-min-microvolt = <928000>; + regulator-max-microvolt = <975000>; + }; + + pm4125_l13: l13 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l14: l14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l15: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l16: l16 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm4125_l17: l17 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3544000>; + }; + + pm4125_l18: l18 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + }; + + pm4125_l19: l19 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + }; + + pm4125_l20: l20 { + regulator-min-microvolt = <2952000>; + regulator-max-microvolt = <2952000>; + }; + + pm4125_l21: l21 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3056000>; + }; + + pm4125_l22: l22 { + regulator-min-microvolt = <3304000>; + regulator-max-microvolt = <3304000>; + }; + }; +}; + +&thermal_zones { + pm4125-thermal { + polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&pm4125_tz>; + + trips { + pm4125_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm4125_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "hot"; + }; + + pm4125_trip2: trip2 { + temperature = <155000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + pm8005-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&pm8005_tz>; + + trips { + pm8005_trip0: trip0 { + temperature = <105000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip1: trip1 { + temperature = <125000>; + hysteresis = <0>; + type = "passive"; + }; + + pm8005_trip2: trip2 { + temperature = <145000>; + hysteresis = <0>; + type = "passive"; + }; + }; + }; + + sys-1-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_pa_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_quiet_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + polling-delay-passive = <2000>; + polling-delay = <0>; + thermal-sensors = <&pm4125_msm_therm_bridge>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi new file mode 100644 index 0000000000000..bd93e84c14250 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* Common daughter cards nodes to be added: + * QPS615 DC + * MIC DC + * Display DC + * Camera DC + * USB hub DC + * Sensor DC + * NFC DC + */ + +&iris { + status = "okay"; +}; + +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + +&qupv3_0 { + firmware-name = "qcom/shikra/qupv3fw.elf"; + status = "okay"; +}; + +&tlmm { + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart8 { + bluetooth { + compatible = "qcom,wcn3988-bt"; + max-speed = <3200000>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-imx577-camera.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-imx577-camera.dtso new file mode 100644 index 0000000000000..f0423f1ab4e93 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-imx577-camera.dtso @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&camss { + vdd-csiphy-1p2-supply = <&pm8150_l11>; + vdd-csiphy-1p8-supply = <&pm8150_l12>; + + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + csiphy1_ep: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&imx577_ep1>; + }; + }; + }; +}; + +&cci { + status = "okay"; +}; + +&cci_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx577"; + reg = <0x1a>; + + reset-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&mclk1_default>; + pinctrl-names = "default"; + + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + assigned-clock-rates = <24000000>; + + dovdd-supply = <&pm8150_l15>; + + port { + imx577_ep1: endpoint { + link-frequencies = /bits/ 64 <600000000>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&csiphy1_ep>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts new file mode 100644 index 0000000000000..7a153f904f081 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -0,0 +1,881 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "shikra-iqs-som.dtsi" +#include "shikra-evk.dtsi" +#include +#include + +/ { + model = "Qualcomm Technologies, Inc. Shikra IQS EVK"; + compatible = "qcom,shikra-iqs-evk", "qcom,shikra-iqs-som", "qcom,shikra"; + chassis-type = "embedded"; + + aliases { + i2c3 = &i2c3; + mmc0 = &sdhc_1; + mmc1 = &sdhc_2; /* SDC2 SD card slot */ + serial0 = &uart0; + serial1 = &uart8; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + sound { + compatible = "qcom,shikra-sndcard"; + model = "shikra-iqs-evk"; + + pinctrl-0 = <&i2s0_clk>, <&i2s0_ws>, <&i2s0_data>, <&ext_mclk2_active>; + pinctrl-names = "default"; + + audio-routing = "IN34", "Headset Mic", + "Headset Mic", "MICBIAS", + "DMICL", "Int Mic", + "Int Mic", "MICBIAS", + "Headphone", "HPL", + "Headphone", "HPR", + "Speaker", "SPKL", + "Speaker", "SPKR", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + codec { + sound-dai = <&vamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + pri-i2s-playback-dai-link { + link-name = "Analog Playback"; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; + }; + + codec { + sound-dai = <&max98091>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + pri-i2s-capture-dai-link { + link-name = "Analog Capture"; + + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_TX>; + }; + + codec { + sound-dai = <&max98091>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <<9611_out>; + }; + }; + }; + + vreg_lt9611_vcc: regulator-lt9611-vcc { + compatible = "regulator-fixed"; + regulator-name = "lt9611_vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_reg_en>; + }; + + vreg_lt9611_vdd: regulator-lt9611-vdd { + compatible = "regulator-fixed"; + regulator-name = "lt9611_vdd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + regulator-name = "wcn_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + wcn3988-pmu { + compatible = "qcom,wcn3988-pmu"; + + pinctrl-0 = <&sw_ctrl_default>; + pinctrl-names = "default"; + + vddio-supply = <&pm8150_s4>; + vddxo-supply = <&pm8150_l12>; + vddrf-supply = <&pm8150_l8>; + vddch0-supply = <&vreg_wcn_3p3>; + + swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_io: ldo0 { + regulator-name = "vreg_pmu_io"; + }; + + vreg_pmu_xo: ldo1 { + regulator-name = "vreg_pmu_xo"; + }; + + vreg_pmu_rf: ldo2 { + regulator-name = "vreg_pmu_rf"; + }; + + vreg_pmu_ch0: ldo3 { + regulator-name = "vreg_pmu_ch0"; + }; + + vreg_pmu_ch1: ldo4 { + regulator-name = "vreg_pmu_ch1"; + }; + }; + }; +}; + +ðernet0 { + status = "okay"; + phy-handle = <ðphy0>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet0_defaults>; + + snps,mtl-rx-config = <&emac0_mtl_rx_setup>; + snps,mtl-tx-config = <&emac0_mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + emac0_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + emac0_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +ðernet1 { + status = "okay"; + phy-handle = <ðphy1>; + phy-mode = "rgmii-id"; + + pinctrl-names = "default"; + pinctrl-0 = <ðernet1_defaults>; + + snps,mtl-rx-config = <&emac1_mtl_rx_setup>; + snps,mtl-tx-config = <&emac1_mtl_tx_setup>; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy1: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + reset-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + ti,tx-internal-delay = ; + ti,rx-internal-delay = ; + }; + }; + + emac1_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + emac1_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/shikra/a704_zap.mbn"; +}; + +&i2c3 { + status = "okay"; + + max98091: audio-codec@10 { + compatible = "maxim,max98091"; + reg = <0x10>; + + pinctrl-0 = <&max98091_default>; + pinctrl-names = "default"; + + interrupts-extended = <&tlmm 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_2 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk"; + assigned-clocks = <&q6prmcc LPASS_CLK_ID_MCLK_2 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <12288000>; + #sound-dai-cells = <0>; + }; +}; + +&pcie { + wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + + iommu-map = <0x0 &apps_smmu 0x0800 0x1>, + <0x100 &apps_smmu 0x0801 0x1>, + <0x208 &apps_smmu 0x0802 0x1>, + <0x210 &apps_smmu 0x0803 0x1>, + <0x218 &apps_smmu 0x0804 0x1>, + <0x300 &apps_smmu 0x0805 0x1>, + <0x400 &apps_smmu 0x0806 0x1>, + <0x500 &apps_smmu 0x0807 0x1>, + <0x501 &apps_smmu 0x0808 0x1>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_phy { + vdda-phy-supply = <&pm8150_l12>; + vdda-pll-supply = <&pm8150_l9>; + + status = "okay"; +}; + +&pcie_port0 { + #address-cells = <3>; + #size-cells = <2>; + + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c3 0x77>; + + resx-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_n>; + pinctrl-names = "default"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x3 0xff>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpio = <&tc9563 4 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 3 GPIO_ACTIVE_HIGH>; + }; + + pcie@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + + pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + }; + }; + }; +}; + +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + + dai@16 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_AUD_INTF0_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + +&i2c4 { + status = "okay"; + + lt9611uxd: lt9611uxd@41 { + compatible = "lontium,lt9611uxd"; + reg = <0x41>; + interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; + vcc-supply = <&vreg_lt9611_vcc>; + vdd-supply = <&vreg_lt9611_vdd>; + lontium,port-select = <1>; /* PORT_SELECT_B */ + + pinctrl-names = "default"; + pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9611_a: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm8150_l11>; + status = "okay"; + +}; + +&mdss_dsi0_out { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm8150_gpios { + hdmi_reg_en: hdmi-reg-en-state { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-disable; + }; +}; + +&pm8150_l11 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/shikra/cdsp.mbn"; + + status = "okay"; +}; + +&remoteproc_lpaicp { + firmware-name = "qcom/shikra/lpaicp.mbn", + "qcom/shikra/lpaicp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/shikra/cqs/qdsp6sw.mbn"; + + status = "okay"; +}; + +&sdhc_1 { + vmmc-supply = <&pm8150_l17>; + vqmmc-supply = <&pm8150_s4>; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + +&sdhc_2 { + vmmc-supply = <&pm8150_l10>; + vqmmc-supply = <&pm8150_l2>; + + no-sdio; + no-mmc; + + pinctrl-0 = <&sdc2_default &sdc2_card_det_n>; + pinctrl-1 = <&sdc2_sleep &sdc2_card_det_n>; + pinctrl-names = "default", "sleep"; + + cd-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&tlmm { + gpio-reserved-ranges = <6 4>, <14 4>, <30 2>, <115 2>, <138 1>, <155 11>; + + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio96"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio97"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio98"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio99"; + function = "dmic"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic_eldo_en_default: dmic-eldo-en-default-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + ethernet0_defaults: ethernet0-defaults-state { + rgmii-rx-pins { + pins = "gpio121", "gpio122", "gpio123", + "gpio124", "gpio125", "gpio126"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio127", "gpio128", "gpio129", + "gpio130", "gpio131", "gpio132"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio133", "gpio134"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + ethernet1_defaults: ethernet1-defaults-state { + rgmii-rx-pins { + pins = "gpio137", "gpio139", "gpio140", + "gpio141", "gpio142"; + function = "rgmii"; + bias-disable; + drive-strength = <16>; + }; + rgmii-tx-pins { + pins = "gpio143", "gpio144", "gpio145", + "gpio146", "gpio147", "gpio148"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + rgmii-mdio-pins { + pins = "gpio149", "gpio150"; + function = "rgmii"; + bias-pull-up; + drive-strength = <16>; + }; + }; + + emac0_phy_en_hog: emac0-phy-en-hog { + gpio-hog; + gpios = <66 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac0-phy-en"; + }; + + emac1_phy_en_hog: emac1-phy-en-hog { + gpio-hog; + gpios = <53 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac1-phy-en"; + }; + + ext_mclk2_active: ext-mclk2-state { + pins = "gpio110"; + function = "ext_mclk"; + drive-strength = <8>; + bias-disable; + }; + + i2s0_clk: i2s0-clk-active-state { + pins = "gpio105"; + function = "i2s0"; + drive-strength = <8>; + bias-disable; + }; + + i2s0_data: i2s0-data-active-state { + pins = "gpio107", "gpio108", "gpio109"; + function = "i2s0"; + drive-strength = <8>; + bias-disable; + }; + + i2s0_ws: i2s0-ws-active-state { + pins = "gpio106"; + function = "i2s0"; + drive-strength = <8>; + bias-disable; + }; + + max98091_default: max98091-default-state { + pins = "gpio28"; + function = "gpio"; + bias-pull-up; + }; + + sw_ctrl_default: sw-ctrl-default-state { + pins = "gpio88"; + function = "gpio"; + bias-pull-down; + }; +}; + +&tlmm { + lt9611_irq_pin: lt9611-irq-state { + pins = "gpio85"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + lt9611_rst_pin: lt9611-rst-state { + pins = "gpio76"; + function = "gpio"; + drive-strength = <8>; + output-high; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart8 { + status = "okay"; + + bluetooth { + vddio-supply = <&vreg_pmu_io>; + vddxo-supply = <&vreg_pmu_xo>; + vddrf-supply = <&vreg_pmu_rf>; + vddch0-supply = <&vreg_pmu_ch0>; + }; +}; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdd-supply = <&pm8150_l4>; + vdda-pll-supply = <&pm8150_l12>; + vdda-phy-dpdm-supply = <&pm8150_l13>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&pm8150_l6>; + vdda-pll-supply = <&pm8150_l12>; + + status = "okay"; +}; + +&vamacro { + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", "npl"; + + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&dmic_eldo_en_default>; + pinctrl-names = "default"; + + qcom,dmic-sample-rate = <4800000>; + + status = "okay"; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm8150_s4>; + vdd-1.8-xo-supply = <&vreg_pmu_xo>; + vdd-1.3-rfa-supply = <&vreg_pmu_rf>; + vdd-3.3-ch0-supply = <&vreg_pmu_ch0>; + qcom,calibration-variant = "Shikra_EVK"; + firmware-name = "shikra"; + + status = "okay"; +}; + +&tlmm { + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio117"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-pins { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + tc9563_resx_n: tc9563-resx-state { + pins = "gpio118"; + function = "gpio"; + bias-disable; + /* Reset pin of tc9563 is active low hence set default + * state of this pin to output-high. + */ + output-high; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi new file mode 100644 index 0000000000000..88b1472cf87cc --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +#include "shikra.dtsi" +#include "pm8150.dtsi" + +/* APQ (No Modem), Wailua PMIC */ + +/ { + gpio-key { + compatible = "gpio-keys"; + label = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&vol_up_n>; + + key-volume-up { + label = "Volume Up"; + gpios = <&pm8150_gpios 6 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + linux,code = ; + wakeup-source; + debounce-interval = <15>; + linux,can-disable; + }; + }; +}; + +&pm8150_adc { + pinctrl-0 = <&pm8150_adc_gpio2_default>, <&pm8150_adc_gpio3_default>; + pinctrl-names = "default"; + + channel@4d { + reg = ; + label = "msm_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4e { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@52 { + reg = ; + label = "gnss_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@55 { + reg = ; + label = "pa_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; +}; + +&pm8150_adc_tm { + status = "okay"; + + pa-therm@0 { + reg = <0>; + io-channels = <&pm8150_adc ADC5_GPIO4_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; + + quiet-therm@1 { + reg = <1>; + io-channels = <&pm8150_adc ADC5_AMUX_THM2_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; + + msm-therm@2 { + reg = <2>; + io-channels = <&pm8150_adc ADC5_AMUX_THM1_100K_PU>; + qcom,ratiometric; + qcom,hw-settle-time-us = <200>; + }; +}; + +&pm8150_gpios { + pm8150_adc_gpio2_default: pm8150-adc-gpio2-state { + pins = "gpio2"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + pm8150_adc_gpio3_default: pm8150-adc-gpio3-state { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; + + vol_up_n: vol-up-n-state { + pins = "gpio6"; + function = PMIC_GPIO_FUNC_NORMAL; + input-enable; + bias-pull-up; + power-source = <0>; + }; + +}; + +&pon_pwrkey { + status = "okay"; +}; + +&pon_resin { + linux,code = ; + status = "okay"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-pm8150-regulators"; + + pm8150_s4: s4 { + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <2040000>; + }; + + pm8150_s5: s5 { + regulator-min-microvolt = <1574000>; + regulator-max-microvolt = <2040000>; + }; + + pm8150_s6: s6 { + regulator-min-microvolt = <382000>; + regulator-max-microvolt = <1352000>; + }; + + pm8150_s7: s7 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + }; + + pm8150_s8: s8 { + regulator-min-microvolt = <570000>; + regulator-max-microvolt = <650000>; + }; + + pm8150_l1: l1 { + regulator-min-microvolt = <312000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l2: l2 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3300000>; + }; + + pm8150_l3: l3 { + regulator-min-microvolt = <312000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l4: l4 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <975000>; + }; + + pm8150_l5: l5 { + regulator-min-microvolt = <788000>; + regulator-max-microvolt = <1050000>; + }; + + pm8150_l6: l6 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm8150_l7: l7 { + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <2000000>; + }; + + pm8150_l8: l8 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l9: l9 { + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <1000000>; + }; + + pm8150_l10:l10{ + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3544000>; + }; + + pm8150_l11:l11{ + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1304000>; + }; + + pm8150_l12:l12{ + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <1950000>; + }; + + pm8150_l13:l13{ + regulator-min-microvolt = <2921000>; + regulator-max-microvolt = <3230000>; + }; + + pm8150_l14:l14{ + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1910000>; + }; + + pm8150_l15:l15{ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + }; + + pm8150_l16:l16{ + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3544000>; + }; + + pm8150_l17:l17{ + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3544000>; + }; + + pm8150_l18:l18{ + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <728000>; + }; + }; +}; + +&thermal_zones { + sys-1-thermal { + thermal-sensors = <&pm8150_adc_tm 0>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-2-thermal { + thermal-sensors = <&pm8150_adc_tm 1>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + sys-3-thermal { + thermal-sensors = <&pm8150_adc_tm 2>; + + trips { + active-config0 { + temperature = <125000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi new file mode 100644 index 0000000000000..0809afc65e0ef --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -0,0 +1,5261 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + bam_dmux: bam-dmux { + compatible = "qcom,bam-dmux"; + + interrupts-extended = + <&modem_smsm 1 IRQ_TYPE_EDGE_BOTH>, + <&modem_smsm 11 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "pc", "pc-ack"; + + qcom,smem-states = + <&apps_smsm 1>, + <&apps_smsm 11>; + qcom,smem-state-names = "pc", "pc-ack"; + + dmas = <&bam_dmux_dma 4>, <&bam_dmux_dma 5>; + dma-names = "tx", "rx"; + }; + + clocks { + xo_board: xo-board { + compatible = "fixed-clock"; + clock-frequency = <38400000>; + #clock-cells = <0>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32764>; + #clock-cells = <0>; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&l3>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + clocks = <&cpufreq_hw 0>; + qcom,freq-domain = <&cpufreq_hw 0>; + #cooling-cells = <2>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; + }; + + cpu1: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x100>; + enable-method = "psci"; + next-level-cache = <&l3>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + clocks = <&cpufreq_hw 0>; + qcom,freq-domain = <&cpufreq_hw 0>; + #cooling-cells = <2>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; + }; + + cpu2: cpu@200 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x200>; + enable-method = "psci"; + next-level-cache = <&l3>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; + clocks = <&cpufreq_hw 0>; + qcom,freq-domain = <&cpufreq_hw 0>; + #cooling-cells = <2>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; + }; + + cpu3: cpu@300 { + device_type = "cpu"; + compatible = "arm,cortex-a78c"; + reg = <0x0 0x300>; + enable-method = "psci"; + next-level-cache = <&l2_3>; + capacity-dmips-mhz = <1946>; + dynamic-power-coefficient = <489>; + clocks = <&cpufreq_hw 1>; + qcom,freq-domain = <&cpufreq_hw 1>; + #cooling-cells = <2>; + operating-points-v2 = <&cpu3_opp_table>; + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>, + <&epss_l3 MASTER_EPSS_L3_APPS + &epss_l3 SLAVE_EPSS_L3_SHARED>; + + l2_3: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + next-level-cache = <&l3>; + cache-size = <0x40000>; + }; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + + core1 { + cpu = <&cpu1>; + }; + + core2 { + cpu = <&cpu2>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu3>; + }; + }; + }; + + l3: l3-cache { + compatible = "cache"; + cache-level = <3>; + cache-unified; + cache-size = <0x80000>; + }; + }; + + dummy-eud { + compatible = "arm,coresight-dummy-sink"; + + label = "eud"; + + in-ports { + port { + eud_in: endpoint { + remote-endpoint = <&replicator_eud_out1>; + }; + }; + }; + }; + + firmware { + scm { + compatible = "qcom,scm-shikra", "qcom,scm"; + clocks = <&rpmcc RPM_SMD_CE1_CLK>; + clock-names = "core"; + qcom,dload-mode = <&tcsr_regs 0x13000>; + #reset-cells = <1>; + interconnects = <&system_noc MASTER_CRYPTO_CORE0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + }; + }; + + memory@80000000 { + device_type = "memory"; + /* We expect the bootloader to fill in the size */ + reg = <0x0 0x80000000 0x0 0x0>; + }; + + modem-etm0 { + compatible = "arm,coresight-dummy-source"; + + label = "modem_etm0"; + arm,static-trace-id = <36>; + + out-ports { + port { + modem_etm0_out: endpoint { + remote-endpoint = <&funnel_in1_in4>; + }; + }; + }; + }; + + cpu0_opp_table: opp-table-cpu0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-768000000 { + opp-hz = /bits/ 64 <768000000>; + opp-peak-kBps = <1200000 17817600>; + }; + + opp-1017600000 { + opp-hz = /bits/ 64 <1017600000>; + opp-peak-kBps = <2188000 25804800>; + }; + + opp-1094400000 { + opp-hz = /bits/ 64 <1094400000>; + opp-peak-kBps = <3072000 30105600>; + }; + + opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + opp-peak-kBps = <4068000 38707200>; + }; + + opp-1612800000 { + opp-hz = /bits/ 64 <1612800000>; + opp-peak-kBps = <6220000 43008000>; + }; + + opp-1804800000 { + opp-hz = /bits/ 64 <1804800000>; + opp-peak-kBps = <7216000 43622400>; + }; + + opp-2208000000 { + opp-hz = /bits/ 64 <2208000000>; + opp-peak-kBps = <7216000 43622400>; + }; + }; + + cpu3_opp_table: opp-table-cpu3 { + compatible = "operating-points-v2"; + opp-shared; + + opp-768000000 { + opp-hz = /bits/ 64 <768000000>; + opp-peak-kBps = <1200000 17817600>; + }; + + opp-1017600000 { + opp-hz = /bits/ 64 <1017600000>; + opp-peak-kBps = <2188000 25804800>; + }; + + opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; + opp-peak-kBps = <3072000 30105600>; + }; + + opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + opp-peak-kBps = <4068000 38707200>; + }; + + opp-1708800000 { + opp-hz = /bits/ 64 <1708800000>; + opp-peak-kBps = <6220000 43008000>; + }; + + opp-1900800000 { + opp-hz = /bits/ 64 <1900800000>; + opp-peak-kBps = <7216000 43622400>; + }; + + opp-2208000000 { + opp-hz = /bits/ 64 <2208000000>; + opp-peak-kBps = <7216000 43622400>; + }; + }; + + pmu-a55 { + compatible = "arm,cortex-a55-pmu"; + interrupts = ; + }; + + pmu-a78c { + compatible = "arm,cortex-a78-pmu"; + interrupts = ; + }; + + psci: psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + rpm: remoteproc { + compatible = "qcom,shikra-rpm-proc", "qcom,rpm-proc"; + + glink-edge { + compatible = "qcom,glink-rpm"; + interrupts = ; + qcom,rpm-msg-ram = <&rpm_msg_ram>; + mboxes = <&apcs_glb 0>; + + rpm_requests: rpm-requests { + compatible = "qcom,rpm-shikra", "qcom,glink-smd-rpm"; + qcom,glink-channels = "rpm_requests"; + + rpmcc: clock-controller { + compatible = "qcom,rpmcc-shikra", "qcom,rpmcc-qcm2290", "qcom,rpmcc"; + clocks = <&xo_board>; + clock-names = "xo"; + #clock-cells = <1>; + }; + + rpmpd: power-controller { + compatible = "qcom,shikra-rpmpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmpd_opp_table>; + + rpmpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmpd_opp_min_svs: opp1 { + opp-level = ; + }; + + rpmpd_opp_low_svs: opp2 { + opp-level = ; + }; + + rpmpd_opp_svs: opp3 { + opp-level = ; + }; + + rpmpd_opp_svs_plus: opp4 { + opp-level = ; + }; + + rpmpd_opp_nom: opp5 { + opp-level = ; + }; + + rpmpd_opp_nom_plus: opp6 { + opp-level = ; + }; + + rpmpd_opp_turbo: opp7 { + opp-level = ; + }; + + rpmpd_opp_turbo_plus: opp8 { + opp-level = ; + }; + }; + }; + }; + }; + + mpm: interrupt-controller { + compatible = "qcom,mpm"; + qcom,rpm-msg-ram = <&apss_mpm>; + interrupts = ; + mboxes = <&apcs_glb 1>; + interrupt-controller; + #interrupt-cells = <2>; + #power-domain-cells = <0>; + interrupt-parent = <&intc>; + qcom,mpm-pin-count = <96>; + qcom,mpm-pin-map = <2 275>, /* TSENS0 uplow */ + <12 422>, /* DWC3 ss_phy_irq */ + <58 272>, /* QUSB2_PHY dmse_hv_vddmx */ + <59 273>, /* QUSB2_PHY dpse_hv_vddmx */ + <86 183>, /* MPM wake, SPMI */ + <90 157>, /* QUSB2_PHY DM */ + <91 158>; /* QUSB2_PHY DP */ + }; + }; + + reserved_memory: reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hyp_mem: hyp@80000000 { + reg = <0x0 0x80000000 0x0 0x1600000>; + no-map; + }; + + xblboot_mem: xblboot@85e00000 { + reg = <0x0 0x85e00000 0x0 0x100000>; + no-map; + }; + + secdata_apss_mem: secdata-apss@85fff000 { + reg = <0x0 0x85fff000 0x0 0x1000>; + no-map; + }; + + smem_mem: smem_region@86000000 { + compatible = "qcom,smem"; + reg = <0x0 0x86000000 0x0 0x200000>; + no-map; + + hwlocks = <&tcsr_mutex 3>; + }; + + audio_carveout_mem: audio-carveout@86200000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x86200000 0x0 0x40000>; + no-map; + }; + + audio_mdsp_carveout_mem: audio-mdsp-carveout@86240000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x86240000 0x0 0x100000>; + no-map; + }; + + tz_stat_mem: tz-stat@a0000000 { + reg = <0x0 0xa0000000 0x0 0x100000>; + no-map; + }; + + qtee_mem: qtee@a1300000 { + reg = <0x0 0xa1300000 0x0 0x500000>; + no-map; + }; + + tz_apps_mem: tz-apps@a1800000 { + reg = <0x0 0xa1800000 0x0 0x2100000>; + no-map; + }; + + mpss_wlan_mem: mpss-wlan@ab000000 { + reg = <0x0 0xab000000 0x0 0x6e00000>; + no-map; + }; + + wlan_mem: wlan@b2300000 { + reg = <0x0 0xb2300000 0x0 0x100000>; + no-map; + }; + + cdsp_mem: cdsp@b2400000 { + reg = <0x0 0xb2400000 0x0 0x1900000>; + no-map; + }; + + gpu_micro_code_mem: gpu-micro-code@b3d00000 { + reg = <0x0 0xb3d00000 0x0 0x2000>; + no-map; + }; + + video_mem: video@b3d02000 { + reg = <0x0 0xb3d02000 0x0 0x700000>; + no-map; + }; + + lmcu_mem: lmcu@b4402000 { + reg = <0x0 0xb4402000 0x0 0x300000>; + no-map; + }; + + lmcu_dtb_mem: lmcu-dtb@b4702000 { + reg = <0x0 0xb4702000 0x0 0x40000>; + no-map; + }; + + }; + + smp2p-cdsp { + compatible = "qcom,smp2p"; + qcom,smem = <94>, <432>; + + interrupts = ; + + mboxes = <&apcs_glb 6>; + + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + cdsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + cdsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-lmcu { + compatible = "qcom,smp2p"; + qcom,smem = <617>, <616>; + + interrupts = ; + + mboxes = <&apcs_glb 10>; + + qcom,local-pid = <0>; + qcom,remote-pid = <26>; + + lmcu_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + lmcu_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-mpss { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupts = ; + + mboxes = <&apcs_glb 14>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + modem_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + modem_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smsm { + compatible = "qcom,smsm"; + + #address-cells = <1>; + #size-cells = <0>; + + mboxes = <0>, <&apcs_glb 13>; + + apps_smsm: apps@0 { + reg = <0>; + #qcom,smem-state-cells = <1>; + }; + + modem_smsm: modem@1 { + reg = <1>; + interrupts = ; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + soc: soc@0 { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <2>; + dma-ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; + ranges = <0x0 0x0 0x0 0x0 0x10 0x0>; + + ethernet0: ethernet@5d00000 { + compatible = "qcom,shikra-ethqos"; + reg = <0x0 0x05d00000 0x0 0x10000>, + <0x0 0x05d16000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + interrupts = ; + interrupt-names = "macirq"; + + clocks = <&gcc GCC_EMAC0_AXI_CLK>, + <&gcc GCC_EMAC0_AHB_CLK>, + <&gcc GCC_EMAC0_PTP_CLK>, + <&gcc GCC_EMAC0_RGMII_CLK>, + <&gcc GCC_EMAC0_AXI_CLK>, + <&gcc GCC_EMAC0_AXI_SYS_NOC_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii", + "axi", "axi-noc", "pcie-tile-axi-noc"; + + power-domains = <&gcc GCC_EMAC0_GDSC>; + resets = <&gcc GCC_EMAC0_BCR>; + iommus = <&apps_smmu 0x0380 0x0007>; + + interconnects = <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC0_CFG QCOM_ICC_TAG_ALWAYS>, + <&system_noc MASTER_EMAC_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", "mac-mem"; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + ethernet1: ethernet@5d20000 { + compatible = "qcom,shikra-ethqos"; + reg = <0x0 0x05d20000 0x0 0x10000>, + <0x0 0x05d36000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + interrupts = ; + interrupt-names = "macirq"; + + clocks = <&gcc GCC_EMAC1_AXI_CLK>, + <&gcc GCC_EMAC1_AHB_CLK>, + <&gcc GCC_EMAC1_PTP_CLK>, + <&gcc GCC_EMAC1_RGMII_CLK>, + <&gcc GCC_EMAC1_AXI_CLK>, + <&gcc GCC_EMAC1_AXI_SYS_NOC_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii", + "axi", "axi-noc", "pcie-tile-axi-noc"; + + power-domains = <&gcc GCC_EMAC1_GDSC>; + resets = <&gcc GCC_EMAC1_BCR>; + iommus = <&apps_smmu 0x03a0 0x0007>; + + interconnects = <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC1_CFG QCOM_ICC_TAG_ALWAYS>, + <&system_noc MASTER_EMAC_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", "mac-mem"; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + tcsr_mutex: syscon@340000 { + compatible = "qcom,tcsr-mutex"; + reg = <0x0 0x00340000 0x0 0x20000>; + #hwlock-cells = <1>; + }; + + tcsr_regs: syscon@3c0000 { + compatible = "qcom,shikra-tcsr", "syscon"; + reg = <0x0 0x003c0000 0x0 0x40000>; + }; + + tlmm: pinctrl@500000 { + compatible = "qcom,shikra-tlmm"; + reg = <0x0 0x00500000 0x0 0x700000>; + + interrupts = ; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + gpio-ranges = <&tlmm 0 0 165>; + wakeup-parent = <&mpm>; + + cci_i2c0_default: cci-i2c0-default-state { + /* SDA, SCL */ + pins = "gpio36", "gpio37"; + function = "cci_i2c0"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + cci_i2c0_sleep: cci-i2c0-sleep-state { + /* SDA, SCL */ + pins = "gpio36", "gpio37"; + function = "cci_i2c0"; + drive-strength = <2>; + bias-pull-down; + }; + + cci_i2c1_default: cci-i2c1-default-state { + /* SDA, SCL */ + pins = "gpio41", "gpio42"; + function = "cci_i2c1"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + cci_i2c1_sleep: cci-i2c1-sleep-state { + /* SDA, SCL */ + pins = "gpio41", "gpio42"; + function = "cci_i2c1"; + drive-strength = <2>; + bias-pull-down; + }; + + mclk0_default: mclk0-default-state { + pins = "gpio34"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk1_default: mclk1-default-state { + pins = "gpio35"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk2_default: mclk2-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk3_default: mclk3-default-state { + pins = "gpio98"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + qup_i2c0_data_clk: qup-i2c0-data-clk-state { + /* SDA, SCL */ + pins = "gpio2", "gpio3"; + function = "qup0_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c1_data_clk: qup-i2c1-data-clk-state { + /* SDA, SCL */ + pins = "gpio4", "gpio5"; + function = "qup0_se1_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c2_data_clk: qup-i2c2-data-clk-state { + /* SDA, SCL */ + pins = "gpio6", "gpio7"; + function = "qup0_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c3_data_clk: qup-i2c3-data-clk-state { + /* SDA, SCL */ + pins = "gpio10", "gpio11"; + function = "qup0_se3_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c4_data_clk: qup-i2c4-data-clk-state { + /* SDA, SCL */ + pins = "gpio12", "gpio13"; + function = "qup0_se4_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c5_data_clk: qup-i2c5-data-clk-state { + /* SDA, SCL */ + pins = "gpio14", "gpio15"; + function = "qup0_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c6_data_clk: qup-i2c6-data-clk-state { + /* SDA, SCL */ + pins = "gpio18", "gpio19"; + function = "qup0_se6"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c7_data_clk: qup-i2c7-data-clk-state { + /* SDA, SCL */ + pins = "gpio20", "gpio21"; + function = "qup0_se7_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c8_data_clk: qup-i2c8-data-clk-state { + /* SDA, SCL */ + pins = "gpio22", "gpio23"; + function = "qup0_se8"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c9_data_clk: qup-i2c9-data-clk-state { + /* SDA, SCL */ + pins = "gpio27", "gpio26"; + function = "qup0_se9_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi0_cs: qup-spi0-cs-state { + pins = "gpio1"; + function = "qup0_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi0_data_clk: qup-spi0-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio2", "gpio3", "gpio0"; + function = "qup0_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi2_cs: qup-spi2-cs-state { + pins = "gpio9"; + function = "qup0_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi2_data_clk: qup-spi2-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio6", "gpio7", "gpio8"; + function = "qup0_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi5_cs: qup-spi5-cs-state { + pins = "gpio17"; + function = "qup0_se5"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi5_data_clk: qup-spi5-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio14", "gpio15", "gpio16"; + function = "qup0_se5"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi6_cs: qup-spi6-cs-state { + pins = "gpio29"; + function = "qup0_se6"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi6_data_clk: qup-spi6-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio18", "gpio19", "gpio28"; + function = "qup0_se6"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi8_cs: qup-spi8-cs-state { + pins = "gpio25"; + function = "qup0_se8"; + drive-strength = <6>; + bias-disable; + }; + + qup_spi8_data_clk: qup-spi8-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio22", "gpio23", "gpio24"; + function = "qup0_se8"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart0_default: qup-uart0-default-state { + pins = "gpio0", "gpio1"; + function = "qup0_se0"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart1_default: qup-uart1-default-state { + pins = "gpio4", "gpio5"; + function = "qup0_se1_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart2_default: qup-uart2-default-state { + /* TX, RX */ + pins = "gpio8", "gpio9"; + function = "qup0_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart2_cts_rts: qup-uart2-cts-rts-state { + /* CTS, RTS */ + pins = "gpio6", "gpio7"; + function = "qup0_se2"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart3_default: qup-uart3-default-state { + pins = "gpio10", "gpio11"; + function = "qup0_se3_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart4_default: qup-uart4-default-state { + pins = "gpio12", "gpio13"; + function = "qup0_se4_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart5_default: qup-uart5-default-state { + /* TX, RX */ + pins = "gpio16", "gpio17"; + function = "qup0_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart5_cts_rts: qup-uart5-cts-rts-state { + /* CTS, RTS */ + pins = "gpio14", "gpio15"; + function = "qup0_se5"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart6_default: qup-uart6-default-state { + /* TX, RX */ + pins = "gpio28", "gpio29"; + function = "qup0_se6"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart6_cts_rts: qup-uart6-cts-rts-state { + /* CTS, RTS */ + pins = "gpio18", "gpio19"; + function = "qup0_se6"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart7_default: qup-uart7-default-state { + pins = "gpio20", "gpio21"; + function = "qup0_se7_23"; + drive-strength = <2>; + bias-disable; + }; + + qup_uart8_default: qup-uart8-default-state { + /* TX, RX */ + pins = "gpio24", "gpio25"; + function = "qup0_se8"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart8_cts_rts: qup-uart8-cts-rts-state { + /* CTS, RTS */ + pins = "gpio22", "gpio23"; + function = "qup0_se8"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart9_default: qup-uart9-default-state { + pins = "gpio26", "gpio27"; + function = "qup0_se9_23"; + drive-strength = <2>; + bias-disable; + }; + + sdc1_state_on: sdc1-on-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <6>; + bias-disable; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <6>; + bias-pull-up; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <6>; + bias-pull-up; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-pull-down; + }; + }; + + sdc1_state_off: sdc1-off-state { + clk-pins { + pins = "sdc1_clk"; + drive-strength = <2>; + bias-bus-hold; + }; + + cmd-pins { + pins = "sdc1_cmd"; + drive-strength = <2>; + bias-bus-hold; + }; + + data-pins { + pins = "sdc1_data"; + drive-strength = <2>; + bias-bus-hold; + }; + + rclk-pins { + pins = "sdc1_rclk"; + bias-bus-hold; + }; + }; + + sdc2_default: sdc2-default-state { + clk-pins { + pins = "sdc2_clk"; + drive-strength = <14>; + bias-disable; + }; + + cmd-pins { + pins = "sdc2_cmd"; + drive-strength = <14>; + bias-pull-up; + }; + + data-pins { + pins = "sdc2_data"; + drive-strength = <14>; + bias-pull-up; + }; + }; + + sdc2_sleep: sdc2-sleep-state { + clk-pins { + pins = "sdc2_clk"; + drive-strength = <2>; + bias-disable; + }; + + cmd-pins { + pins = "sdc2_cmd"; + drive-strength = <2>; + bias-pull-up; + }; + + data-pins { + pins = "sdc2_data"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + sdc2_card_det_n: sd-card-det-n-state { + pins = "gpio89"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + swr_rx_clk: swr-rx-clk { + pins = "gpio107"; + function = "swr0_rx"; + drive-strength = <8>; + bias-disable; + }; + + swr_rx_data0: swr-rx-data0 { + pins = "gpio108"; + function = "swr0_rx"; + drive-strength = <8>; + bias-bus-hold; + }; + + swr_rx_data1: swr-rx-data1 { + pins = "gpio109"; + function = "swr0_rx"; + drive-strength = <8>; + bias-bus-hold; + }; + + swr_tx_clk: swr-tx-clk { + pins = "gpio105"; + function = "swr0_tx"; + drive-strength = <8>; + bias-disable; + }; + + swr_tx_data0: swr-tx-data0 { + pins = "gpio106"; + function = "swr0_tx"; + drive-strength = <8>; + bias-bus-hold; + }; + }; + + pmu@c91000 { + compatible = "qcom,shikra-cpu-bwmon", "qcom,sc7280-llcc-bwmon"; + reg = <0x0 0x00c91000 0x0 0x1000>; + + interrupts = ; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ACTIVE_TAG>; + + operating-points-v2 = <&cpu_bwmon_opp_table>; + + cpu_bwmon_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-0 { + opp-peak-kBps = <1200000>; + }; + + opp-1 { + opp-peak-kBps = <2188000>; + }; + + opp-2 { + opp-peak-kBps = <3072000>; + }; + + opp-3 { + opp-peak-kBps = <4068000>; + }; + + opp-4 { + opp-peak-kBps = <6220000>; + }; + + opp-5 { + opp-peak-kBps = <7216000>; + }; + }; + }; + + mem_noc: interconnect@d00000 { + compatible = "qcom,shikra-mem-noc-core"; + reg = <0x0 0x00d00000 0x0 0x43080>; + clocks = <&gcc GCC_DDRSS_GPU_AXI_CLK>; + clock-names = "gpu_axi"; + #interconnect-cells = <2>; + }; + + llcc: system-cache-controller@e00000 { + compatible = "qcom,shikra-llcc"; + reg = <0x0 0x00e00000 0x0 0x80000>, + <0x0 0x0f00000 0x0 0x80000>, + <0x0 0x1000000 0x0 0x80000>; + reg-names = "llcc0_base", + "llcc1_base", + "llcc_broadcast_base"; + interrupts = ; + }; + + gcc: clock-controller@1400000 { + compatible = "qcom,shikra-gcc"; + reg = <0x0 0x01400000 0x0 0x1f0000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>; + power-domains = <&rpmpd RPMPD_VDDCX>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + usb_1_hsphy: phy@1613000 { + compatible = "qcom,shikra-qusb2-phy"; + reg = <0x0 0x01613000 0x0 0x180>; + + clocks = <&gcc GCC_AHB2PHY_USB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "cfg_ahb", "ref"; + + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; + nvmem-cells = <&qusb2_hstx_trim_1>; + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_qmpphy: phy@1615000 { + compatible = "qcom,shikra-qmp-usb3-phy"; + reg = <0x0 0x01615000 0x0 0x1000>; + + clocks = <&gcc GCC_AHB2PHY_USB_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_EN>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "cfg_ahb", + "ref", + "com_aux", + "pipe"; + + resets = <&gcc GCC_USB3_PHY_PRIM_SP0_BCR>, + <&gcc GCC_USB3PHY_PHY_PRIM_SP0_BCR>; + reset-names = "phy", + "phy_phy"; + + #clock-cells = <0>; + clock-output-names = "usb3_phy_pipe_clk_src"; + + #phy-cells = <0>; + orientation-switch; + + qcom,tcsr-reg = <&tcsr_regs 0xb244>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_qmpphy_out: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_qmpphy_usb_ss_in: endpoint { + remote-endpoint = <&usb_1_dwc3_ss>; + }; + }; + }; + }; + + system_noc: interconnect@1880000 { + compatible = "qcom,shikra-sys-noc"; + reg = <0x0 0x01880000 0x0 0x6a080>; + clocks = <&gcc GCC_EMAC0_AXI_SYS_NOC_CLK>, + <&gcc GCC_EMAC1_AXI_SYS_NOC_CLK>, + <&gcc GCC_SYS_NOC_USB2_PRIM_AXI_CLK>, + <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>; + clock-names = "emac0_axi", + "emac1_axi", + "usb2_axi", + "usb3_axi"; + #interconnect-cells = <2>; + + clk_virt: interconnect-clk { + compatible = "qcom,shikra-clk-virt"; + #interconnect-cells = <2>; + }; + + mc_virt: interconnect-mc { + compatible = "qcom,shikra-mc-virt"; + #interconnect-cells = <2>; + }; + + mmrt_virt: interconnect-mmrt { + compatible = "qcom,shikra-mmrt-virt"; + #interconnect-cells = <2>; + }; + + mmnrt_virt: interconnect-mmnrt { + compatible = "qcom,shikra-mmnrt-virt"; + #interconnect-cells = <2>; + }; + }; + + config_noc: interconnect@1900000 { + compatible = "qcom,shikra-config-noc"; + reg = <0x0 0x01900000 0x0 0x8080>; + #interconnect-cells = <2>; + }; + + cryptobam: dma-controller@1b04000 { + compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; + reg = <0x0 0x01b04000 0x0 0x24000>; + interrupts = ; + #dma-cells = <1>; + iommus = <&apps_smmu 0x84 0x0011>, + <&apps_smmu 0x86 0x0011>, + <&apps_smmu 0x92 0x0>, + <&apps_smmu 0x94 0x0011>, + <&apps_smmu 0x96 0x0011>, + <&apps_smmu 0x98 0x0001>, + <&apps_smmu 0x9F 0x0>; + qcom,ee = <0>; + qcom,controlled-remotely; + num-channels = <16>; + qcom,num-ees = <4>; + }; + + crypto: crypto@1b3a000 { + compatible = "qcom,shikra-qce", "qcom,sm8150-qce", "qcom,qce"; + reg = <0x0 0x01b3a000 0x0 0x6000>; + dmas = <&cryptobam 4>, <&cryptobam 5>; + dma-names = "rx", "tx"; + iommus = <&apps_smmu 0x84 0x0011>, + <&apps_smmu 0x86 0x0011>, + <&apps_smmu 0x92 0x0>, + <&apps_smmu 0x94 0x0011>, + <&apps_smmu 0x96 0x0011>, + <&apps_smmu 0x98 0x0001>, + <&apps_smmu 0x9F 0x0>; + interconnects = <&system_noc MASTER_CRYPTO_CORE0 0 + &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "memory"; + }; + + qfprom: efuse@1b44000 { + compatible = "qcom,shikra-qfprom", "qcom,qfprom"; + reg = <0x0 0x01b44000 0x0 0x3000>; + #address-cells = <1>; + #size-cells = <1>; + + qusb2_hstx_trim_1: hstx-trim@25b { + reg = <0x25b 0x1>; + bits = <1 4>; + }; + + gpu_speed_bin: gpu-speed-bin@2006 { + reg = <0x2006 0x2>; + bits = <5 8>; + }; + }; + + spmi_bus: spmi@1c40000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0 0x01c40000 0x0 0x1100>, + <0x0 0x01e00000 0x0 0x2000000>, + <0x0 0x03e00000 0x0 0x100000>, + <0x0 0x03f00000 0x0 0xa0000>, + <0x0 0x01c0a000 0x0 0x26000>; + reg-names = "core", + "chnls", + "obsrvr", + "intr", + "cnfg"; + interrupts-extended = <&mpm 86 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "periph_irq"; + interrupt-controller; + #interrupt-cells = <4>; + #address-cells = <2>; + #size-cells = <0>; + qcom,channel = <0>; + qcom,ee = <0>; + }; + + tsens0: thermal-sensor@4411000 { + compatible = "qcom,shikra-tsens", "qcom,tsens-v2"; + reg = <0x0 0x04411000 0x0 0x1000>, + <0x0 0x04410000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <14>; + #thermal-sensor-cells = <1>; + }; + + rng: rng@4454000 { + compatible = "qcom,shikra-trng", "qcom,trng"; + reg = <0 0x04454000 0 0x1000>; + }; + + pcie: pcie@45e8000 { + device_type = "pci"; + compatible = "qcom,pcie-shikra"; + reg = <0x0 0x045e8000 0x0 0x3000>, + <0x0 0x60000000 0x0 0xf1d>, + <0x0 0x60000f20 0x0 0xa8>, + <0x0 0x60001000 0x0 0x1000>, + <0x0 0x60100000 0x0 0x100000>, + <0x0 0x045eb000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>; + bus-range = <0x00 0xff>; + + linux,pci-domain = <0>; + num-lanes = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + interrupt-map = <0 0 0 1 &intc 0 0 0 499 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 500 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 501 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 502 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_SLV_AXI_CLK>, + <&gcc GCC_PCIE_SLV_Q2A_AXI_CLK>, + <&gcc GCC_PCIE_SLEEP_CLK>, + <&gcc GCC_PCIE_THROTTLE_CORE_CLK>, + <&gcc GCC_PCIE_THROTTLE_XO_CLK>, + <&gcc GCC_QMIP_PCIE_CFG_AHB_CLK>, + <&gcc GCC_DDRSS_MEMNOC_PCIE_SF_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "sleep", + "throttle_core", + "throttle_xo", + "qmip", + "ddrss", + "tile"; + assigned-clocks = <&gcc GCC_PCIE_AUX_CLK>; + assigned-clock-rates = <19200000>; + + + interconnects = <&system_noc MASTER_PCIE2_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_PCIE2_0 RPM_ACTIVE_TAG>; + + interconnect-names = "pcie-mem", "cpu-pcie"; + + iommu-map = <0x0 &apps_smmu 0x800 0x1>, + <0x100 &apps_smmu 0x801 0x1>; + + resets = <&gcc GCC_PCIE_BCR>; + reset-names = "pci"; + + power-domains = <&gcc GCC_PCIE_GDSC>; + + max-link-speed = <2>; + + operating-points-v2 = <&pcie_opp_table>; + + status = "disabled"; + + pcie_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + }; + + pcie_port0: pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + bus-range = <0x01 0x8>; + + phys = <&pcie_phy>; + }; + }; + + pcie_phy: phy@45ee000 { + compatible = "qcom,shikra-qmp-gen2x1-pcie-phy"; + reg = <0x0 0x045ee000 0x0 0x1000>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_CLKREF_EN>, + <&gcc GCC_PCIE_RCHNG_PHY_CLK>, + <&gcc GCC_PCIE_PIPE_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "refgen", + "pipe"; + + resets = <&gcc GCC_PCIE_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE_RCHNG_PHY_CLK>; + assigned-clock-rates = <100000000>; + + #clock-cells = <0>; + clock-output-names = "pcie_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + rpm_msg_ram: sram@45f0000 { + compatible = "qcom,rpm-msg-ram", "mmio-sram"; + reg = <0x0 0x045f0000 0x0 0x7000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x045f0000 0x7000>; + + apss_mpm: sram@1b8 { + reg = <0x1b8 0x48>; + }; + }; + + sram@4690000 { + compatible = "qcom,rpm-stats"; + reg = <0x0 0x04690000 0x0 0x14000>; + }; + + sdhc_1: mmc@4744000 { + compatible = "qcom,shikra-sdhci", "qcom,sdhci-msm-v5"; + + reg = <0x0 0x04744000 0x0 0x1000>, + <0x0 0x04745000 0x0 0x1000>; + reg-names = "hc", + "cqhci"; + + iommus = <&apps_smmu 0xc0 0x0>; + + interrupts = , + ; + interrupt-names = "hc_irq", + "pwr_irq"; + + clocks = <&gcc GCC_SDCC1_AHB_CLK>, + <&gcc GCC_SDCC1_APPS_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", + "core", + "xo"; + + interconnects = <&system_noc MASTER_SDCC_1 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_SDCC_1 RPM_ACTIVE_TAG>; + interconnect-names = "sdhc-ddr", + "cpu-sdhc"; + + power-domains = <&rpmpd RPMPD_VDDCX>; + operating-points-v2 = <&sdhc1_opp_table>; + + qcom,dll-config = <0x000f642c>; + qcom,ddr-config = <0x80040868>; + + bus-width = <8>; + + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + + resets = <&gcc GCC_SDCC1_BCR>; + qcom,ice = <&sdhc_ice>; + + status = "disabled"; + + sdhc1_opp_table: opp-table-1 { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmpd_opp_low_svs>; + opp-peak-kBps = <250000 133320>; + opp-avg-kBps = <104000 0>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <800000 300000>; + opp-avg-kBps = <400000 0>; + }; + }; + }; + + sdhc_2: mmc@4784000 { + compatible = "qcom,shikra-sdhci", "qcom,sdhci-msm-v5"; + reg = <0x0 0x4784000 0x0 0x1000>; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + bus-width = <4>; + + clocks = <&gcc GCC_SDCC2_AHB_CLK>, + <&gcc GCC_SDCC2_APPS_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", "core", "xo"; + + qcom,dll-config = <0x0007442c>; + qcom,ddr-config = <0x80040868>; + + iommus = <&apps_smmu 0x0a0 0x0>; + + interconnects = <&system_noc MASTER_SDCC_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>, + <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_SDCC_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "sdhc-ddr","cpu-sdhc"; + operating-points-v2 = <&sdhc2_opp_table>; + + status = "disabled"; + + sdhc2_opp_table: opp-table-2 { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + + usb_1: usb@4e00000 { + compatible = "qcom,shikra-dwc3", "qcom,snps-dwc3"; + reg = <0x0 0x04e00000 0x0 0xfc100>; + + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_EN>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi", + "xo"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <133333333>; + + interrupts-extended = <&intc GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH 0>, + <&intc GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH 0>, + <&intc GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH 0>, + <&intc GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "dwc_usb3", + "pwr_event", + "qusb2_phy", + "ss_phy_irq"; + + iommus = <&apps_smmu 0x120 0x0>; + + phys = <&usb_1_hsphy>, <&usb_qmpphy>; + phy-names = "usb2-phy", "usb3-phy"; + + power-domains = <&gcc GCC_USB30_PRIM_GDSC>; + + resets = <&gcc GCC_USB30_PRIM_BCR>; + + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + snps,has-lpm-erratum; + snps,hird-threshold = /bits/ 8 <0x10>; + snps,usb3_lpm_capable; + snps,parkmode-disable-ss-quirk; + + usb-role-switch; + + wakeup-source; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_1_dwc3_hs: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_1_dwc3_ss: endpoint { + remote-endpoint = <&usb_qmpphy_usb_ss_in>; + }; + }; + }; + }; + + gpu: gpu@5900000 { + compatible = "qcom,adreno-07000400", "qcom,adreno"; + reg = <0x0 0x05900000 0x0 0x40000>, + <0x0 0x0599e000 0x0 0x1000>, + <0x0 0x05961000 0x0 0x800>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem", + "cx_dbgc"; + + interrupts = ; + + clocks = <&gpucc GPU_CC_GX_GFX3D_CLK>, + <&gpucc GPU_CC_AHB_CLK>, + <&gcc GCC_DDRSS_GPU_AXI_CLK>, + <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>; + clock-names = "core", + "iface", + "mem_iface", + "alt_mem_iface", + "gmu", + "xo"; + + interconnects = <&mem_noc MASTER_GRAPHICS_3D RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "gfx-mem"; + + iommus = <&adreno_smmu 0 1>; + operating-points-v2 = <&gpu_opp_table>; + power-domains = <&rpmpd QCM2290_VDDCX>; + qcom,gmu = <&gmu_wrapper>; + + #cooling-cells = <2>; + + status = "disabled"; + + gpu_zap_shader: zap-shader { + memory-region = <&gpu_micro_code_mem>; + }; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-1142400000 { + opp-hz = /bits/ 64 <1142400000>; + required-opps = <&rpmpd_opp_turbo_plus>; + opp-peak-kBps = <8171875>; + }; + + opp-1017600000 { + opp-hz = /bits/ 64 <1017600000>; + required-opps = <&rpmpd_opp_turbo>; + opp-peak-kBps = <8171875>; + }; + + opp-921600000 { + opp-hz = /bits/ 64 <921600000>; + required-opps = <&rpmpd_opp_nom_plus>; + opp-peak-kBps = <7046875>; + }; + + opp-844800000 { + opp-hz = /bits/ 64 <844800000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <6074218>; + }; + + opp-672000000 { + opp-hz = /bits/ 64 <672000000>; + required-opps = <&rpmpd_opp_svs_plus>; + opp-peak-kBps = <5285156>; + }; + + opp-537600000 { + opp-hz = /bits/ 64 <537600000>; + required-opps = <&rpmpd_opp_svs>; + opp-peak-kBps = <3972656>; + }; + + opp-355200000 { + opp-hz = /bits/ 64 <355200000>; + required-opps = <&rpmpd_opp_low_svs>; + opp-peak-kBps = <2136718>; + }; + }; + }; + + gmu_wrapper: gmu@596a000 { + compatible = "qcom,adreno-gmu-wrapper"; + reg = <0x0 0x0596a000 0x0 0x30000>; + reg-names = "gmu"; + power-domains = <&gpucc GPU_CX_GDSC>, + <&gpucc GPU_GX_GDSC>; + power-domain-names = "cx", + "gx"; + }; + + gpucc: clock-controller@5990000 { + compatible = "qcom,shikra-gpucc"; + reg = <0x0 0x05990000 0x0 0x9000>; + clocks = <&gcc GCC_GPU_CFG_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + power-domains = <&rpmpd RPMPD_VDDCX>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + adreno_smmu: iommu@59a0000 { + compatible = "qcom,shikra-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x059a0000 0x0 0x10000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + + clocks = <&gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>, + <&gcc GCC_GPU_MEMNOC_GFX_CLK>, + <&gcc GCC_GPU_SNOC_DVM_GFX_CLK>, + <&gpucc GPU_CC_AHB_CLK>; + clock-names = "hlos", + "mem", + "iface", + "ahb"; + + power-domains = <&gpucc GPU_CX_GDSC>; + }; + + iris: video-codec@5a00000 { + compatible = "qcom,shikra-iris", "qcom,qcm2290-venus"; + reg = <0 0x5a00000 0 0x200000>; + interrupts = ; + + power-domains = <&gcc GCC_VENUS_GDSC>, + <&gcc GCC_VCODEC0_GDSC>, + <&rpmpd QCM2290_VDDCX>; + power-domain-names = "venus", + "vcodec0", + "cx"; + operating-points-v2 = <&venus_opp_table>; + + clocks = <&gcc GCC_VIDEO_VENUS_CTL_CLK>, + <&gcc GCC_VIDEO_AHB_CLK>, + <&gcc GCC_VENUS_CTL_AXI_CLK>, + <&gcc GCC_VIDEO_THROTTLE_CORE_CLK>, + <&gcc GCC_VIDEO_VCODEC0_SYS_CLK>, + <&gcc GCC_VCODEC0_AXI_CLK>; + clock-names = "core", + "iface", + "bus", + "throttle", + "vcodec0_core", + "vcodec0_bus"; + + memory-region = <&video_mem>; + interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_VENUS_CFG RPM_ACTIVE_TAG>; + interconnect-names = "video-mem", + "cpu-cfg"; + + iommus = <&apps_smmu 0x780 0x0020>; + + venus_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133333333 { + opp-hz = /bits/ 64 <133333333>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + + camss: camss@5c11000 { + compatible = "qcom,shikra-camss"; + + reg = <0x0 0x05c11000 0x0 0x1000>, + <0x0 0x05c6e000 0x0 0x1000>, + <0x0 0x05c75000 0x0 0x1000>, + <0x0 0x05c52000 0x0 0x1000>, + <0x0 0x05c53000 0x0 0x1000>, + <0x0 0x05c66000 0x0 0x400>, + <0x0 0x05c68000 0x0 0x400>, + <0x0 0x05c6f000 0x0 0x4000>, + <0x0 0x05c76000 0x0 0x4000>; + reg-names = "top", + "csid0", + "csid1", + "csiphy0", + "csiphy1", + "csitpg0", + "csitpg1", + "vfe0", + "vfe1"; + + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>, + <&gcc GCC_CAMSS_NRT_AXI_CLK>, + <&gcc GCC_CAMSS_RT_AXI_CLK>, + <&gcc GCC_CAMSS_TFE_0_CSID_CLK>, + <&gcc GCC_CAMSS_TFE_1_CSID_CLK>, + <&gcc GCC_CAMSS_CPHY_0_CLK>, + <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>, + <&gcc GCC_CAMSS_CPHY_1_CLK>, + <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>, + <&gcc GCC_CAMSS_TOP_AHB_CLK>, + <&gcc GCC_CAMSS_TFE_0_CLK>, + <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, + <&gcc GCC_CAMSS_TFE_1_CLK>, + <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>; + clock-names = "ahb", + "axi", + "camnoc_nrt_axi", + "camnoc_rt_axi", + "csi0", + "csi1", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "top_ahb", + "vfe0", + "vfe0_cphy_rx", + "vfe1", + "vfe1_cphy_rx"; + + interrupts = , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csiphy0", + "csiphy1", + "csitpg0", + "csitpg1", + "vfe0", + "vfe1"; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_CAMERA_CFG RPM_ACTIVE_TAG>, + <&mmrt_virt MASTER_CAMNOC_HF RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mmnrt_virt MASTER_CAMNOC_SF RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc"; + + iommus = <&apps_smmu 0x400 0x0>; + + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + }; + }; + }; + + cci: cci@5c1b000 { + compatible = "qcom,shikra-cci", "qcom,msm8996-cci"; + + reg = <0x0 0x05c1b000 0x0 0x1000>; + interrupts = ; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>, + <&gcc GCC_CAMSS_CCI_0_CLK>; + clock-names = "ahb", + "cci"; + + pinctrl-0 = <&cci_i2c0_default &cci_i2c1_default>; + pinctrl-1 = <&cci_i2c0_sleep &cci_i2c1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + mdss: display-subsystem@5e00000 { + compatible = "qcom,shikra-mdss"; + reg = <0x0 0x05e00000 0x0 0x1000>; + reg-names = "mdss"; + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", + "bus", + "core"; + + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + + power-domains = <&dispcc MDSS_GDSC>; + + iommus = <&apps_smmu 0x420 0x2>; + interconnects = <&mmrt_virt MASTER_MDP_PORT0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_DISPLAY_CFG RPM_ALWAYS_TAG>; + interconnect-names = "mdp0-mem", + "cpu-cfg"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdp: display-controller@5e01000 { + compatible = "qcom,shikra-dpu"; + reg = <0x0 0x05e01000 0x0 0x8f000>, + <0x0 0x05eb0000 0x0 0x3000>; + reg-names = "mdp", + "vbif"; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "bus", + "iface", + "core", + "lut", + "vsync"; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmpd QCM2290_VDDCX>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&mdss_dsi0_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-192000000 { + opp-hz = /bits/ 64 <192000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-256000000 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-307200000 { + opp-hz = /bits/ 64 <307200000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + + mdss_dsi0: dsi@5e94000 { + compatible = "qcom,shikra-dsi-ctrl", + "qcom,mdss-dsi-ctrl"; + reg = <0x0 0x05e94000 0x0 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; + assigned-clock-parents = <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmpd QCM2290_VDDCX>; + phys = <&mdss_dsi0_phy>; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + dsi_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-164000000 { + opp-hz = /bits/ 64 <164000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-187500000 { + opp-hz = /bits/ 64 <187500000>; + required-opps = <&rpmpd_opp_svs>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dsi0_out: endpoint { + }; + }; + }; + }; + + mdss_dsi0_phy: phy@5e94400 { + compatible = "qcom,dsi-phy-14nm-2290"; + reg = <0x0 0x05e94400 0x0 0x100>, + <0x0 0x05e94500 0x0 0x300>, + <0x0 0x05e94800 0x0 0x188>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", + "ref"; + + power-domains = <&rpmpd QCM2290_VDDMX>; + required-opps = <&rpmpd_opp_nom>; + + #clock-cells = <1>; + #phy-cells = <0>; + + status = "disabled"; + }; + }; + + dispcc: clock-controller@5f00000 { + compatible = "qcom,shikra-dispcc", "qcom,qcm2290-dispcc"; + reg = <0x0 0x05f00000 0x0 0x20000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&rpmcc RPM_SMD_XO_A_CLK_SRC>, + <&gcc GCC_DISP_GPLL0_CLK_SRC>, + <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, + <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>, + <0>, + <0>, + <&sleep_clk>; + clock-names = "bi_tcxo", + "bi_tcxo_ao", + "gcc_disp_gpll0_clk_src", + "gcc_disp_gpll0_div_clk_src", + "dsi0_phy_pll_out_byteclk", + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "sleep_clk"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + qaif_cpu: audio@a000000 { + compatible = "qcom,shikra-qaif-cpu"; + reg = <0x0 0x0a000000 0x0 0x20000>; + reg-names = "audio-qaif-core"; + + interrupts = ; + interrupt-names = "qaif-irq-audio-core"; + + clocks = <&gcc GCC_LPASS_CONFIG_CLK>, + <&gcc GCC_LPASS_CORE_AXIM_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_MEM_CLK>, + <&audiocorecc AUDIO_CORE_CC_BUS_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_EBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK>, + <&audiocorecc AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK>; + clock-names = "gcc_lpass_config_clk", + "gcc_lpass_core_axim_clk", + "audio_core_cc_aud_dma_clk", + "audio_core_cc_aud_dma_mem_clk", + "audio_core_cc_bus_clk", + "audio_core_cc_aif_if0_ebit_clk", + "audio_core_cc_aif_if0_ibit_clk", + "audio_core_cc_aif_if1_ebit_clk", + "audio_core_cc_aif_if1_ibit_clk", + "audio_core_cc_aif_if2_ebit_clk", + "audio_core_cc_aif_if2_ibit_clk", + "audio_core_cc_aif_if3_ebit_clk", + "audio_core_cc_aif_if3_ibit_clk", + "audio_core_cc_ext_mclka_clk", + "audio_core_cc_ext_mclkb_clk"; + + iommus = <&apps_smmu 0x1c0 0x0>; + + #sound-dai-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + rxmacro: codec@a040000 { + compatible = "qcom,shikra-lpass-rx-macro"; + reg = <0x0 0x0a040000 0x0 0x1000>; + + pinctrl-0 = <&swr_rx_clk>, <&swr_rx_data0>, <&swr_rx_data1>; + pinctrl-names = "default"; + + clocks = <&audiocorecc AUDIO_CORE_CC_RX_MCLK_CLK>, + <&audiocorecc AUDIO_CORE_CC_RX_MCLK_2X_CLK>, + <&vamacro>; + clock-names = "mclk", + "npl", + "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + swr0: soundwire@a060000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x0a060000 0x0 0x10000>; + qcom,swr-master-ee-val = <0>; + + interrupts = ; + + clocks = <&rxmacro>; + clock-names = "iface"; + + label = "RX"; + qcom,din-ports = <0>; + qcom,dout-ports = <5>; + + resets = <&audiocorecc AUDIO_CORE_CSR_RX_SWR_CGCR>; + reset-names = "swr_audio_cgcr"; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + + status = "disabled"; + }; + + vamacro: codec@a078000 { + compatible = "qcom,shikra-lpass-va-macro"; + reg = <0x0 0x0a078000 0x0 0x2000>; + + pinctrl-0 = <&swr_tx_clk>, <&swr_tx_data0>; + pinctrl-names = "default"; + + clocks = <&audiocorecc AUDIO_CORE_CC_TX_MCLK_CLK>, + <&audiocorecc AUDIO_CORE_CC_TX_MCLK_2X_CLK>; + clock-names = "mclk", + "npl"; + + #clock-cells = <0>; + #sound-dai-cells = <1>; + clock-output-names = "fsgen"; + status = "disabled"; + }; + + swr1: soundwire@a080000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x0a080000 0x0 0x10000>; + qcom,swr-master-ee-val = <0>; + + interrupts = , + ; + interrupt-names = "core", "wakeup"; + + clocks = <&vamacro>; + clock-names = "iface"; + + label = "VA_TX"; + + qcom,din-ports = <3>; + qcom,dout-ports = <0>; + + resets = <&audiocorecc AUDIO_CORE_CSR_TX_SWR_CGCR>; + reset-names = "swr_audio_cgcr"; + + qcom,ports-sinterval-low = /bits/ 8 <0x01 0x03 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x01 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x00 0x01 0x00>; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + + status = "disabled"; + }; + + sram@c11e000 { + compatible = "qcom,shikra-imem", "syscon", "simple-mfd"; + reg = <0x0 0x0c11e000 0x0 0x1000>; + ranges = <0x0 0x0 0x0c11e000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + pil-reloc@94c { + compatible = "qcom,pil-reloc-info"; + reg = <0x94c 0xc8>; + }; + }; + + apps_smmu: iommu@c600000 { + compatible = "qcom,shikra-smmu-500", "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x0c600000 0x0 0x80000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + + wifi: wifi@c800000 { + compatible = "qcom,wcn3990-wifi"; + reg = <0x0 0x0c800000 0x0 0x800000>; + reg-names = "membase"; + memory-region = <&wlan_mem>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + iommus = <&apps_smmu 0x1a0 0x1>; + qcom,msa-fixed-perm; + + status = "disabled"; + }; + + intc: interrupt-controller@f200000 { + compatible = "arm,gic-v3"; + reg = <0x0 0xf200000 0x0 0x10000>, /* GICD */ + <0x0 0xf240000 0x0 0x80000>; /* GICR * 4 regions */ + + interrupts = ; + + #interrupt-cells = <4>; + interrupt-controller; + + #redistributor-regions = <1>; + redistributor-stride = <0x0 0x20000>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ppi-partitions { + ppi_cluster0: interrupt-partition-0 { + affinity = <&cpu0 &cpu1 &cpu2>; + }; + + ppi_cluster1: interrupt-partition-1 { + affinity = <&cpu3>; + }; + }; + }; + + apcs_glb: mailbox@f400000 { + compatible = "qcom,shikra-apss-shared", "qcom,sdm845-apss-shared"; + reg = <0x0 0x0f400000 0x0 0x1000>; + #mbox-cells = <1>; + }; + + watchdog@f410000 { + compatible = "qcom,apss-wdt-shikra", "qcom,kpss-wdt"; + reg = <0x0 0x0f410000 0x0 0x1000>; + interrupts = , + ; + clocks = <&sleep_clk>; + }; + + timer@f420000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x0f420000 0x0 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x0 0x10000000>; + + frame@f421000 { + reg = <0x0f421000 0x1000>, + <0x0f422000 0x1000>; + frame-number = <0>; + interrupts = , + ; + }; + + frame@f423000 { + reg = <0x0f423000 0x1000>; + frame-number = <1>; + interrupts = ; + status = "disabled"; + }; + + frame@f425000 { + reg = <0x0f425000 0x1000>; + frame-number = <2>; + interrupts = ; + status = "disabled"; + }; + + frame@f427000 { + reg = <0x0f427000 0x1000>; + frame-number = <3>; + interrupts = ; + status = "disabled"; + }; + + frame@f429000 { + reg = <0x0f429000 0x1000>; + frame-number = <4>; + interrupts = ; + status = "disabled"; + }; + + frame@f42b000 { + reg = <0x0f42b000 0x1000>; + frame-number = <5>; + interrupts = ; + status = "disabled"; + }; + + frame@f42d000 { + reg = <0x0f42d000 0x1000>; + frame-number = <6>; + interrupts = ; + status = "disabled"; + }; + }; + + gpi_dma0: dma-controller@4a00000 { + compatible = "qcom,shikra-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x04a00000 0x0 0x60000>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + dma-channels = <16>; + dma-channel-mask = <0xff>; + #dma-cells = <3>; + + iommus = <&apps_smmu 0xf6 0x0>; + }; + + sdhc_ice: crypto@4748000 { + compatible = "qcom,shikra-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x04748000 0x0 0x18000>; + clocks = <&gcc GCC_SDCC1_ICE_CORE_CLK>, + <&gcc GCC_SDCC1_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&rpmpd RPMHPD_CX>; + }; + + qupv3_0: geniqup@4ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x04ac0000 0x0 0x2000>; + + clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>; + clock-names = "m-ahb", + "s-ahb"; + + iommus = <&apps_smmu 0xe3 0x0>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + i2c0: i2c@4a80000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>, + <&gpi_dma0 1 0 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c0_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi0: spi@4a80000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>, + <&gpi_dma0 1 0 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi0_data_clk>, <&qup_spi0_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart0: serial@4a80000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x04a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart0_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c1: i2c@4a84000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>, + <&gpi_dma0 1 1 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c1_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart1: serial@4a84000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart1_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c2: i2c@4a88000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + pinctrl-0 = <&qup_i2c2_data_clk>; + pinctrl-names = "default"; + + dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>, + <&gpi_dma0 1 2 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi2: spi@4a88000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>, + <&gpi_dma0 1 2 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi2_data_clk>, <&qup_spi2_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart2: serial@4a88000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a88000 0x0 0x4000>; + + interrupts-extended = <&intc GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH 0>, + <&tlmm 9 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart2_default>, <&qup_uart2_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c3: i2c@4a8c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>, + <&gpi_dma0 1 3 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c3_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart3: serial@4a8c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart3_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c4: i2c@4a90000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>, + <&gpi_dma0 1 4 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c4_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart4: serial@4a90000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart4_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c5: i2c@4a94000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>, + <&gpi_dma0 1 5 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c5_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi5: spi@4a94000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>, + <&gpi_dma0 1 5 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi5_data_clk>, <&qup_spi5_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart5: serial@4a94000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart5_default>, <&qup_uart5_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c6: i2c@4a98000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 6 QCOM_GPI_I2C>, + <&gpi_dma0 1 6 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c6_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi6: spi@4a98000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 6 QCOM_GPI_SPI>, + <&gpi_dma0 1 6 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi6_data_clk>, <&qup_spi6_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart6: serial@4a98000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart6_default>, <&qup_uart6_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c7: i2c@4a9c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4a9c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 7 QCOM_GPI_I2C>, + <&gpi_dma0 1 7 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c7_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart7: serial@4a9c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a9c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart7_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c8: i2c@4aa0000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4aa0000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 8 QCOM_GPI_I2C>, + <&gpi_dma0 1 8 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c8_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi8: spi@4aa0000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x4aa0000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma0 0 8 QCOM_GPI_SPI>, + <&gpi_dma0 1 8 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_spi8_data_clk>, <&qup_spi8_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart8: serial@4aa0000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04aa0000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S8_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart8_default>, <&qup_uart8_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c9: i2c@4aa4000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x4aa4000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S9_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>, + <&system_noc MASTER_QUP_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma0 0 9 QCOM_GPI_I2C>, + <&gpi_dma0 1 9 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + + pinctrl-0 = <&qup_i2c9_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart9: serial@4aa4000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04aa4000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP0_S9_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &clk_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart9_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + }; + + bam_dmux_dma: dma-controller@6044000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x0 0x06044000 0x0 0x19000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <0>; + + num-channels = <6>; + qcom,num-ees = <1>; + qcom,powered-remotely; + }; + + remoteproc_mpss: remoteproc@6080000 { + compatible = "qcom,shikra-mpss-pas"; + reg = <0x0 0x06080000 0x0 0x100>; + + interrupts-extended = <&intc GIC_SPI 307 IRQ_TYPE_EDGE_RISING 0>, + <&modem_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&modem_smp2p_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + + power-domains = <&rpmpd RPMHPD_CX>; + + memory-region = <&mpss_wlan_mem>; + + qcom,smem-states = <&modem_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 12>; + qcom,remote-pid = <1>; + label = "mpss"; + + gpr { + compatible = "qcom,gpr"; + qcom,glink-channels = "modem_apps"; + qcom,domain = ; + qcom,intents = <200 20>; + #address-cells = <1>; + #size-cells = <0>; + + q6apm: service@1 { + compatible = "qcom,q6apm"; + reg = ; + #sound-dai-cells = <0>; + + q6apmbedai: bedais { + compatible = "qcom,q6apm-lpass-dais"; + #sound-dai-cells = <1>; + }; + + q6apmdai: dais { + compatible = "qcom,q6apm-dais"; + memory-region = <&audio_mdsp_carveout_mem>; + qcom,vmid = ; + }; + }; + + q6prm: service@2 { + compatible = "qcom,q6prm"; + reg = ; + + q6prmcc: clock-controller { + compatible = "qcom,q6prm-lpass-clocks"; + #clock-cells = <2>; + }; + }; + }; + }; + }; + + ctcu@8001000 { + compatible = "qcom,shikra-ctcu","qcom,sa8775p-ctcu"; + reg = <0x0 0x08001000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb"; + + in-ports { + port { + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + }; + }; + + stm@8002000 { + compatible = "arm,coresight-stm", "arm,primecell"; + reg = <0x0 0x08002000 0x0 0x1000>, + <0x0 0x0e280000 0x0 0x180000>; + reg-names = "stm-base", + "stm-stimulus-base"; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + out-ports { + port { + stm_out: endpoint { + remote-endpoint = <&funnel_in0_in7>; + }; + }; + }; + }; + + tpdm@8003000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08003000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_dcc"; + qcom,cmb-element-bits = <32>; + + out-ports { + port { + tpdm_dcc_out: endpoint { + remote-endpoint = <&tpda_qdss_in0>; + }; + }; + }; + }; + + tpda@8004000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x08004000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpda_qdss_in0: endpoint { + remote-endpoint = <&tpdm_dcc_out>; + }; + }; + + port@1 { + reg = <1>; + + tpda_qdss_in1: endpoint { + remote-endpoint = <&tpdm_spdm_out>; + }; + }; + }; + + out-ports { + port { + tpda_qdss_out: endpoint { + remote-endpoint = <&funnel_in0_in6>; + }; + }; + }; + }; + + tpdm@800f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x0800f000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_spdm"; + qcom,cmb-element-bits = <32>; + + out-ports { + port { + tpdm_spdm_out: endpoint { + remote-endpoint = <&tpda_qdss_in1>; + }; + }; + }; + }; + + funnel@8041000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08041000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@5 { + reg = <5>; + + funnel_in0_in5: endpoint { + remote-endpoint = <&snoc_out>; + }; + }; + + port@6 { + reg = <6>; + + funnel_in0_in6: endpoint { + remote-endpoint = <&tpda_qdss_out>; + }; + }; + + port@7 { + reg = <7>; + + funnel_in0_in7: endpoint { + remote-endpoint = <&stm_out>; + }; + }; + }; + + out-ports { + port { + funnel_in0_out: endpoint { + remote-endpoint = <&funnel_merg_in0>; + }; + }; + }; + }; + + funnel@8042000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08042000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + funnel_in1_in1: endpoint { + remote-endpoint = <&tpda_aodbg_out>; + }; + }; + + port@4 { + reg = <4>; + + funnel_in1_in4: endpoint { + remote-endpoint = <&modem_etm0_out>; + }; + }; + + port@6 { + reg = <6>; + + funnel_in1_in6: endpoint { + remote-endpoint = <&funnel_cpuss1_out>; + }; + }; + + port@7 { + reg = <7>; + + funnel_in1_in7: endpoint { + remote-endpoint = <&funnel_center_out>; + }; + }; + }; + + out-ports { + port { + funnel_in1_out: endpoint { + remote-endpoint = <&funnel_merg_in1>; + }; + }; + }; + }; + + funnel@8045000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08045000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + funnel_merg_in0: endpoint { + remote-endpoint = <&funnel_in0_out>; + }; + }; + + port@1 { + reg = <1>; + + funnel_merg_in1: endpoint { + remote-endpoint = <&funnel_in1_out>; + }; + }; + }; + + out-ports { + port { + funnel_merg_out: endpoint { + remote-endpoint = <&tmc_etf_in>; + }; + }; + }; + }; + + replicator@8046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x08046000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_qdss_in: endpoint { + remote-endpoint = <&tmc_etf_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + replicator_qdss_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + replicator_qdss_out1: endpoint { + remote-endpoint = <&replicator_eud_in>; + }; + }; + }; + }; + + tmc@8047000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x08047000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + tmc_etf_in: endpoint { + remote-endpoint = <&funnel_merg_out>; + }; + }; + }; + + out-ports { + port { + tmc_etf_out: endpoint { + remote-endpoint = <&replicator_qdss_in>; + }; + }; + }; + }; + + tmc@8048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x08048000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0160 0x0>; + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&replicator_qdss_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@804a000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x0804a000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_eud_in: endpoint { + remote-endpoint = <&replicator_qdss_out1>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + replicator_eud_out1: endpoint { + remote-endpoint = <&eud_in>; + }; + }; + }; + }; + + tpdm@8800000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08800000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_cdsp"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <4>; + + out-ports { + port { + tpdm_cdsp_out: endpoint { + remote-endpoint = <&funnel_cdsp_in0>; + }; + }; + }; + }; + + funnel@8801000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08801000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + funnel_cdsp_in0: endpoint { + remote-endpoint = <&tpdm_cdsp_out>; + }; + }; + }; + + out-ports { + port { + funnel_cdsp_out0: endpoint { + remote-endpoint = <&tpda_center_in3>; + }; + }; + }; + }; + + cti@8807000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08807000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_turing_q6"; + }; + + cti@8833000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08833000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_mss_q6"; + }; + + tpdm@8840000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08840000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_vsense"; + qcom,cmb-element-bits = <32>; + + out-ports { + port { + tpdm_vsense_out: endpoint { + remote-endpoint = <&tpda_center_in6>; + }; + }; + }; + }; + + tpdm@8844000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08844000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_dlct_1"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tpdm_dlct_1_out: endpoint { + remote-endpoint = <&tpda_center_in13>; + }; + }; + }; + }; + + tpda@8845000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x08845000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpda_center_in0: endpoint { + remote-endpoint = <&funnel_mcu_out>; + }; + }; + + port@2 { + reg = <2>; + + tpda_center_in2: endpoint { + remote-endpoint = <&tpdm_dlct_out>; + }; + }; + + port@3 { + reg = <3>; + + tpda_center_in3: endpoint { + remote-endpoint = <&funnel_cdsp_out0>; + }; + }; + + port@4 { + reg = <4>; + + tpda_center_in4: endpoint { + remote-endpoint = <&funnel_ddr_out0>; + }; + }; + + port@6 { + reg = <6>; + + tpda_center_in6: endpoint { + remote-endpoint = <&tpdm_vsense_out>; + }; + }; + + port@7 { + reg = <7>; + + tpda_center_in7: endpoint { + remote-endpoint = <&tpdm_prng_out>; + }; + }; + + port@8 { + reg = <8>; + + tpda_center_in8: endpoint { + remote-endpoint = <&tpdm_west_out>; + }; + }; + + port@9 { + reg = <9>; + + tpda_center_in9: endpoint { + remote-endpoint = <&tpdm_qm_out>; + }; + }; + + port@a { + reg = <0xa>; + + tpda_center_in10: endpoint { + remote-endpoint = <&tpdm_pimem_out>; + }; + }; + + port@d { + reg = <0xd>; + + tpda_center_in13: endpoint { + remote-endpoint = <&tpdm_dlct_1_out>; + }; + }; + }; + + out-ports { + port { + tpda_center_out: endpoint { + remote-endpoint = <&funnel_center_in0>; + }; + }; + }; + }; + + funnel@8846000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08846000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + funnel_center_in0: endpoint { + remote-endpoint = <&tpda_center_out>; + }; + }; + }; + + out-ports { + port { + funnel_center_out: endpoint { + remote-endpoint = <&funnel_in1_in7>; + }; + }; + }; + }; + + tpdm@884c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x0884c000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_prng"; + qcom,cmb-element-bits = <32>; + + out-ports { + port { + tpdm_prng_out: endpoint { + remote-endpoint = <&tpda_center_in7>; + }; + }; + }; + }; + + tpdm@8850000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08850000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_pimem"; + qcom,cmb-element-bits = <64>; + qcom,dsb-element-bits = <32>; + + out-ports { + port { + tpdm_pimem_out: endpoint { + remote-endpoint = <&tpda_center_in10>; + }; + }; + }; + }; + + tpdm@8980000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08980000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_mcu"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_mcu_out: endpoint { + remote-endpoint = <&funnel_mcu_in0>; + }; + }; + }; + }; + + funnel@8982000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08982000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + funnel_mcu_in0: endpoint { + remote-endpoint = <&tpdm_mcu_out>; + }; + }; + }; + + out-ports { + port { + funnel_mcu_out: endpoint { + remote-endpoint = <&tpda_center_in0>; + }; + }; + }; + }; + + tpdm@89d0000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x089d0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_qm"; + qcom,dsb-element-bits = <32>; + + out-ports { + port { + tpdm_qm_out: endpoint { + remote-endpoint = <&tpda_center_in9>; + }; + }; + }; + }; + + tpdm@8a01000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08a01000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_mapss"; + qcom,cmb-element-bits = <32>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_mapss_out: endpoint { + remote-endpoint = <&tpda_aodbg_in>; + }; + }; + }; + }; + + cti@8a02000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08a02000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_mapss"; + }; + + tpda@8a04000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x08a04000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + port { + tpda_aodbg_in: endpoint { + remote-endpoint = <&tpdm_mapss_out>; + }; + }; + }; + + out-ports { + port { + tpda_aodbg_out: endpoint { + remote-endpoint = <&funnel_in1_in1>; + }; + }; + }; + }; + + tpdm@8a58000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08a58000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_west"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_west_out: endpoint { + remote-endpoint = <&tpda_center_in8>; + }; + }; + }; + }; + + cti@8b30000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b30000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_cortex_m3"; + }; + + tpdm@8b58000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08b58000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_dlct"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <16>; + + out-ports { + port { + tpdm_dlct_out: endpoint { + remote-endpoint = <&tpda_center_in2>; + }; + }; + }; + }; + + cti@8b59000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b59000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_0"; + }; + + cti@8b5a000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b5a000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_1"; + }; + + cti@8b5b000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b5b000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_2"; + }; + + cti@8b5c000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b5c000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_dlct_3"; + }; + + tpdm@8b60000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x08b60000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_ddr"; + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <1>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tpdm_ddr_out: endpoint { + remote-endpoint = <&funnel_ddr_in0>; + }; + }; + }; + }; + + cti@8b62000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b62000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_ddr_dl_0"; + }; + + funnel@8b65000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x08b65000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + funnel_ddr_in0: endpoint { + remote-endpoint = <&tpdm_ddr_out>; + }; + }; + }; + + out-ports { + port { + funnel_ddr_out0: endpoint { + remote-endpoint = <&tpda_center_in4>; + }; + }; + }; + }; + + cti@8b70000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b70000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_ddr_dl_0_1"; + }; + + cti@8b71000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x08b71000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_ddr_dl_1_1"; + }; + + cti@9020000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09020000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe0"; + }; + + etm@9040000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09040000 0x0 0x1000>; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in0>; + }; + }; + }; + }; + + cti@90e0000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x090e0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_cluster"; + }; + + cti@9120000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09120000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe1"; + }; + + etm@9140000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09140000 0x0 0x1000>; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in1>; + }; + }; + }; + }; + + cti@9220000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09220000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe2"; + }; + + etm@9240000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09240000 0x0 0x1000>; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in2>; + }; + }; + }; + }; + + cti@9320000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09320000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_pe3"; + }; + + etm@9340000 { + compatible = "arm,coresight-etm4x-sysreg"; + reg = <0x0 0x09340000 0x0 0x1000>; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in3>; + }; + }; + }; + }; + + funnel@9800000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x09800000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + funnel_cpuss0_in0: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + + port@1 { + reg = <1>; + + funnel_cpuss0_in1: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + + port@2 { + reg = <2>; + + funnel_cpuss0_in2: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + + port@3 { + reg = <3>; + + funnel_cpuss0_in3: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + funnel_cpuss0_out: endpoint { + remote-endpoint = <&funnel_cpuss1_in0>; + }; + }; + }; + }; + + funnel@9810000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x09810000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + funnel_cpuss1_in0: endpoint { + remote-endpoint = <&funnel_cpuss0_out>; + }; + }; + + port@3 { + reg = <3>; + + funnel_cpuss1_in3: endpoint { + remote-endpoint = <&tpda_apss_out>; + }; + }; + }; + + out-ports { + port { + funnel_cpuss1_out: endpoint { + remote-endpoint = <&funnel_in1_in6>; + }; + }; + }; + }; + + cti@982b000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x0982b000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_riscv"; + }; + + tpdm@9860000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x09860000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_actpm"; + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <1>; + + out-ports { + port { + tpdm_actpm_out: endpoint { + remote-endpoint = <&tpda_apss_in2>; + }; + }; + }; + }; + + tpdm@9861000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x09861000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_hwe"; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tpdm_hwe_out: endpoint { + remote-endpoint = <&tpda_apss_in3>; + }; + }; + }; + }; + + tpda@9863000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x09863000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpda_apss_in0: endpoint { + remote-endpoint = <&tpdm_llm_silver_out>; + }; + }; + + port@2 { + reg = <2>; + + tpda_apss_in2: endpoint { + remote-endpoint = <&tpdm_actpm_out>; + }; + }; + + port@3 { + reg = <3>; + + tpda_apss_in3: endpoint { + remote-endpoint = <&tpdm_hwe_out>; + }; + }; + }; + + out-ports { + port { + tpda_apss_out: endpoint { + remote-endpoint = <&funnel_cpuss1_in3>; + }; + }; + }; + }; + + tpdm@98a0000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x098a0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + + label = "tpdm_llm_silver"; + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <12>; + + out-ports { + port { + tpdm_llm_silver_out: endpoint { + remote-endpoint = <&tpda_apss_in0>; + }; + }; + }; + }; + + cti@98e0000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x098e0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_0"; + }; + + cti@98f0000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x098f0000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_1"; + }; + + cti@9900000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x09900000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + label = "cti_apss_2"; + }; + + audiocorecc: clock-controller@a0a0000 { + compatible = "qcom,shikra-cqm-audiocorecc"; + reg = <0x0 0x0a0a0000 0x0 0x10000>, + <0x0 0x0a0b4000 0x0 0x1000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep_clk>, + <0>; + #clock-cells = <1>; + #reset-cells = <1>; + status = "disabled"; + }; + + remoteproc_cdsp: remoteproc@b300000 { + compatible = "qcom,shikra-cdsp-pas"; + reg = <0x0 0x0b300000 0x0 0x100000>; + + interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING 0>, + <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&cdsp_smp2p_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + + power-domains = <&rpmpd RPMHPD_CX>; + + memory-region = <&cdsp_mem>; + + qcom,smem-states = <&cdsp_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 4>; + qcom,remote-pid = <5>; + label = "cdsp"; + + fastrpc { + compatible = "qcom,fastrpc"; + #address-cells = <1>; + #size-cells = <0>; + label = "cdsp"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu 0x0201 0x0000>; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu 0x0202 0x0000>; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x0203 0x0000>; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x0204 0x0000>; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x0205 0x0000>; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x0206 0x0000>; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu 0x0209 0x0000>; + }; + }; + }; + + cooling { + compatible = "qcom,qmi-cooling-cdsp"; + cdsp_sw: cdsp_sw { + label = "cdsp_sw"; + #cooling-cells = <2>; + }; + }; + }; + + remoteproc_lpaicp: remoteproc@b800000 { + compatible = "qcom,shikra-lpaicp-pas"; + reg = <0x0 0x0b800000 0x0 0x200000>; + + interrupts-extended = <&intc GIC_SPI 257 IRQ_TYPE_EDGE_RISING 0>, + <&lmcu_smp2p_in 0 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 1 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 2 IRQ_TYPE_NONE>, + <&lmcu_smp2p_in 3 IRQ_TYPE_NONE>; + + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "xo"; + + memory-region = <&lmcu_mem &lmcu_dtb_mem>; + + qcom,smem-states = <&lmcu_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts = ; + mboxes = <&apcs_glb 9>; + qcom,remote-pid = <26>; + label = "lpaicp"; + }; + }; + + epss_l3: interconnect@fd90000 { + compatible = "qcom,shikra-epss-l3"; + reg = <0x0 0x0fd90000 0x0 0x1000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + #interconnect-cells = <1>; + }; + + cpufreq_hw: cpufreq@fd91000 { + compatible = "qcom,shikra-epss"; + reg = <0x0 0x0fd91000 0x0 0x1000>, + <0x0 0x0fd92000 0x0 0x1000>; + reg-names = "freq-domain0", + "freq-domain1"; + + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>; + clock-names = "xo", "alternate"; + + interrupts = , + ; + interrupt-names = "dcvsh-irq-0", + "dcvsh-irq-1"; + + #freq-domain-cells = <1>; + #clock-cells = <1>; + }; + }; + + snoc { + compatible = "arm,coresight-dummy-source"; + arm,static-trace-id = <18>; + + label = "snoc"; + + out-ports { + port { + snoc_out: endpoint { + remote-endpoint = <&funnel_in0_in5>; + }; + }; + }; + }; + + thermal_zones: thermal-zones { + aoss0-thermal { + thermal-sensors = <&tsens0 0>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + aoss0-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-0-thermal { + thermal-sensors = <&tsens0 1>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu00-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-1-thermal { + thermal-sensors = <&tsens0 2>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu01-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-1-0-thermal { + thermal-sensors = <&tsens0 3>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu10-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-1-1-thermal { + thermal-sensors = <&tsens0 4>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu11-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpuss0-thermal { + thermal-sensors = <&tsens0 5>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpuss0-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpuss-thermal { + polling-delay-passive = <10>; + thermal-sensors = <&tsens0 6>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpuss_alert0: gpuss-alert0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + + gpuss-critical { + temperature = <120000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpuss_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + nsp-thermal { + thermal-sensors = <&tsens0 7>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + nsp_0_alert0: trip-point1 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + + nsp-critical { + temperature = <118000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp_0_alert0>; + cooling-device = <&cdsp_sw + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + mdmss0-thermal { + thermal-sensors = <&tsens0 8>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss0-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + mdmss1-thermal { + thermal-sensors = <&tsens0 9>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss1-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + camera-thermal { + thermal-sensors = <&tsens0 10>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + camera-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + video-thermal { + thermal-sensors = <&tsens0 11>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + video-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-2-thermal { + thermal-sensors = <&tsens0 12>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu02-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpuss1-thermal { + thermal-sensors = <&tsens0 13>; + + trips { + trip-point0 { + temperature = <110000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpuss1-critical { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + + interrupts = , + , + , + ; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts index cb59c122f6f6a..f99a47334452f 100644 --- a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts +++ b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts @@ -90,6 +90,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -99,7 +100,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1440,10 +1441,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vdd_a_usbhs_core>; vdda18-supply = <&vdd_a_usbhs_1p8>; @@ -1459,3 +1456,7 @@ &wifi { status = "okay"; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts index 3837f6785320d..4343ec5ca201c 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts @@ -462,7 +462,7 @@ vreg_l12b_1p8: ldo12 { regulator-name = "vreg_l12b_1p8"; - regulator-min-microvolt = <1200000>; + regulator-min-microvolt = <1650000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = ; regulator-allow-set-load; @@ -1426,3 +1426,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts index 801c46d556022..795d0d34e47ef 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts @@ -1154,3 +1154,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750-staging.dtso b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso new file mode 100644 index 0000000000000..c9741b3832dd4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso @@ -0,0 +1,671 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * SM8750 staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&{/} { + etm-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + etm-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + etm-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + etm-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + etm-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + etm-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + etm-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + etm-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; +}; + +&soc { + tn@109ab000 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@21 { + reg = <0x21>; + + tn_ag_in33: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + }; + }; + + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + apss_funnel: funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in33>; + }; + }; + }; + }; + + funnel@13401000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13401000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@13409000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13409000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + funnel@13481000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13481000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + replicator@13490000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13490000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@134a0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@134b0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@134c0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@134d0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@134e0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x134e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@13d01000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13d01000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@13d09000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb961>; + reg = <0x0 0x13d09000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + funnel@13d81000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb908>; + reg = <0x0 0x13d81000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + replicator@13d90000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13d90000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@13da0000 { + compatible = "arm,primecell"; + arm,primecell-periphid = <0x000bb909>; + reg = <0x0 0x13da0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + qcom,cpu-bound-components; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index fafed417c66fc..250d1a1818a26 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -261,7 +261,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -3037,6 +3037,299 @@ #power-domain-cells = <1>; }; + cci0: cci@ac7b000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7b000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac7c000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7c000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci1_0_default &cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep &cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@ac7d000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7d000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + camss: isp@ad27000 { + compatible = "qcom,sm8750-camss"; + + reg = <0x0 0x0ad27000 0x0 0x2b00>, + <0x0 0x0ad2a000 0x0 0x2b00>, + <0x0 0x0ad2d000 0x0 0x2b00>, + <0x0 0x0ad6d000 0x0 0xa00>, + <0x0 0x0ad72000 0x0 0xa00>, + <0x0 0x0ada9000 0x0 0x2000>, + <0x0 0x0adab000 0x0 0x2000>, + <0x0 0x0adad000 0x0 0x2000>, + <0x0 0x0adaf000 0x0 0x2000>, + <0x0 0x0adb1000 0x0 0x2000>, + <0x0 0x0adb3000 0x0 0x2000>, + <0x0 0x0ad8b000 0x0 0x400>, + <0x0 0x0ad8c000 0x0 0x400>, + <0x0 0x0ad8d000 0x0 0x400>, + <0x0 0x0ac86000 0x0 0x10000>, + <0x0 0x0ac96000 0x0 0x10000>, + <0x0 0x0aca6000 0x0 0x10000>, + <0x0 0x0ad6e000 0x0 0x3000>, + <0x0 0x0ad73000 0x0 0x3000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + }; + + port@2 { + reg = <2>; + }; + + port@3 { + reg = <3>; + }; + + port@4 { + reg = <4>; + }; + + port@5 { + reg = <5>; + }; + }; + + }; + mdss: display-subsystem@ae00000 { compatible = "qcom,sm8750-mdss"; reg = <0x0 0x0ae00000 0x0 0x1000>; @@ -3606,6 +3899,254 @@ gpio-ranges = <&tlmm 0 0 216>; wakeup-parent = <&pdc>; + cam0_default: cam0-default-state { + pins = "gpio89"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam1_default: cam1-default-state { + pins = "gpio90"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam2_default: cam2-default-state { + pins = "gpio91"; + function = "cam_aon_mclk2"; + drive-strength = <2>; + bias-disable; + }; + + cam3_default: cam3-default-state { + pins = "gpio92"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam4_default: cam4-default-state { + pins = "gpio93"; + function = "cam_aon_mclk4"; + drive-strength = <2>; + bias-disable; + }; + + cam5_default: cam5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam6_default: cam6-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam7_default: cam7-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio164"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio164"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + hub_i2c0_data_clk: hub-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio64", "gpio65"; @@ -4106,6 +4647,35 @@ #reset-cells = <1>; }; + ctcu@10001000 { + compatible = "qcom,sm8750-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&etr1_out>; + }; + }; + }; + }; + stm@10002000 { compatible = "arm,coresight-stm", "arm,primecell"; reg = <0x0 0x10002000 0x0 0x1000>, @@ -4219,6 +4789,122 @@ }; }; + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep_in: endpoint { + remote-endpoint = <&swao_rep_out0>; + }; + }; + }; + + out-ports { + port { + qdss_rep_out0: endpoint { + remote-endpoint = <&etr_rep_in>; + }; + }; + }; + }; + + tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x04e0 0x0>; + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&etr_rep_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_rep_in: endpoint { + remote-endpoint = <&qdss_rep_out0>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + etr_rep_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + etr_rep_out1: endpoint { + remote-endpoint = <&etr1_in>; + }; + }; + }; + }; + + tmc_etr1: tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0500 0x0>; + arm,scatter-gather; + arm,buffer-size = <0x400000>; + + in-ports { + port { + etr1_in: endpoint { + remote-endpoint = <&etr_rep_out1>; + }; + }; + }; + + out-ports { + port { + etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + tpdm@10800000 { compatible = "qcom,coresight-tpdm", "arm,primecell"; reg = <0x0 0x10800000 0x0 0x1000>; @@ -4889,6 +5575,38 @@ }; }; }; + + out-ports { + port { + tmc_etf_out: endpoint { + remote-endpoint = <&swao_rep_in>; + }; + }; + }; + }; + + replicator@10b06000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10b06000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + swao_rep_in: endpoint { + remote-endpoint = <&tmc_etf_out>; + }; + }; + }; + + out-ports { + port { + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + }; }; tpda@10b08000 { @@ -5445,6 +6163,7 @@ phy-names = "ufsphy"; #reset-cells = <1>; + qcom,ice = <&ice>; status = "disabled"; diff --git a/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi new file mode 100644 index 0000000000000..7e76197614781 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci { + /*cam0-imx577*/ + tl_slot0: qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam0>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 28 0>, + <&tlmm 75 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*cam1-imx577*/ + t1_slot1: qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam1>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 30 0>, + <&tlmm 29 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK1", "CAMIF_RESET1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; + + /*cam0-imx577-eeprom*/ + eeprom_cam0: qcom,eeprom0 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 28 0>, + <&tlmm 75 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*cam1-imx577-eeprom*/ + eeprom_cam1: qcom,eeprom1 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 30 0>, + <&tlmm 29 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK1", "CAMIF_RESET1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi new file mode 100644 index 0000000000000..7d6f1268fa396 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -0,0 +1,1985 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac00000 { + compatible = "qcom,cam-icp_v1"; + icp-version = <0x0100>; + reg = <0x0 0xac00000 0x0 0x6000>, + <0x0 0xac10000 0x0 0x8000>, + <0x0 0xac18000 0x0 0x3000>; + reg-names = "icp_qgic", "icp_sierra", "icp_csr"; + reg-cam-base = <0x00000 0x10000 0x18000>; + interrupts = ; + interrupt-names = "a5"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_ICP_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_icp_clk", + "cam_cc_icp_clk_src"; + clock-rates = <0 0 100000000 0 0 0 0 240000000>, + <0 0 200000000 0 0 0 0 360000000>, + <0 0 300000000 0 0 0 0 432000000>, + <0 0 404000000 0 0 0 0 480000000>, + <0 0 404000000 0 0 0 0 540000000>, + <0 0 404000000 0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_icp_clk_src"; + operating-points-v2 = <&a5_opp_table>; + fw_name = "qcom/qcs615/CAMERA_ICP.elf"; + ubwc-cfg = <0x73 0x1CF>; + cam_hw_pid = <15>; + cell-index = <0>; + status = "okay"; + + a5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + qcom,cam-cpas@ac40000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac40000 0x0 0x1000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg-cam-base = <0x40000 0x42000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0>, + <0 0 0 80000000 0 150000000>, + <0 0 0 80000000 0 240000000>, + <0 0 0 80000000 0 265000000>, + <0 0 0 80000000 0 355000000>, + <0 0 0 80000000 0 426000000>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_camnoc_axi_clk"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_HF1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cam_ahb", + "cam_hf_0_mnoc", + "cam_hf_1_mnoc", + "cam_sf_0_mnoc"; + cam-ahb-num-cases = <9>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>, + <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", + "svs_l1", "nominal", "nominal", + "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "cci0", + "csid0", "csid1", "csid2","ife0", + "ife1", "ife2", "ipe0", "cam-cdm-intf0", + "cpas-cdm0", "bps0", "icp0", "jpeg-dma0", + "jpeg-enc0", "lrmecpas0"; + cell-index = <0>; + status = "okay"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-265000000 { + opp-hz = /bits/ 64 <265000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-355000000 { + opp-hz = /bits/ 64 <355000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-426000000 { + opp-hz = /bits/ 64 <426000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + cpas_cdm0_all_rd: cpas-cdm0-all-rd { + cell-index = <2>; + node-name = "cpas-cdm0-all-rd"; + client-name = "cpas-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read2>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <3>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read3>; + }; + + ife0_linear_pdaf_wr: ife0-linear-pdaf-wr { + cell-index = <4>; + node-name = "ife0-linear-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife0_ubwc_stats_wr: ife0-ubwc-stats-wr { + cell-index = <6>; + node-name = "ife0-ubwc-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife1_linear_pdaf_wr: ife1-linear-pdaf-wr { + cell-index = <7>; + node-name = "ife1-linear-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <8>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_ubwc_stats_wr: ife1-ubwc-stats-wr { + cell-index = <9>; + node-name = "ife1-ubwc-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife2_rdi_wr: ife2-rdi-wr { + cell-index = <10>; + node-name = "ife2-rdi-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ipe0_all_rd: ipe0-all-rd { + cell-index = <11>; + node-name = "ipe0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_read0>; + }; + + ipe0_ref_wr: ipe0-ref-wr { + cell-index = <12>; + node-name = "ipe0-ref-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + ipe0_viddisp_wr: ipe0-viddisp-wr { + cell-index = <13>; + node-name = "ipe0-viddisp-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_write0>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <14>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = + ; + parent-node = <&level1_nrt0_read1>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <15>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write1>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <16>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read1>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <17>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write1>; + }; + + lrme0_all_rd: lrme0-all-rd { + cell-index = <18>; + node-name = "lrme0-all-rd"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + lrme0_all_wr: lrme0-all-wr { + cell-index = <19>; + node-name = "lrme0-all-wr"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_read0: level1-nrt0-read0 { + cell-index = <20>; + node-name = "level1-nrt0-read0"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read1: level1-nrt0-read1 { + cell-index = <21>; + node-name = "level1-nrt0-read1"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read2: level1-nrt0-read2 { + cell-index = <22>; + node-name = "level1-nrt0-read2"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read3: level1-nrt0-read3 { + cell-index = <23>; + node-name = "level1-nrt0-read3"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_write0: level1-nrt0-write0 { + cell-index = <24>; + node-name = "level1-nrt0-write0"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_write1: level1-nrt0-write1 { + cell-index = <25>; + node-name = "level1-nrt0-write1"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_rt0_write0: level1-rt0-write0 { + cell-index = <26>; + node-name = "level1-rt0-write0"; + parent-node = <&level2_rt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_rt1_write0: level1-rt1-write0 { + cell-index = <27>; + node-name = "level1-rt1-write0"; + parent-node = <&level2_rt1_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + + level2_nrt0_rd_wr_sum: level2-nrt0-rd-wr-sum { + cell-index = <28>; + node-name = "level2-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0_mnoc"; + }; + }; + + level2_rt0_rd_wr_sum: level2-rt0-rd-wr-sum { + cell-index = <29>; + node-name = "level2-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0_mnoc"; + }; + }; + + level2_rt1_rd_wr_sum: level2-rt1-rd-wr-sum { + cell-index = <30>; + node-name = "level3-rt1-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_1_mnoc"; + }; + }; + }; + }; + }; + + qcom,cpas-cdm0@ac48000 { + compatible = "qcom,cam170-cpas-cdm0"; + label = "cpas-cdm"; + reg = <0x0 0xac48000 0x0 0x1000>; + reg-names = "cpas-cdm"; + reg-cam-base = <0x48000>; + interrupts = ; + interrupt-names = "cpas-cdm"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_slow_ahb_clk_src"; + clock-rates = <0 0 0 0 0 80000000>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + operating-points-v2 = <&cpas_cdm_opp_table>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "ife1", "ife2", + "ife3", "dualife"; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cpas_cdm_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_cci: qcom,cci@ac4a000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4a000 0x0 0x4000>; + reg-names = "cci"; + reg-cam-base = <0x4a000>; + interrupts = ; + interrupt-names = "CCI"; + operating-points-v2 = <&cci_opp_table>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_CLK_SRC>, + <&camcc CAM_CC_CCI_CLK>; + clock-names = "cci_clk_src", + "cci_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "okay"; + + cci_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac4e000 { + compatible = "qcom,cam_jpeg_enc_170"; + reg = <0x0 0xac4e000 0x0 0x4000>; + reg-names = "jpege_hw"; + reg-cam-base = <0x4e000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_jpeg_clk_src", + "cam_cc_jpeg_clk"; + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "cam_cc_jpeg_clk_src"; + operating-points-v2 = <&jpeg_enc_opp_table>; + clock-cntl-level = "turbo"; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac52000{ + compatible = "qcom,cam_jpeg_dma_170"; + reg = <0x0 0xac52000 0x0 0x4000>; + reg-names = "jpegdma_hw"; + reg-cam-base = <0x52000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_jpeg_clk_src", + "cam_cc_jpeg_clk"; + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "cam_cc_jpeg_clk_src"; + operating-points-v2 = <&jpeg_dma_opp_table>; + clock-cntl-level = "turbo"; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy@ac65000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0x0ac65000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x65000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy@ac66000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0xac66000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x66000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy@ac67000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0xac67000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0x67000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <2>; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_lrme: qcom,lrme@ac6b000 { + compatible = "qcom,lrme"; + reg = <0x0 0xac6b000 0x0 0xa00>; + reg-names = "lrme"; + reg-cam-base = <0x6b000>; + interrupts = ; + interrupt-names = "lrme"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_LRME_CLK_SRC>, + <&camcc CAM_CC_LRME_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_lrme_clk_src", + "cam_cc_lrme_clk"; + clock-rates = <0 0 0 0 0 200000000 0>, + <0 0 0 0 0 216000000 0>, + <0 0 0 0 0 300000000 0>, + <0 0 0 0 0 404000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "cam_cc_lrme_clk_src"; + operating-points-v2 = <&lrme_opp_table>; + cam_hw_pid = <6 10>; + cell-index = <0>; + status = "okay"; + + lrme_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-216000000 { + opp-hz = /bits/ 64 <216000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@0x0ac6f000 { + compatible = "qcom,cam-bps"; + reg = <0x0 0xac6f000 0x0 0x3000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; + power-domains = <&camcc BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_AREG_CLK>, + <&camcc CAM_CC_BPS_AXI_CLK>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>; + clock-names = "cam_cc_bps_ahb_clk", + "cam_cc_bps_areg_clk", + "cam_cc_bps_axi_clk", + "cam_cc_bps_clk", + "cam_cc_bps_clk_src"; + clock-rates = <0 0 0 0 200000000>, + <0 0 0 0 360000000>, + <0 0 0 0 432000000>, + <0 0 0 0 480000000>, + <0 0 0 0 540000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + cam_hw_pid = <5 9>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@0x0ac87000 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac87000 0x0 0x3000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; + power-domains = <&camcc IPE_0_GDSC>; + clock-names = "cam_cc_ipe_0_ahb_clk", + "cam_cc_ipe_0_areg_clk", + "cam_cc_ipe_0_axi_clk", + "cam_cc_ipe_0_clk", + "cam_cc_ipe_0_clk_src"; + clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, + <&camcc CAM_CC_IPE_0_AREG_CLK>, + <&camcc CAM_CC_IPE_0_AXI_CLK>, + <&camcc CAM_CC_IPE_0_CLK>, + <&camcc CAM_CC_IPE_0_CLK_SRC>; + clock-rates = <0 0 0 0 240000000>, + <0 0 0 0 360000000>, + <0 0 0 0 432000000>, + <0 0 0 0 480000000>, + <0 0 0 0 540000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs","svs", "svs_l1", + "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ipe_0_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + cam_hw_pid = <4 8>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe0: qcom,vfe0@acaf000 { + compatible = "qcom,vfe170"; + reg = <0x0 0xacaf000 0x0 0x4000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0xaf000 0x42000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc IFE_0_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_0_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-names-option = "cam_cc_ife_0_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <600000000>; + cam_hw_pid = <1>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb3000 { + compatible = "qcom,csid170"; + reg = <0x0 0xacb3000 0x0 0x1000>; + reg-names = "csid0"; + reg-cam-base = <0xb3000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc IFE_0_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_0_csid_clk", + "cam_cc_ife_0_csid_clk_src", + "cam_cc_ife_0_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_0_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + operating-points-v2 = <&csid0_opp_table>; + src-clock-name = "cam_cc_ife_0_csid_clk_src"; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe1: qcom,vfe1@acb6000 { + compatible = "qcom,vfe170"; + reg = <0x0 0xacb6000 0x0 0x4000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0xb6000 0x42000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc IFE_1_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_1_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-names-option = "cam_cc_ife_1_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <600000000>; + cam_hw_pid = <2>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid1: qcom,csid1@acba000 { + compatible = "qcom,csid170"; + reg = <0x0 0xacba000 0x0 0x1000>; + reg-names = "csid1"; + reg-cam-base = <0xba000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc IFE_1_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_1_csid_clk", + "cam_cc_ife_1_csid_clk_src", + "cam_cc_ife_1_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_1_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ife_1_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe_lite: qcom,vfe-lite@acc4000 { + compatible = "qcom,vfe-lite170"; + reg = <0x0 0xacc4000 0x0 0x4000>; + reg-names = "ife-lite0"; + reg-cam-base = <0xc4000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0>, + <0 0 0 0 0 0 360000000 0>, + <0 0 0 0 0 0 432000000 0>, + <0 0 0 0 0 0 540000000 0>, + <0 0 0 0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + cam_hw_pid = <3>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid_lite: qcom,csid-lite@acc8000 { + compatible = "qcom,csid-lite170"; + reg = <0x0 0xacc8000 0x0 0x1000>; + reg-names = "csid-lite0"; + reg-cam-base = <0xc8000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", "jpegdma", + "jpegenc", "lrmecdm"; + status = "okay"; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + ipe0-mask = <0x1000>; + icp_pc_en; + status = "okay"; + }; + + cam_isp_mgr: qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + cam_jpeg_mgr: qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + cam_lrme_mgr: qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + arch-compat = "lrme"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_qcs615"; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + + msm-cam-icp-fw { + compatible = "qcom,msm-cam-smmu-fw-dev"; + label="icp"; + memory-region = <&pil_camera_mem>; + }; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0c00 0x0>; + cam-smmu-label = "cpas-cdm"; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0de2 0x0>, + <&apps_smmu 0x0c80 0x0>, + <&apps_smmu 0x0ca0 0x0>, + <&apps_smmu 0x0d00 0x0>, + <&apps_smmu 0x0d20 0x0>; + cam-smmu-label = "icp"; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 8MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x800000>; + iova-region-id = <0x0>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.3 GB */ + iova-region-name = "io"; + iova-region-start = <0x10C00000>; + iova-region-len = <0xCF300000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-qdss-region { + /* qdss region is approximately 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10B00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-secondary-heap { + /* Secondary heap region is 1MB long */ + iova-region-name = "secheap"; + iova-region-start = <0x10A00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x4>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is 150MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x9600000>; + iova-region-id = <0x1>; + iova-granularity = <0x15>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0820 0x40>, + <&apps_smmu 0x0840 0x00>, + <&apps_smmu 0x0860 0x40>; + cam-smmu-label = "ife"; + multiple-client-devices; + com,iommu-faults = "stall-disable", "non-fatal"; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0xd80 0x20>, + <&apps_smmu 0xda0 0x20>; + cam-smmu-label = "jpeg"; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-lrme { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0cc0 0x0>, + <&apps_smmu 0x0d40 0x0>; + cam-smmu-label = "lrme"; + + lrme_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "okay"; + }; + + /* IO region is approximately 3.3 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0xd800000>; + iova-region-len = <0xd2800000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio29"; + function = "gpio"; + }; + + config { + pins = "gpio29"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio37"; + function = "gpio"; + }; + + config { + pins = "gpio37"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio30"; + function = "cam_mclk"; + }; + + config { + pins = "gpio30"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio30"; + function = "cam_mclk"; + }; + + config { + pins = "gpio30"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio29"; + function = "gpio"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio37"; + function = "gpio"; + }; + + config { + pins = "gpio37"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + /* CLK, DATA */ + pins = "gpio33"; + function = "cci_i2c"; + }; + + config { + pins = "gpio33"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio33"; + function = "cci_i2c"; + }; + + config { + pins = "gpio33"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + /* CLK, DATA */ + pins = "gpio35"; + function = "cci_i2c"; + }; + + config { + pins = "gpio35"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio35"; + function = "cci_i2c"; + }; + + config { + pins = "gpio35"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + /* CLK, DATA */ + pins = "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio32"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio32"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + /* CLK, DATA */ + pins = "gpio34"; + function = "cci_i2c"; + }; + + config { + pins = "gpio34"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio34"; + function = "cci_i2c"; + }; + + config { + pins = "gpio34"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/talos-el2.dtso b/arch/arm64/boot/dts/qcom/talos-el2.dtso index f6818c058d724..08b5c9a537fb6 100644 --- a/arch/arm64/boot/dts/qcom/talos-el2.dtso +++ b/arch/arm64/boot/dts/qcom/talos-el2.dtso @@ -5,6 +5,8 @@ * Talos specific modifications required to boot in EL2. */ +#include + /dts-v1/; /plugin/; @@ -21,5 +23,6 @@ }; &venus { - status = "disabled"; + iommu-map = ; + status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso b/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso new file mode 100644 index 0000000000000..a40d8817a7a20 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "talos-camera.dtsi" +#include "talos-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi b/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi index 294354c034c37..6d2cff3cf23cc 100644 --- a/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-evk-som.dtsi @@ -317,6 +317,14 @@ status = "okay"; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcs615/a612_zap.mbn"; +}; + &i2c5 { clock-frequency = <400000>; status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/talos-staging.dtso b/arch/arm64/boot/dts/qcom/talos-staging.dtso new file mode 100644 index 0000000000000..04602073418d4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-staging.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Talos staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@6b0c000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x6b0c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index fb1bbc51bb8a4..2cef84842e383 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -580,7 +580,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -677,6 +677,11 @@ reg = <0x0 0x97715000 0x0 0x2000>; no-map; }; + + pil_camera_mem: pil-camera-region@97717000 { + reg = <0x0 0x97717000 0x0 0x800000>; + no-map; + }; }; soc: soc@0 { @@ -2090,6 +2095,8 @@ "iface"; power-domains = <&gpucc CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; stm@6002000 { @@ -2242,6 +2249,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss"; }; cti@6011000 { @@ -2250,6 +2258,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_1"; }; cti@6012000 { @@ -2258,6 +2267,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_2"; }; cti@6013000 { @@ -2266,6 +2276,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_3"; }; cti@6014000 { @@ -2274,6 +2285,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_4"; }; cti@6015000 { @@ -2282,6 +2294,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_5"; }; cti@6016000 { @@ -2290,6 +2303,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_6"; }; cti@6017000 { @@ -2298,6 +2312,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_7"; }; cti@6018000 { @@ -2306,6 +2321,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_8"; }; cti@6019000 { @@ -2314,6 +2330,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_9"; }; cti@601a000 { @@ -2322,6 +2339,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_10"; }; cti@601b000 { @@ -2330,6 +2348,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_11"; }; cti@601c000 { @@ -2338,6 +2357,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_12"; }; cti@601d000 { @@ -2346,6 +2366,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_13"; }; cti@601e000 { @@ -2354,6 +2375,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_14"; }; cti@601f000 { @@ -2362,6 +2384,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdss_15"; }; funnel@6041000 { @@ -2594,6 +2617,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_qdsp6"; }; tpdm@6840000 { @@ -2602,6 +2626,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_vsense"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -2622,6 +2647,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_prng"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -2641,6 +2667,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_pimem"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -2662,6 +2689,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_cdsp"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2705,6 +2733,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_cdsp"; }; tpdm@6870000 { @@ -2713,6 +2742,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_dcc"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -2733,6 +2763,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_wcss"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -2755,6 +2786,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_monaq"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2798,6 +2830,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_qm"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2818,6 +2851,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_ddr"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2838,6 +2872,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl0"; }; cti@6a03000 { @@ -2846,6 +2881,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl0_1"; }; cti@6a10000 { @@ -2854,6 +2890,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl1"; }; cti@6a11000 { @@ -2862,6 +2899,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_ddr_dl1_1"; }; funnel@6a05000 { @@ -2932,6 +2970,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_0"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -2952,6 +2991,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_swao_1"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -2972,6 +3012,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao"; }; cti@6b05000 { @@ -2980,6 +3021,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_1"; }; cti@6b06000 { @@ -2988,6 +3030,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_2"; }; cti@6b07000 { @@ -2996,6 +3039,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_swao_3"; }; funnel@6b08000 { @@ -3102,6 +3146,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_aop_m3"; }; tpdm@6b48000 { @@ -3110,6 +3155,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_west"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3129,6 +3175,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_titan"; /* Not all required clocks can be enabled from the OS */ status = "fail"; @@ -3140,6 +3187,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_venus"; status = "disabled"; }; @@ -3149,6 +3197,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_center"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3168,6 +3217,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_dlct"; }; cti@6c2a000 { @@ -3176,6 +3226,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_dlct_1"; }; cti@7020000 { @@ -3184,6 +3235,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_2"; }; etm@7040000 { @@ -3212,6 +3264,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_3"; }; etm@7140000 { @@ -3240,6 +3293,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_4"; }; etm@7240000 { @@ -3268,6 +3322,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_5"; }; etm@7340000 { @@ -3296,6 +3351,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_6"; }; etm@7440000 { @@ -3324,6 +3380,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_7"; }; etm@7540000 { @@ -3352,6 +3409,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_8"; }; etm@7640000 { @@ -3380,6 +3438,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_apb_9"; }; etm@7740000 { @@ -3554,6 +3613,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_olc"; qcom,cmb-element-bits = <64>; qcom,cmb-msrs-num = <32>; @@ -3597,6 +3657,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_apss"; qcom,dsb-element-bits = <32>; qcom,dsb-msrs-num = <32>; @@ -3640,6 +3701,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_silver"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3659,6 +3721,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "tpdm_llm_gold"; qcom,cmb-element-bits = <32>; qcom,cmb-msrs-num = <32>; @@ -3726,6 +3789,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss"; }; cti@78f0000 { @@ -3734,6 +3798,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_1"; }; cti@7900000 { @@ -3742,6 +3807,7 @@ clocks = <&aoss_qmp>; clock-names = "apb_pclk"; + label = "cti_apss_2"; }; remoteproc_cdsp: remoteproc@8300000 { @@ -3772,6 +3838,9 @@ qcom,smem-states = <&cdsp_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <2>; + tmd-names = "cdsp_sw"; + status = "disabled"; glink-edge { @@ -5425,15 +5494,31 @@ }; q6-hvx-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens0 10>; trips { + q6_hvx_alert0: trip-point0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + q6-hvx-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&q6_hvx_alert0>; + cooling-device = <&remoteproc_cdsp THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; }; mdm-core-thermal { diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index a9c5c523575ee..818475cee571f 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -897,12 +898,101 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; }; &gpu { status = "okay"; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&ov08x40_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov08x40"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam_rgb_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov08x40_ep: endpoint { + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; @@ -1074,6 +1164,16 @@ #phy-cells = <0>; }; + + embedded-controller@76 { + compatible = "qcom,hamoa-crd-ec"; + reg = <0x76>; + + interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&ec_int_n_default>; + pinctrl-names = "default"; + }; }; &i2c7 { @@ -1523,6 +1623,28 @@ <44 4>, /* SPI (TPM) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + + ec_int_n_default: ec-int-n-state { + pins = "gpio66"; + function = "gpio"; + bias-disable; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi index db291730130c7..58d390fe3af88 100644 --- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "hamoa-pmics.dtsi" @@ -792,6 +793,66 @@ }; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02e10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@10 { + compatible = "ovti,ov02e10"; + reg = <0x10>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_cam_1p8>; + + port { + ov02e10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <360000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; diff --git a/arch/arm64/boot/dts/qcom/x1-el2.dtso b/arch/arm64/boot/dts/qcom/x1-el2.dtso index ee006742d6f3b..8bbe5e61402b0 100644 --- a/arch/arm64/boot/dts/qcom/x1-el2.dtso +++ b/arch/arm64/boot/dts/qcom/x1-el2.dtso @@ -17,8 +17,10 @@ }; &iris { - /* TODO: Add video-firmware iommus to start IRIS from EL2 */ - status = "disabled"; + status = "okay"; + video-firmware { + iommus = <&apps_smmu 0x1942 0x0>; + }; }; /* diff --git a/arch/arm64/boot/dts/qcom/x1-staging.dtsi b/arch/arm64/boot/dts/qcom/x1-staging.dtsi new file mode 100644 index 0000000000000..24dfda988bd9d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1-staging.dtsi @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Shared X1 staging device tree modifications. + */ + +#include + +&soc { + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; + +&remoteproc_cdsp { + cooling { + compatible = "qcom,qmi-cooling-cdsp"; + + cdsp_tmd0: cdsp-tmd0 { + label = "cdsp_sw"; + #cooling-cells = <2>; + }; + }; +}; + +&thermal_nsp0 { + trips { + nsp0_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp1 { + trips { + nsp1_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp2 { + trips { + nsp2_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp3 { + trips { + nsp3_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 5d49df41be02a..8ca7294187dfe 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -562,6 +563,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; @@ -805,6 +813,118 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; + +}; + +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02c10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7m_2p8>; + dvdd-supply = <&vreg_l2m_1p2>; + dovdd-supply = <&vreg_l4m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; }; &gpu { @@ -1388,6 +1508,22 @@ <72 2>, /* Secure EC I2C connection (?) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index beb1475d7fa0c..06300d21223fb 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -7,6 +7,7 @@ #include #include +#include #include #include "hamoa.dtsi" @@ -552,6 +553,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; @@ -795,6 +803,57 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; }; &gpu { @@ -805,6 +864,66 @@ firmware-name = "qcom/x1e80100/LENOVO/83ED/qcdxkmsuc8380.mbn"; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02c10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l1m_1p2>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; @@ -1352,6 +1471,22 @@ <44 4>, /* SPI (TPM) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 654a102cb5bc5..6d070683e0298 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -108,6 +108,7 @@ CONFIG_ARM_IMX_CPUFREQ_DT=m CONFIG_ARM_MEDIATEK_CPUFREQ=y CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y CONFIG_ARM_QCOM_CPUFREQ_HW=y +CONFIG_CLK_SHIKRA_AUDIOCORECC=m CONFIG_ARM_RASPBERRYPI_CPUFREQ=m CONFIG_ARM_SCMI_CPUFREQ=y CONFIG_ARM_TEGRA186_CPUFREQ=y @@ -339,6 +340,10 @@ CONFIG_PATA_PLATFORM=y CONFIG_PATA_OF_PLATFORM=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y CONFIG_BLK_DEV_DM=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m @@ -521,6 +526,7 @@ CONFIG_WLCORE_SDIO=m CONFIG_WWAN=m CONFIG_MHI_WWAN_CTRL=m CONFIG_MHI_WWAN_MBIM=m +CONFIG_QCOM_BAM_DMUX=m CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_ADC=m CONFIG_KEYBOARD_GPIO=y @@ -961,7 +967,9 @@ CONFIG_DRM_FSL_LDB=m CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_ITE_IT6263=m CONFIG_DRM_LONTIUM_LT8912B=m +CONFIG_DRM_LONTIUM_LT9211=m CONFIG_DRM_LONTIUM_LT9611=m +CONFIG_DRM_LONTIUM_LT9611C=m CONFIG_DRM_LONTIUM_LT9611UXC=m CONFIG_DRM_LONTIUM_LT8713SX=m CONFIG_DRM_ITE_IT66121=m @@ -1007,6 +1015,7 @@ CONFIG_DRM_MXSFB=m CONFIG_DRM_IMX_LCDIF=m CONFIG_DRM_NOUVEAU=m CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m +CONFIG_DRM_PANEL_DLC0697=m CONFIG_DRM_PANEL_LVDS=m CONFIG_DRM_PANEL_HIMAX_HX8279=m CONFIG_DRM_PANEL_HIMAX_HX83112A=m @@ -1096,6 +1105,8 @@ CONFIG_SND_MESON_AXG_SOUND_CARD=m CONFIG_SND_MESON_GX_SOUND_CARD=m CONFIG_SND_SOC_QCOM=m CONFIG_SND_SOC_APQ8016_SBC=m +CONFIG_SND_SOC_PM4125=m +CONFIG_SND_SOC_PM4125_SDW=m CONFIG_SND_SOC_QDSP6_USB=m CONFIG_SND_SOC_MSM8996=m CONFIG_SND_SOC_SDM845=m @@ -1132,6 +1143,7 @@ CONFIG_SND_SOC_TEGRA210_AMX=m CONFIG_SND_SOC_TEGRA210_ADX=m CONFIG_SND_SOC_TEGRA210_MIXER=m CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=m +CONFIG_SND_SOC_DMIC=m CONFIG_SND_SOC_J721E_EVM=m CONFIG_SND_SOC_XILINX_I2S=m CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=m @@ -1152,6 +1164,8 @@ CONFIG_SND_SOC_GTM601=m CONFIG_SND_SOC_MAX98090=m CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m +CONFIG_SND_SOC_PM4125_SDW=m +CONFIG_SND_SOC_PCM3168A_I2C=m CONFIG_SND_SOC_RK3308=m CONFIG_SND_SOC_RK817=m CONFIG_SND_SOC_RT5640=m @@ -1174,6 +1188,7 @@ CONFIG_SND_SOC_WM8978=m CONFIG_SND_SOC_WSA881X=m CONFIG_SND_SOC_WSA883X=m CONFIG_SND_SOC_WSA884X=m +CONFIG_SND_SOC_WSA885X_I2C=m CONFIG_SND_SOC_NAU8822=m CONFIG_SND_SOC_LPASS_WSA_MACRO=m CONFIG_SND_SOC_LPASS_VA_MACRO=m @@ -1426,6 +1441,7 @@ CONFIG_EC_HUAWEI_GAOKUN=m CONFIG_EC_LENOVO_YOGA_C630=m CONFIG_EC_LENOVO_THINKPAD_T14S=m CONFIG_COMMON_CLK_APPLE_NCO=m +CONFIG_EC_QCOM_HAMOA=m CONFIG_COMMON_CLK_RK808=y CONFIG_COMMON_CLK_SCMI=y CONFIG_COMMON_CLK_SCPI=y @@ -1446,6 +1462,9 @@ CONFIG_CLK_IMX8QXP=y CONFIG_CLK_IMX8ULP=y CONFIG_CLK_IMX93=y CONFIG_CLK_IMX95_BLK_CTL=y +CONFIG_CLK_SHIKRA_DISPCC=y +CONFIG_CLK_SHIKRA_GCC=y +CONFIG_CLK_SHIKRA_GPUCC=y CONFIG_TI_SCI_CLK=y CONFIG_COMMON_CLK_MT8192_AUDSYS=y CONFIG_COMMON_CLK_MT8192_CAMSYS=y @@ -1460,12 +1479,18 @@ CONFIG_COMMON_CLK_MT8192_SCP_ADSP=y CONFIG_COMMON_CLK_MT8192_VDECSYS=y CONFIG_COMMON_CLK_MT8192_VENCSYS=y CONFIG_COMMON_CLK_QCOM=y +CONFIG_CLK_ELIZA_CAMCC=m CONFIG_CLK_ELIZA_DISPCC=m CONFIG_CLK_ELIZA_GCC=y +CONFIG_CLK_ELIZA_GPUCC=m CONFIG_CLK_ELIZA_TCSRCC=m +CONFIG_CLK_ELIZA_VIDEOCC=m +CONFIG_CLK_GLYMUR_CAMCC=m CONFIG_CLK_GLYMUR_DISPCC=m CONFIG_CLK_GLYMUR_GCC=y +CONFIG_CLK_GLYMUR_GPUCC=m CONFIG_CLK_GLYMUR_TCSRCC=m +CONFIG_CLK_GLYMUR_VIDEOCC=m CONFIG_CLK_KAANAPALI_CAMCC=m CONFIG_CLK_KAANAPALI_DISPCC=m CONFIG_CLK_KAANAPALI_GCC=y @@ -1477,7 +1502,9 @@ CONFIG_CLK_X1E80100_DISPCC=m CONFIG_CLK_X1E80100_GCC=y CONFIG_CLK_X1E80100_GPUCC=m CONFIG_CLK_X1E80100_TCSRCC=y +CONFIG_CLK_X1P42100_CAMCC=m CONFIG_CLK_X1P42100_GPUCC=m +CONFIG_CLK_X1P42100_VIDEOCC=m CONFIG_CLK_QCM2290_GPUCC=m CONFIG_QCOM_A53PLL=y CONFIG_QCOM_CLK_APCS_MSM8916=y @@ -1568,6 +1595,7 @@ CONFIG_SM_GPUCC_8450=m CONFIG_SM_GPUCC_8550=m CONFIG_SM_GPUCC_8650=m CONFIG_SM_GPUCC_8750=m +CONFIG_SM_LPASSCC_6115=m CONFIG_SM_TCSRCC_8550=y CONFIG_SM_TCSRCC_8650=y CONFIG_SM_TCSRCC_8750=m @@ -1878,6 +1906,7 @@ CONFIG_INTERCONNECT_QCOM_SC8180X=y CONFIG_INTERCONNECT_QCOM_SC8280XP=y CONFIG_INTERCONNECT_QCOM_SDM845=y CONFIG_INTERCONNECT_QCOM_SDX75=y +CONFIG_INTERCONNECT_QCOM_SHIKRA=y CONFIG_INTERCONNECT_QCOM_SM6115=y CONFIG_INTERCONNECT_QCOM_SM6350=y CONFIG_INTERCONNECT_QCOM_MILOS=y diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config new file mode 100644 index 0000000000000..40665245e406f --- /dev/null +++ b/arch/arm64/configs/prune.config @@ -0,0 +1,400 @@ +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AIROHA is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BCMBCA is not set +# CONFIG_ARCH_BRCMSTB is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_BLAIZE is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SPARX5 is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_KEEMBAY is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_NXP is not set +# CONFIG_ARCH_MA35 is not set +# CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_INTEL_SOCFPGA is not set +# CONFIG_ARCH_STM32 is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_TESLA_FSD is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VISCONTI is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set +# CONFIG_MOUSE_PS2 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VSOCKETS_LOOPBACK is not set +# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set +# CONFIG_NET_DSA_TAG_OCELOT is not set +# CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set +# CONFIG_BT_HCIBTUSB_MTK is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIUART_MRVL is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_MRVL_SDIO is not set +# CONFIG_PCIE_ALTERA is not set +# CONFIG_PCIE_ALTERA_MSI is not set +# CONFIG_PCI_HOST_THUNDER_PEM is not set +# CONFIG_PCI_HOST_THUNDER_ECAM is not set +# CONFIG_PCI_XGENE is not set +# CONFIG_PCI_MESON is not set +# CONFIG_PCI_HISI is not set +# CONFIG_PCIE_KIRIN is not set +# CONFIG_BRCMSTB_GISB_ARB is not set +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_GNSS_MTK_SERIAL is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_BRCMNAND_BCMBCA is not set +# CONFIG_MTD_NAND_BRCMNAND_BRCMSTB is not set +# CONFIG_MTD_NAND_BRCMNAND_IPROC is not set +# CONFIG_B53_SRAB_DRIVER is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_MACB is not set +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HNS3 is not set +# CONFIG_HNS3_HCLGE is not set +# CONFIG_HNS3_ENET is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGBVF is not set +# CONFIG_MVMDIO is not set +# CONFIG_SKY2 is not set +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLX5_CORE_EN is not set +# CONFIG_R8169 is not set +# CONFIG_SMC91X is not set +# CONFIG_SMSC911X is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_DP83TD510_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_CAN_FLEXCAN is not set +# CONFIG_CAN_MCP251XFD is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_LAN78XX is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_BRCMFMAC is not set +# CONFIG_MWIFIEX is not set +# CONFIG_MWIFIEX_SDIO is not set +# CONFIG_MWIFIEX_PCIE is not set +# CONFIG_MT7921E is not set +# CONFIG_WL18XX is not set +# CONFIG_WLCORE_SDIO is not set +# CONFIG_KEYBOARD_CROS_EC is not set +# CONFIG_KEYBOARD_MTK_PMIC is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_INPUT_TPS65219_PWRBUTTON is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_XILINX_PS_UART_CONSOLE is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_FSL_LPUART_CONSOLE is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE is not set +# CONFIG_TCG_TIS_SPI_CR50 is not set +# CONFIG_TCG_TIS_I2C_CR50 is not set +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_CROS_EC_TUNNEL is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_DW_DMA is not set +# CONFIG_SPI_DW_MMIO is not set +# CONFIG_PINCTRL_MAX77620 is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_MB86S7X is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_BD9571MWV is not set +# CONFIG_GPIO_MAX77620 is not set +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MT6360 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_PM8916_WATCHDOG is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MT6360 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_RK8XX_I2C is not set +# CONFIG_MFD_RK8XX_SPI is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_TPS65219 is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_REGULATOR_AXP20X is not set +# CONFIG_REGULATOR_BD718XX is not set +# CONFIG_REGULATOR_BD9571MWV is not set +# CONFIG_REGULATOR_CROS_EC is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_HI6421V530 is not set +# CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MP8859 is not set +# CONFIG_REGULATOR_MT6315 is not set +# CONFIG_REGULATOR_MT6357 is not set +# CONFIG_REGULATOR_MT6358 is not set +# CONFIG_REGULATOR_MT6359 is not set +# CONFIG_REGULATOR_MT6360 is not set +# CONFIG_REGULATOR_MT6397 is not set +# CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF8X00 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_RK808 is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS65219 is not set +# CONFIG_REGULATOR_RK808 is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS65219 is not set +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_IMX412 is not set +# CONFIG_VIDEO_OV5640 is not set +# CONFIG_VIDEO_OV5645 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_KOMEDA is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_SAMSUNG_DSIM is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_ADV7511_AUDIO is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_AUDMIX is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_FSL_MICFIL is not set +# CONFIG_SND_SOC_FSL_EASRC is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_DA7213 is not set +# CONFIG_SND_SOC_DMIC is not set +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_RT5659 is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIMPLE_MUX is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8524 is not set +# CONFIG_SND_SOC_WM8904 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_MT6358 is not set +# CONFIG_SND_SOC_NAU8822 is not set +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CDNS3_GADGET is not set +# CONFIG_USB_CDNS3_HOST is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_CHIPIDEA_UDC is not set +# CONFIG_USB_CHIPIDEA_HOST is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_TYPEC_FUSB302 is not set +# CONFIG_UCSI_CCG is not set +# CONFIG_TYPEC_TPS6598X is not set +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_MMC_SDHCI_AM654 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX77686 is not set +# CONFIG_RTC_DRV_RK808 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_S5M is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_CROS_EC is not set +# CONFIG_RTC_DRV_MT6397 is not set +# CONFIG_BCM_SBA_RAID is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_MV_XOR_V2 is not set +# CONFIG_VIDEO_MAX96712 is not set +# CONFIG_CHROME_PLATFORMS is not set +# CONFIG_CROS_EC is not set +# CONFIG_CROS_EC_I2C is not set +# CONFIG_CROS_EC_RPMSG is not set +# CONFIG_CROS_EC_SPI is not set +# CONFIG_CROS_EC_CHARDEV is not set +# CONFIG_CLK_VEXPRESS_OSC is not set +# CONFIG_COMMON_CLK_RK808 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_COMMON_CLK_S2MPS11 is not set +# CONFIG_COMMON_CLK_XGENE is not set +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_BD718XX is not set +# CONFIG_SOC_TI is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_USBC_CROS_EC is not set +# CONFIG_MAX9611 is not set +# CONFIG_TI_ADS1015 is not set +# CONFIG_TI_AM335X_ADC is not set +# CONFIG_IIO_CROS_EC_SENSORS_CORE is not set +# CONFIG_IIO_CROS_EC_SENSORS is not set +# CONFIG_IIO_ST_LSM6DSX is not set +# CONFIG_IIO_CROS_EC_LIGHT_PROX is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_VCNL4000 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set +# CONFIG_IIO_CROS_EC_BARO is not set +# CONFIG_MPL3115 is not set +# CONFIG_PWM_CROS_EC is not set +# CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set +# CONFIG_CRYPTO_DEV_HISI_SEC2 is not set +# CONFIG_CRYPTO_DEV_HISI_ZIP is not set +# CONFIG_CRYPTO_DEV_HISI_HPRE is not set +# CONFIG_CRYPTO_DEV_HISI_TRNG is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set +# CONFIG_DEVMEM is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DEVELOP is not set +# CONFIG_SECURITY_SELINUX_AVC_STATS is not set +# CONFIG_AUDIT_GENERIC is not set +# CONFIG_EFI_DISABLE_RUNTIME is not set +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_ARM_SMMU_MMU_500_CPRE_ERRATA is not set diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config new file mode 100644 index 0000000000000..b286309f0c251 --- /dev/null +++ b/arch/arm64/configs/qcom.config @@ -0,0 +1,142 @@ +# qcom.config for Qualcomm-specific kernel configuration +# +# $ make ARCH=arm64 defconfig qcom.config +# +# Keep alphabetically sorted +CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CMA=y +CONFIG_CONNECTOR=y +CONFIG_CORESIGHT_TNOC=m +CONFIG_CORESIGHT_CTCU=m +CONFIG_CORESIGHT_DUMMY=m +CONFIG_CORESIGHT_CTCU=m +CONFIG_CORESIGHT_SOURCE_ETM4X=m +CONFIG_CORESIGHT_TPDM=m +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_GOV_TEO=y +CONFIG_CPU_IDLE_THERMAL=y +# CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DEBUG_INFO_BTF=y +CONFIG_DEBUG_INFO_BTF_MODULES=y +# CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set +CONFIG_DMA_CMA=y +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT=60 +CONFIG_EDAC_QCOM=m +CONFIG_EXPERT=y +CONFIG_FW_LOADER_COMPRESS=y +CONFIG_FW_LOADER_COMPRESS_ZSTD=y +CONFIG_GUNYAH_WATCHDOG=y +CONFIG_I2C_QCOM_GENI=y +CONFIG_I6300ESB_WDT=y +CONFIG_IDLE_INJECT=y +CONFIG_INPUT_UINPUT=y +CONFIG_IXGBE=m +CONFIG_IXGBEVF=m +CONFIG_KPROBES=y +CONFIG_MACVLAN=y +CONFIG_MACVTAP=y +CONFIG_NL80211_TESTMODE=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM=y +CONFIG_POWERCAP=y +CONFIG_PROC_EVENTS=y +CONFIG_QCA808X_PHY=m +CONFIG_QCOM_QMI_COOLING=y +CONFIG_QCOM_SPEL=m +CONFIG_QCOM_TGU=m +CONFIG_REMOTEPROC_THERMAL=y +CONFIG_SCHED_CLASS_EXT=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_SYS_T=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_FTRACE=m +CONFIG_STM_SOURCE_HEARTBEAT=m +CONFIG_SENSORS_AMC6821=y +CONFIG_SENSORS_EMC2305=y +CONFIG_SENSORS_QCOM_BCL=y +CONFIG_SWIOTLB_DYNAMIC=y +CONFIG_TRACE_MMIO_ACCESS=y +CONFIG_UCLAMP_TASK_GROUP=y +CONFIG_UCLAMP_TASK=y +CONFIG_UHID=m +CONFIG_USB_CONFIGFS_F_UVC=y +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_VCPU_STALL_DETECTOR=y +CONFIG_VHOST_NET=y +CONFIG_VHOST_VSOCK=y +CONFIG_VSOCKETS=y +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VSOCKETS_LOOPBACK is not set +# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_SYSFS=y +CONFIG_ZRAM=y +CONFIG_ZRAM_BACKEND_LZ4=y + +# Kubernetes support +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_FAVOR_DYNMODS=y +CONFIG_IPC_NS=y +CONFIG_NAMESPACES=y +CONFIG_NET_NS=y +CONFIG_PID_NS=y +CONFIG_UTS_NS=y + +# Support Crypto api +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_AEAD=y + +# Support ICE/UFS crypto driver +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_MMC_CRYPTO=y +CONFIG_FS_ENCRYPTION=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=m +CONFIG_BLK_DEV_BSG=y +# +# SCSI Transports +# +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_SMARTPQI=m + +# Support performance profiling +CONFIG_FTRACE=y + +# QCOM SCMI memlat bus scaling +CONFIG_QCOM_SCMI_GENERIC_EXT=y +CONFIG_DEVFREQ_GOV_REMOTE=y +CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ=m + +# GPU Virtualization support +CONFIG_DRM_VIRTIO_GPU=m +CONFIG_DRM_VIRTIO_GPU_KMS=m diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config new file mode 100644 index 0000000000000..1399972795b68 --- /dev/null +++ b/arch/arm64/configs/qcom_debug.config @@ -0,0 +1,4 @@ +CONFIG_QCOM_DCC=y +CONFIG_QCOM_DCC_DEV=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_MEMORY_DUMP_DEV=y diff --git a/arch/arm64/configs/rt.config b/arch/arm64/configs/rt.config new file mode 100644 index 0000000000000..ca92615d38a17 --- /dev/null +++ b/arch/arm64/configs/rt.config @@ -0,0 +1,3 @@ +# rt.config for Real time kernel features +CONFIG_EXPERT=y +CONFIG_PREEMPT_RT=y diff --git a/arch/arm64/include/asm/arm-cmn.h b/arch/arm64/include/asm/arm-cmn.h new file mode 100644 index 0000000000000..1b9f506797944 --- /dev/null +++ b/arch/arm64/include/asm/arm-cmn.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2015 ARM Ltd. + */ +#ifndef __ASM_ARM_CMN_H +#define __ASM_ARM_CMN_H + +#include + +/* Common register stuff */ +#define CMN_NODE_INFO 0x0000 +#define CMN_NI_NODE_TYPE GENMASK_ULL(15, 0) +#define CMN_NI_NODE_ID GENMASK_ULL(31, 16) +#define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32) + +enum cmn_node_type { + CMN_TYPE_INVALID, + CMN_TYPE_DVM, + CMN_TYPE_CFG, + CMN_TYPE_DTC, + CMN_TYPE_HNI, + CMN_TYPE_HNF, + CMN_TYPE_XP, + CMN_TYPE_SBSX, + CMN_TYPE_MPAM_S, + CMN_TYPE_MPAM_NS, + CMN_TYPE_RNI, + CMN_TYPE_RND = 0xd, + CMN_TYPE_RNSAM = 0xf, + CMN_TYPE_MTSX, + CMN_TYPE_HNP, + CMN_TYPE_CXRA = 0x100, + CMN_TYPE_CXHA, + CMN_TYPE_CXLA, + CMN_TYPE_CCRA, + CMN_TYPE_CCHA, + CMN_TYPE_CCLA, + CMN_TYPE_CCLA_RNI, + CMN_TYPE_HNS = 0x200, + CMN_TYPE_HNS_MPAM_S, + CMN_TYPE_HNS_MPAM_NS, + CMN_TYPE_APB = 0x1000, + /* Not a real node type */ + CMN_TYPE_WP = 0x7770 +}; + +#endif /* __ASM_ARM_CMN_H */ diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h new file mode 100644 index 0000000000000..02cf15278d9ff --- /dev/null +++ b/arch/arm64/include/asm/ras.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_RAS_H +#define __ASM_RAS_H + +#include +#include + +/* ERRFR */ +#define ERR_FR_CE GENMASK_ULL(54, 53) +#define ERR_FR_RP BIT(15) +#define ERR_FR_CEC GENMASK_ULL(14, 12) + +#define ERR_FR_RP_SINGLE_COUNTER 0 +#define ERR_FR_RP_DOUBLE_COUNTER 1 + +#define ERR_FR_CEC_0B_COUNTER 0 +#define ERR_FR_CEC_8B_COUNTER BIT(1) +#define ERR_FR_CEC_16B_COUNTER BIT(2) + +/* ERRMISC0 */ + +/* ERRFR.CEC == 0b010, ERRFR.RP == 0 */ +#define ERR_MISC0_8B_OF BIT(39) +#define ERR_MISC0_8B_CEC GENMASK_ULL(38, 32) + +/* ERRFR.CEC == 0b100, ERRFR.RP == 0 */ +#define ERR_MISC0_16B_OF BIT(47) +#define ERR_MISC0_16B_CEC GENMASK_ULL(46, 32) + +#define ERR_MISC0_CEC_SHIFT 31 + +#define ERR_8B_CEC_MAX (ERR_MISC0_8B_CEC >> ERR_MISC0_CEC_SHIFT) +#define ERR_16B_CEC_MAX (ERR_MISC0_16B_CEC >> ERR_MISC0_CEC_SHIFT) + +/* ERRFR.CEC == 0b100, ERRFR.RP == 1 */ +#define ERR_MISC0_16B_OFO BIT(63) +#define ERR_MISC0_16B_CECO GENMASK_ULL(62, 48) +#define ERR_MISC0_16B_OFR BIT(47) +#define ERR_MISC0_16B_CECR GENMASK_ULL(46, 32) + +/* ERRSTATUS */ +#define ERR_STATUS_AV BIT(31) +#define ERR_STATUS_V BIT(30) +#define ERR_STATUS_UE BIT(29) +#define ERR_STATUS_ER BIT(28) +#define ERR_STATUS_OF BIT(27) +#define ERR_STATUS_MV BIT(26) +#define ERR_STATUS_CE (BIT(25) | BIT(24)) +#define ERR_STATUS_DE BIT(23) +#define ERR_STATUS_PN BIT(22) +#define ERR_STATUS_UET (BIT(21) | BIT(20)) +#define ERR_STATUS_CI BIT(19) +#define ERR_STATUS_IERR GENMASK_ULL(15, 8) +#define ERR_STATUS_SERR GENMASK_ULL(7, 0) + +/* Theses bits are write-one-to-clear */ +#define ERR_STATUS_W1TC \ + (ERR_STATUS_AV | ERR_STATUS_V | ERR_STATUS_UE | ERR_STATUS_ER | \ + ERR_STATUS_OF | ERR_STATUS_MV | ERR_STATUS_CE | ERR_STATUS_DE | \ + ERR_STATUS_PN | ERR_STATUS_UET | ERR_STATUS_CI) + +#define ERR_STATUS_UET_UC 0 +#define ERR_STATUS_UET_UEU 1 +#define ERR_STATUS_UET_UEO 2 +#define ERR_STATUS_UET_UER 3 + +/* ERRADDR */ +#define ERR_ADDR_AI BIT(61) +#define ERR_ADDR_PADDR GENMASK_ULL(55, 0) + +/* ERRCTLR */ +#define ERR_CTLR_CFI BIT(8) +#define ERR_CTLR_FI BIT(3) +#define ERR_CTLR_UI BIT(2) + +/* ERRDEVARCH */ +#define ERRDEVARCH_REV GENMASK(19, 16) + +enum ras_ce_threshold { + RAS_CE_THRESHOLD_0B, + RAS_CE_THRESHOLD_8B, + RAS_CE_THRESHOLD_16B, + RAS_CE_THRESHOLD_32B, + UNKNOWN, +}; + +struct ras_ext_regs { + u64 err_fr; + u64 err_ctlr; + u64 err_status; + u64 err_addr; + u64 err_misc[4]; +}; + +#endif /* __ASM_RAS_H */ diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 97987f850a33c..38de7ab5ddf76 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -48,6 +48,7 @@ #include #include #include +#include /* * We need to be able to catch inadvertent references to memstart_addr @@ -324,6 +325,9 @@ void __init bootmem_init(void) * reserved, so do it here. */ arch_reserve_crashkernel(); +#if defined(CONFIG_QCOM_MEMORY_DUMP_V2) + reserve_memdump_cma(); +#endif memblock_dump_all(); } diff --git a/drivers/Makefile b/drivers/Makefile index 0841ea851847e..6a2cbe5b340f5 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -176,6 +176,7 @@ obj-$(CONFIG_RAS) += ras/ obj-$(CONFIG_USB4) += thunderbolt/ obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/ obj-y += hwtracing/intel_th/ +obj-y += hwtracing/qcom/ obj-$(CONFIG_STM) += hwtracing/stm/ obj-$(CONFIG_HISI_PTT) += hwtracing/ptt/ obj-y += android/ diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig index f2fd79f22e7d8..52df190356c82 100644 --- a/drivers/acpi/arm64/Kconfig +++ b/drivers/acpi/arm64/Kconfig @@ -24,3 +24,14 @@ config ACPI_APMT config ACPI_MPAM bool + +config ACPI_AEST + bool "ARM Error Source Table Support" + depends on ARM64_RAS_EXTN + + help + The Arm Error Source Table (AEST) provides details on ACPI + extensions that enable kernel-first handling of errors in a + system that supports the Armv8 RAS extensions. + + If set, the kernel will report and log hardware errors. diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile index 9390b57cb5648..bad77fdbf8dd0 100644 --- a/drivers/acpi/arm64/Makefile +++ b/drivers/acpi/arm64/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_ACPI_IORT) += iort.o obj-$(CONFIG_ACPI_MPAM) += mpam.o obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o obj-$(CONFIG_ARM_AMBA) += amba.o +obj-$(CONFIG_ACPI_AEST) += aest.o obj-y += dma.o init.o obj-y += thermal_cpufreq.o diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c new file mode 100644 index 0000000000000..b8359b95f40f9 --- /dev/null +++ b/drivers/acpi/arm64/aest.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include +#include + +#include "init.h" + +#undef pr_fmt +#define pr_fmt(fmt) "ACPI AEST: " fmt + +static struct xarray *aest_array; + +static void __init aest_init_interface(struct acpi_aest_hdr *hdr, + struct acpi_aest_node *node) +{ + struct acpi_aest_node_interface_header *interface; + + interface = ACPI_ADD_PTR(struct acpi_aest_node_interface_header, hdr, + hdr->node_interface_offset); + + node->type = hdr->type; + node->interface_hdr = interface; + + switch (interface->group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: { + struct acpi_aest_node_interface_4k *interface_4k = + (struct acpi_aest_node_interface_4k *)(interface + 1); + + node->common = &interface_4k->common; + node->record_implemented = + (unsigned long *)&interface_4k->error_record_implemented; + node->status_reporting = + (unsigned long *)&interface_4k->error_status_reporting; + node->addressing_mode = + (unsigned long *)&interface_4k->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_16K: { + struct acpi_aest_node_interface_16k *interface_16k = + (struct acpi_aest_node_interface_16k *)(interface + 1); + + node->common = &interface_16k->common; + node->record_implemented = + (unsigned long *)interface_16k->error_record_implemented; + node->status_reporting = + (unsigned long *)interface_16k->error_status_reporting; + node->addressing_mode = + (unsigned long *)interface_16k->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_64K: { + struct acpi_aest_node_interface_64k *interface_64k = + (struct acpi_aest_node_interface_64k *)(interface + 1); + + node->common = &interface_64k->common; + node->record_implemented = + (unsigned long *)interface_64k->error_record_implemented; + node->status_reporting = + (unsigned long *)interface_64k->error_status_reporting; + node->addressing_mode = + (unsigned long *)interface_64k->addressing_mode; + break; + } + default: + pr_err("invalid group format: %d\n", interface->group_format); + } + + node->interrupt = ACPI_ADD_PTR(struct acpi_aest_node_interrupt_v2, hdr, + hdr->node_interrupt_offset); + + node->interrupt_count = hdr->node_interrupt_count; +} + +static struct aest_hnode *__init +acpi_aest_alloc_ahnode(struct acpi_aest_node *node, u64 error_device_id) +{ + struct aest_hnode *ahnode __free(kfree) = NULL; + + ahnode = kzalloc(sizeof(*ahnode), GFP_KERNEL); + if (!ahnode) + return NULL; + + INIT_LIST_HEAD(&ahnode->list); + ahnode->id = error_device_id; + ahnode->count = 0; + ahnode->type = node->type; + + return_ptr(ahnode); +} +static int __init acpi_aest_init_node(struct acpi_aest_hdr *aest_hdr) +{ + struct aest_hnode *ahnode; + u64 error_device_id; + struct acpi_aest_node *node; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + node->spec_pointer = + ACPI_ADD_PTR(void, aest_hdr, aest_hdr->node_specific_offset); + if (aest_hdr->type == ACPI_AEST_PROCESSOR_ERROR_NODE) + node->processor_spec_pointer = + ACPI_ADD_PTR(void, node->spec_pointer, + sizeof(struct acpi_aest_processor)); + + aest_init_interface(aest_hdr, node); + + if (node->interrupt_count <= 0) + return -EINVAL; + + error_device_id = node->interrupt[0].gsiv; + ahnode = xa_load(aest_array, error_device_id); + if (!ahnode) { + ahnode = acpi_aest_alloc_ahnode(node, error_device_id); + if (!ahnode) + return -ENOMEM; + xa_store(aest_array, error_device_id, ahnode, GFP_KERNEL); + } + + list_add_tail(&node->list, &ahnode->list); + ahnode->count++; + + return 0; +} + +static int __init acpi_aest_init_nodes(struct acpi_table_header *aest_table) +{ + struct acpi_aest_hdr *aest_node, *aest_end; + struct acpi_table_aest *aest; + int rc; + + aest = (struct acpi_table_aest *)aest_table; + aest_node = ACPI_ADD_PTR(struct acpi_aest_hdr, aest, + sizeof(struct acpi_table_header)); + aest_end = ACPI_ADD_PTR(struct acpi_aest_hdr, aest, aest_table->length); + + while (aest_node < aest_end) { + if (((u64)aest_node + aest_node->length) > (u64)aest_end) { + pr_warn(FW_WARN + "AEST node pointer overflow, bad table.\n"); + return -EINVAL; + } + + rc = acpi_aest_init_node(aest_node); + if (rc) + return rc; + + aest_node = ACPI_ADD_PTR(struct acpi_aest_hdr, aest_node, + aest_node->length); + } + + return 0; +} + +static int acpi_aest_parse_irqs(struct platform_device *pdev, + struct acpi_aest_node *anode, + struct resource *res, int *res_idx, int irqs[2]) +{ + int i; + struct acpi_aest_node_interrupt_v2 *interrupt; + int trigger, irq; + + for (i = 0; i < anode->interrupt_count; i++) { + interrupt = &anode->interrupt[i]; + if (irqs[interrupt->type]) + continue; + + trigger = (interrupt->flags & AEST_INTERRUPT_MODE) ? + ACPI_LEVEL_SENSITIVE : + ACPI_EDGE_SENSITIVE; + + irq = acpi_register_gsi(&pdev->dev, interrupt->gsiv, trigger, + ACPI_ACTIVE_HIGH); + if (irq <= 0) { + pr_err("failed to map AEST GSI %d\n", interrupt->gsiv); + return irq; + } + + res[*res_idx].start = irq; + res[*res_idx].end = irq; + res[*res_idx].flags = IORESOURCE_IRQ; + res[*res_idx].name = interrupt->type ? AEST_ERI_NAME : + AEST_FHI_NAME; + + (*res_idx)++; + + irqs[interrupt->type] = irq; + } + + return 0; +} + +DEFINE_FREE(res, struct resource *, if (_T) kfree(_T)) +static struct platform_device *__init +acpi_aest_alloc_pdev(struct aest_hnode *ahnode, int index) +{ + struct platform_device *pdev __free(platform_device_put) = + platform_device_alloc("AEST", index++); + struct resource *res __free(res); + struct acpi_aest_node *anode; + int ret, size, j, irq[AEST_MAX_INTERRUPT_PER_NODE] = { 0 }; + + if (!pdev) + return ERR_PTR(-ENOMEM); + + res = kcalloc(ahnode->count + AEST_MAX_INTERRUPT_PER_NODE, sizeof(*res), + GFP_KERNEL); + if (!res) + return ERR_PTR(-ENOMEM); + + j = 0; + list_for_each_entry(anode, &ahnode->list, list) { + if (anode->interface_hdr->type != + ACPI_AEST_NODE_SYSTEM_REGISTER) { + res[j].name = AEST_NODE_NAME; + res[j].start = anode->interface_hdr->address; + switch (anode->interface_hdr->group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: + size = 4 * KB; + break; + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + size = 16 * KB; + break; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + size = 64 * KB; + break; + default: + size = 4 * KB; + } + res[j].end = res[j].start + size - 1; + res[j].flags = IORESOURCE_MEM; + } + + ret = acpi_aest_parse_irqs(pdev, anode, res, &j, irq); + if (ret) + return ERR_PTR(ret); + } + + ret = platform_device_add_resources(pdev, res, j); + if (ret) + return ERR_PTR(ret); + + ret = platform_device_add_data(pdev, &ahnode, sizeof(ahnode)); + if (ret) + return ERR_PTR(ret); + + ret = platform_device_add(pdev); + if (ret) + return ERR_PTR(ret); + + return_ptr(pdev); +} +static int __init acpi_aest_alloc_pdevs(void) +{ + int ret = 0, index = 0; + struct aest_hnode *ahnode = NULL; + unsigned long i; + + xa_for_each(aest_array, i, ahnode) { + struct platform_device *pdev = + acpi_aest_alloc_pdev(ahnode, index++); + + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + break; + } + } + + return ret; +} + +static int __init acpi_aest_init(void) +{ + int ret; + + if (acpi_disabled) + return 0; + + struct acpi_table_header *aest_table __free(acpi_put_table) = + acpi_get_table_pointer(ACPI_SIG_AEST, 0); + if (IS_ERR(aest_table)) + return 0; + + aest_array = kzalloc(sizeof(struct xarray), GFP_KERNEL); + if (!aest_array) + return -ENOMEM; + + xa_init(aest_array); + + ret = acpi_aest_init_nodes(aest_table); + if (ret) { + pr_err("Failed init aest node %d\n", ret); + return ret; + } + + ret = acpi_aest_alloc_pdevs(); + if (ret) { + pr_err("Failed alloc pdev %d\n", ret); + return ret; + } + + return 0; +} +subsys_initcall_sync(acpi_aest_init); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 60c005223844d..25cf17e4b4349 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -257,7 +257,11 @@ static int deferred_devs_show(struct seq_file *s, void *data) } DEFINE_SHOW_ATTRIBUTE(deferred_devs); -static int driver_deferred_probe_timeout = CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT; +#ifdef CONFIG_MODULES +static int driver_deferred_probe_timeout = 15; +#else +static int driver_deferred_probe_timeout; +#endif static int __init deferred_probe_timeout_setup(char *str) { diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 04ebe290bc784..ae3f6e7d8ea95 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -614,6 +614,53 @@ static int qca_download_firmware(struct hci_dev *hdev, memcpy(data, fw->data, size); release_firmware(fw); + /* For QCC2072, combine the NVM (type 2) with the calibration file + * into a single TLV of outer type 4. + */ + if (soc_type == QCA_QCC2072 && config->type == TLV_TYPE_NVM) { + const struct firmware *calib_fw = NULL; + char calib_name[32]; + u8 *combined_data = NULL; + size_t inner_len, combined_size; + struct tlv_type_hdr *outer_hdr; + int err; + + snprintf(calib_name, sizeof(calib_name), + "qca/ornbcscal%02x.bin", rom_ver); + err = request_firmware(&calib_fw, calib_name, &hdev->dev); + if (err) { + bt_dev_err(hdev, "QCA Failed to request file: %s (%d)", + calib_name, err); + goto skip_combination; + } + + bt_dev_info(hdev, "QCA Downloading %s", calib_name); + + inner_len = size + calib_fw->size; + combined_size = sizeof(*outer_hdr) + inner_len; + combined_data = vmalloc(combined_size); + if (!combined_data) { + bt_dev_warn(hdev, + "QCA Failed to allocate memory for file: %s", + calib_name); + release_firmware(calib_fw); + goto skip_combination; + } + + outer_hdr = (struct tlv_type_hdr *)combined_data; + /* high 24 bits = payload length, low 8 bits = type */ + outer_hdr->type_len = cpu_to_le32((inner_len << 8) | 4); + memcpy(combined_data + sizeof(*outer_hdr), data, size); + memcpy(combined_data + sizeof(*outer_hdr) + size, + calib_fw->data, calib_fw->size); + release_firmware(calib_fw); + vfree(data); + data = combined_data; + size = combined_size; +skip_combination: + ; + } + ret = qca_tlv_check_data(hdev, config, data, size, soc_type); if (ret) goto out; @@ -845,6 +892,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/hmtbtfw%02x.tlv", rom_ver); break; + case QCA_QCC2072: + snprintf(config.fwname, sizeof(config.fwname), + "qca/ornbtfw%02x.tlv", rom_ver); + break; default: snprintf(config.fwname, sizeof(config.fwname), "qca/rampatch_%08x.bin", soc_ver); @@ -939,6 +990,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname), "hmtnv", soc_type, ver, rom_ver, boardid); break; + case QCA_QCC2072: + snprintf(config.fwname, sizeof(config.fwname), + "qca/ornnv%02x.bin", rom_ver); + break; default: snprintf(config.fwname, sizeof(config.fwname), "qca/nvm_%08x.bin", soc_ver); @@ -1001,6 +1056,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: /* get fw build info */ err = qca_read_fw_build_info(hdev); if (err < 0) diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 8f3c1b1c77b3d..a175ac31e7b23 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -158,6 +158,7 @@ enum qca_btsoc_type { QCA_WCN6750, QCA_WCN6855, QCA_WCN7850, + QCA_QCC2072, }; #if IS_ENABLED(CONFIG_BT_QCA) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 2444471956197..4170a15a90bc2 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1372,6 +1373,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) /* Give the controller time to process the request */ switch (qca_soc_type(hu)) { + case QCA_QCC2072: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -1459,6 +1461,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, static int qca_check_speeds(struct hci_uart *hu) { switch (qca_soc_type(hu)) { + case QCA_QCC2072: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -1510,6 +1513,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: hci_uart_set_flow_control(hu, true); break; @@ -1545,6 +1549,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: hci_uart_set_flow_control(hu, false); break; @@ -1861,6 +1866,7 @@ static int qca_power_on(struct hci_dev *hdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: ret = qca_regulator_init(hu); break; @@ -1960,6 +1966,10 @@ static int qca_setup(struct hci_uart *hu) soc_name = "wcn7850"; break; + case QCA_QCC2072: + soc_name = "qcc2072"; + break; + default: soc_name = "ROME/QCA6390"; } @@ -1983,6 +1993,7 @@ static int qca_setup(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: if (qcadev && qcadev->bdaddr_property_broken) hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN); @@ -2016,6 +2027,7 @@ static int qca_setup(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: break; default: @@ -2169,6 +2181,12 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = { .num_vregs = 4, }; +static const struct qca_device_data qca_soc_data_qcc2072 __maybe_unused = { + .soc_type = QCA_QCC2072, + .num_vregs = 0, + .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, +}; + static const struct qca_device_data qca_soc_data_wcn6750 __maybe_unused = { .soc_type = QCA_WCN6750, .vregs = (struct qca_vreg []) { @@ -2271,6 +2289,7 @@ static void qca_power_off(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: + case QCA_QCC2072: gpiod_set_value_cansleep(qcadev->bt_en, 0); msleep(100); qca_regulator_disable(qcadev); @@ -2392,7 +2411,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) struct hci_dev *hdev; const struct qca_device_data *data; int err; - bool power_ctrl_enabled = true; + bool bt_en_available = true; qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL); if (!qcadev) @@ -2417,6 +2436,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->btsoc_type = QCA_ROME; switch (qcadev->btsoc_type) { + case QCA_QCC2072: case QCA_QCA6390: case QCA_WCN3950: case QCA_WCN3988: @@ -2445,6 +2465,26 @@ static int qca_serdev_probe(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: + /* + * OF graph link is only present for BT devices attached through + * the M.2 Key E connector. + */ + if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) { + struct device *dev; + + qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev, + "uart"); + if (IS_ERR(qcadev->bt_power->pwrseq)) + return PTR_ERR(qcadev->bt_power->pwrseq); + + dev = pwrseq_to_device(qcadev->bt_power->pwrseq); + if (!device_property_present(dev, "w-disable2-gpios")) + bt_en_available = false; + + break; + } + if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the @@ -2487,14 +2527,16 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (!qcadev->bt_en && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_QCC2072 || data->soc_type == QCA_WCN7850)) - power_ctrl_enabled = false; + bt_en_available = false; qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", GPIOD_IN); if (IS_ERR(qcadev->sw_ctrl) && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_QCC2072 || data->soc_type == QCA_WCN7850)) { dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); return PTR_ERR(qcadev->sw_ctrl); @@ -2526,7 +2568,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) } if (!qcadev->bt_en) - power_ctrl_enabled = false; + bt_en_available = false; qcadev->susclk = devm_clk_get_optional_enabled_with_rate( &serdev->dev, NULL, SUSCLK_RATE_32KHZ); @@ -2544,7 +2586,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) hdev = qcadev->serdev_hu.hdev; - if (power_ctrl_enabled) { + if (bt_en_available) { hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); hdev->shutdown = qca_hci_shutdown; } @@ -2573,6 +2615,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) struct qca_power *power = qcadev->bt_power; switch (qcadev->btsoc_type) { + case QCA_QCC2072: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -2782,6 +2825,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,wcn6750-bt", .data = &qca_soc_data_wcn6750}, { .compatible = "qcom,wcn6855-bt", .data = &qca_soc_data_wcn6855}, { .compatible = "qcom,wcn7850-bt", .data = &qca_soc_data_wcn7850}, + { .compatible = "qcom,qcc2072-bt", .data = &qca_soc_data_qcc2072}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 7d84c2f1d911a..8b6ec3aa818cd 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -19,6 +19,17 @@ menuconfig COMMON_CLK_QCOM if COMMON_CLK_QCOM +config CLK_ELIZA_CAMCC + tristate "Eliza Camera Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_ELIZA_GCC + default m if ARCH_QCOM + help + Support for the camera clock controller on Qualcomm Technologies, Inc + Eliza devices. + Say Y if you want to support camera devices and functionality such as + capturing pictures. + config CLK_ELIZA_DISPCC tristate "Eliza Display Clock Controller" depends on ARM64 || COMPILE_TEST @@ -37,6 +48,16 @@ config CLK_ELIZA_GCC Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, UFS, SDCC, etc. +config CLK_ELIZA_GPUCC + tristate "Eliza Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_ELIZA_GCC + default m if ARCH_QCOM + help + Support for the graphics clock controller on Eliza devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config CLK_ELIZA_TCSRCC tristate "Eliza TCSR Clock Controller" depends on ARM64 || COMPILE_TEST @@ -45,6 +66,26 @@ config CLK_ELIZA_TCSRCC Support for the TCSR clock controller on Eliza devices. Say Y if you want to use peripheral devices such as USB/PCIe/UFS. +config CLK_ELIZA_VIDEOCC + tristate "Eliza Video Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_ELIZA_GCC + default m if ARCH_QCOM + help + Support for the video clock controller on Eliza devices. + Say Y if you want to support video devices and functionality such as + video encode and decode. + +config CLK_GLYMUR_CAMCC + tristate "Glymur Camera Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_GLYMUR_GCC + help + Support for the camera clock controller on Qualcomm Technologies, Inc + Glymur devices. + Say Y if you want to support camera devices and functionality such as + capturing pictures. + config CLK_GLYMUR_DISPCC tristate "Glymur Display Clock Controller" depends on ARM64 || COMPILE_TEST @@ -55,6 +96,17 @@ config CLK_GLYMUR_DISPCC Say Y if you want to support display devices and functionality such as splash screen. +config CLK_GLYMUR_EVACC + tristate "Glymur EVA Clock Controller" + depends on ARM64 || COMPILE_TEST + default m if ARCH_QCOM + select CLK_GLYMUR_GCC + help + Support for the Enhanced Video Analytics (EVA) clock controller on + Qualcomm Technologies, Inc. Glymur devices. + Say Y if you want to support EVA devices and functionality such as + vision processing. + config CLK_GLYMUR_GCC tristate "Glymur Global Clock Controller" depends on ARM64 || COMPILE_TEST @@ -155,6 +207,26 @@ config CLK_NORD_GCC SPI, I2C, USB, SD/UFS, PCIe etc. The clock controller is a combination of GCC, SE_GCC, NE_GCC and NW_GCC. +config CLK_SHIKRA_AUDIOCORECC + tristate "Shikra Audio Core Clock Controller" + depends on ARM64 || COMPILE_TEST + select CLK_SHIKRA_GCC + default m if ARCH_QCOM + help + Support for the Audio Core clock controller on Qualcomm Technologies, Inc + Shikra devices. + Say Y if you want to use AudioCoreCC clocks required to support audio + devices and it's functionality. + +config CLK_SHIKRA_GCC + tristate "Shikra Global Clock Controller" + depends on ARM64 || COMPILE_TEST + select QCOM_GDSC + help + Support for the global clock controller on Shikra devices. + Say Y if you want to use multimedia devices or peripheral + devices such as Camera, Video, UART, SPI, I2C, USB, SD/eMMC etc. + config CLK_X1E80100_CAMCC tristate "X1E80100 Camera Clock Controller" depends on ARM64 || COMPILE_TEST @@ -1781,4 +1853,19 @@ config SM_VIDEOCC_8450 SM8450 or SM8475 devices. Say Y if you want to support video devices and functionality such as video encode/decode. + +config QCOM_CLK_GP_MND + tristate "Qualcomm PDM GP_MN clock divider" + depends on ARM64 || COMPILE_TEST + help + Support for the Qualcomm PDM GP_MN clock divider found in PDM + (Pulse Density Modulation) hardware blocks. + Given an input clock of frequency Fin (TCXO4), the output + frequency is Fout = Fin * (M / N). For every N input cycles + the divider produces M output cycles. D controls the duty + cycle: it is the number of native clock cycles in which the + GP_MN output is low, counted over 8192 native clock cycles. + + Say Y or M if you want to support GP_MN-based frequency and + duty-cycle configuration on Qualcomm SoCs. endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 58f9a5eb6fd7f..d792e69f8ede0 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -20,11 +20,16 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o # Keep alphabetically sorted by config obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o +obj-$(CONFIG_CLK_ELIZA_CAMCC) += cambistmclkcc-eliza.o camcc-eliza.o obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o +obj-$(CONFIG_CLK_ELIZA_GPUCC) += gpucc-eliza.o obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o +obj-$(CONFIG_CLK_ELIZA_VIDEOCC) += videocc-eliza.o obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o +obj-$(CONFIG_CLK_GLYMUR_CAMCC) += camcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_DISPCC) += dispcc-glymur.o +obj-$(CONFIG_CLK_GLYMUR_EVACC) += evacc-glymur.o obj-$(CONFIG_CLK_GLYMUR_GCC) += gcc-glymur.o obj-$(CONFIG_CLK_GLYMUR_GPUCC) += gpucc-glymur.o gxclkctl-kaanapali.o obj-$(CONFIG_CLK_GLYMUR_TCSRCC) += tcsrcc-glymur.o @@ -39,6 +44,8 @@ obj-$(CONFIG_CLK_KAANAPALI_TCSRCC) += tcsrcc-kaanapali.o obj-$(CONFIG_CLK_KAANAPALI_VIDEOCC) += videocc-kaanapali.o obj-$(CONFIG_CLK_NORD_GCC) += gcc-nord.o negcc-nord.o nwgcc-nord.o segcc-nord.o obj-$(CONFIG_CLK_NORD_TCSRCC) += tcsrcc-nord.o +obj-$(CONFIG_CLK_SHIKRA_AUDIOCORECC) += audiocorecc-shikra.o +obj-$(CONFIG_CLK_SHIKRA_GCC) += gcc-shikra.o obj-$(CONFIG_CLK_X1E80100_CAMCC) += camcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_DISPCC) += dispcc-x1e80100.o obj-$(CONFIG_CLK_X1E80100_GCC) += gcc-x1e80100.o @@ -209,6 +216,7 @@ obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o obj-$(CONFIG_SM_VIDEOCC_8750) += videocc-sm8750.o obj-$(CONFIG_SM_VIDEOCC_MILOS) += videocc-milos.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o +obj-$(CONFIG_QCOM_CLK_GP_MND) += clk-gp-mnd.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o obj-$(CONFIG_KRAITCC) += krait-cc.o diff --git a/drivers/clk/qcom/audiocorecc-shikra.c b/drivers/clk/qcom/audiocorecc-shikra.c new file mode 100644 index 0000000000000..f7655b2cbd458 --- /dev/null +++ b/drivers/clk/qcom/audiocorecc-shikra.c @@ -0,0 +1,815 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_AUD_REF_CLK_SRC, +}; + +enum { + P_AUD_REF_CLK_SRC, + P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, + P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, + P_BI_TCXO, + P_SLEEP_CLK, +}; + +static const struct pll_vco spark_vco[] = { + { 500000000, 1000000000, 2 }, +}; + +/* 614.4 MHz Configuration */ +static const struct alpha_pll_config audio_core_cc_dig_pll_config = { + .l = 0x20, + .alpha = 0x0, + .vco_val = BIT(21), + .post_div_val = 0x28100, + .post_div_mask = GENMASK(17, 8), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .aux2_output_mask = BIT(2), + .config_ctl_val = 0x4001055b, + .test_ctl_hi_val = 0x1, + .test_ctl_hi_mask = 0x1, +}; + +static struct clk_alpha_pll audio_core_cc_dig_pll = { + .offset = 0x0, + .config = &audio_core_cc_dig_pll_config, + .vco_table = spark_vco, + .num_vco = ARRAY_SIZE(spark_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_dig_pll", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static struct clk_fixed_factor audio_core_cc_dig_pll_out_aux = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data) { + .name = "audio_core_cc_dig_pll_out_aux", + .parent_data = &(const struct clk_parent_data) { + .hw = &audio_core_cc_dig_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor audio_core_cc_dig_pll_out_aux2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data) { + .name = "audio_core_cc_dig_pll_out_aux2", + .parent_data = &(const struct clk_parent_data) { + .hw = &audio_core_cc_dig_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static const struct parent_map audio_core_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_AUD_REF_CLK_SRC, 1 }, + { P_SLEEP_CLK, 2 }, + { P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 4 }, + { P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 6 }, +}; + +static const struct clk_parent_data audio_core_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .index = DT_AUD_REF_CLK_SRC }, + { .index = DT_SLEEP_CLK }, + { .hw = &audio_core_cc_dig_pll_out_aux.hw }, + { .hw = &audio_core_cc_dig_pll_out_aux2.hw }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_aif_if0_clk_src[] = { + F(240000, P_BI_TCXO, 10, 1, 8), + F(256000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 32), + F(512000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 16), + F(768000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 16), + F(1024000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 8), + F(1536000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 8), + F(2048000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 4), + F(3072000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 4), + F(4096000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 2), + F(6144000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 2), + F(8192000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(12288000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 5, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_aif_if0_clk_src = { + .cmd_rcgr = 0x104c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if0_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_aif_if1_clk_src = { + .cmd_rcgr = 0x10b0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if1_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_aif_if2_clk_src = { + .cmd_rcgr = 0x1114, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if2_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_aif_if3_clk_src[] = { + F(240000, P_BI_TCXO, 10, 1, 8), + F(256000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 32), + F(512000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 16), + F(768000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 16), + F(1024000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 8), + F(1536000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 8), + F(2048000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 4), + F(3072000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 4), + F(4096000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 1, 2), + F(6144000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 1, 2), + F(8192000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(12288000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 5, 0, 0), + F(49152000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_aif_if3_clk_src = { + .cmd_rcgr = 0x1178, + .mnd_width = 16, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if3_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if3_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_aud_dma_clk_src[] = { + F(102400000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 3, 0, 0), + F(153600000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 2, 0, 0), + F(307200000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_aud_dma_clk_src = { + .cmd_rcgr = 0x1028, + .mnd_width = 0, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aud_dma_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aud_dma_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_bus_clk_src[] = { + F(38400000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 8, 0, 0), + F(76800000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX2, 4, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_bus_clk_src = { + .cmd_rcgr = 0x1008, + .mnd_width = 0, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_bus_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_bus_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_ext_mclka_clk_src = { + .cmd_rcgr = 0x123c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclka_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 audio_core_cc_ext_mclkb_clk_src = { + .cmd_rcgr = 0x125c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_aif_if0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclkb_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_lpaif_pcmoe_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(15360000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 8, 0, 0), + F(30720000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 4, 0, 0), + F(61440000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 2, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_lpaif_pcmoe_clk_src = { + .cmd_rcgr = 0x12ac, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_lpaif_pcmoe_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_lpaif_pcmoe_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_audio_core_cc_tx_mclk_rcg_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_AUDIO_CORE_CC_DIG_PLL_OUT_AUX, 5, 0, 0), + { } +}; + +static struct clk_rcg2 audio_core_cc_tx_mclk_rcg_clk_src = { + .cmd_rcgr = 0x127c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = audio_core_cc_parent_map_0, + .freq_tbl = ftbl_audio_core_cc_tx_mclk_rcg_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_tx_mclk_rcg_clk_src", + .parent_data = audio_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(audio_core_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div audio_core_cc_cdiv_tx_mclk_div_clk_src = { + .reg = 0x129c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_cdiv_tx_mclk_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch audio_core_cc_aif_if0_ebit_clk = { + .halt_reg = 0x1068, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1068, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if0_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if0_ibit_clk = { + .halt_reg = 0x1064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if0_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if1_ebit_clk = { + .halt_reg = 0x10cc, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x10cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if1_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if1_ibit_clk = { + .halt_reg = 0x10c8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10c8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if1_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if2_ebit_clk = { + .halt_reg = 0x1130, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1130, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if2_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if2_ibit_clk = { + .halt_reg = 0x112c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if2_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if3_ebit_clk = { + .halt_reg = 0x1194, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1194, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if3_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aif_if3_ibit_clk = { + .halt_reg = 0x1190, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1190, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aif_if3_ibit_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aif_if3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aud_dma_clk = { + .halt_reg = 0x1040, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aud_dma_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aud_dma_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_aud_dma_mem_clk = { + .halt_reg = 0x1044, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_aud_dma_mem_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_aud_dma_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_bus_clk = { + .halt_reg = 0x1020, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x1020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_bus_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_bus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_ext_mclka_out_clk = { + .halt_reg = 0x1254, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1254, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclka_out_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_ext_mclka_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_ext_mclkb_out_clk = { + .halt_reg = 0x1274, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1274, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_ext_mclkb_out_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_ext_mclkb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_im_sleep_clk = { + .halt_reg = 0x12cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_im_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_lpaif_pcmoe_clk = { + .halt_reg = 0x12c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_lpaif_pcmoe_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_lpaif_pcmoe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_rx_mclk_2x_clk = { + .halt_reg = 0x1298, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1298, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_rx_mclk_2x_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_rx_mclk_clk = { + .halt_reg = 0x12a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_rx_mclk_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_cdiv_tx_mclk_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_sampling_clk = { + .halt_reg = 0x1000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_sampling_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_tx_mclk_2x_clk = { + .halt_reg = 0x1294, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1294, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_tx_mclk_2x_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch audio_core_cc_tx_mclk_clk = { + .halt_reg = 0x12a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "audio_core_cc_tx_mclk_clk", + .parent_hws = (const struct clk_hw*[]) { + &audio_core_cc_cdiv_tx_mclk_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_hw *audio_core_cc_shikra_hws[] = { + [AUDIO_CORE_CC_DIG_PLL_OUT_AUX] = &audio_core_cc_dig_pll_out_aux.hw, + [AUDIO_CORE_CC_DIG_PLL_OUT_AUX2] = &audio_core_cc_dig_pll_out_aux2.hw, +}; + +static struct clk_regmap *audio_core_cc_shikra_clocks[] = { + [AUDIO_CORE_CC_AIF_IF0_CLK_SRC] = &audio_core_cc_aif_if0_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF0_EBIT_CLK] = &audio_core_cc_aif_if0_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF0_IBIT_CLK] = &audio_core_cc_aif_if0_ibit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF1_CLK_SRC] = &audio_core_cc_aif_if1_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF1_EBIT_CLK] = &audio_core_cc_aif_if1_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF1_IBIT_CLK] = &audio_core_cc_aif_if1_ibit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF2_CLK_SRC] = &audio_core_cc_aif_if2_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF2_EBIT_CLK] = &audio_core_cc_aif_if2_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF2_IBIT_CLK] = &audio_core_cc_aif_if2_ibit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF3_CLK_SRC] = &audio_core_cc_aif_if3_clk_src.clkr, + [AUDIO_CORE_CC_AIF_IF3_EBIT_CLK] = &audio_core_cc_aif_if3_ebit_clk.clkr, + [AUDIO_CORE_CC_AIF_IF3_IBIT_CLK] = &audio_core_cc_aif_if3_ibit_clk.clkr, + [AUDIO_CORE_CC_AUD_DMA_CLK] = &audio_core_cc_aud_dma_clk.clkr, + [AUDIO_CORE_CC_AUD_DMA_CLK_SRC] = &audio_core_cc_aud_dma_clk_src.clkr, + [AUDIO_CORE_CC_AUD_DMA_MEM_CLK] = &audio_core_cc_aud_dma_mem_clk.clkr, + [AUDIO_CORE_CC_BUS_CLK] = &audio_core_cc_bus_clk.clkr, + [AUDIO_CORE_CC_BUS_CLK_SRC] = &audio_core_cc_bus_clk_src.clkr, + [AUDIO_CORE_CC_CDIV_TX_MCLK_DIV_CLK_SRC] = &audio_core_cc_cdiv_tx_mclk_div_clk_src.clkr, + [AUDIO_CORE_CC_DIG_PLL] = &audio_core_cc_dig_pll.clkr, + [AUDIO_CORE_CC_EXT_MCLKA_CLK_SRC] = &audio_core_cc_ext_mclka_clk_src.clkr, + [AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK] = &audio_core_cc_ext_mclka_out_clk.clkr, + [AUDIO_CORE_CC_EXT_MCLKB_CLK_SRC] = &audio_core_cc_ext_mclkb_clk_src.clkr, + [AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK] = &audio_core_cc_ext_mclkb_out_clk.clkr, + [AUDIO_CORE_CC_IM_SLEEP_CLK] = &audio_core_cc_im_sleep_clk.clkr, + [AUDIO_CORE_CC_LPAIF_PCMOE_CLK] = &audio_core_cc_lpaif_pcmoe_clk.clkr, + [AUDIO_CORE_CC_LPAIF_PCMOE_CLK_SRC] = &audio_core_cc_lpaif_pcmoe_clk_src.clkr, + [AUDIO_CORE_CC_RX_MCLK_2X_CLK] = &audio_core_cc_rx_mclk_2x_clk.clkr, + [AUDIO_CORE_CC_RX_MCLK_CLK] = &audio_core_cc_rx_mclk_clk.clkr, + [AUDIO_CORE_CC_SAMPLING_CLK] = &audio_core_cc_sampling_clk.clkr, + [AUDIO_CORE_CC_TX_MCLK_2X_CLK] = &audio_core_cc_tx_mclk_2x_clk.clkr, + [AUDIO_CORE_CC_TX_MCLK_CLK] = &audio_core_cc_tx_mclk_clk.clkr, + [AUDIO_CORE_CC_TX_MCLK_RCG_CLK_SRC] = &audio_core_cc_tx_mclk_rcg_clk_src.clkr, +}; + +static struct clk_alpha_pll *audio_core_cc_shikra_plls[] = { + &audio_core_cc_dig_pll, +}; + +static const struct regmap_config audio_core_cc_shikra_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x305c, + .fast_io = true, +}; + +static const struct qcom_reset_map audio_core_cc_shikra_resets[] = { + [AUDIO_CORE_CSR_RX_SWR_CGCR] = { 0x1c }, + [AUDIO_CORE_CSR_TX_SWR_CGCR] = { 0x30 }, +}; + +static const struct regmap_config audio_core_cc_shikra_reset_regmap_config = { + .name = "audio_core_cc_shikra_reset", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .max_register = 0x34, +}; + +static struct qcom_cc_driver_data audio_core_cc_shikra_driver_data = { + .alpha_plls = audio_core_cc_shikra_plls, + .num_alpha_plls = ARRAY_SIZE(audio_core_cc_shikra_plls), +}; + +static const struct qcom_cc_desc audio_core_cc_shikra_reset_desc = { + .config = &audio_core_cc_shikra_reset_regmap_config, + .resets = audio_core_cc_shikra_resets, + .num_resets = ARRAY_SIZE(audio_core_cc_shikra_resets), +}; + +static const struct qcom_cc_desc audio_core_cc_shikra_desc = { + .config = &audio_core_cc_shikra_regmap_config, + .clk_hws = audio_core_cc_shikra_hws, + .num_clk_hws = ARRAY_SIZE(audio_core_cc_shikra_hws), + .clks = audio_core_cc_shikra_clocks, + .num_clks = ARRAY_SIZE(audio_core_cc_shikra_clocks), + .driver_data = &audio_core_cc_shikra_driver_data, +}; + +static const struct of_device_id audio_core_cc_shikra_match_table[] = { + { .compatible = "qcom,shikra-cqm-audiocorecc" }, + { .compatible = "qcom,shikra-cqs-audiocorecc" }, + { } +}; +MODULE_DEVICE_TABLE(of, audio_core_cc_shikra_match_table); + +static int audio_core_cc_shikra_probe(struct platform_device *pdev) +{ + int ret; + + ret = qcom_cc_probe_by_index(pdev, 1, &audio_core_cc_shikra_reset_desc); + if (ret) + return ret; + + if (device_is_compatible(&pdev->dev, "qcom,shikra-cqs-audiocorecc")) + return 0; + + return qcom_cc_probe(pdev, &audio_core_cc_shikra_desc); +} + +static struct platform_driver audio_core_cc_shikra_driver = { + .probe = audio_core_cc_shikra_probe, + .driver = { + .name = "audiocorecc-shikra", + .of_match_table = audio_core_cc_shikra_match_table, + }, +}; + +module_platform_driver(audio_core_cc_shikra_driver); + +MODULE_DESCRIPTION("QTI AUDIOCORECC Shikra Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/cambistmclkcc-eliza.c b/drivers/clk/qcom/cambistmclkcc-eliza.c new file mode 100644 index 0000000000000..b65e224a1be90 --- /dev/null +++ b/drivers/clk/qcom/cambistmclkcc-eliza.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_AHB_CLK, +}; + +enum { + P_BI_TCXO, + P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, + P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, + P_SLEEP_CLK, +}; + +static const struct pll_vco rivian_ole_vco[] = { + { 777000000, 1285000000, 0 }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_bist_mclk_cc_pll0_config = { + .l = 0x32, + .cal_l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x10000030, + .config_ctl_hi_val = 0x80890263, + .config_ctl_hi1_val = 0x00000217, + .user_ctl_val = 0x00000001, + .user_ctl_hi_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_bist_mclk_cc_pll0 = { + .offset = 0x0, + .config = &cam_bist_mclk_cc_pll0_config, + .vco_table = rivian_ole_vco, + .num_vco = ARRAY_SIZE(rivian_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EVO], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_rivian_evo_ops, + }, + }, +}; + +static const struct parent_map cam_bist_mclk_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, 3 }, + { P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data cam_bist_mclk_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_bist_mclk_cc_pll0.clkr.hw }, + { .hw = &cam_bist_mclk_cc_pll0.clkr.hw }, +}; + +static const struct parent_map cam_bist_mclk_cc_parent_map_1[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_bist_mclk_cc_parent_data_1[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_cam_bist_mclk_cc_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, 10, 1, 4), + F(68571429, P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, 14, 0, 0), + { } +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk0_clk_src = { + .cmd_rcgr = 0x4000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk0_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk1_clk_src = { + .cmd_rcgr = 0x401c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk1_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk2_clk_src = { + .cmd_rcgr = 0x4038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk2_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk3_clk_src = { + .cmd_rcgr = 0x4054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk3_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk4_clk_src = { + .cmd_rcgr = 0x4070, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk4_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk5_clk_src = { + .cmd_rcgr = 0x408c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk5_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk6_clk_src = { + .cmd_rcgr = 0x40a8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk6_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_bist_mclk_cc_mclk7_clk_src = { + .cmd_rcgr = 0x40c4, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_0, + .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk7_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_bist_mclk_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_bist_mclk_cc_sleep_clk_src = { + .cmd_rcgr = 0x40e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_bist_mclk_cc_parent_map_1, + .freq_tbl = ftbl_cam_bist_mclk_cc_sleep_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_sleep_clk_src", + .parent_data = cam_bist_mclk_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk0_clk = { + .halt_reg = 0x4018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk1_clk = { + .halt_reg = 0x4034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk2_clk = { + .halt_reg = 0x4050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk3_clk = { + .halt_reg = 0x406c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x406c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk3_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk4_clk = { + .halt_reg = 0x4088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk5_clk = { + .halt_reg = 0x40a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x40a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk5_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk6_clk = { + .halt_reg = 0x40c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x40c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk6_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_bist_mclk_cc_mclk7_clk = { + .halt_reg = 0x40dc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x40dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_bist_mclk_cc_mclk7_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_bist_mclk_cc_mclk7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *cam_bist_mclk_cc_eliza_clocks[] = { + [CAM_BIST_MCLK_CC_MCLK0_CLK] = &cam_bist_mclk_cc_mclk0_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK0_CLK_SRC] = &cam_bist_mclk_cc_mclk0_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK1_CLK] = &cam_bist_mclk_cc_mclk1_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK1_CLK_SRC] = &cam_bist_mclk_cc_mclk1_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK2_CLK] = &cam_bist_mclk_cc_mclk2_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK2_CLK_SRC] = &cam_bist_mclk_cc_mclk2_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK3_CLK] = &cam_bist_mclk_cc_mclk3_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK3_CLK_SRC] = &cam_bist_mclk_cc_mclk3_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK4_CLK] = &cam_bist_mclk_cc_mclk4_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK4_CLK_SRC] = &cam_bist_mclk_cc_mclk4_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK5_CLK] = &cam_bist_mclk_cc_mclk5_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK5_CLK_SRC] = &cam_bist_mclk_cc_mclk5_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK6_CLK] = &cam_bist_mclk_cc_mclk6_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK6_CLK_SRC] = &cam_bist_mclk_cc_mclk6_clk_src.clkr, + [CAM_BIST_MCLK_CC_MCLK7_CLK] = &cam_bist_mclk_cc_mclk7_clk.clkr, + [CAM_BIST_MCLK_CC_MCLK7_CLK_SRC] = &cam_bist_mclk_cc_mclk7_clk_src.clkr, + [CAM_BIST_MCLK_CC_PLL0] = &cam_bist_mclk_cc_pll0.clkr, + [CAM_BIST_MCLK_CC_SLEEP_CLK_SRC] = &cam_bist_mclk_cc_sleep_clk_src.clkr, +}; + +static struct clk_alpha_pll *cam_bist_mclk_cc_eliza_plls[] = { + &cam_bist_mclk_cc_pll0, +}; + +static u32 cam_bist_mclk_cc_eliza_critical_cbcrs[] = { + 0x40f8, /* CAM_BIST_MCLK_CC_SLEEP_CLK */ +}; + +static const struct regmap_config cam_bist_mclk_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x5010, + .fast_io = true, +}; + +static struct qcom_cc_driver_data cam_bist_mclk_cc_eliza_driver_data = { + .alpha_plls = cam_bist_mclk_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(cam_bist_mclk_cc_eliza_plls), + .clk_cbcrs = cam_bist_mclk_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(cam_bist_mclk_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc cam_bist_mclk_cc_eliza_desc = { + .config = &cam_bist_mclk_cc_eliza_regmap_config, + .clks = cam_bist_mclk_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(cam_bist_mclk_cc_eliza_clocks), + .use_rpm = true, + .driver_data = &cam_bist_mclk_cc_eliza_driver_data, +}; + +static const struct of_device_id cam_bist_mclk_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-cambistmclkcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_bist_mclk_cc_eliza_match_table); + +static int cam_bist_mclk_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &cam_bist_mclk_cc_eliza_desc); +} + +static struct platform_driver cam_bist_mclk_cc_eliza_driver = { + .probe = cam_bist_mclk_cc_eliza_probe, + .driver = { + .name = "cambistmclkcc-eliza", + .of_match_table = cam_bist_mclk_cc_eliza_match_table, + }, +}; + +module_platform_driver(cam_bist_mclk_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI CAMBISTMCLKCC Eliza Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/camcc-eliza.c b/drivers/clk/qcom/camcc-eliza.c new file mode 100644 index 0000000000000..b96a2a58b32a7 --- /dev/null +++ b/drivers/clk/qcom/camcc-eliza.c @@ -0,0 +1,2803 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_AHB_CLK, +}; + +enum { + P_BI_TCXO, + P_CAM_CC_PLL0_OUT_EVEN, + P_CAM_CC_PLL0_OUT_MAIN, + P_CAM_CC_PLL0_OUT_ODD, + P_CAM_CC_PLL1_OUT_EVEN, + P_CAM_CC_PLL2_OUT_EVEN, + P_CAM_CC_PLL3_OUT_EVEN, + P_CAM_CC_PLL4_OUT_EVEN, + P_CAM_CC_PLL5_OUT_EVEN, + P_CAM_CC_PLL6_OUT_EVEN, + P_CAM_CC_PLL6_OUT_ODD, + P_SLEEP_CLK, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +/* 1200.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x3e, + .cal_l = 0x44, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00008400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .config = &cam_cc_pll0_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = { + .offset = 0x0, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = { + .offset = 0x0, + .post_div_shift = 14, + .post_div_table = post_div_table_cam_cc_pll0_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_odd", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 900.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0xe000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .config = &cam_cc_pll1_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = { + .offset = 0x1000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll1_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll1.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 872.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x2d, + .cal_l = 0x44, + .alpha = 0x6aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .config = &cam_cc_pll2_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll2_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll2_out_even = { + .offset = 0x2000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll2_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll2_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 890.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0x5aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .config = &cam_cc_pll3_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = { + .offset = 0x3000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll3_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll3.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 890.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll4_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0x5aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll4 = { + .offset = 0x4000, + .config = &cam_cc_pll4_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = { + .offset = 0x4000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll4_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll4.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 890.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll5_config = { + .l = 0x2e, + .cal_l = 0x44, + .alpha = 0x5aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll5 = { + .offset = 0x5000, + .config = &cam_cc_pll5_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = { + .offset = 0x5000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll5_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll5.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll6_config = { + .l = 0x32, + .cal_l = 0x44, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00008400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll6 = { + .offset = 0x6000, + .config = &cam_cc_pll6_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll6_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll6_out_even = { + .offset = 0x6000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll6_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll6.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll6_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll6_out_odd = { + .offset = 0x6000, + .post_div_shift = 14, + .post_div_table = post_div_table_cam_cc_pll6_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6_out_odd", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll6.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct parent_map cam_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL6_OUT_ODD, 4 }, + { P_CAM_CC_PLL6_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL6_OUT_ODD, 4 }, + { P_CAM_CC_PLL6_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_odd.clkr.hw }, + { .hw = &cam_cc_pll6_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll1_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll2_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll3_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL4_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll4_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL5_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_7[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll5_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_8[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_8[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct freq_tbl ftbl_cam_cc_camnoc_rt_axi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_camnoc_rt_axi_clk_src = { + .cmd_rcgr = 0x112e8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_camnoc_rt_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_axi_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = { + F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .cmd_rcgr = 0x1126c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0x11288, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_2_clk_src = { + .cmd_rcgr = 0x112a4, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_2_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = { + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0x11068, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cphy_rx_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cre_clk_src[] = { + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cre_clk_src = { + .cmd_rcgr = 0x111ac, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cre_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x10000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x10024, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = { + .cmd_rcgr = 0x10044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi2phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .cmd_rcgr = 0x10064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi3phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .cmd_rcgr = 0x10084, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = { + .cmd_rcgr = 0x100a4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi5phytimer_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csid_clk_src = { + .cmd_rcgr = 0x112c0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = { + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x100dc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_fast_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_icp_0_clk_src[] = { + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_icp_0_clk_src = { + .cmd_rcgr = 0x11214, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_icp_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_icp_1_clk_src = { + .cmd_rcgr = 0x1123c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_icp_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0x11150, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0x1117c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_nps_clk_src[] = { + F(450000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(575000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(825000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_nps_clk_src = { + .cmd_rcgr = 0x10190, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0x111d0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cre_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ofe_clk_src[] = { + F(436000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + F(570000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + F(757000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ofe_clk_src = { + .cmd_rcgr = 0x1011c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ofe_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_qdss_debug_clk_src[] = { + F(60000000, P_CAM_CC_PLL6_OUT_EVEN, 8, 0, 0), + F(120000000, P_CAM_CC_PLL0_OUT_EVEN, 5, 0, 0), + F(240000000, P_CAM_CC_PLL0_OUT_MAIN, 5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_qdss_debug_clk_src = { + .cmd_rcgr = 0x1132c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sleep_clk_src = { + .cmd_rcgr = 0x11380, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_sleep_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sleep_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = { + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .cmd_rcgr = 0x10100, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_slow_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_tfe_0_clk_src[] = { + F(445000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(567000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(644000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_tfe_0_clk_src = { + .cmd_rcgr = 0x11018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_tfe_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_tfe_1_clk_src[] = { + F(445000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(567000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(644000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_tfe_1_clk_src = { + .cmd_rcgr = 0x11098, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6, + .freq_tbl = ftbl_cam_cc_tfe_1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_clk_src", + .parent_data = cam_cc_parent_data_6, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_tfe_2_clk_src[] = { + F(445000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(567000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(644000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_tfe_2_clk_src = { + .cmd_rcgr = 0x11100, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_7, + .freq_tbl = ftbl_cam_cc_tfe_2_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_clk_src", + .parent_data = cam_cc_parent_data_7, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_xo_clk_src = { + .cmd_rcgr = 0x11364, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_8, + .freq_tbl = ftbl_cam_cc_xo_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_xo_clk_src", + .parent_data = cam_cc_parent_data_8, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_8), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_branch cam_cc_cam_top_ahb_clk = { + .halt_reg = 0x113ac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x113ac, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cam_top_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cam_top_fast_ahb_clk = { + .halt_reg = 0x1139c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1139c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cam_top_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_dcd_xo_clk = { + .halt_reg = 0x11320, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11320, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_dcd_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_axi_clk = { + .halt_reg = 0x11310, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x11310, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x11310, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_rt_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_cre_clk = { + .halt_reg = 0x111c8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111c8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_cre_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cre_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ipe_nps_clk = { + .halt_reg = 0x101b8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101b8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ofe_anchor_clk = { + .halt_reg = 0x10158, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10158, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ofe_anchor_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ofe_hdr_clk = { + .halt_reg = 0x1016c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1016c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ofe_hdr_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_nrt_ofe_main_clk = { + .halt_reg = 0x10144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_nrt_ofe_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_axi_clk = { + .halt_reg = 0x11300, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11300, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_rt_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_ife_lite_clk = { + .halt_reg = 0x11178, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11178, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_0_bayer_clk = { + .halt_reg = 0x11054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_0_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_0_main_clk = { + .halt_reg = 0x11040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_0_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_1_bayer_clk = { + .halt_reg = 0x110d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_1_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_1_main_clk = { + .halt_reg = 0x110c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_1_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_2_bayer_clk = { + .halt_reg = 0x1113c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1113c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_2_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_rt_tfe_2_main_clk = { + .halt_reg = 0x11128, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11128, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_rt_tfe_2_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_xo_clk = { + .halt_reg = 0x11324, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11324, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_0_clk = { + .halt_reg = 0x11284, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11284, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_1_clk = { + .halt_reg = 0x112a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_2_clk = { + .halt_reg = 0x112bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112bc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_core_ahb_clk = { + .halt_reg = 0x11360, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x11360, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_core_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cre_ahb_clk = { + .halt_reg = 0x111cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cre_clk = { + .halt_reg = 0x111c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cre_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi0phytimer_clk = { + .halt_reg = 0x10018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi1phytimer_clk = { + .halt_reg = 0x1003c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1003c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi2phytimer_clk = { + .halt_reg = 0x1005c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1005c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi2phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi2phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi3phytimer_clk = { + .halt_reg = 0x1007c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1007c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi3phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi3phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi4phytimer_clk = { + .halt_reg = 0x1009c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1009c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi4phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi5phytimer_clk = { + .halt_reg = 0x100bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100bc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi5phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi5phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_clk = { + .halt_reg = 0x112d8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x112d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_csiphy_rx_clk = { + .halt_reg = 0x10020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_csiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy0_clk = { + .halt_reg = 0x1001c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1001c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy1_clk = { + .halt_reg = 0x10040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy2_clk = { + .halt_reg = 0x10060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10060, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy3_clk = { + .halt_reg = 0x10080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10080, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy3_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy4_clk = { + .halt_reg = 0x100a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy5_clk = { + .halt_reg = 0x100c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy5_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_drv_ahb_clk = { + .halt_reg = 0x113c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x113c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_drv_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch cam_cc_drv_xo_clk = { + .halt_reg = 0x113c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x113c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_drv_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_0_ahb_clk = { + .halt_reg = 0x11264, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11264, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_0_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_0_clk = { + .halt_reg = 0x1122c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1122c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_icp_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_1_ahb_clk = { + .halt_reg = 0x11268, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11268, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_1_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_1_clk = { + .halt_reg = 0x11254, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11254, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_icp_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_ahb_clk = { + .halt_reg = 0x111a8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111a8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_clk = { + .halt_reg = 0x11168, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11168, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = { + .halt_reg = 0x111a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_csid_clk = { + .halt_reg = 0x11194, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11194, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_ahb_clk = { + .halt_reg = 0x101d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_clk = { + .halt_reg = 0x101a8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101a8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = { + .halt_reg = 0x101d8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_clk = { + .halt_reg = 0x101bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101bc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = { + .halt_reg = 0x101dc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x101dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_0_clk = { + .halt_reg = 0x111e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111e8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_1_clk = { + .halt_reg = 0x111f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x111f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_ahb_clk = { + .halt_reg = 0x10118, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10118, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_anchor_clk = { + .halt_reg = 0x10148, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10148, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_anchor_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_anchor_fast_ahb_clk = { + .halt_reg = 0x100f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_anchor_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_hdr_clk = { + .halt_reg = 0x1015c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1015c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_hdr_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_hdr_fast_ahb_clk = { + .halt_reg = 0x100fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100fc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_hdr_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_main_clk = { + .halt_reg = 0x10134, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10134, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ofe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ofe_main_fast_ahb_clk = { + .halt_reg = 0x100f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x100f4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ofe_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_clk = { + .halt_reg = 0x11344, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11344, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_qdss_debug_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_xo_clk = { + .halt_reg = 0x11348, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11348, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_bayer_clk = { + .halt_reg = 0x11044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_bayer_fast_ahb_clk = { + .halt_reg = 0x11064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_bayer_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_main_clk = { + .halt_reg = 0x11030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11030, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_0_main_fast_ahb_clk = { + .halt_reg = 0x11060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11060, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_0_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_bayer_clk = { + .halt_reg = 0x110c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_bayer_fast_ahb_clk = { + .halt_reg = 0x110e4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110e4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_bayer_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_main_clk = { + .halt_reg = 0x110b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110b0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_1_main_fast_ahb_clk = { + .halt_reg = 0x110e0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x110e0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_1_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_bayer_clk = { + .halt_reg = 0x1112c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1112c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_bayer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_bayer_fast_ahb_clk = { + .halt_reg = 0x1114c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1114c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_bayer_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_main_clk = { + .halt_reg = 0x11118, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11118, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_main_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_tfe_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_tfe_2_main_fast_ahb_clk = { + .halt_reg = 0x11148, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11148, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_tfe_2_main_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc cam_cc_titan_top_gdsc = { + .gdscr = 0x1134c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ipe_0_gdsc = { + .gdscr = 0x1017c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ipe_0_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ofe_gdsc = { + .gdscr = 0x100c8, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ofe_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_tfe_0_gdsc = { + .gdscr = 0x11004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_tfe_0_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_tfe_1_gdsc = { + .gdscr = 0x11084, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_tfe_1_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_tfe_2_gdsc = { + .gdscr = 0x110ec, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_tfe_2_gdsc", + }, + .parent = &cam_cc_titan_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *cam_cc_eliza_clocks[] = { + [CAM_CC_CAM_TOP_AHB_CLK] = &cam_cc_cam_top_ahb_clk.clkr, + [CAM_CC_CAM_TOP_FAST_AHB_CLK] = &cam_cc_cam_top_fast_ahb_clk.clkr, + [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr, + [CAM_CC_CAMNOC_NRT_AXI_CLK] = &cam_cc_camnoc_nrt_axi_clk.clkr, + [CAM_CC_CAMNOC_NRT_CRE_CLK] = &cam_cc_camnoc_nrt_cre_clk.clkr, + [CAM_CC_CAMNOC_NRT_IPE_NPS_CLK] = &cam_cc_camnoc_nrt_ipe_nps_clk.clkr, + [CAM_CC_CAMNOC_NRT_OFE_ANCHOR_CLK] = &cam_cc_camnoc_nrt_ofe_anchor_clk.clkr, + [CAM_CC_CAMNOC_NRT_OFE_HDR_CLK] = &cam_cc_camnoc_nrt_ofe_hdr_clk.clkr, + [CAM_CC_CAMNOC_NRT_OFE_MAIN_CLK] = &cam_cc_camnoc_nrt_ofe_main_clk.clkr, + [CAM_CC_CAMNOC_RT_AXI_CLK] = &cam_cc_camnoc_rt_axi_clk.clkr, + [CAM_CC_CAMNOC_RT_AXI_CLK_SRC] = &cam_cc_camnoc_rt_axi_clk_src.clkr, + [CAM_CC_CAMNOC_RT_IFE_LITE_CLK] = &cam_cc_camnoc_rt_ife_lite_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_0_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_0_bayer_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_0_main_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_1_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_1_bayer_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_1_main_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_2_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_2_bayer_clk.clkr, + [CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_2_main_clk.clkr, + [CAM_CC_CAMNOC_XO_CLK] = &cam_cc_camnoc_xo_clk.clkr, + [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr, + [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr, + [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr, + [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr, + [CAM_CC_CCI_2_CLK] = &cam_cc_cci_2_clk.clkr, + [CAM_CC_CCI_2_CLK_SRC] = &cam_cc_cci_2_clk_src.clkr, + [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CRE_AHB_CLK] = &cam_cc_cre_ahb_clk.clkr, + [CAM_CC_CRE_CLK] = &cam_cc_cre_clk.clkr, + [CAM_CC_CRE_CLK_SRC] = &cam_cc_cre_clk_src.clkr, + [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr, + [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr, + [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr, + [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr, + [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr, + [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr, + [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr, + [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr, + [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr, + [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr, + [CAM_CC_CSI5PHYTIMER_CLK] = &cam_cc_csi5phytimer_clk.clkr, + [CAM_CC_CSI5PHYTIMER_CLK_SRC] = &cam_cc_csi5phytimer_clk_src.clkr, + [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr, + [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr, + [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.clkr, + [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr, + [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr, + [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr, + [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr, + [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr, + [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr, + [CAM_CC_DRV_AHB_CLK] = &cam_cc_drv_ahb_clk.clkr, + [CAM_CC_DRV_XO_CLK] = &cam_cc_drv_xo_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, + [CAM_CC_ICP_0_AHB_CLK] = &cam_cc_icp_0_ahb_clk.clkr, + [CAM_CC_ICP_0_CLK] = &cam_cc_icp_0_clk.clkr, + [CAM_CC_ICP_0_CLK_SRC] = &cam_cc_icp_0_clk_src.clkr, + [CAM_CC_ICP_1_AHB_CLK] = &cam_cc_icp_1_ahb_clk.clkr, + [CAM_CC_ICP_1_CLK] = &cam_cc_icp_1_clk.clkr, + [CAM_CC_ICP_1_CLK_SRC] = &cam_cc_icp_1_clk_src.clkr, + [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr, + [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr, + [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr, + [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr, + [CAM_CC_IPE_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr, + [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr, + [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr, + [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr, + [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr, + [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr, + [CAM_CC_JPEG_0_CLK] = &cam_cc_jpeg_0_clk.clkr, + [CAM_CC_JPEG_1_CLK] = &cam_cc_jpeg_1_clk.clkr, + [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr, + [CAM_CC_OFE_AHB_CLK] = &cam_cc_ofe_ahb_clk.clkr, + [CAM_CC_OFE_ANCHOR_CLK] = &cam_cc_ofe_anchor_clk.clkr, + [CAM_CC_OFE_ANCHOR_FAST_AHB_CLK] = &cam_cc_ofe_anchor_fast_ahb_clk.clkr, + [CAM_CC_OFE_CLK_SRC] = &cam_cc_ofe_clk_src.clkr, + [CAM_CC_OFE_HDR_CLK] = &cam_cc_ofe_hdr_clk.clkr, + [CAM_CC_OFE_HDR_FAST_AHB_CLK] = &cam_cc_ofe_hdr_fast_ahb_clk.clkr, + [CAM_CC_OFE_MAIN_CLK] = &cam_cc_ofe_main_clk.clkr, + [CAM_CC_OFE_MAIN_FAST_AHB_CLK] = &cam_cc_ofe_main_fast_ahb_clk.clkr, + [CAM_CC_PLL0] = &cam_cc_pll0.clkr, + [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr, + [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr, + [CAM_CC_PLL1] = &cam_cc_pll1.clkr, + [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr, + [CAM_CC_PLL2] = &cam_cc_pll2.clkr, + [CAM_CC_PLL2_OUT_EVEN] = &cam_cc_pll2_out_even.clkr, + [CAM_CC_PLL3] = &cam_cc_pll3.clkr, + [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr, + [CAM_CC_PLL4] = &cam_cc_pll4.clkr, + [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr, + [CAM_CC_PLL5] = &cam_cc_pll5.clkr, + [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr, + [CAM_CC_PLL6] = &cam_cc_pll6.clkr, + [CAM_CC_PLL6_OUT_EVEN] = &cam_cc_pll6_out_even.clkr, + [CAM_CC_PLL6_OUT_ODD] = &cam_cc_pll6_out_odd.clkr, + [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr, + [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr, + [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr, + [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, + [CAM_CC_TFE_0_BAYER_CLK] = &cam_cc_tfe_0_bayer_clk.clkr, + [CAM_CC_TFE_0_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_0_bayer_fast_ahb_clk.clkr, + [CAM_CC_TFE_0_CLK_SRC] = &cam_cc_tfe_0_clk_src.clkr, + [CAM_CC_TFE_0_MAIN_CLK] = &cam_cc_tfe_0_main_clk.clkr, + [CAM_CC_TFE_0_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_0_main_fast_ahb_clk.clkr, + [CAM_CC_TFE_1_BAYER_CLK] = &cam_cc_tfe_1_bayer_clk.clkr, + [CAM_CC_TFE_1_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_1_bayer_fast_ahb_clk.clkr, + [CAM_CC_TFE_1_CLK_SRC] = &cam_cc_tfe_1_clk_src.clkr, + [CAM_CC_TFE_1_MAIN_CLK] = &cam_cc_tfe_1_main_clk.clkr, + [CAM_CC_TFE_1_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_1_main_fast_ahb_clk.clkr, + [CAM_CC_TFE_2_BAYER_CLK] = &cam_cc_tfe_2_bayer_clk.clkr, + [CAM_CC_TFE_2_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_2_bayer_fast_ahb_clk.clkr, + [CAM_CC_TFE_2_CLK_SRC] = &cam_cc_tfe_2_clk_src.clkr, + [CAM_CC_TFE_2_MAIN_CLK] = &cam_cc_tfe_2_main_clk.clkr, + [CAM_CC_TFE_2_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_2_main_fast_ahb_clk.clkr, + [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr, +}; + +static struct gdsc *cam_cc_eliza_gdscs[] = { + [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc, + [CAM_CC_OFE_GDSC] = &cam_cc_ofe_gdsc, + [CAM_CC_TFE_0_GDSC] = &cam_cc_tfe_0_gdsc, + [CAM_CC_TFE_1_GDSC] = &cam_cc_tfe_1_gdsc, + [CAM_CC_TFE_2_GDSC] = &cam_cc_tfe_2_gdsc, + [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc, +}; + +static const struct qcom_reset_map cam_cc_eliza_resets[] = { + [CAM_CC_DRV_BCR] = { 0x113bc }, + [CAM_CC_ICP_BCR] = { 0x11210 }, + [CAM_CC_IPE_0_BCR] = { 0x10178 }, + [CAM_CC_OFE_BCR] = { 0x100c4 }, + [CAM_CC_QDSS_DEBUG_BCR] = { 0x11328 }, + [CAM_CC_TFE_0_BCR] = { 0x11000 }, + [CAM_CC_TFE_1_BCR] = { 0x11080 }, + [CAM_CC_TFE_2_BCR] = { 0x110e8 }, +}; + +static struct clk_alpha_pll *cam_cc_eliza_plls[] = { + &cam_cc_pll0, + &cam_cc_pll1, + &cam_cc_pll2, + &cam_cc_pll3, + &cam_cc_pll4, + &cam_cc_pll5, + &cam_cc_pll6, +}; + +static u32 cam_cc_eliza_critical_cbcrs[] = { + 0x1137c, /* CAM_CC_GDSC_CLK */ + 0x11398, /* CAM_CC_SLEEP_CLK */ +}; + +static const struct regmap_config cam_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1601c, + .fast_io = true, +}; + +static struct qcom_cc_driver_data cam_cc_eliza_driver_data = { + .alpha_plls = cam_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(cam_cc_eliza_plls), + .clk_cbcrs = cam_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(cam_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc cam_cc_eliza_desc = { + .config = &cam_cc_eliza_regmap_config, + .clks = cam_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(cam_cc_eliza_clocks), + .resets = cam_cc_eliza_resets, + .num_resets = ARRAY_SIZE(cam_cc_eliza_resets), + .gdscs = cam_cc_eliza_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_eliza_gdscs), + .driver_data = &cam_cc_eliza_driver_data, +}; + +static const struct of_device_id cam_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_eliza_match_table); + +static int cam_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &cam_cc_eliza_desc); +} + +static struct platform_driver cam_cc_eliza_driver = { + .probe = cam_cc_eliza_probe, + .driver = { + .name = "camcc-eliza", + .of_match_table = cam_cc_eliza_match_table, + }, +}; + +module_platform_driver(cam_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI CAMCC Eliza Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/camcc-glymur.c b/drivers/clk/qcom/camcc-glymur.c new file mode 100644 index 0000000000000..b21e6830a72b4 --- /dev/null +++ b/drivers/clk/qcom/camcc-glymur.c @@ -0,0 +1,2280 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_IFACE, + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, +}; + +enum { + P_BI_TCXO, + P_BI_TCXO_AO, + P_CAM_CC_PLL0_OUT_EVEN, + P_CAM_CC_PLL0_OUT_MAIN, + P_CAM_CC_PLL0_OUT_ODD, + P_CAM_CC_PLL1_OUT_EVEN, + P_CAM_CC_PLL2_OUT_EVEN, + P_CAM_CC_PLL2_OUT_MAIN, + P_CAM_CC_PLL3_OUT_EVEN, + P_CAM_CC_PLL4_OUT_EVEN, + P_CAM_CC_PLL5_OUT_EVEN, + P_SLEEP_CLK, +}; + +static const struct pll_vco rivian_eko_t_vco[] = { + { 883200000, 1171200000, 0 }, +}; + +static const struct pll_vco taycan_eko_t_vco[] = { + { 249600000, 2500000000, 0 }, +}; + +/* 1200.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x3e, + .alpha = 0x8000, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00008408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .config = &cam_cc_pll0_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = { + .offset = 0x0, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = { + .offset = 0x0, + .post_div_shift = 14, + .post_div_table = post_div_table_cam_cc_pll0_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0_out_odd", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 608.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x1f, + .alpha = 0xaaaa, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .config = &cam_cc_pll1_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = { + .offset = 0x1000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll1_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll1.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x12000000, + .config_ctl_hi_val = 0x00890263, + .config_ctl_hi1_val = 0x1af04237, + .config_ctl_hi2_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .config = &cam_cc_pll2_config, + .vco_table = rivian_eko_t_vco, + .num_vco = ARRAY_SIZE(rivian_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_rivian_eko_t_ops, + }, + }, +}; + +/* 691.2 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x24, + .alpha = 0x0, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .config = &cam_cc_pll3_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = { + .offset = 0x3000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll3_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll3.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 691.2 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll4_config = { + .l = 0x24, + .alpha = 0x0, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll4 = { + .offset = 0x4000, + .config = &cam_cc_pll4_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = { + .offset = 0x4000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll4_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll4.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +/* 960.0 MHz Configuration */ +static const struct alpha_pll_config cam_cc_pll5_config = { + .l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000408, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll cam_cc_pll5 = { + .offset = 0x5000, + .config = &cam_cc_pll5_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = { + .offset = 0x5000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll5_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll5.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_taycan_eko_t_ops, + }, +}; + +static const struct parent_map cam_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL5_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll5_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EVEN, 3 }, + { P_CAM_CC_PLL2_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll2.clkr.hw }, + { .hw = &cam_cc_pll2.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll3_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL4_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll4_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll1_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map cam_cc_parent_map_6_ao[] = { + { P_BI_TCXO_AO, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6_ao[] = { + { .index = DT_BI_TCXO_AO }, +}; + +static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = { + F(160000000, P_CAM_CC_PLL0_OUT_ODD, 2.5, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_bps_clk_src = { + .cmd_rcgr = 0x10278, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_camnoc_axi_rt_clk_src[] = { + F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_camnoc_axi_rt_clk_src = { + .cmd_rcgr = 0x137b4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_camnoc_axi_rt_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_axi_rt_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = { + F(30000000, P_CAM_CC_PLL5_OUT_EVEN, 16, 0, 0), + F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .cmd_rcgr = 0x1350c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0x1363c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = { + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0x11168, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cphy_rx_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(266666667, P_CAM_CC_PLL0_OUT_ODD, 1.5, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x150e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x15104, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .cmd_rcgr = 0x15124, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_csid_clk_src = { + .cmd_rcgr = 0x1378c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = { + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x10018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_fast_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_icp_clk_src[] = { + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_icp_clk_src = { + .cmd_rcgr = 0x133cc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_icp_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = { + F(345600000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(432000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(727000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .cmd_rcgr = 0x11018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_1_clk_src[] = { + F(345600000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(432000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(727000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .cmd_rcgr = 0x12018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_1_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_lite_clk_src[] = { + F(266666667, P_CAM_CC_PLL0_OUT_ODD, 1.5, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0x13000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_lite_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0x13140, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_lite_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_nps_clk_src[] = { + F(304000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(364000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(500000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(700000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_nps_clk_src = { + .cmd_rcgr = 0x103d0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = { + F(160000000, P_CAM_CC_PLL0_OUT_ODD, 2.5, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0x13284, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_jpeg_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_CAM_CC_PLL2_OUT_MAIN, 10, 1, 4), + F(68571429, P_CAM_CC_PLL2_OUT_MAIN, 14, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .cmd_rcgr = 0x15000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk0_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .cmd_rcgr = 0x1501c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk1_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .cmd_rcgr = 0x15038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk2_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .cmd_rcgr = 0x15054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk3_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .cmd_rcgr = 0x15070, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk4_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk5_clk_src = { + .cmd_rcgr = 0x1508c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk5_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk6_clk_src = { + .cmd_rcgr = 0x150a8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk6_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 cam_cc_mclk7_clk_src = { + .cmd_rcgr = 0x150c4, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk7_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_qdss_debug_clk_src[] = { + F(60000000, P_CAM_CC_PLL5_OUT_EVEN, 8, 0, 0), + F(75000000, P_CAM_CC_PLL0_OUT_EVEN, 8, 0, 0), + F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_qdss_debug_clk_src = { + .cmd_rcgr = 0x137fc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sleep_clk_src = { + .cmd_rcgr = 0x13964, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_sleep_clk_src, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sleep_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = { + F(64000000, P_CAM_CC_PLL5_OUT_EVEN, 7.5, 0, 0), + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .cmd_rcgr = 0x10148, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_slow_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_xo_clk_src = { + .cmd_rcgr = 0x13948, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6_ao, + .freq_tbl = ftbl_cam_cc_xo_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_xo_clk_src", + .parent_data = cam_cc_parent_data_6_ao, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_6_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_ahb_clk = { + .halt_reg = 0x10274, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10274, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_clk = { + .halt_reg = 0x103a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x103a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_bps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_fast_ahb_clk = { + .halt_reg = 0x10144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_axi_nrt_clk = { + .halt_reg = 0x137e0, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x137e0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x137e0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_axi_nrt_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_axi_rt_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_axi_rt_clk = { + .halt_reg = 0x137cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_axi_rt_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_camnoc_axi_rt_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_dcd_xo_clk = { + .halt_reg = 0x137f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137f0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_dcd_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_xo_clk = { + .halt_reg = 0x137f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137f4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_0_clk = { + .halt_reg = 0x13638, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13638, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_1_clk = { + .halt_reg = 0x13768, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13768, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_core_ahb_clk = { + .halt_reg = 0x13944, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x13944, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_core_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ahb_clk = { + .halt_reg = 0x1376c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1376c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_bps_clk = { + .halt_reg = 0x103b4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x103b4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_bps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_bps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_fast_ahb_clk = { + .halt_reg = 0x1377c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1377c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ife_0_clk = { + .halt_reg = 0x11154, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11154, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ife_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ife_1_clk = { + .halt_reg = 0x12040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ife_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ife_lite_clk = { + .halt_reg = 0x1313c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1313c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ipe_nps_clk = { + .halt_reg = 0x1050c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1050c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi0phytimer_clk = { + .halt_reg = 0x150f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi1phytimer_clk = { + .halt_reg = 0x1511c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1511c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi4phytimer_clk = { + .halt_reg = 0x15250, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15250, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi4phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi4phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_clk = { + .halt_reg = 0x137a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_csiphy_rx_clk = { + .halt_reg = 0x15100, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15100, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_csiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy0_clk = { + .halt_reg = 0x150fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150fc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy1_clk = { + .halt_reg = 0x15120, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15120, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy4_clk = { + .halt_reg = 0x15254, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15254, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_ahb_clk = { + .halt_reg = 0x13508, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13508, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_clk = { + .halt_reg = 0x134f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x134f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_icp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_icp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_clk = { + .halt_reg = 0x11144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_dsp_clk = { + .halt_reg = 0x11158, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11158, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_dsp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_fast_ahb_clk = { + .halt_reg = 0x11164, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11164, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_clk = { + .halt_reg = 0x12030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12030, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_dsp_clk = { + .halt_reg = 0x12044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_dsp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_fast_ahb_clk = { + .halt_reg = 0x12050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_ahb_clk = { + .halt_reg = 0x13280, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13280, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_clk = { + .halt_reg = 0x1312c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1312c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = { + .halt_reg = 0x1327c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1327c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_csid_clk = { + .halt_reg = 0x1326c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1326c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_lite_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_lite_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_ahb_clk = { + .halt_reg = 0x10528, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10528, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_slow_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_clk = { + .halt_reg = 0x104fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x104fc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = { + .halt_reg = 0x1052c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1052c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_clk = { + .halt_reg = 0x10510, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10510, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = { + .halt_reg = 0x10530, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10530, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_fast_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_fast_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_clk = { + .halt_reg = 0x133b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x133b0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk0_clk = { + .halt_reg = 0x15018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk1_clk = { + .halt_reg = 0x15034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk2_clk = { + .halt_reg = 0x15050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk3_clk = { + .halt_reg = 0x1506c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1506c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk3_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk4_clk = { + .halt_reg = 0x15088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk4_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk5_clk = { + .halt_reg = 0x150a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150a4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk5_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk6_clk = { + .halt_reg = 0x150c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk6_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk7_clk = { + .halt_reg = 0x150dc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x150dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk7_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_clk = { + .halt_reg = 0x13928, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13928, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_qdss_debug_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_xo_clk = { + .halt_reg = 0x1392c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1392c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_xo_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc cam_cc_titan_top_gdsc = { + .gdscr = 0x13930, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_bps_gdsc = { + .gdscr = 0x10004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_bps_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ife_0_gdsc = { + .gdscr = 0x11004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ife_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ife_1_gdsc = { + .gdscr = 0x12004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ife_1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ipe_0_gdsc = { + .gdscr = 0x103bc, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ipe_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &cam_cc_titan_top_gdsc.pd, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *cam_cc_glymur_clocks[] = { + [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr, + [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr, + [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr, + [CAM_CC_BPS_FAST_AHB_CLK] = &cam_cc_bps_fast_ahb_clk.clkr, + [CAM_CC_CAMNOC_AXI_NRT_CLK] = &cam_cc_camnoc_axi_nrt_clk.clkr, + [CAM_CC_CAMNOC_AXI_RT_CLK] = &cam_cc_camnoc_axi_rt_clk.clkr, + [CAM_CC_CAMNOC_AXI_RT_CLK_SRC] = &cam_cc_camnoc_axi_rt_clk_src.clkr, + [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr, + [CAM_CC_CAMNOC_XO_CLK] = &cam_cc_camnoc_xo_clk.clkr, + [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr, + [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr, + [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr, + [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr, + [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr, + [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr, + [CAM_CC_CPAS_BPS_CLK] = &cam_cc_cpas_bps_clk.clkr, + [CAM_CC_CPAS_FAST_AHB_CLK] = &cam_cc_cpas_fast_ahb_clk.clkr, + [CAM_CC_CPAS_IFE_0_CLK] = &cam_cc_cpas_ife_0_clk.clkr, + [CAM_CC_CPAS_IFE_1_CLK] = &cam_cc_cpas_ife_1_clk.clkr, + [CAM_CC_CPAS_IFE_LITE_CLK] = &cam_cc_cpas_ife_lite_clk.clkr, + [CAM_CC_CPAS_IPE_NPS_CLK] = &cam_cc_cpas_ipe_nps_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr, + [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr, + [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr, + [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr, + [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr, + [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr, + [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr, + [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr, + [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.clkr, + [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr, + [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr, + [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, + [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr, + [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr, + [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr, + [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr, + [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr, + [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr, + [CAM_CC_IFE_0_FAST_AHB_CLK] = &cam_cc_ife_0_fast_ahb_clk.clkr, + [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr, + [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr, + [CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr, + [CAM_CC_IFE_1_FAST_AHB_CLK] = &cam_cc_ife_1_fast_ahb_clk.clkr, + [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr, + [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr, + [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr, + [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr, + [CAM_CC_IPE_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr, + [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr, + [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr, + [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr, + [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr, + [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr, + [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr, + [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr, + [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr, + [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr, + [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr, + [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr, + [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr, + [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr, + [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr, + [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr, + [CAM_CC_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr, + [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr, + [CAM_CC_MCLK5_CLK] = &cam_cc_mclk5_clk.clkr, + [CAM_CC_MCLK5_CLK_SRC] = &cam_cc_mclk5_clk_src.clkr, + [CAM_CC_MCLK6_CLK] = &cam_cc_mclk6_clk.clkr, + [CAM_CC_MCLK6_CLK_SRC] = &cam_cc_mclk6_clk_src.clkr, + [CAM_CC_MCLK7_CLK] = &cam_cc_mclk7_clk.clkr, + [CAM_CC_MCLK7_CLK_SRC] = &cam_cc_mclk7_clk_src.clkr, + [CAM_CC_PLL0] = &cam_cc_pll0.clkr, + [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr, + [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr, + [CAM_CC_PLL1] = &cam_cc_pll1.clkr, + [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr, + [CAM_CC_PLL2] = &cam_cc_pll2.clkr, + [CAM_CC_PLL3] = &cam_cc_pll3.clkr, + [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr, + [CAM_CC_PLL4] = &cam_cc_pll4.clkr, + [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr, + [CAM_CC_PLL5] = &cam_cc_pll5.clkr, + [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr, + [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr, + [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr, + [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr, + [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, + [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr, +}; + +static struct gdsc *cam_cc_glymur_gdscs[] = { + [CAM_CC_BPS_GDSC] = &cam_cc_bps_gdsc, + [CAM_CC_IFE_0_GDSC] = &cam_cc_ife_0_gdsc, + [CAM_CC_IFE_1_GDSC] = &cam_cc_ife_1_gdsc, + [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc, + [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc, +}; + +static const struct qcom_reset_map cam_cc_glymur_resets[] = { + [CAM_CC_BPS_BCR] = { 0x10000 }, + [CAM_CC_ICP_BCR] = { 0x133c8 }, + [CAM_CC_IFE_0_BCR] = { 0x11000 }, + [CAM_CC_IFE_1_BCR] = { 0x12000 }, + [CAM_CC_IPE_0_BCR] = { 0x103b8 }, + [CAM_CC_QDSS_DEBUG_BCR] = { 0x137f8 }, +}; + +static struct clk_alpha_pll *cam_cc_glymur_plls[] = { + &cam_cc_pll0, + &cam_cc_pll1, + &cam_cc_pll2, + &cam_cc_pll3, + &cam_cc_pll4, + &cam_cc_pll5, +}; + +static u32 cam_cc_glymur_critical_cbcrs[] = { + 0x13960, /* CAM_CC_GDSC_CLK */ + 0x1397c, /* CAM_CC_SLEEP_CLK */ +}; + +static const struct regmap_config cam_cc_glymur_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1603c, + .fast_io = true, +}; + +static struct qcom_cc_driver_data cam_cc_glymur_driver_data = { + .alpha_plls = cam_cc_glymur_plls, + .num_alpha_plls = ARRAY_SIZE(cam_cc_glymur_plls), + .clk_cbcrs = cam_cc_glymur_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(cam_cc_glymur_critical_cbcrs), +}; + +static const struct qcom_cc_desc cam_cc_glymur_desc = { + .config = &cam_cc_glymur_regmap_config, + .clks = cam_cc_glymur_clocks, + .num_clks = ARRAY_SIZE(cam_cc_glymur_clocks), + .resets = cam_cc_glymur_resets, + .num_resets = ARRAY_SIZE(cam_cc_glymur_resets), + .gdscs = cam_cc_glymur_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_glymur_gdscs), + .use_rpm = true, + .driver_data = &cam_cc_glymur_driver_data, +}; + +static const struct of_device_id cam_cc_glymur_match_table[] = { + { .compatible = "qcom,glymur-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_glymur_match_table); + +static int cam_cc_glymur_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &cam_cc_glymur_desc); +} + +static struct platform_driver cam_cc_glymur_driver = { + .probe = cam_cc_glymur_probe, + .driver = { + .name = "camcc-glymur", + .of_match_table = cam_cc_glymur_match_table, + }, +}; + +module_platform_driver(cam_cc_glymur_driver); + +MODULE_DESCRIPTION("QTI CAMCC GLYMUR Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/clk-gp-mnd.c b/drivers/clk/qcom/clk-gp-mnd.c new file mode 100644 index 0000000000000..826b6b62ddc7b --- /dev/null +++ b/drivers/clk/qcom/clk-gp-mnd.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * PDM GP_MND clock divider register offsets. + * + * The hardware computes: + * Fout = Fin * (M / N) + * + * with duty cycle controlled by D, where M < D < (N - M). + * + * Register encoding: + * MDIV = M + * NDIV = ~(N - M) [1's complement of (N - M), masked to N_REG_WIDTH bits] + * DUTY = D + */ +#define GP_MND_MDIV_REG 0x0 +#define GP_MND_NDIV_REG 0x4 +#define GP_MND_DUTY_REG 0x8 + +#define GP_MND_M_WIDTH 9 +#define GP_MND_N_WIDTH 13 + +#define GP_MND_MAX_M GENMASK(GP_MND_M_WIDTH - 1, 0) +#define GP_MND_MAX_N GENMASK(GP_MND_N_WIDTH - 1, 0) + +/** + * struct clk_gp_mnd - GP_MND fractional clock divider + * @pdm_ahb_clk: AHB bus clock required for register access + * @regmap: register map for the PDM block + * @hw: handle between common and hardware-specific interfaces + * @m_val: M value (numerator) + * @n_val: N value (period) + */ +struct clk_gp_mnd { + struct clk *pdm_ahb_clk; + struct regmap *regmap; + struct clk_hw hw; + unsigned int m_val; + unsigned int n_val; +}; + +#define to_clk_gp_mnd(_hw) container_of(_hw, struct clk_gp_mnd, hw) + +static int gp_mnd_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long m = 0, n = 0; + + rational_best_approximation(req->rate, req->best_parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* N = 2M + 1 leaves no valid D satisfying M < D < (N - M) */ + if (n == 2 * m + 1) + return -EINVAL; + + req->rate = DIV_ROUND_CLOSEST_ULL((u64)req->best_parent_rate * m, n); + + return 0; +} + +static int gp_mnd_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned long m = 0, n = 0; + unsigned int d_val, n_val; + int ret; + + rational_best_approximation(rate, parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* + * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty + * cycle can satisfy M < D < (N - M). Reject before touching hw. + */ + if (n == 2 * m + 1) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_MDIV_REG, m); + if (ret) + goto err_unprepare; + + /* N divider holds the 1's complement of (N - M), N_WIDTH bits wide */ + n_val = ~(n - m) & GP_MND_MAX_N; + ret = regmap_write(gp->regmap, GP_MND_NDIV_REG, n_val); + if (ret) + goto err_unprepare; + + /* Program the closest-to-50% duty cycle. */ + d_val = n / 2; + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + if (ret) + goto err_unprepare; + + gp->m_val = m; + gp->n_val = n; + +err_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static unsigned long gp_mnd_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int m_val, n_val; + int ret; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return 0; + + ret = regmap_read(gp->regmap, GP_MND_MDIV_REG, &m_val); + if (ret) + goto out_unprepare; + + m_val &= GP_MND_MAX_M; + + ret = regmap_read(gp->regmap, GP_MND_NDIV_REG, &n_val); + if (ret) + goto out_unprepare; + + /* Reverse the 1's complement encoding: N = ~NDIV_REG + M */ + n_val = (~n_val & GP_MND_MAX_N) + m_val; + +out_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return 0; + + if (!n_val) + return 0; + + gp->m_val = m_val; + gp->n_val = n_val; + + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * m_val, n_val); +} + +static int gp_mnd_clk_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val) { + duty->num = 1; + duty->den = 2; + return 0; + } + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_read(gp->regmap, GP_MND_DUTY_REG, &d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return ret; + + duty->num = d_val; + duty->den = gp->n_val; + + return 0; +} + +static int gp_mnd_clk_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val || !gp->m_val) + return -EINVAL; + + /* D = (1 - duty) * N, giving the low-phase count */ + d_val = DIV_ROUND_UP((u64)(duty->den - duty->num) * gp->n_val, duty->den); + + /* Hardware constraint: M < D < (N - M) */ + if (d_val <= gp->m_val || d_val >= (gp->n_val - gp->m_val)) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static const struct clk_ops clk_gp_mnd_ops = { + .determine_rate = gp_mnd_clk_determine_rate, + .set_rate = gp_mnd_clk_set_rate, + .recalc_rate = gp_mnd_clk_recalc_rate, + .get_duty_cycle = gp_mnd_clk_get_duty_cycle, + .set_duty_cycle = gp_mnd_clk_set_duty_cycle, +}; + +static const struct regmap_config gp_mnd_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static int clk_gp_mnd_probe(struct platform_device *pdev) +{ + struct clk_parent_data parent_data = { .index = 0 }; + struct clk_init_data init = { + .ops = &clk_gp_mnd_ops, + .parent_data = &parent_data, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }; + struct device *dev = &pdev->dev; + struct clk_gp_mnd *gp; + struct clk *clk; + struct pinctrl *pin; + struct pinctrl_state *pin_default_state; + void __iomem *base; + int ret; + + gp = devm_kzalloc(dev, sizeof(*gp), GFP_KERNEL); + if (!gp) + return -ENOMEM; + + gp->pdm_ahb_clk = devm_clk_get(dev, "ahb_clk"); + if (IS_ERR(gp->pdm_ahb_clk)) + return dev_err_probe(dev, PTR_ERR(gp->pdm_ahb_clk), + "failed to get ahb_clk\n"); + + clk = devm_clk_get(dev, "pdm_clk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + /* Set default rate if not already configured */ + if (!clk_get_rate(clk)) { + ret = clk_set_rate(clk, 19200000); + if (ret) + dev_warn(dev, "failed to set default pdm_clk rate\n"); + } + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "failed to map PDM registers\n"); + + gp->regmap = devm_regmap_init_mmio(dev, base, &gp_mnd_regmap_config); + if (IS_ERR(gp->regmap)) + return dev_err_probe(dev, PTR_ERR(gp->regmap), + "failed to init regmap\n"); + + ret = of_property_read_string_index(dev->of_node, + "clock-output-names", 0, + &init.name); + if (ret) + return dev_err_probe(dev, ret, "missing clock-output-names\n"); + + gp->hw.init = &init; + + pin = devm_pinctrl_get(dev); + if (IS_ERR(pin)) + return dev_err_probe(dev, PTR_ERR(pin), "missing pinctrl device\n"); + + pin_default_state = pinctrl_lookup_state(pin, "active"); + if (IS_ERR(pin_default_state)) + return dev_err_probe(dev, PTR_ERR(pin_default_state), + "missing pinctrl default state\n"); + + ret = pinctrl_select_state(pin, pin_default_state); + if (ret) + return dev_err_probe(dev, ret, + "failed to select pinctrl default state\n"); + + ret = devm_clk_hw_register(dev, &gp->hw); + if (ret) + return dev_err_probe(dev, ret, + "failed to register gp_mnd clock\n"); + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &gp->hw); +} + +static const struct of_device_id clk_gp_mnd_match_table[] = { + { .compatible = "qcom,clk-gp-mnd" }, + { } +}; +MODULE_DEVICE_TABLE(of, clk_gp_mnd_match_table); + +static struct platform_driver clk_gp_mnd_driver = { + .probe = clk_gp_mnd_probe, + .driver = { + .name = "qcom-clk-gp-mnd", + .of_match_table = clk_gp_mnd_match_table, + }, +}; +module_platform_driver(clk_gp_mnd_driver); + +MODULE_DESCRIPTION("Qualcomm PDM GP_MND clock divider driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 103db984a40b9..0b624ed4715c7 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -495,6 +495,7 @@ DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(rf_clk2, 5, 19200000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(rf_clk3, 6, 19200000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(ln_bb_clk, 8, 19200000); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PREFIX(38m4_, rf_clk2, 5, 38400000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PREFIX(38m4_, rf_clk3, 6, 38400000); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(cxo_d0, 1, 19200000); @@ -1262,6 +1263,10 @@ static struct clk_smd_rpm *qcm2290_clks[] = { [RPM_SMD_QDSS_A_CLK] = &clk_smd_rpm_branch_qdss_a_clk, [RPM_SMD_LN_BB_CLK2] = &clk_smd_rpm_ln_bb_clk2, [RPM_SMD_LN_BB_CLK2_A] = &clk_smd_rpm_ln_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &clk_smd_rpm_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &clk_smd_rpm_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &clk_smd_rpm_38m4_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &clk_smd_rpm_38m4_rf_clk2_a, [RPM_SMD_RF_CLK3] = &clk_smd_rpm_38m4_rf_clk3, [RPM_SMD_RF_CLK3_A] = &clk_smd_rpm_38m4_rf_clk3_a, [RPM_SMD_IPA_CLK] = &clk_smd_rpm_ipa_clk, diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index eec369d2173b5..23987130c23fa 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -359,17 +359,19 @@ int qcom_cc_really_probe(struct device *dev, qcom_cc_clk_regs_configure(dev, desc->driver_data, regmap); } - reset = &cc->reset; - reset->rcdev.of_node = dev->of_node; - reset->rcdev.ops = &qcom_reset_ops; - reset->rcdev.owner = dev->driver->owner; - reset->rcdev.nr_resets = desc->num_resets; - reset->regmap = regmap; - reset->reset_map = desc->resets; - - ret = devm_reset_controller_register(dev, &reset->rcdev); - if (ret) - goto put_rpm; + if (desc->num_resets) { + reset = &cc->reset; + reset->rcdev.of_node = dev->of_node; + reset->rcdev.ops = &qcom_reset_ops; + reset->rcdev.owner = dev->driver->owner; + reset->rcdev.nr_resets = desc->num_resets; + reset->regmap = regmap; + reset->reset_map = desc->resets; + + ret = devm_reset_controller_register(dev, &reset->rcdev); + if (ret) + goto put_rpm; + } if (desc->gdscs && desc->num_gdscs) { scd = devm_kzalloc(dev, sizeof(*scd), GFP_KERNEL); @@ -406,6 +408,9 @@ int qcom_cc_really_probe(struct device *dev, qcom_cc_drop_protected(dev, cc); for (i = 0; i < num_clk_hws; i++) { + if (!clk_hws[i]) + continue; + ret = devm_clk_hw_register(dev, clk_hws[i]); if (ret) goto put_rpm; @@ -428,7 +433,7 @@ int qcom_cc_really_probe(struct device *dev, put_rpm: if (desc->use_rpm) - pm_runtime_put(dev); + pm_runtime_put_sync(dev); return ret; } diff --git a/drivers/clk/qcom/dispcc-qcm2290.c b/drivers/clk/qcom/dispcc-qcm2290.c index 6d88d067337fa..5109c8e0f4add 100644 --- a/drivers/clk/qcom/dispcc-qcm2290.c +++ b/drivers/clk/qcom/dispcc-qcm2290.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * Copyright (c) 2021, Linaro Ltd. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -23,6 +24,18 @@ #include "gdsc.h" #include "reset.h" +enum { + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_GPLL0_OUT_DIV, + DT_GPLL0, + DT_DSI0_PHY_PLL_OUT_BYTECLK, + DT_DSI0_PHY_PLL_OUT_DSICLK, + DT_DSI1_PHY_PLL_OUT_BYTECLK, + DT_DSI1_PHY_PLL_OUT_DSICLK, + DT_SLEEP_CLK, +}; + enum { P_BI_TCXO, P_BI_TCXO_AO, @@ -32,6 +45,8 @@ enum { P_GPLL0_OUT_DIV, P_GPLL0_OUT_MAIN, P_SLEEP_CLK, + P_DSI1_PHY_PLL_OUT_BYTECLK, + P_DSI1_PHY_PLL_OUT_DSICLK, }; static const struct pll_vco spark_vco[] = { @@ -49,6 +64,7 @@ static const struct alpha_pll_config disp_cc_pll0_config = { static struct clk_alpha_pll disp_cc_pll0 = { .offset = 0x0, + .config = &disp_cc_pll0_config, .vco_table = spark_vco, .num_vco = ARRAY_SIZE(spark_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], @@ -56,7 +72,7 @@ static struct clk_alpha_pll disp_cc_pll0 = { .hw.init = &(struct clk_init_data){ .name = "disp_cc_pll0", .parent_data = &(const struct clk_parent_data){ - .fw_name = "bi_tcxo", + .index = DT_BI_TCXO, }, .num_parents = 1, .ops = &clk_alpha_pll_ops, @@ -70,8 +86,8 @@ static const struct parent_map disp_cc_parent_map_0[] = { }; static const struct clk_parent_data disp_cc_parent_data_0[] = { - { .fw_name = "bi_tcxo" }, - { .fw_name = "dsi0_phy_pll_out_byteclk" }, + { .index = DT_BI_TCXO }, + { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK }, }; static const struct parent_map disp_cc_parent_map_1[] = { @@ -79,17 +95,17 @@ static const struct parent_map disp_cc_parent_map_1[] = { }; static const struct clk_parent_data disp_cc_parent_data_1[] = { - { .fw_name = "bi_tcxo" }, + { .index = DT_BI_TCXO }, }; static const struct parent_map disp_cc_parent_map_2[] = { { P_BI_TCXO_AO, 0 }, - { P_GPLL0_OUT_DIV, 4 }, + { P_GPLL0_OUT_MAIN, 4 }, }; static const struct clk_parent_data disp_cc_parent_data_2[] = { - { .fw_name = "bi_tcxo_ao" }, - { .fw_name = "gcc_disp_gpll0_div_clk_src" }, + { .index = DT_BI_TCXO_AO }, + { .index = DT_GPLL0 }, }; static const struct parent_map disp_cc_parent_map_3[] = { @@ -99,19 +115,21 @@ static const struct parent_map disp_cc_parent_map_3[] = { }; static const struct clk_parent_data disp_cc_parent_data_3[] = { - { .fw_name = "bi_tcxo" }, + { .index = DT_BI_TCXO }, { .hw = &disp_cc_pll0.clkr.hw }, - { .fw_name = "gcc_disp_gpll0_clk_src" }, + { .index = DT_GPLL0 }, }; static const struct parent_map disp_cc_parent_map_4[] = { { P_BI_TCXO, 0 }, { P_DSI0_PHY_PLL_OUT_DSICLK, 1 }, + { P_DSI1_PHY_PLL_OUT_DSICLK, 2 }, }; static const struct clk_parent_data disp_cc_parent_data_4[] = { - { .fw_name = "bi_tcxo" }, - { .fw_name = "dsi0_phy_pll_out_dsiclk" }, + { .index = DT_BI_TCXO }, + { .index = DT_DSI0_PHY_PLL_OUT_DSICLK }, + { .index = DT_DSI1_PHY_PLL_OUT_DSICLK }, }; static const struct parent_map disp_cc_parent_map_5[] = { @@ -119,7 +137,7 @@ static const struct parent_map disp_cc_parent_map_5[] = { }; static const struct clk_parent_data disp_cc_parent_data_5[] = { - { .fw_name = "sleep_clk" }, + { .index = DT_SLEEP_CLK }, }; static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = { @@ -153,8 +171,8 @@ static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { F(19200000, P_BI_TCXO_AO, 1, 0, 0), - F(37500000, P_GPLL0_OUT_DIV, 8, 0, 0), - F(75000000, P_GPLL0_OUT_DIV, 4, 0, 0), + F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0), { } }; @@ -450,11 +468,14 @@ static const struct qcom_reset_map disp_cc_qcm2290_resets[] = { static struct gdsc mdss_gdsc = { .gdscr = 0x3000, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, .pd = { .name = "mdss_gdsc", }, .pwrsts = PWRSTS_OFF_ON, - .flags = HW_CTRL, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; static struct gdsc *disp_cc_qcm2290_gdscs[] = { @@ -483,6 +504,14 @@ static struct clk_regmap *disp_cc_qcm2290_clocks[] = { [DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr, }; +static struct clk_alpha_pll *disp_cc_qcm2290_plls[] = { + &disp_cc_pll0, +}; + +static u32 disp_cc_qcm2290_critical_cbcrs[] = { + 0x604c, /* DISP_CC_XO_CLK */ +}; + static const struct regmap_config disp_cc_qcm2290_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -491,6 +520,13 @@ static const struct regmap_config disp_cc_qcm2290_regmap_config = { .fast_io = true, }; +static struct qcom_cc_driver_data disp_cc_qcm2290_driver_data = { + .alpha_plls = disp_cc_qcm2290_plls, + .num_alpha_plls = ARRAY_SIZE(disp_cc_qcm2290_plls), + .clk_cbcrs = disp_cc_qcm2290_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(disp_cc_qcm2290_critical_cbcrs), +}; + static const struct qcom_cc_desc disp_cc_qcm2290_desc = { .config = &disp_cc_qcm2290_regmap_config, .clks = disp_cc_qcm2290_clocks, @@ -499,6 +535,7 @@ static const struct qcom_cc_desc disp_cc_qcm2290_desc = { .num_gdscs = ARRAY_SIZE(disp_cc_qcm2290_gdscs), .resets = disp_cc_qcm2290_resets, .num_resets = ARRAY_SIZE(disp_cc_qcm2290_resets), + .driver_data = &disp_cc_qcm2290_driver_data, }; static const struct of_device_id disp_cc_qcm2290_match_table[] = { @@ -509,25 +546,7 @@ MODULE_DEVICE_TABLE(of, disp_cc_qcm2290_match_table); static int disp_cc_qcm2290_probe(struct platform_device *pdev) { - struct regmap *regmap; - int ret; - - regmap = qcom_cc_map(pdev, &disp_cc_qcm2290_desc); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - clk_alpha_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config); - - /* Keep some clocks always-on */ - qcom_branch_set_clk_en(regmap, 0x604c); /* DISP_CC_XO_CLK */ - - ret = qcom_cc_really_probe(&pdev->dev, &disp_cc_qcm2290_desc, regmap); - if (ret) { - dev_err(&pdev->dev, "Failed to register DISP CC clocks\n"); - return ret; - } - - return ret; + return qcom_cc_probe(pdev, &disp_cc_qcm2290_desc); } static struct platform_driver disp_cc_qcm2290_driver = { diff --git a/drivers/clk/qcom/evacc-glymur.c b/drivers/clk/qcom/evacc-glymur.c new file mode 100644 index 0000000000000..eab43ba922f37 --- /dev/null +++ b/drivers/clk/qcom/evacc-glymur.c @@ -0,0 +1,453 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_AHB_CLK, + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, +}; + +enum { + P_BI_TCXO, + P_EVA_CC_PLL0_OUT_MAIN, + P_SLEEP_CLK, +}; + +static const struct pll_vco taycan_eko_t_vco[] = { + { 249600000, 2500000000, 0 }, +}; + +/* 840.0 MHz Configuration */ +static const struct alpha_pll_config eva_cc_pll0_config = { + .l = 0x2b, + .alpha = 0xc000, + .config_ctl_val = 0x25c400e7, + .config_ctl_hi_val = 0x0a8060e0, + .config_ctl_hi1_val = 0xf51dea20, + .user_ctl_val = 0x00000008, + .user_ctl_hi_val = 0x00000002, +}; + +static struct clk_alpha_pll eva_cc_pll0 = { + .offset = 0x0, + .config = &eva_cc_pll0_config, + .vco_table = taycan_eko_t_vco, + .num_vco = ARRAY_SIZE(taycan_eko_t_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_taycan_eko_t_ops, + }, + }, +}; + +static const struct parent_map eva_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data eva_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map eva_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_EVA_CC_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data eva_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &eva_cc_pll0.clkr.hw }, +}; + +static const struct parent_map eva_cc_parent_map_2[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data eva_cc_parent_data_2[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_eva_cc_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 eva_cc_ahb_clk_src = { + .cmd_rcgr = 0x8018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_0, + .freq_tbl = ftbl_eva_cc_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_ahb_clk_src", + .parent_data = eva_cc_parent_data_0, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_eva_cc_mvs0_clk_src[] = { + F(840000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1050000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1350000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1500000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1650000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 eva_cc_mvs0_clk_src = { + .cmd_rcgr = 0x8000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_1, + .freq_tbl = ftbl_eva_cc_mvs0_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_clk_src", + .parent_data = eva_cc_parent_data_1, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_eva_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 eva_cc_sleep_clk_src = { + .cmd_rcgr = 0x80e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_2, + .freq_tbl = ftbl_eva_cc_sleep_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_sleep_clk_src", + .parent_data = eva_cc_parent_data_2, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_rcg2 eva_cc_xo_clk_src = { + .cmd_rcgr = 0x80bc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = eva_cc_parent_map_0, + .freq_tbl = ftbl_eva_cc_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_xo_clk_src", + .parent_data = eva_cc_parent_data_0, + .num_parents = ARRAY_SIZE(eva_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, + }, +}; + +static struct clk_regmap_div eva_cc_mvs0_div_clk_src = { + .reg = 0x809c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div eva_cc_mvs0c_div2_div_clk_src = { + .reg = 0x8060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch eva_cc_mvs0_clk = { + .halt_reg = 0x807c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x807c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x807c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0_freerun_clk = { + .halt_reg = 0x808c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x808c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_freerun_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0_shift_clk = { + .halt_reg = 0x80d8, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80d8, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0c_clk = { + .halt_reg = 0x804c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x804c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0c_freerun_clk = { + .halt_reg = 0x805c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x805c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_freerun_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch eva_cc_mvs0c_shift_clk = { + .halt_reg = 0x80dc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80dc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80dc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "eva_cc_mvs0c_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &eva_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc eva_cc_mvs0c_gdsc = { + .gdscr = 0x8034, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "eva_cc_mvs0c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc eva_cc_mvs0_gdsc = { + .gdscr = 0x8068, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "eva_cc_mvs0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, + .parent = &eva_cc_mvs0c_gdsc.pd, +}; + +static struct clk_regmap *eva_cc_glymur_clocks[] = { + [EVA_CC_AHB_CLK_SRC] = &eva_cc_ahb_clk_src.clkr, + [EVA_CC_MVS0_CLK] = &eva_cc_mvs0_clk.clkr, + [EVA_CC_MVS0_CLK_SRC] = &eva_cc_mvs0_clk_src.clkr, + [EVA_CC_MVS0_DIV_CLK_SRC] = &eva_cc_mvs0_div_clk_src.clkr, + [EVA_CC_MVS0_FREERUN_CLK] = &eva_cc_mvs0_freerun_clk.clkr, + [EVA_CC_MVS0_SHIFT_CLK] = &eva_cc_mvs0_shift_clk.clkr, + [EVA_CC_MVS0C_CLK] = &eva_cc_mvs0c_clk.clkr, + [EVA_CC_MVS0C_DIV2_DIV_CLK_SRC] = &eva_cc_mvs0c_div2_div_clk_src.clkr, + [EVA_CC_MVS0C_FREERUN_CLK] = &eva_cc_mvs0c_freerun_clk.clkr, + [EVA_CC_MVS0C_SHIFT_CLK] = &eva_cc_mvs0c_shift_clk.clkr, + [EVA_CC_PLL0] = &eva_cc_pll0.clkr, + [EVA_CC_SLEEP_CLK_SRC] = &eva_cc_sleep_clk_src.clkr, + [EVA_CC_XO_CLK_SRC] = &eva_cc_xo_clk_src.clkr, +}; + +static struct gdsc *eva_cc_glymur_gdscs[] = { + [EVA_CC_MVS0_GDSC] = &eva_cc_mvs0_gdsc, + [EVA_CC_MVS0C_GDSC] = &eva_cc_mvs0c_gdsc, +}; + +static const struct qcom_reset_map eva_cc_glymur_resets[] = { + [EVA_CC_INTERFACE_BCR] = { 0x80a0 }, + [EVA_CC_MVS0_BCR] = { 0x8064 }, + [EVA_CC_MVS0C_CLK_ARES] = { 0x804c, 2 }, + [EVA_CC_MVS0C_BCR] = { 0x8030 }, + [EVA_CC_MVS0C_FREERUN_CLK_ARES] = { 0x805c, 2 }, +}; + +static struct clk_alpha_pll *eva_cc_glymur_plls[] = { + &eva_cc_pll0, +}; + +static const u32 eva_cc_glymur_critical_cbcrs[] = { + 0x80a4, /* EVA_CC_AHB_CLK */ + 0x80f8, /* EVA_CC_SLEEP_CLK */ + 0x80d4, /* EVA_CC_XO_CLK */ +}; + +static const struct regmap_config eva_cc_glymur_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9f50, + .fast_io = true, +}; + +static void clk_glymur_regs_configure(struct device *dev, struct regmap *regmap) +{ + /* Update CTRL_IN register */ + regmap_update_bits(regmap, 0x9f24, BIT(0), BIT(0)); +} + +static const struct qcom_cc_driver_data eva_cc_glymur_driver_data = { + .alpha_plls = eva_cc_glymur_plls, + .num_alpha_plls = ARRAY_SIZE(eva_cc_glymur_plls), + .clk_cbcrs = eva_cc_glymur_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(eva_cc_glymur_critical_cbcrs), + .clk_regs_configure = clk_glymur_regs_configure, +}; + +static const struct qcom_cc_desc eva_cc_glymur_desc = { + .config = &eva_cc_glymur_regmap_config, + .clks = eva_cc_glymur_clocks, + .num_clks = ARRAY_SIZE(eva_cc_glymur_clocks), + .resets = eva_cc_glymur_resets, + .num_resets = ARRAY_SIZE(eva_cc_glymur_resets), + .gdscs = eva_cc_glymur_gdscs, + .num_gdscs = ARRAY_SIZE(eva_cc_glymur_gdscs), + .use_rpm = true, + .driver_data = &eva_cc_glymur_driver_data, +}; + +static const struct of_device_id eva_cc_glymur_match_table[] = { + { .compatible = "qcom,glymur-evacc" }, + { } +}; +MODULE_DEVICE_TABLE(of, eva_cc_glymur_match_table); + +static int eva_cc_glymur_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &eva_cc_glymur_desc); +} + +static struct platform_driver eva_cc_glymur_driver = { + .probe = eva_cc_glymur_probe, + .driver = { + .name = "evacc-glymur", + .of_match_table = eva_cc_glymur_match_table, + }, +}; + +module_platform_driver(eva_cc_glymur_driver); + +MODULE_DESCRIPTION("QTI EVACC Glymur Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/gcc-glymur.c b/drivers/clk/qcom/gcc-glymur.c index 2736465efdea9..32d23bdc819b7 100644 --- a/drivers/clk/qcom/gcc-glymur.c +++ b/drivers/clk/qcom/gcc-glymur.c @@ -3669,21 +3669,6 @@ static struct clk_branch gcc_disp_hf_axi_clk = { }, }; -static struct clk_branch gcc_eva_ahb_clk = { - .halt_reg = 0x9b004, - .halt_check = BRANCH_HALT_VOTED, - .hwcg_reg = 0x9b004, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x9b004, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gcc_eva_ahb_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_eva_axi0_clk = { .halt_reg = 0x9b008, .halt_check = BRANCH_HALT_SKIP, @@ -3714,19 +3699,6 @@ static struct clk_branch gcc_eva_axi0c_clk = { }, }; -static struct clk_branch gcc_eva_xo_clk = { - .halt_reg = 0x9b024, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x9b024, - .enable_mask = BIT(0), - .hw.init = &(const struct clk_init_data) { - .name = "gcc_eva_xo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gp1_clk = { .halt_reg = 0x64000, .halt_check = BRANCH_HALT, @@ -7993,10 +7965,8 @@ static struct clk_regmap *gcc_glymur_clocks[] = { [GCC_CFG_NOC_USB_ANOC_AHB_CLK] = &gcc_cfg_noc_usb_anoc_ahb_clk.clkr, [GCC_CFG_NOC_USB_ANOC_SOUTH_AHB_CLK] = &gcc_cfg_noc_usb_anoc_south_ahb_clk.clkr, [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, - [GCC_EVA_AHB_CLK] = &gcc_eva_ahb_clk.clkr, [GCC_EVA_AXI0_CLK] = &gcc_eva_axi0_clk.clkr, [GCC_EVA_AXI0C_CLK] = &gcc_eva_axi0c_clk.clkr, - [GCC_EVA_XO_CLK] = &gcc_eva_xo_clk.clkr, [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, @@ -8545,6 +8515,8 @@ static const u32 gcc_glymur_critical_cbcrs[] = { 0x71004, /* GCC_GPU_CFG_AHB_CLK */ 0x32004, /* GCC_VIDEO_AHB_CLK */ 0x32058, /* GCC_VIDEO_XO_CLK */ + 0x9b004, /* GCC_EVA_AHB_CLK */ + 0x9b024, /* GCC_EVA_XO_CLK */ }; static const struct regmap_config gcc_glymur_regmap_config = { diff --git a/drivers/clk/qcom/gcc-qcm2290.c b/drivers/clk/qcom/gcc-qcm2290.c index 6684cab63ae11..8751e057d8973 100644 --- a/drivers/clk/qcom/gcc-qcm2290.c +++ b/drivers/clk/qcom/gcc-qcm2290.c @@ -1397,36 +1397,6 @@ static struct clk_branch gcc_cam_throttle_rt_clk = { }, }; -static struct clk_branch gcc_camera_ahb_clk = { - .halt_reg = 0x17008, - .halt_check = BRANCH_HALT_DELAY, - .hwcg_reg = 0x17008, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x17008, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_camera_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gcc_camera_xo_clk = { - .halt_reg = 0x17028, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x17028, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_camera_xo_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_camss_axi_clk = { .halt_reg = 0x58044, .halt_check = BRANCH_HALT, @@ -1825,22 +1795,6 @@ static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { }, }; -static struct clk_branch gcc_disp_ahb_clk = { - .halt_reg = 0x1700c, - .halt_check = BRANCH_HALT, - .hwcg_reg = 0x1700c, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x1700c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_disp_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_regmap_div gcc_disp_gpll0_clk_src = { .reg = 0x17058, .shift = 0, @@ -1899,20 +1853,6 @@ static struct clk_branch gcc_disp_throttle_core_clk = { }, }; -static struct clk_branch gcc_disp_xo_clk = { - .halt_reg = 0x1702c, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x1702c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_disp_xo_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gp1_clk = { .halt_reg = 0x4d000, .halt_check = BRANCH_HALT, @@ -1964,22 +1904,6 @@ static struct clk_branch gcc_gp3_clk = { }, }; -static struct clk_branch gcc_gpu_cfg_ahb_clk = { - .halt_reg = 0x36004, - .halt_check = BRANCH_HALT, - .hwcg_reg = 0x36004, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x36004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_gpu_cfg_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gpu_gpll0_clk_src = { .halt_check = BRANCH_HALT_DELAY, .clkr = { @@ -2012,19 +1936,6 @@ static struct clk_branch gcc_gpu_gpll0_div_clk_src = { }, }; -static struct clk_branch gcc_gpu_iref_clk = { - .halt_reg = 0x36100, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x36100, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_gpu_iref_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gpu_memnoc_gfx_clk = { .halt_reg = 0x3600c, .halt_check = BRANCH_VOTED, @@ -2439,22 +2350,6 @@ static struct clk_branch gcc_sdcc2_apps_clk = { }, }; -static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = { - .halt_reg = 0x2b06c, - .halt_check = BRANCH_HALT_VOTED, - .hwcg_reg = 0x2b06c, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x79004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_sys_noc_cpuss_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_sys_noc_usb3_prim_axi_clk = { .halt_reg = 0x1a080, .halt_check = BRANCH_HALT, @@ -2605,21 +2500,6 @@ static struct clk_branch gcc_venus_ctl_axi_clk = { }, }; -static struct clk_branch gcc_video_ahb_clk = { - .halt_reg = 0x17004, - .halt_check = BRANCH_HALT, - .hwcg_reg = 0x17004, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x17004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_video_ahb_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_video_axi0_clk = { .halt_reg = 0x1701c, .halt_check = BRANCH_HALT, @@ -2686,19 +2566,6 @@ static struct clk_branch gcc_video_venus_ctl_clk = { }, }; -static struct clk_branch gcc_video_xo_clk = { - .halt_reg = 0x17024, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x17024, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_video_xo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct gdsc gcc_camss_top_gdsc = { .gdscr = 0x58004, .pd = { @@ -2775,8 +2642,6 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, [GCC_CAM_THROTTLE_NRT_CLK] = &gcc_cam_throttle_nrt_clk.clkr, [GCC_CAM_THROTTLE_RT_CLK] = &gcc_cam_throttle_rt_clk.clkr, - [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr, - [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, [GCC_CAMSS_AXI_CLK] = &gcc_camss_axi_clk.clkr, [GCC_CAMSS_AXI_CLK_SRC] = &gcc_camss_axi_clk_src.clkr, [GCC_CAMSS_CAMNOC_ATB_CLK] = &gcc_camss_camnoc_atb_clk.clkr, @@ -2817,22 +2682,18 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr, [GCC_CAMSS_TOP_AHB_CLK_SRC] = &gcc_camss_top_ahb_clk_src.clkr, [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, - [GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr, [GCC_DISP_GPLL0_CLK_SRC] = &gcc_disp_gpll0_clk_src.clkr, [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, [GCC_DISP_THROTTLE_CORE_CLK] = &gcc_disp_throttle_core_clk.clkr, - [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, - [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr, [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, - [GCC_GPU_IREF_CLK] = &gcc_gpu_iref_clk.clkr, [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, [GCC_GPU_THROTTLE_CORE_CLK] = &gcc_gpu_throttle_core_clk.clkr, @@ -2870,7 +2731,6 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, - [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr, [GCC_SYS_NOC_USB3_PRIM_AXI_CLK] = &gcc_sys_noc_usb3_prim_axi_clk.clkr, [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, @@ -2887,13 +2747,11 @@ static struct clk_regmap *gcc_qcm2290_clocks[] = { [GCC_VCODEC0_AXI_CLK] = &gcc_vcodec0_axi_clk.clkr, [GCC_VENUS_AHB_CLK] = &gcc_venus_ahb_clk.clkr, [GCC_VENUS_CTL_AXI_CLK] = &gcc_venus_ctl_axi_clk.clkr, - [GCC_VIDEO_AHB_CLK] = &gcc_video_ahb_clk.clkr, [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr, [GCC_VIDEO_VCODEC0_SYS_CLK] = &gcc_video_vcodec0_sys_clk.clkr, [GCC_VIDEO_VENUS_CLK_SRC] = &gcc_video_venus_clk_src.clkr, [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr, - [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, [GPLL0] = &gpll0.clkr, [GPLL0_OUT_AUX2] = &gpll0_out_aux2.clkr, [GPLL1] = &gpll1.clkr, @@ -2943,6 +2801,18 @@ static struct gdsc *gcc_qcm2290_gdscs[] = { [HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc, }; +static u32 gcc_qcm2290_critical_cbcrs[] = { + 0x17008, /* GCC_CAMERA_AHB_CLK */ + 0x17028, /* GCC_CAMERA_XO_CLK */ + 0x1700c, /* GCC_DISP_AHB_CLK */ + 0x1702c, /* GCC_DISP_XO_CLK */ + 0x36004, /* GCC_GPU_CFG_AHB_CLK */ + 0x36100, /* GCC_GPU_IREF_CLK */ + 0x79004, /* GCC_SYS_NOC_CPUSS_AHB_CLK */ + 0x17004, /* GCC_VIDEO_AHB_CLK */ + 0x17024, /* GCC_VIDEO_XO_CLK */ +}; + static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = { DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), @@ -2960,6 +2830,11 @@ static const struct regmap_config gcc_qcm2290_regmap_config = { .fast_io = true, }; +static struct qcom_cc_driver_data gcc_qcm2290_driver_data = { + .clk_cbcrs = gcc_qcm2290_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gcc_qcm2290_critical_cbcrs), +}; + static const struct qcom_cc_desc gcc_qcm2290_desc = { .config = &gcc_qcm2290_regmap_config, .clks = gcc_qcm2290_clocks, @@ -2968,6 +2843,7 @@ static const struct qcom_cc_desc gcc_qcm2290_desc = { .num_resets = ARRAY_SIZE(gcc_qcm2290_resets), .gdscs = gcc_qcm2290_gdscs, .num_gdscs = ARRAY_SIZE(gcc_qcm2290_gdscs), + .driver_data = &gcc_qcm2290_driver_data, }; static const struct of_device_id gcc_qcm2290_match_table[] = { diff --git a/drivers/clk/qcom/gcc-qcs615.c b/drivers/clk/qcom/gcc-qcs615.c index 5b3b8dd4f114b..4e2a9879951f2 100644 --- a/drivers/clk/qcom/gcc-qcs615.c +++ b/drivers/clk/qcom/gcc-qcs615.c @@ -2675,6 +2675,7 @@ static struct gdsc usb20_sec_gdsc = { .clk_dis_wait_val = 0x2, .pd = { .name = "usb20_sec_gdsc", + .power_off = gdsc_synced_poweroff_disable, }, .pwrsts = PWRSTS_OFF_ON, }; @@ -2686,6 +2687,7 @@ static struct gdsc usb30_prim_gdsc = { .clk_dis_wait_val = 0x2, .pd = { .name = "usb30_prim_gdsc", + .power_off = gdsc_synced_poweroff_disable, }, .pwrsts = PWRSTS_OFF_ON, }; diff --git a/drivers/clk/qcom/gcc-shikra.c b/drivers/clk/qcom/gcc-shikra.c new file mode 100644 index 0000000000000..e7b692d7d3496 --- /dev/null +++ b/drivers/clk/qcom/gcc-shikra.c @@ -0,0 +1,4432 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "clk-regmap-phy-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_EMAC0_SGMIIPHY_RCLK, + DT_EMAC0_SGMIIPHY_TCLK, + DT_EMAC1_SGMIIPHY_RCLK, + DT_EMAC1_SGMIIPHY_TCLK, + DT_PCIE_PIPE_CLK, + DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +enum { + P_BI_TCXO, + P_EMAC0_SGMIIPHY_RCLK, + P_EMAC0_SGMIIPHY_TCLK, + P_EMAC1_SGMIIPHY_RCLK, + P_EMAC1_SGMIIPHY_TCLK, + P_GPLL0_OUT_AUX2, + P_GPLL0_OUT_EARLY, + P_GPLL10_OUT_MAIN, + P_GPLL11_OUT_AUX, + P_GPLL11_OUT_AUX2, + P_GPLL11_OUT_MAIN, + P_GPLL12_OUT_AUX2, + P_GPLL12_OUT_EARLY, + P_GPLL3_OUT_EARLY, + P_GPLL3_OUT_MAIN, + P_GPLL4_OUT_MAIN, + P_GPLL5_OUT_MAIN, + P_GPLL6_OUT_EARLY, + P_GPLL6_OUT_MAIN, + P_GPLL7_OUT_MAIN, + P_GPLL8_OUT_EARLY, + P_GPLL8_OUT_MAIN, + P_GPLL9_OUT_EARLY, + P_GPLL9_OUT_MAIN, + P_PCIE_PIPE_CLK, + P_SLEEP_CLK, + P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +static const struct pll_vco brammo_vco[] = { + { 500000000, 1250000000, 0 }, +}; + +static const struct pll_vco default_vco[] = { + { 500000000, 1000000000, 2 }, +}; + +static const struct pll_vco spark_vco[] = { + { 750000000, 1500000000, 1 }, +}; + +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll0_out_aux2[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_aux2 = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll0_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_aux2), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll0_out_aux2", + .parent_hws = (const struct clk_hw*[]) { + &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +/* 1152.0 MHz Configuration */ +static const struct alpha_pll_config gpll10_config = { + .l = 0x3c, + .alpha = 0x0, + .vco_val = BIT(20), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .config_ctl_val = 0x4001055b, + .test_ctl_hi_val = 0x1, +}; + +static struct clk_alpha_pll gpll10 = { + .offset = 0xa000, + .config = &gpll10_config, + .vco_table = spark_vco, + .num_vco = ARRAY_SIZE(spark_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gpll10", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +/* 600.0 MHz Configuration */ +static const struct alpha_pll_config gpll11_config = { + .l = 0x1f, + .alpha = 0x0, + .alpha_hi = 0x40, + .alpha_en_mask = BIT(24), + .vco_val = BIT(21), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .config_ctl_val = 0x4001055b, + .test_ctl_hi_val = 0x1, +}; + +static struct clk_alpha_pll gpll11 = { + .offset = 0xb000, + .config = &gpll11_config, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .flags = SUPPORTS_DYNAMIC_UPDATE, + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gpll11", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll12 = { + .offset = 0xc000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gpll12", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll12_out_aux2[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll12_out_aux2 = { + .offset = 0xc000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll12_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_gpll12_out_aux2), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll12_out_aux2", + .parent_hws = (const struct clk_hw*[]) { + &gpll12.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_alpha_pll gpll3 = { + .offset = 0x3000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gpll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll3_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll3_out_main = { + .offset = 0x3000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll3_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll3_out_main), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll3_out_main", + .parent_hws = (const struct clk_hw*[]) { + &gpll3.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x4000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gpll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll5 = { + .offset = 0x5000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gpll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll6 = { + .offset = 0x6000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gpll6", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll6_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll6_out_main = { + .offset = 0x6000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll6_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll6_out_main), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll6_out_main", + .parent_hws = (const struct clk_hw*[]) { + &gpll6.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_alpha_pll gpll7 = { + .offset = 0x7000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(7), + .hw.init = &(const struct clk_init_data) { + .name = "gpll7", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_ops, + }, + }, +}; + +/* 533.2 MHz Configuration */ +static const struct alpha_pll_config gpll8_config = { + .l = 0x1b, + .alpha = 0x55555555, + .alpha_hi = 0xc5, + .alpha_en_mask = BIT(24), + .vco_val = BIT(21), + .vco_mask = GENMASK(21, 20), + .main_output_mask = BIT(0), + .early_output_mask = BIT(3), + .post_div_val = BIT(8), + .post_div_mask = GENMASK(11, 8), + .config_ctl_val = 0x4001055b, + .test_ctl_hi_val = 0x1, +}; + +static struct clk_alpha_pll gpll8 = { + .offset = 0x8000, + .config = &gpll8_config, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .flags = SUPPORTS_DYNAMIC_UPDATE, + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gpll8", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll8_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll8_out_main = { + .offset = 0x8000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll8_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll8_out_main), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll8_out_main", + .parent_hws = (const struct clk_hw*[]) { + &gpll8.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +/* 1152.0 MHz Configuration */ +static const struct alpha_pll_config gpll9_config = { + .l = 0x3c, + .alpha = 0x0, + .post_div_val = BIT(8), + .post_div_mask = GENMASK(9, 8), + .main_output_mask = BIT(0), + .early_output_mask = BIT(3), + .config_ctl_val = 0x00004289, + .test_ctl_val = 0x08000000, +}; + +static struct clk_alpha_pll gpll9 = { + .offset = 0x9000, + .config = &gpll9_config, + .vco_table = brammo_vco, + .num_vco = ARRAY_SIZE(brammo_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_BRAMMO_EVO], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gpll9", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll9_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll9_out_main = { + .offset = 0x9000, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll9_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll9_out_main), + .width = 2, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_BRAMMO_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpll9_out_main", + .parent_hws = (const struct clk_hw*[]) { + &gpll9.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL6_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll6_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll9_out_main.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll4.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll4.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_7[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll8_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_8[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll8_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL6_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_9[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll6_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_10[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_10[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_11[] = { + { P_BI_TCXO, 0 }, + { P_GPLL12_OUT_EARLY, 1 }, + { P_GPLL12_OUT_AUX2, 4 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_11[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll12.clkr.hw }, + { .hw = &gpll12_out_aux2.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_12[] = { + { P_BI_TCXO, 0 }, + { P_GPLL12_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL12_OUT_AUX2, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_12[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll12.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll12_out_aux2.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_13[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, +}; + +static const struct clk_parent_data gcc_parent_data_13[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_14[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL9_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_14[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll8_out_main.clkr.hw }, + { .hw = &gpll9.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_15[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 2 }, + { P_GPLL10_OUT_MAIN, 3 }, + { P_GPLL6_OUT_EARLY, 5 }, + { P_GPLL3_OUT_MAIN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_15[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll8.clkr.hw }, + { .hw = &gpll10.clkr.hw }, + { .hw = &gpll6.clkr.hw }, + { .hw = &gpll3_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_21[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL7_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_21[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_aux2.clkr.hw }, + { .hw = &gpll7.clkr.hw }, + { .hw = &gpll4.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_22[] = { + { P_BI_TCXO, 0 }, + { P_GPLL12_OUT_EARLY, 1 }, + { P_GPLL5_OUT_MAIN, 3 }, + { P_GPLL12_OUT_AUX2, 4 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_22[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll12.clkr.hw }, + { .hw = &gpll5.clkr.hw }, + { .hw = &gpll12_out_aux2.clkr.hw }, + { .hw = &gpll3.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_24[] = { + { P_BI_TCXO, 0 }, + { P_GPLL11_OUT_MAIN, 1 }, + { P_GPLL11_OUT_AUX, 2 }, + { P_GPLL11_OUT_AUX2, 3 }, +}; + +static const struct clk_parent_data gcc_parent_data_24[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpll11.clkr.hw }, + { .hw = &gpll11.clkr.hw }, + { .hw = &gpll11.clkr.hw }, +}; + +static struct clk_regmap_phy_mux gcc_emac0_cc_sgmiiphy_rx_clk_src = { + .reg = 0xad048, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_rx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC0_SGMIIPHY_RCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_emac0_cc_sgmiiphy_tx_clk_src = { + .reg = 0xad040, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_tx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC0_SGMIIPHY_TCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_emac1_cc_sgmiiphy_rx_clk_src = { + .reg = 0xae048, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_rx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC1_SGMIIPHY_RCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_emac1_cc_sgmiiphy_tx_clk_src = { + .reg = 0xae040, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_tx_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_EMAC1_SGMIIPHY_TCLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_pcie_pipe_clk_src = { + .reg = 0xaf058, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_PCIE_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_phy_mux gcc_usb3_prim_phy_pipe_clk_src = { + .reg = 0x1a05c, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_axi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + F(300000000, P_GPLL0_OUT_AUX2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_axi_clk_src = { + .cmd_rcgr = 0x5802c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_camss_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_axi_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_cci_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_cci_clk_src = { + .cmd_rcgr = 0x56000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_14, + .freq_tbl = ftbl_gcc_camss_cci_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cci_clk_src", + .parent_data = gcc_parent_data_14, + .num_parents = ARRAY_SIZE(gcc_parent_data_14), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csi0phytimer_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + F(268800000, P_GPLL4_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = { + .cmd_rcgr = 0x45000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi0phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = { + .cmd_rcgr = 0x4501c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi1phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_mclk0_clk_src[] = { + F(19200000, P_GPLL9_OUT_EARLY, 1, 1, 60), + F(24000000, P_GPLL9_OUT_MAIN, 1, 1, 24), + F(64000000, P_GPLL9_OUT_EARLY, 9, 1, 2), + { } +}; + +static struct clk_rcg2 gcc_camss_mclk0_clk_src = { + .cmd_rcgr = 0x51000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk0_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk1_clk_src = { + .cmd_rcgr = 0x5101c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk1_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk2_clk_src = { + .cmd_rcgr = 0x51038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk2_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk3_clk_src = { + .cmd_rcgr = 0x51054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk3_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_ope_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(171428571, P_GPLL0_OUT_EARLY, 3.5, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_ope_ahb_clk_src = { + .cmd_rcgr = 0x55024, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_ope_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_ahb_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_ope_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_GPLL8_OUT_MAIN, 2, 0, 0), + F(266600000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(465000000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(580000000, P_GPLL8_OUT_EARLY, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_ope_clk_src = { + .cmd_rcgr = 0x55004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_ope_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_tfe_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(128000000, P_GPLL10_OUT_MAIN, 9, 0, 0), + F(135529412, P_GPLL10_OUT_MAIN, 8.5, 0, 0), + F(144000000, P_GPLL10_OUT_MAIN, 8, 0, 0), + F(153600000, P_GPLL10_OUT_MAIN, 7.5, 0, 0), + F(164571429, P_GPLL10_OUT_MAIN, 7, 0, 0), + F(177230769, P_GPLL10_OUT_MAIN, 6.5, 0, 0), + F(192000000, P_GPLL10_OUT_MAIN, 6, 0, 0), + F(209454545, P_GPLL10_OUT_MAIN, 5.5, 0, 0), + F(230400000, P_GPLL10_OUT_MAIN, 5, 0, 0), + F(256000000, P_GPLL10_OUT_MAIN, 4.5, 0, 0), + F(288000000, P_GPLL10_OUT_MAIN, 4, 0, 0), + F(329142857, P_GPLL10_OUT_MAIN, 3.5, 0, 0), + F(384000000, P_GPLL10_OUT_MAIN, 3, 0, 0), + F(460800000, P_GPLL10_OUT_MAIN, 2.5, 0, 0), + F(576000000, P_GPLL10_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_tfe_0_clk_src = { + .cmd_rcgr = 0x52004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_tfe_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_tfe_0_csid_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(120000000, P_GPLL0_OUT_EARLY, 5, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + F(426400000, P_GPLL3_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_tfe_0_csid_clk_src = { + .cmd_rcgr = 0x52094, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_camss_tfe_0_csid_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_csid_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_tfe_1_clk_src = { + .cmd_rcgr = 0x52024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_tfe_0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_tfe_1_csid_clk_src = { + .cmd_rcgr = 0x520b4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_camss_tfe_0_csid_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_csid_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_tfe_cphy_rx_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + F(341333333, P_GPLL6_OUT_EARLY, 1, 4, 9), + F(384000000, P_GPLL6_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_tfe_cphy_rx_clk_src = { + .cmd_rcgr = 0x52064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_15, + .freq_tbl = ftbl_gcc_camss_tfe_cphy_rx_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_cphy_rx_clk_src", + .parent_data = gcc_parent_data_15, + .num_parents = ARRAY_SIZE(gcc_parent_data_15), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_top_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(40000000, P_GPLL0_OUT_AUX2, 7.5, 0, 0), + F(80000000, P_GPLL0_OUT_EARLY, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_top_ahb_clk_src = { + .cmd_rcgr = 0x58010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_camss_top_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_top_ahb_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_axi_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0), + F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_axi_clk_src = { + .cmd_rcgr = 0x109dc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_emac0_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_phy_aux_clk_src = { + .cmd_rcgr = 0xad01c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_10, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_phy_aux_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_ptp_clk_src[] = { + F(250000000, P_GPLL12_OUT_AUX2, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_ptp_clk_src = { + .cmd_rcgr = 0xad064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_11, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_rgmii_clk_src[] = { + F(2500000, P_GPLL0_OUT_AUX2, 10, 1, 12), + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(125000000, P_GPLL12_OUT_AUX2, 4, 0, 0), + F(250000000, P_GPLL12_OUT_EARLY, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_rgmii_clk_src = { + .cmd_rcgr = 0xad04c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_12, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_axi_clk_src = { + .cmd_rcgr = 0x109fc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_emac0_axi_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_phy_aux_clk_src = { + .cmd_rcgr = 0xae01c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_10, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_phy_aux_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_ptp_clk_src = { + .cmd_rcgr = 0xae064, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_11, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_rgmii_clk_src = { + .cmd_rcgr = 0xae04c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_12, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(200000000, P_GPLL0_OUT_AUX2, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x4d004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x4e004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x4f004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_aux_clk_src = { + .cmd_rcgr = 0xaf074, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_aux_phy_clk_src = { + .cmd_rcgr = 0xaf05c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_phy_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_rchng_phy_clk_src[] = { + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_rchng_phy_clk_src = { + .cmd_rcgr = 0xaf028, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_rchng_phy_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rchng_phy_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_AUX2, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x20010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_AUX2, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_AUX2, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_AUX2, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_AUX2, 1, 8, 75), + F(48000000, P_GPLL0_OUT_AUX2, 1, 4, 25), + F(64000000, P_GPLL0_OUT_AUX2, 1, 16, 75), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(80000000, P_GPLL0_OUT_AUX2, 1, 4, 15), + F(96000000, P_GPLL0_OUT_AUX2, 1, 8, 25), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(102400000, P_GPLL0_OUT_AUX2, 1, 128, 375), + F(112000000, P_GPLL0_OUT_AUX2, 1, 28, 75), + F(117964800, P_GPLL0_OUT_AUX2, 1, 6144, 15625), + F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0), + F(128000000, P_GPLL6_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x1f148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x1f278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x1f3a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x1f4d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x1f608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x1f738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = { + .name = "gcc_qupv3_wrap0_s6_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { + .cmd_rcgr = 0x1f868, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = { + .name = "gcc_qupv3_wrap0_s7_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { + .cmd_rcgr = 0x1f998, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s8_clk_src_init = { + .name = "gcc_qupv3_wrap0_s8_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s8_clk_src = { + .cmd_rcgr = 0x1fac8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s8_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s9_clk_src_init = { + .name = "gcc_qupv3_wrap0_s9_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s9_clk_src = { + .cmd_rcgr = 0x1fbf8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &gcc_qupv3_wrap0_s9_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(20000000, P_GPLL0_OUT_AUX2, 5, 1, 3), + F(25000000, P_GPLL0_OUT_AUX2, 6, 1, 2), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0x38028, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(150000000, P_GPLL0_OUT_AUX2, 2, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(300000000, P_GPLL0_OUT_AUX2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x38010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(202000000, P_GPLL7_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1e00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_21, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_21, + .num_parents = ARRAY_SIZE(gcc_parent_data_21), + .ops = &clk_rcg2_shared_floor_ops, + }, +}; + +static struct clk_rcg2 gcc_tscss_clk_src = { + .cmd_rcgr = 0xac004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_22, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_clk_src", + .parent_data = gcc_parent_data_22, + .num_parents = ARRAY_SIZE(gcc_parent_data_22), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb20_master_clk_src[] = { + F(60000000, P_GPLL0_OUT_AUX2, 5, 0, 0), + F(120000000, P_GPLL0_OUT_EARLY, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb20_master_clk_src = { + .cmd_rcgr = 0xb003c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb20_master_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb20_mock_utmi_clk_src = { + .cmd_rcgr = 0xb0020, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_13, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_mock_utmi_clk_src", + .parent_data = gcc_parent_data_13, + .num_parents = ARRAY_SIZE(gcc_parent_data_13), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, P_GPLL0_OUT_AUX2, 4.5, 0, 0), + F(133333333, P_GPLL0_OUT_EARLY, 4.5, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0x1a01c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0x1a034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0x1a060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_phy_aux_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_video_venus_clk_src[] = { + F(133333333, P_GPLL11_OUT_MAIN, 4.5, 0, 0), + F(240000000, P_GPLL11_OUT_MAIN, 2.5, 0, 0), + F(300000000, P_GPLL11_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL11_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_video_venus_clk_src = { + .cmd_rcgr = 0x6d000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_24, + .freq_tbl = ftbl_gcc_video_venus_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_video_venus_clk_src", + .parent_data = gcc_parent_data_24, + .num_parents = ARRAY_SIZE(gcc_parent_data_24), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gcc_disp_gpll0_clk_src = { + .reg = 0x17058, + .shift = 0, + .width = 2, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + }, +}; + +static struct clk_regmap_div gcc_usb20_mock_utmi_postdiv_clk_src = { + .reg = 0xb0038, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = { + .reg = 0x1a04c, + .shift = 0, + .width = 2, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gcc_ahb2phy_csi_clk = { + .halt_reg = 0x1d004, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x1d004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ahb2phy_csi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy_usb_clk = { + .halt_reg = 0x1d008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1d008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ahb2phy_usb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x23004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x23004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cam_throttle_nrt_clk = { + .halt_reg = 0x17070, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17070, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cam_throttle_nrt_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cam_throttle_rt_clk = { + .halt_reg = 0x1706c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1706c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cam_throttle_rt_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_axi_clk = { + .halt_reg = 0x58044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x58044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_camnoc_atb_clk = { + .halt_reg = 0x5804c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x5804c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5804c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_camnoc_atb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_camnoc_dragonlink_atb_clk = { + .halt_reg = 0x58060, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x58060, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x58060, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_camnoc_dragonlink_atb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_camnoc_nts_xo_clk = { + .halt_reg = 0x58050, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x58050, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x58050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_camnoc_nts_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cci_0_clk = { + .halt_reg = 0x56018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x56018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cci_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_cci_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_0_clk = { + .halt_reg = 0x52088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cphy_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_1_clk = { + .halt_reg = 0x5208c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5208c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_cphy_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0phytimer_clk = { + .halt_reg = 0x45018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x45018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1phytimer_clk = { + .halt_reg = 0x45034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x45034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk0_clk = { + .halt_reg = 0x51018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk1_clk = { + .halt_reg = 0x51034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk2_clk = { + .halt_reg = 0x51050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk3_clk = { + .halt_reg = 0x5106c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5106c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_mclk3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_nrt_axi_clk = { + .halt_reg = 0x58054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x58054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_nrt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_ope_ahb_clk = { + .halt_reg = 0x5503c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5503c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_ope_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_ope_clk = { + .halt_reg = 0x5501c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5501c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_ope_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_ope_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_rt_axi_clk = { + .halt_reg = 0x5805c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5805c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_rt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_0_clk = { + .halt_reg = 0x5201c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5201c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_0_cphy_rx_clk = { + .halt_reg = 0x5207c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5207c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_0_csid_clk = { + .halt_reg = 0x520ac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x520ac, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_0_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_0_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_1_clk = { + .halt_reg = 0x5203c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5203c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_1_cphy_rx_clk = { + .halt_reg = 0x52080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52080, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_cphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_tfe_1_csid_clk = { + .halt_reg = 0x520cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x520cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_tfe_1_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_tfe_1_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_top_ahb_clk = { + .halt_reg = 0x58028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x58028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camss_top_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_camss_top_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb2_prim_axi_clk = { + .halt_reg = 0x111c4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x111c4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x111c4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_usb2_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a07c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1a07c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a07c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_gpu_axi_clk = { + .halt_reg = 0x71000, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x71000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_gpu_axi_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_memnoc_pcie_sf_clk = { + .halt_reg = 0x29044, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x29044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x29044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_memnoc_pcie_sf_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_disp_gpll0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0x17020, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x17020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_throttle_core_clk = { + .halt_reg = 0x17064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(13), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_ahb_clk = { + .halt_reg = 0xad010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xad010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xad010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_axi_clk = { + .halt_reg = 0xad014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xad014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xad014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_axi_sys_noc_clk = { + .halt_reg = 0x109d4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x109d4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x109d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_sys_noc_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_cc_sgmiiphy_rx_clk = { + .halt_reg = 0xad044, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xad044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_cc_sgmiiphy_tx_clk = { + .halt_reg = 0xad03c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xad03c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xad03c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_cc_sgmiiphy_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_phy_aux_clk = { + .halt_reg = 0xad018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xad018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_ptp_clk = { + .halt_reg = 0xad034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xad034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_rgmii_clk = { + .halt_reg = 0xad038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xad038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_ahb_clk = { + .halt_reg = 0xae010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xae010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xae010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_axi_clk = { + .halt_reg = 0xae014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xae014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xae014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_axi_sys_noc_clk = { + .halt_reg = 0x109f4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x109f4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x109f4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_sys_noc_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_cc_sgmiiphy_rx_clk = { + .halt_reg = 0xae044, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xae044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_rx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_cc_sgmiiphy_tx_clk = { + .halt_reg = 0xae03c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xae03c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xae03c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_cc_sgmiiphy_tx_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_phy_aux_clk = { + .halt_reg = 0xae018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xae018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_ptp_clk = { + .halt_reg = 0xae034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xae034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_rgmii_clk = { + .halt_reg = 0xae038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xae038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac1_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x4d000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4d000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x4e000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4e000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x4f000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4f000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpll0_out_aux2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x3600c, + .halt_check = BRANCH_VOTED, + .hwcg_reg = 0x3600c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x3600c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_smmu_vote_clk = { + .halt_reg = 0x7d000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_smmu_vote_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x36018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x36018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_throttle_core_clk = { + .halt_reg = 0x36048, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x36048, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mmu_tcu_vote_clk = { + .halt_reg = 0x7d06c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d06c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_mmu_tcu_vote_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_aux_clk = { + .halt_reg = 0xaf044, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_cfg_ahb_clk = { + .halt_reg = 0xaf010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_clkref_en = { + .halt_reg = 0xb8000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xb8000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_mstr_axi_clk = { + .halt_reg = 0xaf020, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_pipe_clk = { + .halt_reg = 0xaf050, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xaf050, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_rchng_phy_clk = { + .halt_reg = 0xaf040, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(31), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rchng_phy_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_rchng_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_sleep_clk = { + .halt_reg = 0xaf04c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf04c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_sleep_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_aux_phy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_axi_clk = { + .halt_reg = 0xaf018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_slv_q2a_axi_clk = { + .halt_reg = 0xaf014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_tbu_clk = { + .halt_reg = 0xaf098, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf098, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_throttle_core_clk = { + .halt_reg = 0xaf094, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf094, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_throttle_xo_clk = { + .halt_reg = 0xaf090, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_throttle_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_tile_axi_sys_noc_clk = { + .halt_reg = 0x10f2c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x10f2c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x10f2c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_tile_axi_sys_noc_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_emac0_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x2000c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2000c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x20004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x20004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x20004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x20008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x20008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pwm0_xo512_clk = { + .halt_reg = 0x2002c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2002c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pwm0_xo512_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_camera_nrt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_rt_ahb_clk = { + .halt_reg = 0x17060, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17060, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_camera_rt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_ahb_clk = { + .halt_reg = 0x17018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_gpu_cfg_ahb_clk = { + .halt_reg = 0x36040, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x36040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_gpu_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_pcie_cfg_ahb_clk = { + .halt_reg = 0xaf08c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaf08c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79018, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_pcie_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0x17010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_video_vcodec_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x1f014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x1f00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x1f144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x1f274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x1f3a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(24), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x1f4d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(25), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x1f604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x1f734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s6_clk = { + .halt_reg = 0x1f864, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s6_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s7_clk = { + .halt_reg = 0x1f994, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s7_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s8_clk = { + .halt_reg = 0x1fac4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s8_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s8_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s9_clk = { + .halt_reg = 0x1fbf4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(31), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s9_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_qupv3_wrap0_s9_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x1f004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1f004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x1f008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1f008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x38008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x38008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x38008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x38004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc1_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ice_core_clk = { + .halt_reg = 0x3800c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x3800c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x3800c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ice_core_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc1_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1e008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1e008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_usb2_prim_axi_clk = { + .halt_reg = 0x10a14, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x10a14, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x10a14, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sys_noc_usb2_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a078, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1a078, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a078, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sys_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tscss_ahb_clk = { + .halt_reg = 0xac024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xac024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xac024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tscss_cntr_clk = { + .halt_reg = 0xac020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xac020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_cntr_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_tscss_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tscss_etu_clk = { + .halt_reg = 0xac01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xac01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_tscss_etu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_tscss_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_clkref_en = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_master_clk = { + .halt_reg = 0xb0010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb0010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb0010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_master_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_mock_utmi_clk = { + .halt_reg = 0xb001c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb001c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb20_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_sleep_clk = { + .halt_reg = 0xb0018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xb0018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb20_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0x1a010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1a010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_master_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0x1a018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0x1a014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_en = { + .halt_reg = 0x9f000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x9f000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0x1a054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_reg = 0x1a058, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x1a058, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1a058, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vcodec0_axi_clk = { + .halt_reg = 0x6e008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6e008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_vcodec0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_venus_ahb_clk = { + .halt_reg = 0x6e010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6e010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_venus_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_venus_ctl_axi_clk = { + .halt_reg = 0x6e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6e004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_venus_ctl_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi0_clk = { + .halt_reg = 0x1701c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1701c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1701c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_axi0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_throttle_core_clk = { + .halt_reg = 0x17068, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17068, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_vcodec0_sys_clk = { + .halt_reg = 0x6d044, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x6d044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6d044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_vcodec0_sys_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_video_venus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_venus_ctl_clk = { + .halt_reg = 0x6d02c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6d02c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_venus_ctl_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_video_venus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gcc_camss_top_gdsc = { + .gdscr = 0x58004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_camss_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_emac0_gdsc = { + .gdscr = 0xad004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_emac0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_emac1_gdsc = { + .gdscr = 0xae004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_emac1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_pcie_gdsc = { + .gdscr = 0xaf004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_pcie_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_usb20_gdsc = { + .gdscr = 0xb0004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_usb20_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_usb30_prim_gdsc = { + .gdscr = 0x1a004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, + .pd = { + .name = "gcc_usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_venus_gdsc = { + .gdscr = 0x6d01c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_venus_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_vcodec0_gdsc = { + .gdscr = 0x6d038, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_vcodec0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &gcc_venus_gdsc.pd, + .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *gcc_shikra_clocks[] = { + [GCC_AHB2PHY_CSI_CLK] = &gcc_ahb2phy_csi_clk.clkr, + [GCC_AHB2PHY_USB_CLK] = &gcc_ahb2phy_usb_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAM_THROTTLE_NRT_CLK] = &gcc_cam_throttle_nrt_clk.clkr, + [GCC_CAM_THROTTLE_RT_CLK] = &gcc_cam_throttle_rt_clk.clkr, + [GCC_CAMSS_AXI_CLK] = &gcc_camss_axi_clk.clkr, + [GCC_CAMSS_AXI_CLK_SRC] = &gcc_camss_axi_clk_src.clkr, + [GCC_CAMSS_CAMNOC_ATB_CLK] = &gcc_camss_camnoc_atb_clk.clkr, + [GCC_CAMSS_CAMNOC_DRAGONLINK_ATB_CLK] = &gcc_camss_camnoc_dragonlink_atb_clk.clkr, + [GCC_CAMSS_CAMNOC_NTS_XO_CLK] = &gcc_camss_camnoc_nts_xo_clk.clkr, + [GCC_CAMSS_CCI_0_CLK] = &gcc_camss_cci_0_clk.clkr, + [GCC_CAMSS_CCI_CLK_SRC] = &gcc_camss_cci_clk_src.clkr, + [GCC_CAMSS_CPHY_0_CLK] = &gcc_camss_cphy_0_clk.clkr, + [GCC_CAMSS_CPHY_1_CLK] = &gcc_camss_cphy_1_clk.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK] = &gcc_camss_csi0phytimer_clk.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK_SRC] = &gcc_camss_csi0phytimer_clk_src.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK] = &gcc_camss_csi1phytimer_clk.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK_SRC] = &gcc_camss_csi1phytimer_clk_src.clkr, + [GCC_CAMSS_MCLK0_CLK] = &gcc_camss_mclk0_clk.clkr, + [GCC_CAMSS_MCLK0_CLK_SRC] = &gcc_camss_mclk0_clk_src.clkr, + [GCC_CAMSS_MCLK1_CLK] = &gcc_camss_mclk1_clk.clkr, + [GCC_CAMSS_MCLK1_CLK_SRC] = &gcc_camss_mclk1_clk_src.clkr, + [GCC_CAMSS_MCLK2_CLK] = &gcc_camss_mclk2_clk.clkr, + [GCC_CAMSS_MCLK2_CLK_SRC] = &gcc_camss_mclk2_clk_src.clkr, + [GCC_CAMSS_MCLK3_CLK] = &gcc_camss_mclk3_clk.clkr, + [GCC_CAMSS_MCLK3_CLK_SRC] = &gcc_camss_mclk3_clk_src.clkr, + [GCC_CAMSS_NRT_AXI_CLK] = &gcc_camss_nrt_axi_clk.clkr, + [GCC_CAMSS_OPE_AHB_CLK] = &gcc_camss_ope_ahb_clk.clkr, + [GCC_CAMSS_OPE_AHB_CLK_SRC] = &gcc_camss_ope_ahb_clk_src.clkr, + [GCC_CAMSS_OPE_CLK] = &gcc_camss_ope_clk.clkr, + [GCC_CAMSS_OPE_CLK_SRC] = &gcc_camss_ope_clk_src.clkr, + [GCC_CAMSS_RT_AXI_CLK] = &gcc_camss_rt_axi_clk.clkr, + [GCC_CAMSS_TFE_0_CLK] = &gcc_camss_tfe_0_clk.clkr, + [GCC_CAMSS_TFE_0_CLK_SRC] = &gcc_camss_tfe_0_clk_src.clkr, + [GCC_CAMSS_TFE_0_CPHY_RX_CLK] = &gcc_camss_tfe_0_cphy_rx_clk.clkr, + [GCC_CAMSS_TFE_0_CSID_CLK] = &gcc_camss_tfe_0_csid_clk.clkr, + [GCC_CAMSS_TFE_0_CSID_CLK_SRC] = &gcc_camss_tfe_0_csid_clk_src.clkr, + [GCC_CAMSS_TFE_1_CLK] = &gcc_camss_tfe_1_clk.clkr, + [GCC_CAMSS_TFE_1_CLK_SRC] = &gcc_camss_tfe_1_clk_src.clkr, + [GCC_CAMSS_TFE_1_CPHY_RX_CLK] = &gcc_camss_tfe_1_cphy_rx_clk.clkr, + [GCC_CAMSS_TFE_1_CSID_CLK] = &gcc_camss_tfe_1_csid_clk.clkr, + [GCC_CAMSS_TFE_1_CSID_CLK_SRC] = &gcc_camss_tfe_1_csid_clk_src.clkr, + [GCC_CAMSS_TFE_CPHY_RX_CLK_SRC] = &gcc_camss_tfe_cphy_rx_clk_src.clkr, + [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr, + [GCC_CAMSS_TOP_AHB_CLK_SRC] = &gcc_camss_top_ahb_clk_src.clkr, + [GCC_CFG_NOC_USB2_PRIM_AXI_CLK] = &gcc_cfg_noc_usb2_prim_axi_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DDRSS_MEMNOC_PCIE_SF_CLK] = &gcc_ddrss_memnoc_pcie_sf_clk.clkr, + [GCC_DISP_GPLL0_CLK_SRC] = &gcc_disp_gpll0_clk_src.clkr, + [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_THROTTLE_CORE_CLK] = &gcc_disp_throttle_core_clk.clkr, + [GCC_EMAC0_AHB_CLK] = &gcc_emac0_ahb_clk.clkr, + [GCC_EMAC0_AXI_CLK] = &gcc_emac0_axi_clk.clkr, + [GCC_EMAC0_AXI_CLK_SRC] = &gcc_emac0_axi_clk_src.clkr, + [GCC_EMAC0_AXI_SYS_NOC_CLK] = &gcc_emac0_axi_sys_noc_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_RX_CLK] = &gcc_emac0_cc_sgmiiphy_rx_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_rx_clk_src.clkr, + [GCC_EMAC0_CC_SGMIIPHY_TX_CLK] = &gcc_emac0_cc_sgmiiphy_tx_clk.clkr, + [GCC_EMAC0_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac0_cc_sgmiiphy_tx_clk_src.clkr, + [GCC_EMAC0_PHY_AUX_CLK] = &gcc_emac0_phy_aux_clk.clkr, + [GCC_EMAC0_PHY_AUX_CLK_SRC] = &gcc_emac0_phy_aux_clk_src.clkr, + [GCC_EMAC0_PTP_CLK] = &gcc_emac0_ptp_clk.clkr, + [GCC_EMAC0_PTP_CLK_SRC] = &gcc_emac0_ptp_clk_src.clkr, + [GCC_EMAC0_RGMII_CLK] = &gcc_emac0_rgmii_clk.clkr, + [GCC_EMAC0_RGMII_CLK_SRC] = &gcc_emac0_rgmii_clk_src.clkr, + [GCC_EMAC1_AHB_CLK] = &gcc_emac1_ahb_clk.clkr, + [GCC_EMAC1_AXI_CLK] = &gcc_emac1_axi_clk.clkr, + [GCC_EMAC1_AXI_CLK_SRC] = &gcc_emac1_axi_clk_src.clkr, + [GCC_EMAC1_AXI_SYS_NOC_CLK] = &gcc_emac1_axi_sys_noc_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_RX_CLK] = &gcc_emac1_cc_sgmiiphy_rx_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_RX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_rx_clk_src.clkr, + [GCC_EMAC1_CC_SGMIIPHY_TX_CLK] = &gcc_emac1_cc_sgmiiphy_tx_clk.clkr, + [GCC_EMAC1_CC_SGMIIPHY_TX_CLK_SRC] = &gcc_emac1_cc_sgmiiphy_tx_clk_src.clkr, + [GCC_EMAC1_PHY_AUX_CLK] = &gcc_emac1_phy_aux_clk.clkr, + [GCC_EMAC1_PHY_AUX_CLK_SRC] = &gcc_emac1_phy_aux_clk_src.clkr, + [GCC_EMAC1_PTP_CLK] = &gcc_emac1_ptp_clk.clkr, + [GCC_EMAC1_PTP_CLK_SRC] = &gcc_emac1_ptp_clk_src.clkr, + [GCC_EMAC1_RGMII_CLK] = &gcc_emac1_rgmii_clk.clkr, + [GCC_EMAC1_RGMII_CLK_SRC] = &gcc_emac1_rgmii_clk_src.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SMMU_VOTE_CLK] = &gcc_gpu_smmu_vote_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_GPU_THROTTLE_CORE_CLK] = &gcc_gpu_throttle_core_clk.clkr, + [GCC_MMU_TCU_VOTE_CLK] = &gcc_mmu_tcu_vote_clk.clkr, + [GCC_PCIE_AUX_CLK] = &gcc_pcie_aux_clk.clkr, + [GCC_PCIE_AUX_CLK_SRC] = &gcc_pcie_aux_clk_src.clkr, + [GCC_PCIE_AUX_PHY_CLK_SRC] = &gcc_pcie_aux_phy_clk_src.clkr, + [GCC_PCIE_CFG_AHB_CLK] = &gcc_pcie_cfg_ahb_clk.clkr, + [GCC_PCIE_CLKREF_EN] = &gcc_pcie_clkref_en.clkr, + [GCC_PCIE_MSTR_AXI_CLK] = &gcc_pcie_mstr_axi_clk.clkr, + [GCC_PCIE_PIPE_CLK] = &gcc_pcie_pipe_clk.clkr, + [GCC_PCIE_PIPE_CLK_SRC] = &gcc_pcie_pipe_clk_src.clkr, + [GCC_PCIE_RCHNG_PHY_CLK] = &gcc_pcie_rchng_phy_clk.clkr, + [GCC_PCIE_RCHNG_PHY_CLK_SRC] = &gcc_pcie_rchng_phy_clk_src.clkr, + [GCC_PCIE_SLEEP_CLK] = &gcc_pcie_sleep_clk.clkr, + [GCC_PCIE_SLV_AXI_CLK] = &gcc_pcie_slv_axi_clk.clkr, + [GCC_PCIE_SLV_Q2A_AXI_CLK] = &gcc_pcie_slv_q2a_axi_clk.clkr, + [GCC_PCIE_TBU_CLK] = &gcc_pcie_tbu_clk.clkr, + [GCC_PCIE_THROTTLE_CORE_CLK] = &gcc_pcie_throttle_core_clk.clkr, + [GCC_PCIE_THROTTLE_XO_CLK] = &gcc_pcie_throttle_xo_clk.clkr, + [GCC_PCIE_TILE_AXI_SYS_NOC_CLK] = &gcc_pcie_tile_axi_sys_noc_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PWM0_XO512_CLK] = &gcc_pwm0_xo512_clk.clkr, + [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr, + [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr, + [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr, + [GCC_QMIP_GPU_CFG_AHB_CLK] = &gcc_qmip_gpu_cfg_ahb_clk.clkr, + [GCC_QMIP_PCIE_CFG_AHB_CLK] = &gcc_qmip_pcie_cfg_ahb_clk.clkr, + [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.clkr, + [GCC_QUPV3_WRAP0_S6_CLK_SRC] = &gcc_qupv3_wrap0_s6_clk_src.clkr, + [GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.clkr, + [GCC_QUPV3_WRAP0_S7_CLK_SRC] = &gcc_qupv3_wrap0_s7_clk_src.clkr, + [GCC_QUPV3_WRAP0_S8_CLK] = &gcc_qupv3_wrap0_s8_clk.clkr, + [GCC_QUPV3_WRAP0_S8_CLK_SRC] = &gcc_qupv3_wrap0_s8_clk_src.clkr, + [GCC_QUPV3_WRAP0_S9_CLK] = &gcc_qupv3_wrap0_s9_clk.clkr, + [GCC_QUPV3_WRAP0_S9_CLK_SRC] = &gcc_qupv3_wrap0_s9_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SYS_NOC_USB2_PRIM_AXI_CLK] = &gcc_sys_noc_usb2_prim_axi_clk.clkr, + [GCC_SYS_NOC_USB3_PRIM_AXI_CLK] = &gcc_sys_noc_usb3_prim_axi_clk.clkr, + [GCC_TSCSS_AHB_CLK] = &gcc_tscss_ahb_clk.clkr, + [GCC_TSCSS_CLK_SRC] = &gcc_tscss_clk_src.clkr, + [GCC_TSCSS_CNTR_CLK] = &gcc_tscss_cntr_clk.clkr, + [GCC_TSCSS_ETU_CLK] = &gcc_tscss_etu_clk.clkr, + [GCC_UFS_CLKREF_EN] = &gcc_ufs_clkref_en.clkr, + [GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr, + [GCC_USB20_MASTER_CLK_SRC] = &gcc_usb20_master_clk_src.clkr, + [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr, + [GCC_USB20_MOCK_UTMI_CLK_SRC] = &gcc_usb20_mock_utmi_clk_src.clkr, + [GCC_USB20_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb20_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB3_PRIM_CLKREF_EN] = &gcc_usb3_prim_clkref_en.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb3_prim_phy_pipe_clk_src.clkr, + [GCC_VCODEC0_AXI_CLK] = &gcc_vcodec0_axi_clk.clkr, + [GCC_VENUS_AHB_CLK] = &gcc_venus_ahb_clk.clkr, + [GCC_VENUS_CTL_AXI_CLK] = &gcc_venus_ctl_axi_clk.clkr, + [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, + [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr, + [GCC_VIDEO_VCODEC0_SYS_CLK] = &gcc_video_vcodec0_sys_clk.clkr, + [GCC_VIDEO_VENUS_CLK_SRC] = &gcc_video_venus_clk_src.clkr, + [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr, + [GPLL0] = &gpll0.clkr, + [GPLL0_OUT_AUX2] = &gpll0_out_aux2.clkr, + [GPLL10] = &gpll10.clkr, + [GPLL11] = &gpll11.clkr, + [GPLL12] = &gpll12.clkr, + [GPLL12_OUT_AUX2] = &gpll12_out_aux2.clkr, + [GPLL3] = &gpll3.clkr, + [GPLL3_OUT_MAIN] = &gpll3_out_main.clkr, + [GPLL4] = &gpll4.clkr, + [GPLL5] = &gpll5.clkr, + [GPLL6] = &gpll6.clkr, + [GPLL6_OUT_MAIN] = &gpll6_out_main.clkr, + [GPLL7] = &gpll7.clkr, + [GPLL8] = &gpll8.clkr, + [GPLL8_OUT_MAIN] = &gpll8_out_main.clkr, + [GPLL9] = &gpll9.clkr, + [GPLL9_OUT_MAIN] = &gpll9_out_main.clkr, +}; + +static struct gdsc *gcc_shikra_gdscs[] = { + [GCC_CAMSS_TOP_GDSC] = &gcc_camss_top_gdsc, + [GCC_EMAC0_GDSC] = &gcc_emac0_gdsc, + [GCC_EMAC1_GDSC] = &gcc_emac1_gdsc, + [GCC_PCIE_GDSC] = &gcc_pcie_gdsc, + [GCC_USB20_GDSC] = &gcc_usb20_gdsc, + [GCC_USB30_PRIM_GDSC] = &gcc_usb30_prim_gdsc, + [GCC_VCODEC0_GDSC] = &gcc_vcodec0_gdsc, + [GCC_VENUS_GDSC] = &gcc_venus_gdsc, +}; + +static const struct qcom_reset_map gcc_shikra_resets[] = { + [GCC_CAMSS_OPE_BCR] = { 0x55000 }, + [GCC_CAMSS_TFE_BCR] = { 0x52000 }, + [GCC_CAMSS_TOP_BCR] = { 0x58000 }, + [GCC_EMAC0_BCR] = { 0xad000 }, + [GCC_EMAC1_BCR] = { 0xae000 }, + [GCC_GPU_BCR] = { 0x36000 }, + [GCC_MMSS_BCR] = { 0x17000 }, + [GCC_PCIE_BCR] = { 0xaf000 }, + [GCC_PCIE_PHY_BCR] = { 0xb1000 }, + [GCC_PDM_BCR] = { 0x20000 }, + [GCC_QUPV3_WRAPPER_0_BCR] = { 0x1f000 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x1c000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x1c004 }, + [GCC_SDCC1_BCR] = { 0x38000 }, + [GCC_SDCC2_BCR] = { 0x1e000 }, + [GCC_TSCSS_BCR] = { 0xac000 }, + [GCC_USB20_BCR] = { 0xb0000 }, + [GCC_USB30_PRIM_BCR] = { 0x1a000 }, + [GCC_USB3PHY_PHY_PRIM_SP0_BCR] = { 0x1b008 }, + [GCC_USB3_PHY_PRIM_SP0_BCR] = { 0x1b000 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x1d000 }, + [GCC_VCODEC0_BCR] = { 0x6d034 }, + [GCC_VENUS_BCR] = { 0x6d018 }, + [GCC_VIDEO_INTERFACE_BCR] = { 0x6e000 }, +}; + +static struct clk_alpha_pll *gcc_shikra_plls[] = { + &gpll10, + &gpll11, + &gpll8, + &gpll9, +}; + +static u32 gcc_shikra_critical_cbcrs[] = { + 0x17008, /* GCC_CAMERA_AHB_CLK */ + 0x17028, /* GCC_CAMERA_XO_CLK */ + 0x1700c, /* GCC_DISP_AHB_CLK */ + 0x1702c, /* GCC_DISP_XO_CLK */ + 0x36004, /* GCC_GPU_CFG_AHB_CLK */ + 0x36100, /* GCC_GPU_IREF_CLK */ + 0x3a00c, /* GCC_LPASS_CONFIG_CLK */ + 0x3a008, /* GCC_LPASS_CORE_AXIM_CLK */ + 0x79004, /* GCC_SYS_NOC_CPUSS_AHB_CLK */ + 0x17004, /* GCC_VIDEO_AHB_CLK */ + 0x17024, /* GCC_VIDEO_XO_CLK */ +}; + +static const struct clk_rcg_dfs_data gcc_shikra_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s8_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s9_clk_src), +}; + +static const struct regmap_config gcc_shikra_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xc7000, + .fast_io = true, +}; + +static struct qcom_cc_driver_data gcc_shikra_driver_data = { + .alpha_plls = gcc_shikra_plls, + .num_alpha_plls = ARRAY_SIZE(gcc_shikra_plls), + .clk_cbcrs = gcc_shikra_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gcc_shikra_critical_cbcrs), + .dfs_rcgs = gcc_shikra_dfs_clocks, + .num_dfs_rcgs = ARRAY_SIZE(gcc_shikra_dfs_clocks), +}; + +static const struct qcom_cc_desc gcc_shikra_desc = { + .config = &gcc_shikra_regmap_config, + .clks = gcc_shikra_clocks, + .num_clks = ARRAY_SIZE(gcc_shikra_clocks), + .resets = gcc_shikra_resets, + .num_resets = ARRAY_SIZE(gcc_shikra_resets), + .gdscs = gcc_shikra_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_shikra_gdscs), + .driver_data = &gcc_shikra_driver_data, +}; + +static const struct of_device_id gcc_shikra_match_table[] = { + { .compatible = "qcom,shikra-gcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_shikra_match_table); + +static int gcc_shikra_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &gcc_shikra_desc); +} + +static struct platform_driver gcc_shikra_driver = { + .probe = gcc_shikra_probe, + .driver = { + .name = "gcc-shikra", + .of_match_table = gcc_shikra_match_table, + }, +}; + +static int __init gcc_shikra_init(void) +{ + return platform_driver_register(&gcc_shikra_driver); +} +subsys_initcall(gcc_shikra_init); + +static void __exit gcc_shikra_exit(void) +{ + platform_driver_unregister(&gcc_shikra_driver); +} +module_exit(gcc_shikra_exit); + +MODULE_DESCRIPTION("QTI GCC Shikra Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index ee5f86ca50cb7..f419a28f616b6 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -708,3 +708,25 @@ int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain) return ret; } EXPORT_SYMBOL_GPL(gdsc_gx_do_nothing_enable); + +/* + * GX GDSC is a special power domain. Normally, its disable sequence + * is managed by the GMU firmware, and high level OS must not attempt + * to disable it. The only exception is during GMU recovery, where the + * GMU driver can set GenPD’s synced_poweroff flag to allow explicitly + * disable GX GDSC in hardware. + */ +int gdsc_gx_disable(struct generic_pm_domain *domain) +{ + struct gdsc *sc = domain_to_gdsc(domain); + + if (domain->synced_poweroff) + return gdsc_disable(domain); + + /* Remove parent-supply placed in enable */ + if (sc->rsupply) + return regulator_disable(sc->rsupply); + + return 0; +} +EXPORT_SYMBOL_GPL(gdsc_gx_disable); diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 92ff6bcce7b1c..1acb5c97ccd96 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -93,6 +93,8 @@ int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *, struct regmap *); void gdsc_unregister(struct gdsc_desc *desc); int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain); +int gdsc_gx_disable(struct generic_pm_domain *domain); +#define gdsc_synced_poweroff_disable gdsc_gx_disable #else static inline int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *rcdev, diff --git a/drivers/clk/qcom/gpucc-eliza.c b/drivers/clk/qcom/gpucc-eliza.c new file mode 100644 index 0000000000000..18525d1c7d033 --- /dev/null +++ b/drivers/clk/qcom/gpucc-eliza.c @@ -0,0 +1,607 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_GPLL0_OUT_MAIN, + DT_GPLL0_OUT_MAIN_DIV, +}; + +enum { + P_BI_TCXO, + P_BI_TCXO_AO, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL0_OUT_MAIN, + P_GPU_CC_PLL1_OUT_MAIN, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +/* 518.0 MHz Configuration */ +static const struct alpha_pll_config gpu_cc_pll0_config = { + .l = 0x1a, + .alpha = 0xfaaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll gpu_cc_pll0 = { + .offset = 0x0, + .config = &gpu_cc_pll0_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +/* 440.0 MHz Configuration */ +static const struct alpha_pll_config gpu_cc_pll1_config = { + .l = 0x16, + .alpha = 0xeaaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll gpu_cc_pll1 = { + .offset = 0x1000, + .config = &gpu_cc_pll1_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll0.clkr.hw }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .index = DT_GPLL0_OUT_MAIN }, + { .index = DT_GPLL0_OUT_MAIN_DIV }, +}; + +static const struct parent_map gpu_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = { + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_ff_clk_src = { + .cmd_rcgr = 0x94b8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_ff_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_ff_clk_src", + .parent_data = gpu_cc_parent_data_0, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), + F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x935c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_1, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_gmu_clk_src", + .parent_data = gpu_cc_parent_data_1, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gpu_cc_hub_clk_src = { + .cmd_rcgr = 0x9430, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_2, + .freq_tbl = ftbl_gpu_cc_ff_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_clk_src", + .parent_data = gpu_cc_parent_data_2, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_xo_clk_src = { + .cmd_rcgr = 0x9010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_3, + .freq_tbl = ftbl_gpu_cc_xo_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_xo_clk_src", + .parent_data = gpu_cc_parent_data_3, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gpu_cc_xo_div_clk_src = { + .reg = 0x9050, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_xo_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gpu_cc_ahb_clk = { + .halt_reg = 0x914c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x914c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x9150, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9150, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_crc_ahb_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_accu_shift_clk = { + .halt_reg = 0x9480, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9480, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_accu_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_ff_clk = { + .halt_reg = 0x9184, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9184, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_ff_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_ff_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x916c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x916c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cx_gmu_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x917c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x917c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_cxo_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_freq_measure_clk = { + .halt_reg = 0x9008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_freq_measure_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_xo_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { + .halt_reg = 0x7000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_aon_clk = { + .halt_reg = 0x942c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x942c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_aon_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hub_cx_int_clk = { + .halt_reg = 0x9180, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9180, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_hub_cx_int_clk", + .parent_hws = (const struct clk_hw*[]) { + &gpu_cc_hub_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_memnoc_gfx_clk = { + .halt_reg = 0x9188, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9188, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = { + .halt_reg = 0x92cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x92cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_mnd1x_0_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = { + .halt_reg = 0x92d0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x92d0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_mnd1x_1_gfx3d_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_sleep_clk = { + .halt_reg = 0x9164, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9164, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gpu_cc_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cc_cx_gdsc = { + .gdscr = 0x9110, + .gds_hw_ctrl = 0x9124, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x8, + .pd = { + .name = "gpu_cc_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE | RETAIN_FF_ENABLE, +}; + +static struct gdsc gpu_cc_gx_gdsc = { + .gdscr = 0x905c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gpu_cc_gx_gdsc", + .power_on = gdsc_gx_do_nothing_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *gpu_cc_eliza_clocks[] = { + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_ACCU_SHIFT_CLK] = &gpu_cc_cx_accu_shift_clk.clkr, + [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr, + [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, + [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, + [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, + [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, + [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr, + [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr, + [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr, + [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, + [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr, + [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr, +}; + +static struct gdsc *gpu_cc_eliza_gdscs[] = { + [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc, + [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc, +}; + +static const struct qcom_reset_map gpu_cc_eliza_resets[] = { + [GPU_CC_ACD_BCR] = { 0x939c }, + [GPU_CC_CB_BCR] = { 0x93e4 }, + [GPU_CC_CX_BCR] = { 0x910c }, + [GPU_CC_FAST_HUB_BCR] = { 0x9428 }, + [GPU_CC_FF_BCR] = { 0x94b4 }, + [GPU_CC_GFX3D_AON_BCR] = { 0x91dc }, + [GPU_CC_GMU_BCR] = { 0x9358 }, + [GPU_CC_GX_BCR] = { 0x9058 }, + [GPU_CC_RBCPR_BCR] = { 0x9224 }, + [GPU_CC_XO_BCR] = { 0x9000 }, +}; + +static struct clk_alpha_pll *gpu_cc_eliza_plls[] = { + &gpu_cc_pll0, + &gpu_cc_pll1, +}; + +static u32 gpu_cc_eliza_critical_cbcrs[] = { + 0x9004, /* GPU_CC_CXO_AON_CLK */ + 0x900c, /* GPU_CC_DEMET_CLK */ +}; + +static const struct regmap_config gpu_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9988, + .fast_io = true, +}; + +static struct qcom_cc_driver_data gpu_cc_eliza_driver_data = { + .alpha_plls = gpu_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(gpu_cc_eliza_plls), + .clk_cbcrs = gpu_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc gpu_cc_eliza_desc = { + .config = &gpu_cc_eliza_regmap_config, + .clks = gpu_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_eliza_clocks), + .resets = gpu_cc_eliza_resets, + .num_resets = ARRAY_SIZE(gpu_cc_eliza_resets), + .gdscs = gpu_cc_eliza_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_eliza_gdscs), + .use_rpm = true, + .driver_data = &gpu_cc_eliza_driver_data, +}; + +static const struct of_device_id gpu_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_eliza_match_table); + +static int gpu_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &gpu_cc_eliza_desc); +} + +static struct platform_driver gpu_cc_eliza_driver = { + .probe = gpu_cc_eliza_probe, + .driver = { + .name = "gpucc-eliza", + .of_match_table = gpu_cc_eliza_match_table, + }, +}; + +module_platform_driver(gpu_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI GPUCC Eliza Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/gpucc-qcm2290.c b/drivers/clk/qcom/gpucc-qcm2290.c index dc369dff882e6..92d55839ad1e6 100644 --- a/drivers/clk/qcom/gpucc-qcm2290.c +++ b/drivers/clk/qcom/gpucc-qcm2290.c @@ -2,14 +2,13 @@ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * Copyright (c) 2024, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include #include #include #include -#include -#include #include #include @@ -20,7 +19,7 @@ #include "clk-regmap.h" #include "clk-regmap-divider.h" #include "clk-regmap-mux.h" -#include "clk-regmap-phy-mux.h" +#include "common.h" #include "gdsc.h" #include "reset.h" @@ -57,6 +56,7 @@ static const struct alpha_pll_config gpu_cc_pll0_config = { static struct clk_alpha_pll gpu_cc_pll0 = { .offset = 0x0, + .config = &gpu_cc_pll0_config, .vco_table = huayra_vco, .num_vco = ARRAY_SIZE(huayra_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_2290], @@ -133,6 +133,17 @@ static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { { } }; +static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src_shikra[] = { + F(355200000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), + F(537600000, P_GPU_CC_PLL0_OUT_AUX, 2, 0, 0), + F(672000000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(844800000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(921600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(1017600000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + F(1142400000, P_GPU_CC_PLL0_OUT_AUX2, 2, 0, 0), + { } +}; + static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { .cmd_rcgr = 0x101c, .mnd_width = 0, @@ -144,21 +155,7 @@ static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { .parent_data = gpu_cc_parent_data_1, .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, - }, -}; - -static struct clk_branch gpu_cc_ahb_clk = { - .halt_reg = 0x1078, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x1078, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gpu_cc_ahb_clk", - .flags = CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, + .ops = &clk_rcg2_shared_ops, }, }; @@ -224,19 +221,6 @@ static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { }, }; -static struct clk_branch gpu_cc_cxo_aon_clk = { - .halt_reg = 0x1004, - .halt_check = BRANCH_HALT_DELAY, - .clkr = { - .enable_reg = 0x1004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gpu_cc_cxo_aon_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gpu_cc_cxo_clk = { .halt_reg = 0x109c, .halt_check = BRANCH_HALT, @@ -297,11 +281,14 @@ static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { static struct gdsc gpu_cx_gdsc = { .gdscr = 0x106c, .gds_hw_ctrl = 0x1540, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, .pd = { .name = "gpu_cx_gdsc", }, .pwrsts = PWRSTS_OFF_ON, - .flags = VOTABLE, + .flags = RETAIN_FF_ENABLE | VOTABLE, }; static struct gdsc gpu_gx_gdsc = { @@ -309,21 +296,22 @@ static struct gdsc gpu_gx_gdsc = { .clamp_io_ctrl = 0x1508, .resets = (unsigned int []){ GPU_GX_BCR }, .reset_count = 1, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x2, .pd = { .name = "gpu_gx_gdsc", }, .parent = &gpu_cx_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, - .flags = CLAMP_IO | AON_RESET | SW_RESET, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | SW_RESET | CLAMP_IO | AON_RESET, }; static struct clk_regmap *gpu_cc_qcm2290_clocks[] = { - [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, - [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, @@ -342,6 +330,16 @@ static struct gdsc *gpu_cc_qcm2290_gdscs[] = { [GPU_GX_GDSC] = &gpu_gx_gdsc, }; +static struct clk_alpha_pll *gpu_cc_qcm2290_plls[] = { + &gpu_cc_pll0, +}; + +static u32 gpu_cc_qcm2290_critical_cbcrs[] = { + 0x1078, /* GPU_CC_AHB_CLK */ + 0x1004, /* GPU_CC_CXO_AON_CLK */ + 0x1060, /* GPU_CC_GX_CXO_CLK */ +}; + static const struct regmap_config gpu_cc_qcm2290_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -350,6 +348,12 @@ static const struct regmap_config gpu_cc_qcm2290_regmap_config = { .fast_io = true, }; +static struct qcom_cc_driver_data gpu_cc_qcm2290_driver_data = { + .alpha_plls = gpu_cc_qcm2290_plls, + .num_alpha_plls = ARRAY_SIZE(gpu_cc_qcm2290_plls), + .clk_cbcrs = gpu_cc_qcm2290_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_qcm2290_critical_cbcrs), +}; static const struct qcom_cc_desc gpu_cc_qcm2290_desc = { .config = &gpu_cc_qcm2290_regmap_config, @@ -359,55 +363,22 @@ static const struct qcom_cc_desc gpu_cc_qcm2290_desc = { .num_resets = ARRAY_SIZE(gpu_cc_qcm2290_resets), .gdscs = gpu_cc_qcm2290_gdscs, .num_gdscs = ARRAY_SIZE(gpu_cc_qcm2290_gdscs), + .driver_data = &gpu_cc_qcm2290_driver_data, }; static const struct of_device_id gpu_cc_qcm2290_match_table[] = { { .compatible = "qcom,qcm2290-gpucc" }, + { .compatible = "qcom,shikra-gpucc" }, { } }; MODULE_DEVICE_TABLE(of, gpu_cc_qcm2290_match_table); static int gpu_cc_qcm2290_probe(struct platform_device *pdev) { - struct regmap *regmap; - int ret; - - regmap = qcom_cc_map(pdev, &gpu_cc_qcm2290_desc); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - ret = devm_pm_runtime_enable(&pdev->dev); - if (ret) - return ret; - - ret = devm_pm_clk_create(&pdev->dev); - if (ret) - return ret; - - ret = pm_clk_add(&pdev->dev, NULL); - if (ret < 0) { - dev_err(&pdev->dev, "failed to acquire ahb clock\n"); - return ret; - } - - ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret) - return ret; - - clk_huayra_2290_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); - - regmap_update_bits(regmap, 0x1060, BIT(0), BIT(0)); /* GPU_CC_GX_CXO_CLK */ - - ret = qcom_cc_really_probe(&pdev->dev, &gpu_cc_qcm2290_desc, regmap); - if (ret) { - dev_err(&pdev->dev, "Failed to register display clock controller\n"); - goto out_pm_runtime_put; - } - -out_pm_runtime_put: - pm_runtime_put_sync(&pdev->dev); + if (device_is_compatible(&pdev->dev, "qcom,shikra-gpucc")) + gpu_cc_gx_gfx3d_clk_src.freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src_shikra; - return 0; + return qcom_cc_probe(pdev, &gpu_cc_qcm2290_desc); } static struct platform_driver gpu_cc_qcm2290_driver = { diff --git a/drivers/clk/qcom/gxclkctl-kaanapali.c b/drivers/clk/qcom/gxclkctl-kaanapali.c index 7b0af0ba1e685..1991cb6516529 100644 --- a/drivers/clk/qcom/gxclkctl-kaanapali.c +++ b/drivers/clk/qcom/gxclkctl-kaanapali.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ static struct gdsc gx_clkctl_gx_gdsc = { .pd = { .name = "gx_clkctl_gx_gdsc", .power_on = gdsc_gx_do_nothing_enable, + .power_off = gdsc_gx_disable, }, .pwrsts = PWRSTS_OFF_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, @@ -61,7 +63,15 @@ MODULE_DEVICE_TABLE(of, gx_clkctl_kaanapali_match_table); static int gx_clkctl_kaanapali_probe(struct platform_device *pdev) { - return qcom_cc_probe(pdev, &gx_clkctl_kaanapali_desc); + int ret; + + ret = qcom_cc_probe(pdev, &gx_clkctl_kaanapali_desc); + if (ret) + return ret; + + pm_runtime_disable(&pdev->dev); + + return ret; } static struct platform_driver gx_clkctl_kaanapali_driver = { diff --git a/drivers/clk/qcom/videocc-eliza.c b/drivers/clk/qcom/videocc-eliza.c new file mode 100644 index 0000000000000..36af35e070299 --- /dev/null +++ b/drivers/clk/qcom/videocc-eliza.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, + DT_AHB_CLK, +}; + +enum { + P_BI_TCXO, + P_SLEEP_CLK, + P_VIDEO_CC_PLL0_OUT_MAIN, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +/* 576.0 MHz Configuration */ +static const struct alpha_pll_config video_cc_pll0_config = { + .l = 0x1e, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll video_cc_pll0 = { + .offset = 0x0, + .config = &video_cc_pll0_config, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data video_cc_parent_data_0[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_CC_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &video_cc_pll0.clkr.hw }, +}; + +static const struct parent_map video_cc_parent_map_2[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data video_cc_parent_data_2[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_ahb_clk_src = { + .cmd_rcgr = 0x8018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_ahb_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { + F(576000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(633000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1113000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs0_clk_src = { + .cmd_rcgr = 0x8000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_mvs0_clk_src, + .hw_clk_ctrl = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk_src", + .parent_data = video_cc_parent_data_1, + .num_parents = ARRAY_SIZE(video_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_sleep_clk_src = { + .cmd_rcgr = 0x8110, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_2, + .freq_tbl = ftbl_video_cc_sleep_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_sleep_clk_src", + .parent_data = video_cc_parent_data_2, + .num_parents = ARRAY_SIZE(video_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 video_cc_xo_clk_src = { + .cmd_rcgr = 0x80f4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_ahb_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_xo_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0_div_clk_src = { + .reg = 0x80ac, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { + .reg = 0x8058, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_div2_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch video_cc_mvs0_clk = { + .halt_reg = 0x80a0, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x80a0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x80a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0_shift_clk = { + .halt_reg = 0x8144, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8144, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_clk = { + .halt_reg = 0x804c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x804c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0c_shift_clk = { + .halt_reg = 0x8148, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8148, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8148, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "video_cc_mvs0c_shift_clk", + .parent_hws = (const struct clk_hw*[]) { + &video_cc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc video_cc_mvs0c_gdsc = { + .gdscr = 0x8034, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0c_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc video_cc_mvs0_gdsc = { + .gdscr = 0x808c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0x6, + .pd = { + .name = "video_cc_mvs0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .parent = &video_cc_mvs0c_gdsc.pd, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL_TRIGGER, +}; + +static struct clk_regmap *video_cc_eliza_clocks[] = { + [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr, + [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, + [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, + [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr, + [VIDEO_CC_MVS0_SHIFT_CLK] = &video_cc_mvs0_shift_clk.clkr, + [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, + [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, + [VIDEO_CC_MVS0C_SHIFT_CLK] = &video_cc_mvs0c_shift_clk.clkr, + [VIDEO_CC_PLL0] = &video_cc_pll0.clkr, + [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr, + [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr, +}; + +static struct gdsc *video_cc_eliza_gdscs[] = { + [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc, + [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc, +}; + +static const struct qcom_reset_map video_cc_eliza_resets[] = { + [VIDEO_CC_INTERFACE_BCR] = { 0x80d8 }, + [VIDEO_CC_MVS0_CLK_ARES] = { 0x80a0, 2 }, + [VIDEO_CC_MVS0_BCR] = { 0x8088 }, + [VIDEO_CC_MVS0C_CLK_ARES] = { 0x804c, 2 }, + [VIDEO_CC_MVS0C_BCR] = { 0x8030 }, + [VIDEO_CC_XO_CLK_ARES] = { 0x810c, 2 }, +}; + +static struct clk_alpha_pll *video_cc_eliza_plls[] = { + &video_cc_pll0, +}; + +static u32 video_cc_eliza_critical_cbcrs[] = { + 0x80dc, /* VIDEO_CC_AHB_CLK */ + 0x8128, /* VIDEO_CC_SLEEP_CLK */ + 0x810c, /* VIDEO_CC_XO_CLK */ +}; + +static const struct regmap_config video_cc_eliza_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9f50, + .fast_io = true, +}; + +static struct qcom_cc_driver_data video_cc_eliza_driver_data = { + .alpha_plls = video_cc_eliza_plls, + .num_alpha_plls = ARRAY_SIZE(video_cc_eliza_plls), + .clk_cbcrs = video_cc_eliza_critical_cbcrs, + .num_clk_cbcrs = ARRAY_SIZE(video_cc_eliza_critical_cbcrs), +}; + +static const struct qcom_cc_desc video_cc_eliza_desc = { + .config = &video_cc_eliza_regmap_config, + .clks = video_cc_eliza_clocks, + .num_clks = ARRAY_SIZE(video_cc_eliza_clocks), + .resets = video_cc_eliza_resets, + .num_resets = ARRAY_SIZE(video_cc_eliza_resets), + .gdscs = video_cc_eliza_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_eliza_gdscs), + .driver_data = &video_cc_eliza_driver_data, +}; + +static const struct of_device_id video_cc_eliza_match_table[] = { + { .compatible = "qcom,eliza-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_eliza_match_table); + +static int video_cc_eliza_probe(struct platform_device *pdev) +{ + return qcom_cc_probe(pdev, &video_cc_eliza_desc); +} + +static struct platform_driver video_cc_eliza_driver = { + .probe = video_cc_eliza_probe, + .driver = { + .name = "videocc-eliza", + .of_match_table = video_cc_eliza_match_table, + }, +}; + +module_platform_driver(video_cc_eliza_driver); + +MODULE_DESCRIPTION("QTI VIDEOCC Eliza Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2d2f40a2cb813..b876a1a72ec01 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -224,6 +224,9 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev, bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP); ktime_t time_start, time_end; + if (cpus_peek_for_pending_ipi(cpumask_of(dev->cpu))) + return -EBUSY; + instrumentation_begin(); /* diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 9cb11fada2c4d..8831adb7b0f56 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -463,17 +463,17 @@ qce_aead_async_req_handle(struct crypto_async_request *async_req) src_nents = dst_nents - 1; } - ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, - qce_aead_done, async_req); + ret = qce_start(async_req, tmpl->crypto_alg_type); if (ret) goto error_unmap_src; - qce_dma_issue_pending(&qce->dma); - - ret = qce_start(async_req, tmpl->crypto_alg_type); + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, + qce_aead_done, async_req); if (ret) goto error_terminate; + qce_dma_issue_pending(&qce->dma); + return 0; error_terminate: diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c index 54a78a57f6302..37bb6f03244d3 100644 --- a/drivers/crypto/qce/common.c +++ b/drivers/crypto/qce/common.c @@ -25,7 +25,7 @@ static inline u32 qce_read(struct qce_device *qce, u32 offset) static inline void qce_write(struct qce_device *qce, u32 offset, u32 val) { - writel(val, qce->base + offset); + qce_write_dma(qce, offset, val); } static inline void qce_write_array(struct qce_device *qce, u32 offset, @@ -82,6 +82,8 @@ static void qce_setup_config(struct qce_device *qce) { u32 config; + qce_clear_bam_transaction(qce); + /* get big endianness */ config = qce_config_reg(qce, 0); @@ -90,12 +92,14 @@ static void qce_setup_config(struct qce_device *qce) qce_write(qce, REG_CONFIG, config); } -static inline void qce_crypto_go(struct qce_device *qce, bool result_dump) +static inline int qce_crypto_go(struct qce_device *qce, bool result_dump) { if (result_dump) qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); else qce_write(qce, REG_GOPROC, BIT(GO_SHIFT)); + + return qce_submit_cmd_desc(qce); } #if defined(CONFIG_CRYPTO_DEV_QCE_SHA) || defined(CONFIG_CRYPTO_DEV_QCE_AEAD) @@ -223,9 +227,7 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req) config = qce_config_reg(qce, 1); qce_write(qce, REG_CONFIG, config); - qce_crypto_go(qce, true); - - return 0; + return qce_crypto_go(qce, true); } #endif @@ -386,9 +388,7 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) config = qce_config_reg(qce, 1); qce_write(qce, REG_CONFIG, config); - qce_crypto_go(qce, true); - - return 0; + return qce_crypto_go(qce, true); } #endif @@ -535,9 +535,7 @@ static int qce_setup_regs_aead(struct crypto_async_request *async_req) qce_write(qce, REG_CONFIG, config); /* Start the process */ - qce_crypto_go(qce, !IS_CCM(flags)); - - return 0; + return qce_crypto_go(qce, !IS_CCM(flags)); } #endif diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index b966f3365b7de..d7b7a3dda4649 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "core.h" @@ -186,10 +185,26 @@ static int qce_check_version(struct qce_device *qce) return 0; } +static void qce_cancel_work(void *data) +{ + struct work_struct *work = data; + + cancel_work_sync(work); +} + +static void qce_crypto_unmap_dma(void *data) +{ + struct qce_device *qce = data; + + dma_unmap_resource(qce->dev, qce->base_dma, qce->dma_size, + DMA_BIDIRECTIONAL, 0); +} + static int qce_crypto_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct qce_device *qce; + struct resource *res; int ret; qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL); @@ -199,7 +214,7 @@ static int qce_crypto_probe(struct platform_device *pdev) qce->dev = dev; platform_set_drvdata(pdev, qce); - qce->base = devm_platform_ioremap_resource(pdev, 0); + qce->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(qce->base)) return PTR_ERR(qce->base); @@ -227,7 +242,12 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - ret = devm_qce_dma_request(qce->dev, &qce->dma); + INIT_WORK(&qce->done_work, qce_req_done_work); + ret = devm_add_action_or_reset(dev, qce_cancel_work, &qce->done_work); + if (ret) + return ret; + + ret = devm_qce_dma_request(qce); if (ret) return ret; @@ -239,12 +259,23 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - INIT_WORK(&qce->done_work, qce_req_done_work); crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH); qce->async_req_enqueue = qce_async_request_enqueue; qce->async_req_done = qce_async_request_done; + qce->dma_size = resource_size(res); + qce->base_dma = dma_map_resource(dev, res->start, qce->dma_size, + DMA_BIDIRECTIONAL, 0); + qce->base_phys = res->start; + ret = dma_mapping_error(dev, qce->base_dma); + if (ret) + return ret; + + ret = devm_add_action_or_reset(qce->dev, qce_crypto_unmap_dma, qce); + if (ret) + return ret; + return devm_qce_register_algs(qce); } diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h index eb6fa7a8b64a8..a80e12eac6c87 100644 --- a/drivers/crypto/qce/core.h +++ b/drivers/crypto/qce/core.h @@ -8,6 +8,7 @@ #include #include +#include #include "dma.h" @@ -26,6 +27,9 @@ * @dma: pointer to dma data * @burst_size: the crypto burst size * @pipe_pair_id: which pipe pair id the device using + * @base_dma: base DMA address + * @base_phys: base physical address + * @dma_size: size of memory mapped for DMA * @async_req_enqueue: invoked by every algorithm to enqueue a request * @async_req_done: invoked by every algorithm to finish its request */ @@ -42,6 +46,9 @@ struct qce_device { struct qce_dma_data dma; int burst_size; unsigned int pipe_pair_id; + dma_addr_t base_dma; + phys_addr_t base_phys; + size_t dma_size; int (*async_req_enqueue)(struct qce_device *qce, struct crypto_async_request *req); void (*async_req_done)(struct qce_device *qce, int ret); diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 68cafd4741ad3..6410f8dc5bcf5 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -4,52 +4,155 @@ */ #include +#include +#include #include #include +#include "core.h" #include "dma.h" +#include "regs-v5.h" + +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) +#define QCE_BAM_CMD_SGL_SIZE 128 +#define QCE_BAM_CMD_ELEMENT_SIZE 128 + +struct qce_desc_info { + struct dma_async_tx_descriptor *dma_desc; + enum dma_data_direction dir; +}; + +struct qce_bam_transaction { + struct bam_cmd_element bam_ce[QCE_BAM_CMD_ELEMENT_SIZE]; + struct scatterlist wr_sgl[QCE_BAM_CMD_SGL_SIZE]; + struct qce_desc_info *desc; + u32 bam_ce_idx; + u32 pre_bam_ce_idx; + u32 wr_sgl_cnt; +}; + +void qce_clear_bam_transaction(struct qce_device *qce) +{ + struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; + + bam_txn->bam_ce_idx = 0; + bam_txn->wr_sgl_cnt = 0; + bam_txn->pre_bam_ce_idx = 0; +} + +int qce_submit_cmd_desc(struct qce_device *qce) +{ + struct bam_desc_metadata meta = { + .scratchpad_addr = qce->base_phys + REG_VERSION, + .direction = DMA_MEM_TO_DEV, + }; + struct qce_desc_info *qce_desc = qce->dma.bam_txn->desc; + struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; + struct dma_async_tx_descriptor *dma_desc; + struct dma_chan *chan = qce->dma.rxchan; + unsigned long attrs = DMA_PREP_CMD; + dma_cookie_t cookie; + unsigned int mapped; + int ret; + + mapped = dma_map_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + if (!mapped) + return -ENOMEM; + + dma_desc = dmaengine_prep_slave_sg(chan, bam_txn->wr_sgl, mapped, DMA_MEM_TO_DEV, attrs); + if (!dma_desc) { + ret = -ENOMEM; + goto err_unmap_sg; + } + + ret = dmaengine_desc_attach_metadata(dma_desc, &meta, sizeof(meta)); + if (ret) + goto err_free_desc; + + qce_desc->dma_desc = dma_desc; + cookie = dmaengine_submit(qce_desc->dma_desc); + + ret = dma_submit_error(cookie); + if (ret) + goto err_free_desc; + + return 0; + +err_free_desc: + dmaengine_desc_free(dma_desc); +err_unmap_sg: + dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + return ret; +} + +static void qce_prep_dma_cmd_desc(struct qce_device *qce, struct qce_dma_data *dma, + unsigned int addr, void *buf) +{ + struct qce_bam_transaction *bam_txn = dma->bam_txn; + struct bam_cmd_element *bam_ce_buf; + int bam_ce_size, cnt, idx; -static void qce_dma_release(void *data) + idx = bam_txn->bam_ce_idx; + bam_ce_buf = &bam_txn->bam_ce[idx]; + bam_prep_ce_le32(bam_ce_buf, addr, BAM_WRITE_COMMAND, *((__le32 *)buf)); + + bam_ce_buf = &bam_txn->bam_ce[bam_txn->pre_bam_ce_idx]; + bam_txn->bam_ce_idx++; + bam_ce_size = (bam_txn->bam_ce_idx - bam_txn->pre_bam_ce_idx) * sizeof(*bam_ce_buf); + + cnt = bam_txn->wr_sgl_cnt; + + sg_set_buf(&bam_txn->wr_sgl[cnt], bam_ce_buf, bam_ce_size); + + ++bam_txn->wr_sgl_cnt; + bam_txn->pre_bam_ce_idx = bam_txn->bam_ce_idx; +} + +void qce_write_dma(struct qce_device *qce, unsigned int offset, u32 val) +{ + unsigned int reg_addr = ((unsigned int)(qce->base_phys) + offset); + + qce_prep_dma_cmd_desc(qce, &qce->dma, reg_addr, &val); +} + +static void qce_dma_terminate(void *data) { struct qce_dma_data *dma = data; - dma_release_channel(dma->txchan); - dma_release_channel(dma->rxchan); - kfree(dma->result_buf); + dmaengine_terminate_sync(dma->txchan); + dmaengine_terminate_sync(dma->rxchan); } -int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma) +int devm_qce_dma_request(struct qce_device *qce) { - int ret; + struct qce_dma_data *dma = &qce->dma; + struct device *dev = qce->dev; - dma->txchan = dma_request_chan(dev, "tx"); + dma->result_buf = devm_kmalloc(dev, QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ, GFP_KERNEL); + if (!dma->result_buf) + return -ENOMEM; + + dma->txchan = devm_dma_request_chan(dev, "tx"); if (IS_ERR(dma->txchan)) return dev_err_probe(dev, PTR_ERR(dma->txchan), "Failed to get TX DMA channel\n"); - dma->rxchan = dma_request_chan(dev, "rx"); - if (IS_ERR(dma->rxchan)) { - ret = dev_err_probe(dev, PTR_ERR(dma->rxchan), - "Failed to get RX DMA channel\n"); - goto error_rx; - } + dma->rxchan = devm_dma_request_chan(dev, "rx"); + if (IS_ERR(dma->rxchan)) + return dev_err_probe(dev, PTR_ERR(dma->rxchan), + "Failed to get RX DMA channel\n"); - dma->result_buf = kmalloc(QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ, - GFP_KERNEL); - if (!dma->result_buf) { - ret = -ENOMEM; - goto error_nomem; - } + dma->bam_txn = devm_kzalloc(dev, sizeof(*dma->bam_txn), GFP_KERNEL); + if (!dma->bam_txn) + return -ENOMEM; - dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; + dma->bam_txn->desc = devm_kzalloc(dev, sizeof(*dma->bam_txn->desc), GFP_KERNEL); + if (!dma->bam_txn->desc) + return -ENOMEM; - return devm_add_action_or_reset(dev, qce_dma_release, dma); + sg_init_table(dma->bam_txn->wr_sgl, QCE_BAM_CMD_SGL_SIZE); -error_nomem: - dma_release_channel(dma->rxchan); -error_rx: - dma_release_channel(dma->txchan); - return ret; + return devm_add_action_or_reset(dev, qce_dma_terminate, dma); } struct scatterlist * @@ -108,28 +211,36 @@ int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *rx_sg, { struct dma_chan *rxchan = dma->rxchan; struct dma_chan *txchan = dma->txchan; - unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + unsigned long txflags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + unsigned long rxflags = txflags | DMA_PREP_FENCE; int ret; - ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, flags, DMA_MEM_TO_DEV, + ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, rxflags, DMA_MEM_TO_DEV, NULL, NULL); if (ret) return ret; - return qce_dma_prep_sg(txchan, tx_sg, tx_nents, flags, DMA_DEV_TO_MEM, + return qce_dma_prep_sg(txchan, tx_sg, tx_nents, txflags, DMA_DEV_TO_MEM, cb, cb_param); } void qce_dma_issue_pending(struct qce_dma_data *dma) { - dma_async_issue_pending(dma->rxchan); dma_async_issue_pending(dma->txchan); + dma_async_issue_pending(dma->rxchan); } int qce_dma_terminate_all(struct qce_dma_data *dma) { + struct qce_device *qce = container_of(dma, struct qce_device, dma); + struct qce_bam_transaction *bam_txn = dma->bam_txn; int ret; ret = dmaengine_terminate_all(dma->rxchan); - return ret ?: dmaengine_terminate_all(dma->txchan); + if (ret) + return ret; + + dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + + return dmaengine_terminate_all(dma->txchan); } diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h index 31629185000e1..f05dfa9e6b25b 100644 --- a/drivers/crypto/qce/dma.h +++ b/drivers/crypto/qce/dma.h @@ -8,6 +8,9 @@ #include +struct qce_bam_transaction; +struct qce_device; + /* maximum data transfer block size between BAM and CE */ #define QCE_BAM_BURST_SIZE 64 @@ -23,7 +26,6 @@ struct qce_result_dump { u32 status2; }; -#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) #define QCE_RESULT_BUF_SZ \ ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE) @@ -31,10 +33,10 @@ struct qce_dma_data { struct dma_chan *txchan; struct dma_chan *rxchan; struct qce_result_dump *result_buf; - void *ignore_buf; + struct qce_bam_transaction *bam_txn; }; -int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma); +int devm_qce_dma_request(struct qce_device *qce); int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in, int in_ents, struct scatterlist *sg_out, int out_ents, dma_async_tx_callback cb, void *cb_param); @@ -43,5 +45,8 @@ int qce_dma_terminate_all(struct qce_dma_data *dma); struct scatterlist * qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, unsigned int max_len); +void qce_write_dma(struct qce_device *qce, unsigned int offset, u32 val); +int qce_submit_cmd_desc(struct qce_device *qce); +void qce_clear_bam_transaction(struct qce_device *qce); #endif /* _DMA_H_ */ diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index 1b37121cbcdcb..508b4c18d2119 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -109,17 +109,17 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req) goto error_unmap_src; } - ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents, - &rctx->result_sg, 1, qce_ahash_done, async_req); + ret = qce_start(async_req, tmpl->crypto_alg_type); if (ret) goto error_unmap_dst; - qce_dma_issue_pending(&qce->dma); - - ret = qce_start(async_req, tmpl->crypto_alg_type); + ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents, + &rctx->result_sg, 1, qce_ahash_done, async_req); if (ret) goto error_terminate; + qce_dma_issue_pending(&qce->dma); + return 0; error_terminate: diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index db0b648a56eb1..78fe3c3611cfe 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -142,18 +142,18 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) src_nents = dst_nents - 1; } + ret = qce_start(async_req, tmpl->crypto_alg_type); + if (ret) + goto error_unmap_src; + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, qce_skcipher_done, async_req); if (ret) - goto error_unmap_src; + goto error_terminate; qce_dma_issue_pending(&qce->dma); - ret = qce_start(async_req, tmpl->crypto_alg_type); - if (ret) - goto error_terminate; - return 0; error_terminate: diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 1bb26af0405f3..661b362591cd1 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -28,11 +28,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -42,6 +44,7 @@ #include #include #include +#include #include "../dmaengine.h" #include "../virt-dma.h" @@ -59,6 +62,8 @@ struct bam_desc_hw { #define DESC_FLAG_EOB BIT(13) #define DESC_FLAG_NWD BIT(12) #define DESC_FLAG_CMD BIT(11) +#define DESC_FLAG_LOCK BIT(10) +#define DESC_FLAG_UNLOCK BIT(9) struct bam_async_desc { struct virt_dma_desc vd; @@ -71,6 +76,10 @@ struct bam_async_desc { struct bam_desc_hw *curr_desc; + /* BAM locking infrastructure */ + struct scatterlist lock_sg; + struct bam_cmd_element lock_ce; + /* list node for the desc in the bam_chan list of descriptors */ struct list_head desc_node; enum dma_transfer_direction dir; @@ -112,6 +121,11 @@ struct reg_offset_data { unsigned int pipe_mult, evnt_mult, ee_mult; }; +struct bam_device_data { + const struct reg_offset_data *reg_info; + bool pipe_lock_supported; +}; + static const struct reg_offset_data bam_v1_3_reg_info[] = { [BAM_CTRL] = { 0x0F80, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x0F84, 0x00, 0x00, 0x00 }, @@ -141,6 +155,10 @@ static const struct reg_offset_data bam_v1_3_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x1020, 0x00, 0x40, 0x00 }, }; +static const struct bam_device_data bam_v1_3_data = { + .reg_info = bam_v1_3_reg_info, +}; + static const struct reg_offset_data bam_v1_4_reg_info[] = { [BAM_CTRL] = { 0x0000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x0004, 0x00, 0x00, 0x00 }, @@ -170,6 +188,11 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x1820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v1_4_data = { + .reg_info = bam_v1_4_reg_info, + .pipe_lock_supported = true, +}; + static const struct reg_offset_data bam_v1_7_reg_info[] = { [BAM_CTRL] = { 0x00000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x01000, 0x00, 0x00, 0x00 }, @@ -199,6 +222,11 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x13820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v1_7_data = { + .reg_info = bam_v1_7_reg_info, + .pipe_lock_supported = true, +}; + static const struct reg_offset_data bam_v2_0_reg_info[] = { [BAM_CTRL] = { 0x0000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x1000, 0x00, 0x00, 0x00 }, @@ -228,6 +256,11 @@ static const struct reg_offset_data bam_v2_0_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0xC820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v2_0_data = { + .reg_info = bam_v2_0_reg_info, + .pipe_lock_supported = true, +}; + /* BAM CTRL */ #define BAM_SW_RST BIT(0) #define BAM_EN BIT(1) @@ -400,6 +433,11 @@ struct bam_chan { struct list_head desc_list; struct list_head node; + + /* BAM locking infrastructure */ + phys_addr_t scratchpad_addr; + enum dma_transfer_direction direction; + bool bam_locked; }; static inline struct bam_chan *to_bam_chan(struct dma_chan *common) @@ -421,13 +459,13 @@ struct bam_device { bool powered_remotely; u32 active_channels; - const struct reg_offset_data *layout; + const struct bam_device_data *dev_data; struct clk *bamclk; int irq; - /* dma start transaction tasklet */ - struct tasklet_struct task; + /* dma start transaction workqueue */ + struct work_struct work; }; /** @@ -439,7 +477,7 @@ struct bam_device { static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe, enum bam_reg reg) { - const struct reg_offset_data r = bdev->layout[reg]; + const struct reg_offset_data r = bdev->dev_data->reg_info[reg]; return bdev->regs + r.base_offset + r.pipe_mult * pipe + @@ -613,8 +651,10 @@ static void bam_free_chan(struct dma_chan *chan) goto err; } - scoped_guard(spinlock_irqsave, &bchan->vc.lock) + scoped_guard(spinlock_irqsave, &bchan->vc.lock) { bam_reset_channel(bchan); + bchan->bam_locked = false; + } dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt, bchan->fifo_phys); @@ -661,6 +701,35 @@ static int bam_slave_config(struct dma_chan *chan, return 0; } +static int bam_metadata_attach(struct dma_async_tx_descriptor *desc, void *data, size_t len) +{ + struct bam_chan *bchan = to_bam_chan(desc->chan); + const struct bam_device_data *bdata = bchan->bdev->dev_data; + struct bam_desc_metadata *metadata = data; + + if (!data) + return -EINVAL; + + if (!bdata->pipe_lock_supported) + /* + * The client wants to use locking but this BAM version doesn't + * support it. Don't return an error here as this will stop the + * client from using DMA at all for no reason. + */ + return 0; + + guard(spinlock_irqsave)(&bchan->vc.lock); + + bchan->scratchpad_addr = metadata->scratchpad_addr; + bchan->direction = metadata->direction; + + return 0; +} + +static const struct dma_descriptor_metadata_ops bam_metadata_ops = { + .attach = bam_metadata_attach, +}; + /** * bam_prep_slave_sg - Prep slave sg transaction * @@ -677,6 +746,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, void *context) { struct bam_chan *bchan = to_bam_chan(chan); + struct dma_async_tx_descriptor *tx_desc; struct bam_device *bdev = bchan->bdev; struct bam_async_desc *async_desc; struct scatterlist *sg; @@ -732,7 +802,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, } while (remainder > 0); } - return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); + tx_desc = vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); + tx_desc->metadata_ops = &bam_metadata_ops; + + return tx_desc; } /** @@ -777,6 +850,7 @@ static int bam_dma_terminate_all(struct dma_chan *chan) } vchan_get_all_descriptors(&bchan->vc, &head); + bchan->bam_locked = false; } vchan_dma_desc_free_list(&bchan->vc, &head); @@ -834,6 +908,15 @@ static int bam_resume(struct dma_chan *chan) return 0; } +static void bam_dma_free_lock_desc(struct virt_dma_desc *vd) +{ + struct bam_async_desc *async_desc = container_of(vd, struct bam_async_desc, vd); + struct dma_chan *chan = vd->tx.chan; + + dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); + kfree(async_desc); +} + /** * process_channel_irqs - processes the channel interrupts * @bdev: bam controller @@ -892,15 +975,25 @@ static u32 process_channel_irqs(struct bam_device *bdev) /* * if complete, process cookie. Otherwise * push back to front of desc_issued so that - * it gets restarted by the tasklet + * it gets restarted by the work queue. */ + + list_del(&async_desc->desc_node); if (!async_desc->num_desc) { - vchan_cookie_complete(&async_desc->vd); + struct bam_desc_hw *hdesc = async_desc->desc; + u16 flags = le16_to_cpu(hdesc->flags); + + if (flags & (DESC_FLAG_LOCK | DESC_FLAG_UNLOCK)) { + if (flags & DESC_FLAG_UNLOCK) + bchan->bam_locked = false; + bam_dma_free_lock_desc(&async_desc->vd); + } else { + vchan_cookie_complete(&async_desc->vd); + } } else { list_add(&async_desc->vd.node, &bchan->vc.desc_issued); } - list_del(&async_desc->desc_node); } } @@ -922,9 +1015,9 @@ static irqreturn_t bam_dma_irq(int irq, void *data) srcs |= process_channel_irqs(bdev); - /* kick off tasklet to start next dma transfer */ + /* kick off the work queue to start next dma transfer */ if (srcs & P_IRQ) - tasklet_schedule(&bdev->task); + queue_work(system_bh_highpri_wq, &bdev->work); ret = pm_runtime_get_sync(bdev->dev); if (ret < 0) @@ -1021,13 +1114,101 @@ static void bam_apply_new_config(struct bam_chan *bchan, bchan->reconfigure = 0; } +static struct bam_async_desc * +bam_make_lock_desc(struct bam_chan *bchan, unsigned long flag) +{ + struct dma_chan *chan = &bchan->vc.chan; + struct bam_async_desc *async_desc; + struct bam_desc_hw *desc; + struct virt_dma_desc *vd; + struct virt_dma_chan *vc; + unsigned int mapped; + + async_desc = kzalloc_flex(*async_desc, desc, 1, GFP_NOWAIT); + if (!async_desc) { + dev_err(bchan->bdev->dev, "failed to allocate the BAM lock descriptor\n"); + return ERR_PTR(-ENOMEM); + } + + sg_init_table(&async_desc->lock_sg, 1); + + async_desc->num_desc = 1; + async_desc->curr_desc = async_desc->desc; + async_desc->dir = DMA_MEM_TO_DEV; + + desc = async_desc->desc; + + bam_prep_ce_le32(&async_desc->lock_ce, bchan->scratchpad_addr, BAM_WRITE_COMMAND, 0); + sg_set_buf(&async_desc->lock_sg, &async_desc->lock_ce, sizeof(async_desc->lock_ce)); + + mapped = dma_map_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); + if (!mapped) { + kfree(async_desc); + return ERR_PTR(-ENOMEM); + } + + desc->flags |= cpu_to_le16(DESC_FLAG_CMD | flag); + desc->addr = sg_dma_address(&async_desc->lock_sg); + desc->size = cpu_to_le16(sizeof(struct bam_cmd_element)); + + vc = &bchan->vc; + vd = &async_desc->vd; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = DMA_PREP_CMD; + vd->tx_result.result = DMA_TRANS_NOERROR; + vd->tx_result.residue = 0; + + return async_desc; +} + +static int bam_setup_pipe_lock(struct bam_chan *bchan) +{ + const struct bam_device_data *bdata = bchan->bdev->dev_data; + struct bam_async_desc *lock_desc, *unlock_desc; + + lockdep_assert_held(&bchan->vc.lock); + + if (!bdata->pipe_lock_supported || !bchan->scratchpad_addr || + bchan->direction != DMA_MEM_TO_DEV) + return 0; + + /* + * Allocate both the LOCK and the UNLOCK descriptors up-front so the + * operation is all-or-nothing: if either allocation fails we free both + * and run the sequence unlocked rather than leave the pipe locked with + * no matching UNLOCK. + * + * Both are queued in-band around the currently issued work: the LOCK is + * prepended so it enters the FIFO first, the UNLOCK is appended so it is + * the last descriptor of the sequence. They are loaded together with the + * payload in a single operation so the engine executes LOCK, the work + * and UNLOCK as one ordered batch. + */ + lock_desc = bam_make_lock_desc(bchan, DESC_FLAG_LOCK); + if (IS_ERR(lock_desc)) + return PTR_ERR(lock_desc); + + unlock_desc = bam_make_lock_desc(bchan, DESC_FLAG_UNLOCK); + if (IS_ERR(unlock_desc)) { + bam_dma_free_lock_desc(&lock_desc->vd); + return PTR_ERR(unlock_desc); + } + + list_add(&lock_desc->vd.node, &bchan->vc.desc_issued); + list_add_tail(&unlock_desc->vd.node, &bchan->vc.desc_issued); + bchan->bam_locked = true; + + return 0; +} + /** * bam_start_dma - start next transaction * @bchan: bam dma channel */ static void bam_start_dma(struct bam_chan *bchan) { - struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc); + struct virt_dma_desc *vd; struct bam_device *bdev = bchan->bdev; struct bam_async_desc *async_desc = NULL; struct bam_desc_hw *desc; @@ -1039,9 +1220,23 @@ static void bam_start_dma(struct bam_chan *bchan) lockdep_assert_held(&bchan->vc.lock); + vd = vchan_next_desc(&bchan->vc); if (!vd) return; + /* + * Wrap the issued work with a LOCK/UNLOCK pair exactly once, at the + * start of a fresh sequence and only when there is real work to lock + * around. On a re-entry after a full FIFO, we see the BAM is locked + * and must not add another pair we simply continue loading the + * remainder of the same locked sequence. + */ + if (!bchan->bam_locked) { + ret = bam_setup_pipe_lock(bchan); + if (ret == 0 && bchan->bam_locked) + vd = vchan_next_desc(&bchan->vc); + } + ret = pm_runtime_get_sync(bdev->dev); if (ret < 0) return; @@ -1120,14 +1315,14 @@ static void bam_start_dma(struct bam_chan *bchan) } /** - * dma_tasklet - DMA IRQ tasklet - * @t: tasklet argument (bam controller structure) + * bam_dma_work() - DMA interrupt work queue callback + * @work: work queue struct embedded in the BAM controller device struct * * Sets up next DMA operation and then processes all completed transactions */ -static void dma_tasklet(struct tasklet_struct *t) +static void bam_dma_work(struct work_struct *work) { - struct bam_device *bdev = from_tasklet(bdev, t, task); + struct bam_device *bdev = from_work(bdev, work, work); struct bam_chan *bchan; unsigned int i; @@ -1140,14 +1335,13 @@ static void dma_tasklet(struct tasklet_struct *t) if (!list_empty(&bchan->vc.desc_issued) && !IS_BUSY(bchan)) bam_start_dma(bchan); } - } /** * bam_issue_pending - starts pending transactions * @chan: dma channel * - * Calls tasklet directly which in turn starts any pending transactions + * Calls work queue directly which in turn starts any pending transactions */ static void bam_issue_pending(struct dma_chan *chan) { @@ -1167,8 +1361,12 @@ static void bam_issue_pending(struct dma_chan *chan) */ static void bam_dma_free_desc(struct virt_dma_desc *vd) { - struct bam_async_desc *async_desc = container_of(vd, - struct bam_async_desc, vd); + struct bam_async_desc *async_desc = container_of(vd, struct bam_async_desc, vd); + struct bam_desc_hw *desc = async_desc->desc; + struct dma_chan *chan = vd->tx.chan; + + if (le16_to_cpu(desc->flags) & (DESC_FLAG_LOCK | DESC_FLAG_UNLOCK)) + dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); kfree(async_desc); } @@ -1234,10 +1432,10 @@ static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan, } static const struct of_device_id bam_of_match[] = { - { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_reg_info }, - { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_reg_info }, - { .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_reg_info }, - { .compatible = "qcom,bam-v2.0.0", .data = &bam_v2_0_reg_info }, + { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_data }, + { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_data }, + { .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_data }, + { .compatible = "qcom,bam-v2.0.0", .data = &bam_v2_0_data }, {} }; @@ -1261,7 +1459,7 @@ static int bam_dma_probe(struct platform_device *pdev) return -ENODEV; } - bdev->layout = match->data; + bdev->dev_data = match->data; bdev->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bdev->regs)) @@ -1316,14 +1514,14 @@ static int bam_dma_probe(struct platform_device *pdev) if (ret) goto err_disable_clk; - tasklet_setup(&bdev->task, dma_tasklet); + INIT_WORK(&bdev->work, bam_dma_work); bdev->channels = devm_kcalloc(bdev->dev, bdev->num_channels, sizeof(*bdev->channels), GFP_KERNEL); if (!bdev->channels) { ret = -ENOMEM; - goto err_tasklet_kill; + goto err_workqueue_cancel; } /* allocate and initialize channels */ @@ -1332,8 +1530,7 @@ static int bam_dma_probe(struct platform_device *pdev) for (i = 0; i < bdev->num_channels; i++) bam_channel_init(bdev, &bdev->channels[i], i); - ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq, - IRQF_TRIGGER_HIGH, "bam_dma", bdev); + ret = request_irq(bdev->irq, bam_dma_irq, IRQF_TRIGGER_NONE, "bam_dma", bdev); if (ret) goto err_bam_channel_exit; @@ -1361,12 +1558,13 @@ static int bam_dma_probe(struct platform_device *pdev) bdev->common.device_terminate_all = bam_dma_terminate_all; bdev->common.device_issue_pending = bam_issue_pending; bdev->common.device_tx_status = bam_tx_status; + bdev->common.desc_metadata_modes = DESC_METADATA_CLIENT; bdev->common.dev = bdev->dev; ret = dma_async_device_register(&bdev->common); if (ret) { dev_err(bdev->dev, "failed to register dma async device\n"); - goto err_bam_channel_exit; + goto err_free_irq; } ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate, @@ -1385,11 +1583,13 @@ static int bam_dma_probe(struct platform_device *pdev) err_unregister_dma: dma_async_device_unregister(&bdev->common); +err_free_irq: + free_irq(bdev->irq, bdev); err_bam_channel_exit: for (i = 0; i < bdev->num_channels; i++) tasklet_kill(&bdev->channels[i].vc.task); -err_tasklet_kill: - tasklet_kill(&bdev->task); +err_workqueue_cancel: + cancel_work_sync(&bdev->work); err_disable_clk: clk_disable_unprepare(bdev->bamclk); @@ -1401,6 +1601,8 @@ static void bam_dma_remove(struct platform_device *pdev) struct bam_device *bdev = platform_get_drvdata(pdev); u32 i; + free_irq(bdev->irq, bdev); + pm_runtime_force_suspend(&pdev->dev); of_dma_controller_free(pdev->dev.of_node); @@ -1409,8 +1611,6 @@ static void bam_dma_remove(struct platform_device *pdev) /* mask all interrupts for this execution environment */ writel_relaxed(0, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); - devm_free_irq(bdev->dev, bdev->irq, bdev); - for (i = 0; i < bdev->num_channels; i++) { bam_dma_terminate_all(&bdev->channels[i].vc.chan); tasklet_kill(&bdev->channels[i].vc.task); @@ -1423,7 +1623,7 @@ static void bam_dma_remove(struct platform_device *pdev) bdev->channels[i].fifo_phys); } - tasklet_kill(&bdev->task); + cancel_work_sync(&bdev->work); clk_disable_unprepare(bdev->bamclk); } diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index a5055a6273af6..6ef72dffd3307 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2020, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -67,6 +68,14 @@ #define TRE_DMA_LEN GENMASK(23, 0) #define TRE_DMA_IMMEDIATE_LEN GENMASK(3, 0) +/* Lock TRE */ +#define TRE_LOCK BIT(0) +#define TRE_MINOR_TYPE GENMASK(19, 16) +#define TRE_MAJOR_TYPE GENMASK(23, 20) + +/* Unlock TRE */ +#define TRE_UNLOCK BIT(8) + /* Register offsets from gpi-top */ #define GPII_n_CH_k_CNTXT_0_OFFS(n, k) (0x20000 + (0x4000 * (n)) + (0x80 * (k))) #define GPII_n_CH_k_CNTXT_0_EL_SIZE GENMASK(31, 24) @@ -518,7 +527,7 @@ struct gpii { bool ieob_set; }; -#define MAX_TRE 3 +#define MAX_TRE 5 struct gpi_desc { struct virt_dma_desc vd; @@ -615,7 +624,8 @@ static int gpi_config_interrupts(struct gpii *gpii, enum gpii_irq_settings setti if (!gpii->configured_irq) { ret = devm_request_irq(gpii->gpi_dev->dev, gpii->irq, - gpi_handle_irq, IRQF_TRIGGER_HIGH, + gpi_handle_irq, + IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME, "gpi-dma", gpii); if (ret < 0) { dev_err(gpii->gpi_dev->dev, "error request irq:%d ret:%d\n", @@ -1625,12 +1635,27 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, unsigned long flags) { struct gpi_i2c_config *i2c = chan->config; + enum gpi_lock_action lock_action = i2c->lock_action; struct device *dev = chan->gpii->gpi_dev->dev; unsigned int tre_idx = 0; dma_addr_t address; struct gpi_tre *tre; unsigned int i; + /* Optional lock TRE before transfer */ + if (lock_action == GPI_LOCK_ACQUIRE) { + tre = &desc->tre[tre_idx]; + tre_idx++; + + tre->dword[0] = 0; + tre->dword[1] = 0; + tre->dword[2] = 0; + tre->dword[3] = u32_encode_bits(1, TRE_LOCK); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); + tre->dword[3] |= u32_encode_bits(0, TRE_MINOR_TYPE); + tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE); + } + /* first create config tre if applicable */ if (i2c->set_config) { tre = &desc->tre[tre_idx]; @@ -1690,6 +1715,24 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, if (!(flags & DMA_PREP_INTERRUPT)) tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_BEI); + + /* If multi-owner and this is the release boundary, chain it */ + if (i2c->lock_action == GPI_LOCK_RELEASE) + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN); + } + + /* Optional unlock TRE after transfer */ + if (lock_action == GPI_LOCK_RELEASE && i2c->op != I2C_READ) { + tre = &desc->tre[tre_idx]; + tre_idx++; + + tre->dword[0] = 0; + tre->dword[1] = 0; + tre->dword[2] = 0; + tre->dword[3] = u32_encode_bits(1, TRE_UNLOCK); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); + tre->dword[3] |= u32_encode_bits(1, TRE_MINOR_TYPE); + tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE); } for (i = 0; i < tre_idx; i++) diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 1cf158eb7bdb5..fb21e0df5ab7b 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -3408,7 +3408,7 @@ static int udma_set_metadata_len(struct dma_async_tx_descriptor *desc, return 0; } -static struct dma_descriptor_metadata_ops metadata_ops = { +static const struct dma_descriptor_metadata_ops metadata_ops = { .attach = udma_attach_metadata, .get_ptr = udma_get_metadata_ptr, .set_len = udma_set_metadata_len, diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 404235c173538..165b11a7c776a 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -653,7 +653,7 @@ static void *xilinx_dma_get_metadata_ptr(struct dma_async_tx_descriptor *tx, return seg->hw.app; } -static struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = { +static const struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = { .get_ptr = xilinx_dma_get_metadata_ptr, }; diff --git a/drivers/firmware/psci/Kconfig b/drivers/firmware/psci/Kconfig index 97944168b5e66..93ff7b071a0c3 100644 --- a/drivers/firmware/psci/Kconfig +++ b/drivers/firmware/psci/Kconfig @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only config ARM_PSCI_FW bool + select POWER_RESET + select REBOOT_MODE config ARM_PSCI_CHECKER bool "ARM PSCI checker" diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index e73bae6cb23a3..158a0a1b9b879 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -8,15 +8,18 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include @@ -51,6 +54,24 @@ static int resident_cpu = -1; struct psci_operations psci_ops; static enum arm_smccc_conduit psci_conduit = SMCCC_CONDUIT_NONE; +struct psci_vendor_sysreset2 { + u32 reset_type; + u32 cookie; + bool valid; +}; + +static struct psci_vendor_sysreset2 vendor_reset; + +static int psci_panic_event(struct notifier_block *nb, unsigned long v, void *p) +{ + vendor_reset.valid = false; + return NOTIFY_DONE; +} + +static struct notifier_block psci_panic_block = { + .notifier_call = psci_panic_event +}; + bool psci_tos_resident_on(int cpu) { return cpu == resident_cpu; @@ -309,7 +330,10 @@ static int get_set_conduit_method(const struct device_node *np) static int psci_sys_reset(struct notifier_block *nb, unsigned long action, void *data) { - if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && + if (vendor_reset.valid && psci_system_reset2_supported) { + invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), vendor_reset.reset_type, + vendor_reset.cookie, 0); + } else if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && psci_system_reset2_supported) { /* * reset_type[31] = 0 (architectural) @@ -557,6 +581,72 @@ static const struct platform_suspend_ops psci_suspend_ops = { .begin = psci_system_suspend_begin, }; +static int psci_set_vendor_sys_reset2(struct reboot_mode_driver *reboot, u64 magic) +{ + u32 magic_32; + + if (psci_system_reset2_supported) { + magic_32 = magic & GENMASK(31, 0); + vendor_reset.reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic_32; + vendor_reset.cookie = (magic >> 32) & GENMASK(31, 0); + vendor_reset.valid = true; + } + + return NOTIFY_DONE; +} + +static int __init psci_init_vendor_reset(void) +{ + struct reboot_mode_driver *reboot; + struct device_node *psci_np; + struct device_node *np; + int ret; + + if (!psci_system_reset2_supported) + return -EINVAL; + + psci_np = of_find_compatible_node(NULL, NULL, "arm,psci-1.0"); + if (!psci_np) + return -ENODEV; + + np = of_find_node_by_name(psci_np, "reboot-mode"); + if (!np) { + of_node_put(psci_np); + return -ENODEV; + } + + ret = atomic_notifier_chain_register(&panic_notifier_list, &psci_panic_block); + if (ret) + goto err_notifier; + + reboot = kzalloc(sizeof(*reboot), GFP_KERNEL); + if (!reboot) { + ret = -ENOMEM; + goto err_kzalloc; + } + + reboot->write = psci_set_vendor_sys_reset2; + reboot->name = "psci"; + + ret = reboot_mode_register(reboot, of_fwnode_handle(np)); + if (ret) + goto err_register; + + of_node_put(psci_np); + of_node_put(np); + return 0; + +err_register: + kfree(reboot); +err_kzalloc: + atomic_notifier_chain_unregister(&panic_notifier_list, &psci_panic_block); +err_notifier: + of_node_put(psci_np); + of_node_put(np); + return ret; +} +late_initcall(psci_init_vendor_reset) + static void __init psci_init_system_reset2(void) { int ret; diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index b477d54b495a6..dd20fed163e3f 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -74,4 +74,20 @@ config QCOM_QSEECOM_UEFISECAPP Select Y here to provide access to EFI variables on the aforementioned platforms. +config QCOM_MEMORY_DUMP_V2 + tristate "QCOM Memory Dump V2 Support" + depends on QCOM_TZMEM + depends on CMA + help + This enables memory dump feature. It allows various client + subsystems to register respective dump regions. At the time + of deadlocks or cpu hangs these dump regions are captured to + give a snapshot of the system at the time of the crash. + +config QCOM_MEMORY_DUMP_DEV + tristate "QCOM Memory Dump V2 device stub" + depends on QCOM_MEMORY_DUMP_V2 + help + Device stub for memory dump V2 driver. + endmenu diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile index 0be40a1abc13c..01b293cae79ed 100644 --- a/drivers/firmware/qcom/Makefile +++ b/drivers/firmware/qcom/Makefile @@ -8,3 +8,5 @@ qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o +obj-$(CONFIG_QCOM_MEMORY_DUMP_V2) += memory_dump_v2.o +obj-$(CONFIG_QCOM_MEMORY_DUMP_DEV) += memory_dump_dev.o diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c new file mode 100644 index 0000000000000..fb9d4dc0dceab --- /dev/null +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -0,0 +1,564 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#define DEV_NAME "msm_mem_dump" + +static struct platform_device *mem_dump_pdev; + +enum dump_ids { + C0_CONTEXT = 0x0, + C100_CONTEXT = 0x1, + C200_CONTEXT = 0x2, + C300_CONTEXT = 0x3, + C400_CONTEXT = 0x4, + C500_CONTEXT = 0x5, + C600_CONTEXT = 0x6, + C700_CONTEXT = 0x7, + L1_ITLB10000 = 0x24, + L1_ITLB10100 = 0x25, + L1_ITLB10200 = 0x26, + L1_ITLB10300 = 0x27, + L1_DTLB10000 = 0x44, + L1_DTLB10100 = 0x45, + L1_DTLB10200 = 0x46, + L1_DTLB10300 = 0x47, + L1_ICACHE0 = 0x60, + L1_ICACHE100 = 0x61, + L1_ICACHE200 = 0x62, + L1_ICACHE300 = 0x63, + L1_ICACHE10000 = 0x64, + L1_ICACHE10100 = 0x65, + L1_ICACHE10200 = 0x66, + L1_ICACHE10300 = 0x67, + L1_DCACHE0 = 0x80, + L1_DCACHE100 = 0x81, + L1_DCACHE200 = 0x82, + L1_DCACHE300 = 0x83, + L1_DCACHE10000 = 0x84, + L1_DCACHE10100 = 0x85, + L1_DCACHE10200 = 0x86, + L1_DCACHE10300 = 0x87, + L2_CACHE10000 = 0xc4, + L2_CACHE10100 = 0xc5, + L2_CACHE10200 = 0xc6, + L2_CACHE10300 = 0xc7, + PMIC = 0xe4, + MISC_DATA = 0xe8, + RPM_SW = 0xea, + RPMH = 0xec, + CPUSS_REG = 0xef, + TMC_ETF = 0xf0, + ETF_SWAO = 0xf1, + ETF_SLPI = 0xf3, + ETF_LPASS = 0xf4, + FCM = 0xee, + ETR_REG = 0x100, + ETF_REG = 0x101, + ETFSWAO_REG = 0x102, + ETFSLPI_REG = 0x103, + ETFLPASS_REG = 0x104, + ETR1_REG = 0x105, + L2_TLB0 = 0x120, + L2_TLB100 = 0x121, + L2_TLB200 = 0x122, + L2_TLB300 = 0x123, + L2_TLB10000 = 0x124, + L2_TLB10100 = 0x125, + L2_TLB10200 = 0x126, + L2_TLB10300 = 0x127, + C0_SCANDUMP = 0x130, + C100_SCANDUMP = 0x131, + C200_SCANDUMP = 0x132, + C300_SCANDUMP = 0x133, + C10000_SCANDUMP = 0x134, + C10100_SCANDUMP = 0x135, + C10200_SCANDUMP = 0x136, + C10300_SCANDUMP = 0x137, + LLCC1_D_CACHE = 0x140, + LLCC2_D_CACHE = 0x141, + MHM_SCAN = 0x161, + GEMNOC = 0x162, + OSM_REG = 0x163, + PCU_REG = 0x164, + FSM_DATA = 0x165, + SCANDUMP_SMMU = 0x220, +}; + +static const struct dump_item lemans_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C0_SCANDUMP, 0x40000, "c0-scandump" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C100_SCANDUMP, 0x40000, "c100-scandump" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C200_SCANDUMP, 0x40000, "c200-scandump" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C300_SCANDUMP, 0x40000, "c300-scandump" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { C10000_SCANDUMP, 0x40000, "c10000-scandump" }, + { C10100_SCANDUMP, 0x40000, "c10100-scandump" }, + { C10200_SCANDUMP, 0x40000, "c10200-scandump" }, + { C10300_SCANDUMP, 0x40000, "c10300-scandump" }, + { CPUSS_REG, 0x20000, "cpuss-reg" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR_REG, 0x1000, "etr-reg" }, + { FCM, 0x8400, "fcm" }, + { L1_DCACHE0, 0x12100, "l1-dcache0" }, + { L1_DCACHE100, 0x12100, "l1-dcache100" }, + { L1_DCACHE200, 0x12100, "l1-dcache200" }, + { L1_DCACHE300, 0x12100, "l1-dcache300" }, + { L1_DCACHE10000, 0x12100, "l1-dcache10000" }, + { L1_DCACHE10100, 0x12100, "l1-dcache10100" }, + { L1_DCACHE10200, 0x12100, "l1-dcache10200" }, + { L1_DCACHE10300, 0x12100, "l1-dcache10300" }, + { L1_DTLB10000, 0x300, "l1-dtlb10000" }, + { L1_DTLB10100, 0x300, "l1-dtlb10100" }, + { L1_DTLB10200, 0x300, "l1-dtlb10200" }, + { L1_DTLB10300, 0x300, "l1-dtlb10300" }, + { L1_ICACHE0, 0x26100, "l1-icache0" }, + { L1_ICACHE100, 0x26100, "l1-icache100" }, + { L1_ICACHE200, 0x26100, "l1-icache200" }, + { L1_ICACHE300, 0x26100, "l1-icache300" }, + { L1_ICACHE10000, 0x26100, "l1-icache10000" }, + { L1_ICACHE10100, 0x26100, "l1-icache10100" }, + { L1_ICACHE10200, 0x26100, "l1-icache10200" }, + { L1_ICACHE10300, 0x26100, "l1-icache10300" }, + { L1_ITLB10000, 0x300, "l1-itlb10000" }, + { L1_ITLB10100, 0x300, "l1-itlb10100" }, + { L1_ITLB10200, 0x300, "l1-itlb10200" }, + { L1_ITLB10300, 0x300, "l1-itlb10300" }, + { L2_CACHE10000, 0x90100, "l2-cache10000" }, + { L2_CACHE10100, 0x90100, "l2-cache10100" }, + { L2_CACHE10200, 0x90100, "l2-cache10200" }, + { L2_CACHE10300, 0x90100, "l2-cache10300" }, + { L2_TLB0, 0x6100, "l2-tlb0" }, + { L2_TLB100, 0x6100, "l2-tlb100" }, + { L2_TLB200, 0x6100, "l2-tlb200" }, + { L2_TLB300, 0x6100, "l2-tlb300" }, + { L2_TLB10000, 0x6100, "l2-tlb10000" }, + { L2_TLB10100, 0x6100, "l2-tlb10100" }, + { L2_TLB10200, 0x6100, "l2-tlb10200" }, + { L2_TLB10300, 0x6100, "l2-tlb10300" }, + { MISC_DATA, 0x1000, "misc-data" }, + { PMIC, 0x80000, "pmic" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { RPMH, 0x2000000, "rpmh" }, +}; + +static const struct dump_item talos_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x2000000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x10000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { TMC_ETF, 0x8000, "tmc-etf" }, + { ETF_SWAO, 0x8000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETF_REG, 0x1000, "etf-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { MISC_DATA, 0x1000, "misc-data" }, + { L1_ICACHE0, 0x8800, "l1-icache0" }, + { L1_ICACHE100, 0x8800, "l1-icache100" }, + { L1_ICACHE200, 0x8800, "l1-icache200" }, + { L1_ICACHE300, 0x8800, "l1-icache300" }, + { L1_ICACHE10000, 0x8800, "l1-icache400" }, + { L1_ICACHE10100, 0x8800, "l1-icache500" }, + { L1_ICACHE10200, 0x11000, "l1-icache600" }, + { L1_ICACHE10300, 0x11000, "l1-icache700" }, + { L1_DCACHE0, 0x9000, "l1-dcache0" }, + { L1_DCACHE100, 0x9000, "l1-dcache100" }, + { L1_DCACHE200, 0x9000, "l1-dcache200" }, + { L1_DCACHE300, 0x9000, "l1-dcache300" }, + { L1_DCACHE10000, 0x9000, "l1-dcache400" }, + { L1_DCACHE10100, 0x9000, "l1-dcache500" }, + { L1_DCACHE10200, 0x12000, "l1-dcache600" }, + { L1_DCACHE10300, 0x12000, "l1-dcache700" }, + { L1_ITLB10200, 0x300, "l1-itlb600" }, + { L1_ITLB10300, 0x300, "l1-itlb700" }, + { L1_DTLB10200, 0x480, "l1-dtlb600" }, + { L1_DTLB10300, 0x480, "l1-dtlb700" }, + { L2_CACHE10200, 0x48000, "l2-cache600" }, + { L2_CACHE10300, 0x48000, "l2-cache700" }, + { L2_TLB0, 0x5000, "l2-tlb0" }, + { L2_TLB100, 0x5000, "l2-tlb100" }, + { L2_TLB200, 0x5000, "l2-tlb200" }, + { L2_TLB300, 0x5000, "l2-tlb300" }, + { L2_TLB10000, 0x5000, "l2-tlb400" }, + { L2_TLB10100, 0x5000, "l2-tlb500" }, + { L2_TLB10200, 0x7800, "l2-tlb600" }, + { L2_TLB10300, 0x7800, "l2-tlb700" }, + { LLCC1_D_CACHE, 0x6c000, "llcc1-d-cache" }, +}; + +static const struct dump_item kodiak_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C0_SCANDUMP, 0x10100, "c0-scandump" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C100_SCANDUMP, 0x10100, "c100-scandump" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C200_SCANDUMP, 0x10100, "c200-scandump" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C300_SCANDUMP, 0x10100, "c300-scandump" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C10000_SCANDUMP, 0x40000, "c400-scandump" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C10100_SCANDUMP, 0x40000, "c500-scandump" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C10200_SCANDUMP, 0x40000, "c600-scandump" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { C10300_SCANDUMP, 0x40000, "c700-scandump" }, + { CPUSS_REG, 0x30000, "cpuss-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR_REG, 0x1000, "etr-reg" }, + { FCM, 0x8400, "fcm" }, + { FSM_DATA, 0x400, "fsm-data" }, + { GEMNOC, 0x100000, "gemnoc" }, + { L1_DCACHE0, 0x9100, "l1-dcache0" }, + { L1_DCACHE100, 0x9100, "l1-dcache100" }, + { L1_DCACHE200, 0x9100, "l1-dcache200" }, + { L1_DCACHE300, 0x9100, "l1-dcache300" }, + { L1_DCACHE10000, 0x9100, "l1-dcache400" }, + { L1_DCACHE10100, 0x9100, "l1-dcache500" }, + { L1_DCACHE10200, 0x9100, "l1-dcache600" }, + { L1_DCACHE10300, 0x12100, "l1-dcache700" }, + { L1_DTLB10000, 0x300, "l1-dtlb400" }, + { L1_DTLB10100, 0x300, "l1-dtlb500" }, + { L1_DTLB10200, 0x300, "l1-dtlb600" }, + { L1_DTLB10300, 0x3a0, "l1-dtlb700" }, + { L1_ICACHE0, 0x10900, "l1-icache0" }, + { L1_ICACHE100, 0x10900, "l1-icache100" }, + { L1_ICACHE200, 0x10900, "l1-icache200" }, + { L1_ICACHE300, 0x10900, "l1-icache300" }, + { L1_ICACHE10000, 0x15100, "l1-icache400" }, + { L1_ICACHE10100, 0x15100, "l1-icache500" }, + { L1_ICACHE10200, 0x15100, "l1-icache600" }, + { L1_ICACHE10300, 0x32100, "l1-icache700" }, + { L1_ITLB10000, 0x300, "l1-itlb400" }, + { L1_ITLB10100, 0x300, "l1-itlb500" }, + { L1_ITLB10200, 0x300, "l1-itlb600" }, + { L1_ITLB10300, 0x400, "l1-itlb700" }, + { L2_CACHE10000, 0x90100, "l2-cache400" }, + { L2_CACHE10100, 0x90100, "l2-cache500" }, + { L2_CACHE10200, 0x90100, "l2-cache600" }, + { L2_CACHE10300, 0x120100, "l2-cache700" }, + { L2_TLB0, 0x5b00, "l2-tlb0" }, + { L2_TLB100, 0x5b00, "l2-tlb100" }, + { L2_TLB200, 0x5b00, "l2-tlb200" }, + { L2_TLB300, 0x5b00, "l2-tlb300" }, + { L2_TLB10000, 0x6100, "l2-tlb400" }, + { L2_TLB10100, 0x6100, "l2-tlb500" }, + { L2_TLB10200, 0x6100, "l2-tlb600" }, + { L2_TLB10300, 0xc100, "l2-tlb700" }, + { LLCC1_D_CACHE, 0x1141c0, "llcc1-d-cache" }, + { LLCC2_D_CACHE, 0x1141c0, "llcc2-d-cache" }, + { MHM_SCAN, 0x20000, "mhm-scan" }, + { MISC_DATA, 0x1000, "misc-data" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { PMIC, 0x200000, "pmic" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { RPMH, 0x2000000, "rpmh" }, +}; + +static const struct dump_item pakala_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x400000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x200000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR1_REG, 0x1000, "etr1-reg" }, + { ETF_SLPI, 0x4000, "etf-slpi" }, + { ETFSLPI_REG, 0x1000, "etfslpi-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { FSM_DATA, 0x400, "fsm-data" }, + { SCANDUMP_SMMU, 0x40000, "scandump-smmu" }, + { C0_SCANDUMP, 0x380000, "apps-scandump" }, +}; + +static const struct dump_item kaanapali_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x400000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x200000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR1_REG, 0x1000, "etr1-reg" }, + { ETF_SLPI, 0x4000, "etf-slpi" }, + { ETFSLPI_REG, 0x1000, "etfslpi-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { FSM_DATA, 0x400, "fsm-data" }, + { SCANDUMP_SMMU, 0x40000, "scandump-smmu" }, + { C0_SCANDUMP, 0x380000, "apps-scandump" }, +}; + +static const struct dump_item hamoa_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0xc10000, "rpmh" }, + { PMIC, 0x200000, "pmic" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, +}; + +static const struct dump_item shikra_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C0_SCANDUMP, 0x10000, "c0-scandump" }, + { C100_SCANDUMP, 0x10000, "c100-scandump" }, + { C200_SCANDUMP, 0x10000, "c200-scandump" }, + { C300_SCANDUMP, 0x40000, "c300-scandump" }, + { L1_ICACHE0, 0x8900, "l1-icache0" }, + { L1_ICACHE100, 0x8900, "l1-icache100" }, + { L1_ICACHE200, 0x8900, "l1-icache200" }, + { L1_ICACHE300, 0x8900, "l1-icache300" }, + { L1_DCACHE0, 0x9100, "l1-dcache0" }, + { L1_DCACHE100, 0x9100, "l1-dcache100" }, + { L1_DCACHE200, 0x9100, "l1-dcache200" }, + { L1_DCACHE300, 0x9100, "l1-dcache300" }, + { L2_TLB0, 0x2100, "l2-tlb0" }, + { L2_TLB100, 0x2100, "l2-tlb100" }, + { L2_TLB200, 0x2100, "l2-tlb200" }, + { L2_TLB300, 0x2100, "l2-tlb300" }, + { RPM_SW, 0x30000, "rpm-sw" }, + { PMIC, 0x40000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { TMC_ETF, 0x8000, "tmc-etf" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETF_REG, 0x1000, "etf-reg" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_LPASS, 0x8000, "etf-lpass" }, +}; + +static const struct dump_table lemans_dump_table = { + .items = lemans_items, + .num_of_items = ARRAY_SIZE(lemans_items), + .imem_base = 0x146d8010, + .imem_size = 0x8, +}; + +static const struct dump_table talos_dump_table = { + .items = talos_items, + .num_of_items = ARRAY_SIZE(talos_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + +static const struct dump_table kodiak_dump_table = { + .items = kodiak_items, + .num_of_items = ARRAY_SIZE(kodiak_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + +static const struct dump_table pakala_dump_table = { + .items = pakala_items, + .num_of_items = ARRAY_SIZE(pakala_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + +static const struct dump_table kaanapali_dump_table = { + .items = kaanapali_items, + .num_of_items = ARRAY_SIZE(kaanapali_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + +static const struct dump_table hamoa_dump_table = { + .items = hamoa_items, + .num_of_items = ARRAY_SIZE(hamoa_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + +static const struct dump_table shikra_dump_table = { + .items = shikra_items, + .num_of_items = ARRAY_SIZE(shikra_items), + .imem_base = 0xc11e010, + .imem_size = 0x8, +}; + +static int __init mem_dump_dev_init(void) +{ + int ret; + u32 soc_id; + + mem_dump_pdev = platform_device_alloc(DEV_NAME, -1); + if (!mem_dump_pdev) + return -ENOMEM; + + ret = qcom_smem_get_soc_id(&soc_id); + if (ret) + goto fail; + + switch (soc_id) { + case 377: + case 380: + case 384: + case 401: + case 406: + case 680: + ret = platform_device_add_data(mem_dump_pdev, + &talos_dump_table, sizeof(talos_dump_table)); + if (ret) + goto fail; + + break; + case 534: + case 606: + case 667: + case 674: + case 675: + case 676: + ret = platform_device_add_data(mem_dump_pdev, + &lemans_dump_table, sizeof(lemans_dump_table)); + if (ret) + goto fail; + + break; + case 475: + case 497: + case 498: + case 515: + ret = platform_device_add_data(mem_dump_pdev, + &kodiak_dump_table, sizeof(kodiak_dump_table)); + if (ret) + goto fail; + + break; + case 618: + case 639: + case 705: + case 706: + ret = platform_device_add_data(mem_dump_pdev, + &pakala_dump_table, sizeof(pakala_dump_table)); + if (ret) + goto fail; + + break; + case 660: + case 661: + case 704: + case 722: + case 723: + case 730: + case 743: + ret = platform_device_add_data(mem_dump_pdev, + &kaanapali_dump_table, sizeof(kaanapali_dump_table)); + if (ret) + goto fail; + + break; + /* Hamoa chip IDs */ + case 555: + case 615: + case 616: + case 709: + case 710: + /* Glymur chip IDs */ + case 662: + case 698: + case 699: + case 718: + case 719: + ret = platform_device_add_data(mem_dump_pdev, + &hamoa_dump_table, sizeof(hamoa_dump_table)); + if (ret) + goto fail; + + break; + case 756: + case 758: + case 759: + ret = platform_device_add_data(mem_dump_pdev, + &shikra_dump_table, sizeof(shikra_dump_table)); + if (ret) + goto fail; + break; + default: + dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); + ret = -EINVAL; + goto fail; + } + + ret = platform_device_add(mem_dump_pdev); + if (ret) + goto fail; + + dev_info(&mem_dump_pdev->dev, "Register platform device successfully\n"); + + return 0; + +fail: + dev_err(&mem_dump_pdev->dev, + "Failed to register memory dump platform device\n"); + platform_device_put(mem_dump_pdev); + + return ret; +} + +static void __exit mem_dump_dev_exit(void) +{ + platform_device_unregister(mem_dump_pdev); +} + +late_initcall(mem_dump_dev_init); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. Memory Dump driver V2, device stub"); diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c new file mode 100644 index 0000000000000..831d1aea86e09 --- /dev/null +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -0,0 +1,1102 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) + +#define SCM_CMD_DEBUG_LAR_UNLOCK 0x4 + +#define CPUSS_REGDUMP 0xEF +#define SPR_DUMP_CPU0 0x1F0 +#define SPR_DUMP_CPU1 0x1F1 +#define SPR_DUMP_CPU2 0x1F2 +#define SPR_DUMP_CPU3 0x1F3 +#define SPR_DUMP_CPU4 0x1F4 +#define SPR_DUMP_CPU5 0x1F5 +#define SPR_DUMP_CPU6 0x1F6 +#define SPR_DUMP_CPU7 0x1F7 +#define SPR_DATA_HEADER_SIZE 5 +#define SPR_DATA_HEADER_TAIL_SIZE 1 +#define SPR_INPUT_DATA_TAIL_SIZE 1 +#define SPR_INPUT_DATA_SIZE 1 +#define SPR_OUTPUT_DATA_SIZE 2 +#define MAX_CORE_NUM 8 + +#define INPUT_DATA_BY_HLOS 0x00C0FFEE +#define FORMAT_VERSION_1 0x1 +#define FORMAT_VERSION_2 0x2 +#define CORE_REG_NUM_DEFAULT 0x1 + +#define MAGIC_INDEX 0 +#define FORMAT_VERSION_INDEX 1 +#define SYS_REG_INPUT_INDEX 2 +#define OUTPUT_DUMP_INDEX 3 +#define PERCORE_INDEX 4 +#define SYSTEM_REGS_INPUT_INDEX 5 + +#define CMD_REPEAT_READ (0x2 << 24) +#define CMD_DELAY (0x1 << 24) +#define CMD_READ 0x0 +#define CMD_READ_WORD 0x1 +#define CMD_WRITE 0x2 +#define CMD_EXTRA 0x3 + +#define CMD_MASK 0x3 +#define OFFSET_MASK GENMASK(31, 2) +#define EXTRA_CMD_MASK GENMASK(31, 24) +#define EXTRA_VALUE_MASK GENMASK(23, 0) +#define MAX_EXTRA_VALUE 0xffffff + +struct sprs_dump_data { + void *dump_vaddr; + u32 size; + u32 sprs_data_index; + u32 used_memory; +}; + +struct cpuss_regdump_data { + void *dump_vaddr; + u32 size; + u32 core_reg_num; + u32 core_reg_used_num; + u32 core_reg_end_index; + u32 sys_reg_size; + u32 used_memory; +}; + +struct cpuss_dump_data { + struct mutex mutex; + struct cpuss_regdump_data *cpussregdata; + struct sprs_dump_data *sprdata[MAX_CORE_NUM]; +}; + +struct reg_dump_data { + uint32_t magic; + uint32_t version; + uint32_t system_regs_input_index; + uint32_t regdump_output_byte_offset; +}; + +struct msm_dump_table { + uint32_t version; + uint32_t num_entries; + struct msm_dump_entry entries[MAX_NUM_ENTRIES]; +}; + +struct msm_memory_dump { + uint64_t table_phys; + struct msm_dump_table *table; +}; + +/** + * Set bit 0 if percore reg dump initialized. + * Set bit 1 if spr dump initialized. + */ +#define PERCORE_REG_INITIALIZED BIT(0) +#define SPRS_INITIALIZED BIT(1) + +static struct msm_memory_dump memdump; + +/** + * reset_sprs_dump_table - reset the sprs dump table + * + * This function calculates system_regs_input_index and + * regdump_output_byte_offset to store into the dump memory. + * It also updates members of cpudata by the parameter core_reg_num. + * + * Returns 0 on success, or -ENOMEM on error of no enough memory. + */ +static int reset_sprs_dump_table(struct device *dev) +{ + int ret = 0; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int i = 0; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (cpudata->sprdata[i]) { + cpudata->sprdata[i]->sprs_data_index = 0; + cpudata->sprdata[i]->used_memory = (SPR_DATA_HEADER_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t); + memset(cpudata->sprdata[i]->dump_vaddr, 0xDE, + cpudata->sprdata[i]->size); + p = (struct reg_dump_data *)cpudata->sprdata[i]->dump_vaddr; + p->magic = INPUT_DATA_BY_HLOS; + p->version = FORMAT_VERSION_1; + p->system_regs_input_index = SYSTEM_REGS_INPUT_INDEX; + p->regdump_output_byte_offset = (SPR_DATA_HEADER_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t); + memset((uint32_t *)cpudata->sprdata[i]->dump_vaddr + + PERCORE_INDEX, 0x0, (SPR_DATA_HEADER_TAIL_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t)); + } + } + + mutex_unlock(&cpudata->mutex); + return ret; +} + + +/** + * update_reg_dump_table - update the register dump table + * @core_reg_num: the number of per-core registers + * + * This function calculates system_regs_input_index and + * regdump_output_byte_offset to store into the dump memory. + * It also updates members of cpudata by the parameter core_reg_num. + * + * Returns 0 on success, or -ENOMEM on error of no enough memory. + */ +static int update_reg_dump_table(struct device *dev, u32 core_reg_num) +{ + int ret = 0; + u32 system_regs_input_index = SYSTEM_REGS_INPUT_INDEX + + core_reg_num * 2; + u32 regdump_output_byte_offset = (system_regs_input_index + 1) + * sizeof(uint32_t); + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + mutex_lock(&cpudata->mutex); + + if (regdump_output_byte_offset >= cpudata->cpussregdata->size || + regdump_output_byte_offset / sizeof(uint32_t) + < system_regs_input_index + 1) { + ret = -ENOMEM; + goto err; + } + + cpudata->cpussregdata->core_reg_num = core_reg_num; + cpudata->cpussregdata->core_reg_used_num = 0; + cpudata->cpussregdata->core_reg_end_index = PERCORE_INDEX; + cpudata->cpussregdata->sys_reg_size = 0; + cpudata->cpussregdata->used_memory = regdump_output_byte_offset; + + memset(cpudata->cpussregdata->dump_vaddr, 0xDE, cpudata->cpussregdata->size); + p = (struct reg_dump_data *)cpudata->cpussregdata->dump_vaddr; + p->magic = INPUT_DATA_BY_HLOS; + p->version = FORMAT_VERSION_2; + p->system_regs_input_index = system_regs_input_index; + p->regdump_output_byte_offset = regdump_output_byte_offset; + memset((uint32_t *)cpudata->cpussregdata->dump_vaddr + PERCORE_INDEX, 0x0, + (system_regs_input_index - PERCORE_INDEX + 1) + * sizeof(uint32_t)); + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} + +static ssize_t core_reg_num_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + ret = scnprintf(buf, PAGE_SIZE, "%u\n", cpudata->cpussregdata->core_reg_num); + + mutex_unlock(&cpudata->mutex); + return ret; +} + +static ssize_t core_reg_num_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + unsigned int val; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + + mutex_lock(&cpudata->mutex); + + if (cpudata->cpussregdata->core_reg_used_num || cpudata->cpussregdata->sys_reg_size) { + dev_err(dev, "Couldn't set core_reg_num, register available in list\n"); + ret = -EPERM; + goto err; + } + if (val == cpudata->cpussregdata->core_reg_num) { + mutex_unlock(&cpudata->mutex); + return size; + } + + mutex_unlock(&cpudata->mutex); + + ret = update_reg_dump_table(dev, val); + if (ret) { + dev_err(dev, "Couldn't set core_reg_num, no enough memory\n"); + return ret; + } + + return size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(core_reg_num); + +/** + * This function shows configs of per-core and system registers. + */ +static ssize_t register_config_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0; + int index, system_index_start, index_end; + uint32_t register_offset, val; + uint32_t *p, cmd; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + p = (uint32_t *)cpudata->cpussregdata->dump_vaddr; + + /* print per-core & system registers */ + len = scnprintf(local_buf, 64, "per-core registers:\n"); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + + system_index_start = *(p + SYS_REG_INPUT_INDEX); + index_end = system_index_start + + cpudata->cpussregdata->sys_reg_size / sizeof(uint32_t) + 1; + for (index = PERCORE_INDEX; index < index_end;) { + if (index == system_index_start) { + len = scnprintf(local_buf, 64, "system registers:\n"); + if ((count + len) > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + + register_offset = *(p + index); + if (register_offset == 0) { + index++; + continue; + } + + cmd = register_offset & CMD_MASK; + register_offset &= OFFSET_MASK; + + switch (cmd) { + case CMD_READ: + val = *(p + index + 1); + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, r\n", + register_offset, val); + index += 2; + break; + case CMD_READ_WORD: + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, r\n", + register_offset, 0x4); + index++; + break; + case CMD_WRITE: + val = *(p + index + 1); + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, w\n", + register_offset, val); + index += 2; + break; + case CMD_EXTRA: + val = *(p + index + 1); + cmd = val & EXTRA_CMD_MASK; + val &= EXTRA_VALUE_MASK; + if (cmd == CMD_DELAY) + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, d\n", + register_offset, val); + else + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, R\n", + register_offset, val); + index += 2; + break; + } + + if ((count + len) > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + + mutex_unlock(&cpudata->mutex); + return count; +} + +static int config_cpuss_register(struct device *dev, + uint32_t *p, uint32_t index, char cmd, + uint32_t register_offset, uint32_t val) +{ + int ret = 0; + + switch (cmd) { + case 'r': + if (val > 4) { + *(p + index) = register_offset; + *(p + index + 1) = val; + } else { + *(p + index) = register_offset | CMD_READ_WORD; + } + break; + case 'R': + if (val > MAX_EXTRA_VALUE) { + dev_err(dev, "repeat read time exceeded the limit\n"); + ret = -EINVAL; + return ret; + } + *(p + index) = register_offset | CMD_EXTRA; + *(p + index + 1) = val | CMD_REPEAT_READ; + break; + case 'd': + if (val > MAX_EXTRA_VALUE) { + dev_err(dev, "sleep time exceeded the limit\n"); + ret = -EINVAL; + return ret; + } + *(p + index) = CMD_EXTRA; + *(p + index + 1) = val | CMD_DELAY; + break; + case 'w': + *(p + index) = register_offset | CMD_WRITE; + *(p + index + 1) = val; + break; + default: + dev_err(dev, "Don't support this command\n"); + ret = -EINVAL; + } + return ret; +} +/** + * This function sets configs of per-core or system registers. + */ +static ssize_t register_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + uint32_t register_offset, val, reserve_size = 4, per_core = 0; + int nval; + char cmd; + uint32_t num_cores; + u32 extra_memory; + u32 used_memory; + u32 system_reg_end_index; + uint32_t *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + nval = sscanf(buf, "%x %x %c %u", ®ister_offset, + &val, &cmd, &per_core); + if (nval < 2) + return -EINVAL; + if (nval == 2) + cmd = 'r'; + if (per_core > 1) + return -EINVAL; + if (register_offset & 0x3) { + dev_err(dev, "Invalid address, must be 4 byte aligned\n"); + return -EINVAL; + } + + if (cmd == 'r' || cmd == 'R') { + if (val == 0) { + dev_err(dev, "Invalid length of 0\n"); + return -EINVAL; + } + if (cmd == 'r' && val & 0x3) { + dev_err(dev, "Invalid length, must be 4 byte aligned\n"); + return -EINVAL; + } + if (cmd == 'R') + reserve_size = val * 4; + else + reserve_size = val; + } + + mutex_lock(&cpudata->mutex); + + p = (uint32_t *)cpudata->cpussregdata->dump_vaddr; + if (per_core) { /* per-core register */ + if (cpudata->cpussregdata->core_reg_used_num == + cpudata->cpussregdata->core_reg_num) { + dev_err(dev, "Couldn't add per-core config, out of range\n"); + ret = -EINVAL; + goto err; + } + + num_cores = num_possible_cpus(); + extra_memory = reserve_size * num_cores; + used_memory = cpudata->cpussregdata->used_memory + extra_memory; + if (extra_memory / num_cores < reserve_size || + used_memory > cpudata->cpussregdata->size || + used_memory < cpudata->cpussregdata->used_memory) { + dev_err(dev, "Couldn't add per-core reg config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + + ret = config_cpuss_register(dev, p, cpudata->cpussregdata->core_reg_end_index, + cmd, register_offset, val); + if (ret) + goto err; + + if (cmd == 'r' && val == 4) + cpudata->cpussregdata->core_reg_end_index++; + else + cpudata->cpussregdata->core_reg_end_index += 2; + + cpudata->cpussregdata->core_reg_used_num++; + cpudata->cpussregdata->used_memory = used_memory; + } else { /* system register */ + system_reg_end_index = *(p + SYS_REG_INPUT_INDEX) + + cpudata->cpussregdata->sys_reg_size / sizeof(uint32_t); + + if (cmd == 'r' && reserve_size == 4) + extra_memory = sizeof(uint32_t) + reserve_size; + else + extra_memory = sizeof(uint32_t) * 2 + reserve_size; + + used_memory = cpudata->cpussregdata->used_memory + extra_memory; + if (extra_memory < reserve_size || + used_memory > cpudata->cpussregdata->size || + used_memory < cpudata->cpussregdata->used_memory) { + dev_err(dev, "Couldn't add system reg config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + + ret = config_cpuss_register(dev, p, system_reg_end_index, + cmd, register_offset, val); + if (ret) + goto err; + + if (cmd == 'r' && val == 4) { + system_reg_end_index++; + cpudata->cpussregdata->sys_reg_size += sizeof(uint32_t); + } else { + system_reg_end_index += 2; + cpudata->cpussregdata->sys_reg_size += sizeof(uint32_t) * 2; + } + + cpudata->cpussregdata->used_memory = used_memory; + *(p + system_reg_end_index) = 0x0; + *(p + OUTPUT_DUMP_INDEX) = (system_reg_end_index + 1) + * sizeof(uint32_t); + } + + ret = size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(register_config); + +static ssize_t format_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + p = (struct reg_dump_data *)cpudata->cpussregdata->dump_vaddr; + ret = scnprintf(buf, PAGE_SIZE, "%u\n", p->version); + + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RO(format_version); +/** + * This function resets the register dump table. + */ +static ssize_t register_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int val; + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + if (val != 1) + return -EINVAL; + + update_reg_dump_table(dev, CORE_REG_NUM_DEFAULT); + + return size; +} +static DEVICE_ATTR_WO(register_reset); + +/** + * This function shows configs of per-core spr dump. + */ +static ssize_t spr_config_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int i = 0, index = 0; + uint32_t *p; + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + len = scnprintf(local_buf, 64, "spr data list below:\n"); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (count > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + if (!cpudata->sprdata[i]) { + dev_err(dev, "SPR data pinter for CPU%d is empty\n", i); + continue; + } + p = (uint32_t *)cpudata->sprdata[i]->dump_vaddr; + len = scnprintf(local_buf, 64, "spr data for CPU[%d] below:\n", i); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + index = 0; + while (index < cpudata->sprdata[i]->sprs_data_index) { + if (count > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + len = scnprintf(local_buf, 64, "%d\n", *(p + SPR_DATA_HEADER_SIZE + index)); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + index++; + } + } + + mutex_unlock(&cpudata->mutex); + return count; +} + +/** + * This function sets configs for sprs dump. + */ +static ssize_t spr_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + uint32_t spr_data, cpu_num; + uint32_t index; + int nval; + uint32_t *p; + u32 reserved = 0; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + nval = sscanf(buf, "%d %d", &spr_data, &cpu_num); + if (nval != 2) + return -EINVAL; + if (!cpudata) + return -EFAULT; + + if (cpu_num >= MAX_CORE_NUM) { + dev_err(dev, "Input the wrong CPU number\n"); + return -EINVAL; + } + reserved = (SPR_INPUT_DATA_SIZE + SPR_OUTPUT_DATA_SIZE) * sizeof(uint32_t); + + mutex_lock(&cpudata->mutex); + if (cpudata->sprdata[cpu_num]) { + p = (uint32_t *)cpudata->sprdata[cpu_num]->dump_vaddr; + index = cpudata->sprdata[cpu_num]->sprs_data_index; + + if (cpudata->sprdata[cpu_num]->size > + cpudata->sprdata[cpu_num]->used_memory + reserved) { + p = (uint32_t *)cpudata->sprdata[cpu_num]->dump_vaddr; + *(p + OUTPUT_DUMP_INDEX) = (SPR_DATA_HEADER_SIZE + + index + SPR_INPUT_DATA_TAIL_SIZE + 1) * sizeof(uint32_t); + *(p + SPR_DATA_HEADER_SIZE + index) = spr_data; + *(p + SPR_DATA_HEADER_SIZE + index + 1) = 0; + cpudata->sprdata[cpu_num]->sprs_data_index++; + cpudata->sprdata[cpu_num]->used_memory = + cpudata->sprdata[cpu_num]->used_memory + reserved; + } else { + dev_err(dev, "Couldn't add SPR config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + } + ret = size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(spr_config); + +/** + * This function resets the sprs dump table. + */ +static ssize_t sprs_register_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int val; + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + if (val != 1) + return -EINVAL; + + reset_sprs_dump_table(dev); + + return size; +} +static DEVICE_ATTR_WO(sprs_register_reset); + +static ssize_t sprs_format_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0, i = 0; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (cpudata->sprdata[i]) { + p = (struct reg_dump_data *)cpudata->sprdata[i]->dump_vaddr; + len = scnprintf(local_buf, 64, + "SPR data format version for cpu%d is %d\n", i, p->version); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + } + + mutex_unlock(&cpudata->mutex); + return count; +} +static DEVICE_ATTR_RO(sprs_format_version); + + +static const struct device_attribute *register_dump_attrs[] = { + &dev_attr_core_reg_num, + &dev_attr_register_config, + &dev_attr_register_reset, + &dev_attr_format_version, + NULL, +}; + +static const struct device_attribute *spr_dump_attrs[] = { + &dev_attr_spr_config, + &dev_attr_sprs_register_reset, + &dev_attr_sprs_format_version, + NULL, +}; + +static int memory_dump_create_files(struct device *dev, + const struct device_attribute **attrs) +{ + int ret = 0; + int i, j; + + for (i = 0; attrs[i] != NULL; i++) { + ret = device_create_file(dev, attrs[i]); + if (ret) { + dev_err(dev, "Couldn't create sysfs attribute: %s\n", + attrs[i]->attr.name); + for (j = 0; j < i; j++) + device_remove_file(dev, attrs[j]); + break; + } + } + return ret; +} + +static void cpuss_create_nodes(struct platform_device *pdev, + int initialized) +{ + if (initialized & PERCORE_REG_INITIALIZED) { + if (memory_dump_create_files(&pdev->dev, register_dump_attrs)) + dev_err(&pdev->dev, "Fail to create files for cpuss register dump\n"); + } + if (initialized & SPRS_INITIALIZED) { + if (memory_dump_create_files(&pdev->dev, spr_dump_attrs)) + dev_err(&pdev->dev, "Fail to create files for spr dump\n"); + } +} + +uint32_t msm_dump_table_version(void) +{ + return MSM_DUMP_TABLE_VERSION; +} +EXPORT_SYMBOL_GPL(msm_dump_table_version); + +static int msm_dump_table_register(struct msm_dump_entry *entry) +{ + struct msm_dump_entry *e; + struct msm_dump_table *table = memdump.table; + + if (!table || table->num_entries >= MAX_NUM_ENTRIES) + return -EINVAL; + + e = &table->entries[table->num_entries]; + e->id = entry->id; + e->type = MSM_DUMP_TYPE_TABLE; + e->addr = entry->addr; + table->num_entries++; + + return 0; +} + +static struct msm_dump_table *msm_dump_get_table(enum msm_dump_table_ids id) +{ + struct msm_dump_table *table = memdump.table; + int i; + unsigned long offset; + + if (!table) { + pr_err("mem dump base table does not exist\n"); + return ERR_PTR(-EINVAL); + } + + for (i = 0; i < MAX_NUM_ENTRIES; i++) { + if (table->entries[i].id == id) + break; + } + if (i == MAX_NUM_ENTRIES || !table->entries[i].addr) { + pr_err("mem dump base table entry %d invalid\n", id); + return ERR_PTR(-EINVAL); + } + + offset = table->entries[i].addr - memdump.table_phys; + /* Get the apps table pointer */ + table = (void *)memdump.table + offset; + + return table; +} + +static int register_dump_table_entry(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + struct msm_dump_entry *e; + struct msm_dump_table *table; + + table = msm_dump_get_table(id); + if (IS_ERR(table)) + return PTR_ERR(table); + + if (!table || table->num_entries >= MAX_NUM_ENTRIES) + return -EINVAL; + + e = &table->entries[table->num_entries]; + e->id = entry->id; + e->type = MSM_DUMP_TYPE_DATA; + e->addr = entry->addr; + table->num_entries++; + + return 0; +} + +/** + * msm_dump_data_register_nominidump - register to dump data framework + * @id: ID of the dump table. + * @entry: dump entry to be registered + * This api will register the entry passed to dump table only + */ +int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return register_dump_table_entry(id, entry); +} +EXPORT_SYMBOL_GPL(msm_dump_data_register_nominidump); + +#define MSM_DUMP_TOTAL_SIZE_OFFSET 0x724 +static int init_memdump_imem_area(const struct dump_table *table, size_t size) +{ + void __iomem *imem_base; + + imem_base = ioremap(table->imem_base, table->imem_size); + if (!imem_base) { + pr_err("mem dump base table imem offset mapping failed\n"); + return -ENOMEM; + } + + memcpy_toio(imem_base, &memdump.table_phys, + sizeof(memdump.table_phys)); + memcpy_toio(imem_base + MSM_DUMP_TOTAL_SIZE_OFFSET, + &size, sizeof(size_t)); + + /* Ensure write to imem_base is complete before unmapping */ + mb(); + pr_info("MSM Memory Dump base table set up in IMEM\n"); + + iounmap(imem_base); + return 0; +} + +static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) +{ + struct msm_dump_table *table; + struct msm_dump_entry entry; + int ret; + + memdump.table = dump_vaddr; + memdump.table->version = MSM_DUMP_TABLE_VERSION; + memdump.table_phys = phys_addr; + dump_vaddr += sizeof(*table); + phys_addr += sizeof(*table); + table = dump_vaddr; + table->version = MSM_DUMP_TABLE_VERSION; + entry.id = MSM_DUMP_TABLE_APPS; + entry.addr = phys_addr; + ret = msm_dump_table_register(&entry); + if (ret) { + pr_err("mem dump apps data table register failed\n"); + return ret; + } + pr_info("MSM Memory Dump apps data table set up\n"); + + return 0; +} + +static int cpuss_regdump_init(struct device *dev, + void *dump_vaddr, u32 size) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + cpudata->cpussregdata = devm_kzalloc(dev, + sizeof(struct cpuss_regdump_data), GFP_KERNEL); + + if (cpudata->cpussregdata) { + cpudata->cpussregdata->dump_vaddr = dump_vaddr; + cpudata->cpussregdata->size = size; + return 0; + } + return -ENOMEM; +} + +static int sprs_dump_init(struct device *dev, + void *dump_vaddr, u32 size, u32 id) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int core_num = 0; + + core_num = id - SPR_DUMP_CPU0; + + cpudata->sprdata[core_num] = devm_kzalloc(dev, + sizeof(struct sprs_dump_data), GFP_KERNEL); + if (cpudata->sprdata[core_num]) { + cpudata->sprdata[core_num]->dump_vaddr = dump_vaddr; + cpudata->sprdata[core_num]->size = size; + return 0; + } + return -ENOMEM; +} + +static int cpuss_dump_init(struct platform_device *pdev, + void *dump_vaddr, u32 size, u32 id) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(&pdev->dev); + static int initialized; + + if (!cpudata) { + cpudata = devm_kzalloc(&pdev->dev, + sizeof(struct cpuss_dump_data), GFP_KERNEL); + if (cpudata) { + mutex_init(&cpudata->mutex); + platform_set_drvdata(pdev, cpudata); + } else + return initialized; + } + + if (id == CPUSS_REGDUMP) { + if (!cpuss_regdump_init(&pdev->dev, dump_vaddr, size)) + initialized |= PERCORE_REG_INITIALIZED; + } else { + if (!sprs_dump_init(&pdev->dev, dump_vaddr, size, id)) + initialized |= SPRS_INITIALIZED; + } + + return initialized; +} + +struct cma *memdump_cma; +void __init reserve_memdump_cma(void) +{ + unsigned long long cma_size = 0x3000000; + unsigned long long request_size = roundup(cma_size, PAGE_SIZE); + + if (cma_declare_contiguous(0, request_size, 0, 0, 0, false, + "memdump", &memdump_cma)) { + pr_warn("memdump CMA reservation failed\n"); + } +} + +#define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) +static int mem_dump_alloc(struct platform_device *pdev) +{ + struct msm_dump_data *dump_data; + struct msm_dump_entry dump_entry; + size_t total_size; + u32 size, id; + int i, ret, no_of_nodes; + phys_addr_t phys_addr; + void *dump_vaddr; + u64 shm_bridge_handle; + int initialized = 0; + const struct dump_table *table = dev_get_platdata(&pdev->dev); + struct page *reserved_page; + + total_size = size = ret = no_of_nodes = 0; + /* For dump table registration with IMEM */ + total_size = sizeof(struct msm_dump_table) * 2; + for (i = 0; i < table->num_of_items; i++) { + total_size += table->items[i].size; + no_of_nodes++; + } + + total_size += (MSM_DUMP_DATA_SIZE * no_of_nodes); + total_size = ALIGN(total_size, SZ_4K); + reserved_page = cma_alloc(memdump_cma, total_size >> PAGE_SHIFT, + 0, false); + if (!reserved_page) + return -ENOMEM; + phys_addr = page_to_phys(reserved_page); + dump_vaddr = page_to_virt(reserved_page); + + memset(dump_vaddr, 0x0, total_size); + ret = qcom_tzmem_shm_bridge_create(phys_addr, total_size, &shm_bridge_handle); + if (ret) { + dev_err(&pdev->dev, "Failed to create shm bridge.ret=%d\n", ret); + return ret; + } + + ret = init_memory_dump(dump_vaddr, phys_addr); + if (ret) { + dev_err(&pdev->dev, "Memory Dump table set up is failed\n"); + qcom_tzmem_shm_bridge_delete(shm_bridge_handle); + return ret; + } + + ret = init_memdump_imem_area(table, total_size); + if (ret) { + qcom_tzmem_shm_bridge_delete(shm_bridge_handle); + return ret; + } + + dump_vaddr += (sizeof(struct msm_dump_table) * 2); + phys_addr += (sizeof(struct msm_dump_table) * 2); + for (i = 0; i < table->num_of_items; i++) { + size = table->items[i].size; + id = table->items[i].dump_id; + dump_data = dump_vaddr; + dump_data->addr = phys_addr + MSM_DUMP_DATA_SIZE; + dump_data->len = size; + dump_entry.id = id; + strscpy(dump_data->name, table->items[i].name, + sizeof(table->items[i].name)); + dump_entry.addr = phys_addr; + ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS, + &dump_entry); + if (ret) + dev_err(&pdev->dev, "Data dump setup failed, id = %d\n", + id); + + if ((id == CPUSS_REGDUMP) || + ((id >= SPR_DUMP_CPU0) && (id <= SPR_DUMP_CPU7))) + initialized = cpuss_dump_init(pdev, + (dump_vaddr + MSM_DUMP_DATA_SIZE), size, id); + + dump_vaddr += (size + MSM_DUMP_DATA_SIZE); + phys_addr += (size + MSM_DUMP_DATA_SIZE); + } + + cpuss_create_nodes(pdev, initialized); + + if (initialized & SPRS_INITIALIZED) + reset_sprs_dump_table(&pdev->dev); + + return ret; +} + +static int mem_dump_probe(struct platform_device *pdev) +{ + int ret; + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (ret < 0) + return ret; + + ret = mem_dump_alloc(pdev); + return ret; +} + +static struct platform_driver mem_dump_driver = { + .probe = mem_dump_probe, + .driver = { + .name = "msm_mem_dump", + }, +}; + +module_platform_driver(mem_dump_driver); + +MODULE_DESCRIPTION("Memory Dump V2 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 6b601a4b89dbf..1a2b1976ae2ed 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2311,7 +2311,6 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "microsoft,denali", }, { .compatible = "microsoft,romulus13", }, { .compatible = "microsoft,romulus15", }, - { .compatible = "qcom,glymur-crd" }, { .compatible = "qcom,hamoa-iot-evk" }, { .compatible = "qcom,mahua-crd" }, { .compatible = "qcom,purwa-iot-evk" }, @@ -2563,6 +2562,51 @@ bool qcom_scm_is_available(void) } EXPORT_SYMBOL_GPL(qcom_scm_is_available); +int qcom_scm_camera_update_camnoc_qos(uint32_t use_case_id, + uint32_t cam_qos_cnt, struct qcom_scm_camera_qos *cam_qos) +{ + int ret; + dma_addr_t payload_phys; + u32 *payload_buf = NULL; + u32 payload_size = 0; + + if ((cam_qos_cnt > QCOM_SCM_CAMERA_MAX_QOS_CNT) || (cam_qos_cnt && !cam_qos)) { + pr_err("Invalid input SmartQoS count: %d\n", cam_qos_cnt); + return -EINVAL; + } + + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_CAMERA, + .cmd = QCOM_SCM_CAMERA_UPDATE_CAMNOC_QOS, + .owner = ARM_SMCCC_OWNER_SIP, + .args[0] = use_case_id, + .args[2] = payload_size, + .arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL), + }; + + payload_size = cam_qos_cnt * sizeof(struct qcom_scm_camera_qos); + + /* fill all required qos settings */ + if (use_case_id && payload_size && cam_qos) { + payload_buf = dma_alloc_coherent(__scm->dev, + payload_size, &payload_phys, GFP_KERNEL); + if (!payload_buf) + return -ENOMEM; + + memcpy(payload_buf, cam_qos, payload_size); + desc.args[1] = payload_phys; + desc.args[2] = payload_size; + + } + ret = qcom_scm_call(__scm->dev, &desc, NULL); + + if (payload_buf) + dma_free_coherent(__scm->dev, payload_size, payload_buf, payload_phys); + + return ret; +} +EXPORT_SYMBOL_GPL(qcom_scm_camera_update_camnoc_qos); + static int qcom_scm_fill_irq_fwspec_params(struct irq_fwspec *fwspec, u32 hwirq) { if (hwirq >= GIC_SPI_BASE && hwirq <= GIC_MAX_SPI) { diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h index caab80a73e17f..d8c39bfec47f7 100644 --- a/drivers/firmware/qcom/qcom_scm.h +++ b/drivers/firmware/qcom/qcom_scm.h @@ -175,6 +175,9 @@ int qcom_scm_shm_bridge_enable(struct device *scm_dev); #define QCOM_SCM_INTERRUPTED 1 #define QCOM_SCM_WAITQ_SLEEP 2 +#define QCOM_SCM_SVC_CAMERA 0x18 +#define QCOM_SCM_CAMERA_UPDATE_CAMNOC_QOS 0xA + static inline int qcom_scm_remap_error(int err) { switch (err) { diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 4a57d49b4c6d3..b8959b8e2ad05 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -177,6 +177,24 @@ config DRM_LONTIUM_LT9611 HDMI signals Please say Y if you have such hardware. +config DRM_LONTIUM_LT9611C + tristate "Lontium LT9611C DSI/HDMI bridge" + select SND_SOC_HDMI_CODEC if SND_SOC + depends on OF + select CRC8 + select FW_LOADER + select DRM_PANEL_BRIDGE + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_DISPLAY_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select REGMAP_I2C + help + Driver for Lontium DSI to HDMI bridge + chip driver that converts dual DSI and I2S to + HDMI signals + Please say Y if you have such hardware. + config DRM_LONTIUM_LT9611UXC tristate "Lontium LT9611UXC DSI/HDMI bridge" select SND_SOC_HDMI_CODEC if SND_SOC diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 15cc821d85b7e..f322f3f89f6bf 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o +obj-$(CONFIG_DRM_LONTIUM_LT9611C) += lontium-lt9611c.o obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o obj-$(CONFIG_DRM_LONTIUM_LT8713SX) += lontium-lt8713sx.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index f02a38a2638ad..0e2f0b0461213 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -136,16 +136,19 @@ struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_n EXPORT_SYMBOL_GPL(drm_dp_hpd_bridge_register); /** - * drm_aux_hpd_bridge_notify - notify hot plug detection events + * drm_aux_hpd_bridge_notify_extra - notify hot plug detection events * @dev: device created for the HPD bridge * @status: output connection status + * @extra_status: extra status bits like DRM_CONNECTOR_DP_IRQ_HPD * * A wrapper around drm_bridge_hpd_notify() that is used to report hot plug * detection events for bridges created via drm_dp_hpd_bridge_register(). * * This function shall be called in a context that can sleep. */ -void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct auxiliary_device *adev = to_auxiliary_dev(dev); struct drm_aux_hpd_bridge_data *data = auxiliary_get_drvdata(adev); @@ -153,9 +156,9 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta if (!data) return; - drm_bridge_hpd_notify(&data->bridge, status); + drm_bridge_hpd_notify_extra(&data->bridge, status, extra_status); } -EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify); +EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify_extra); static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge, struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c index a237c65ebd690..35df99b02c9c7 100644 --- a/drivers/gpu/drm/bridge/chrontel-ch7033.c +++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c @@ -258,7 +258,8 @@ static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = { .best_encoder = ch7033_connector_best_encoder, }; -static void ch7033_hpd_event(void *arg, enum drm_connector_status status) +static void ch7033_hpd_event(void *arg, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct ch7033_priv *priv = arg; diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c index 16c0631adeb18..f7a5bfd9c0754 100644 --- a/drivers/gpu/drm/bridge/display-connector.c +++ b/drivers/gpu/drm/bridge/display-connector.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,8 @@ struct display_connector { struct regulator *supply; struct gpio_desc *ddc_en; + + struct work_struct hpd_work; }; static inline struct display_connector * @@ -87,6 +90,34 @@ display_connector_bridge_detect(struct drm_bridge *bridge, struct drm_connector return display_connector_detect(bridge); } +static void display_connector_hpd_enable(struct drm_bridge *bridge) +{ + struct display_connector *conn = to_display_connector(bridge); + + enable_irq(conn->hpd_irq); + + if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + schedule_work(&conn->hpd_work); +} + +static void display_connector_hpd_disable(struct drm_bridge *bridge) +{ + struct display_connector *conn = to_display_connector(bridge); + + if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) + cancel_work_sync(&conn->hpd_work); + + disable_irq(conn->hpd_irq); +} + +static void display_connector_hpd_work(struct work_struct *work) +{ + struct display_connector *conn = container_of(work, struct display_connector, hpd_work); + struct drm_bridge *bridge = &conn->bridge; + + drm_bridge_hpd_notify(bridge, display_connector_detect(bridge)); +} + static const struct drm_edid *display_connector_edid_read(struct drm_bridge *bridge, struct drm_connector *connector) { @@ -178,6 +209,8 @@ static u32 *display_connector_get_input_bus_fmts(struct drm_bridge *bridge, static const struct drm_bridge_funcs display_connector_bridge_funcs = { .attach = display_connector_attach, .detect = display_connector_bridge_detect, + .hpd_enable = display_connector_hpd_enable, + .hpd_disable = display_connector_hpd_disable, .edid_read = display_connector_edid_read, .atomic_get_output_bus_fmts = display_connector_get_output_bus_fmts, .atomic_get_input_bus_fmts = display_connector_get_input_bus_fmts, @@ -307,6 +340,7 @@ static int display_connector_probe(struct platform_device *pdev) NULL, display_connector_hpd_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_NO_AUTOEN | IRQF_ONESHOT, "HPD", conn); if (ret) { @@ -378,6 +412,8 @@ static int display_connector_probe(struct platform_device *pdev) conn->bridge.ops |= DRM_BRIDGE_OP_DETECT; if (conn->hpd_irq >= 0) conn->bridge.ops |= DRM_BRIDGE_OP_HPD; + if (conn->hpd_irq >= 0 && type == DRM_MODE_CONNECTOR_DisplayPort) + INIT_WORK(&conn->hpd_work, display_connector_hpd_work); dev_dbg(&pdev->dev, "Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n", diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index 729b12b674706..b8e643cf1d4da 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -505,7 +505,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt) return 0; } -static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status) +static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct lt8912 *lt = data; diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c index 870175a848390..2d14fa0b3a9a2 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9211.c +++ b/drivers/gpu/drm/bridge/lontium-lt9211.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -36,20 +37,39 @@ #define REG_CHIPID2 0x8102 #define REG_CHIPID2_VALUE 0xe3 +/* LT9211C chip ID values */ +#define REG_CHIPID0_LT9211C_VALUE 0x21 +#define REG_CHIPID1_LT9211C_VALUE 0x03 +#define REG_CHIPID2_LT9211C_VALUE 0xe1 + #define REG_DSI_LANE 0xd000 /* DSI lane count - 0 means 4 lanes ; 1, 2, 3 means 1, 2, 3 lanes. */ #define REG_DSI_LANE_COUNT(n) ((n) & 3) +/* Chip type enum */ +enum lt9211_chip_type { + LT9211, + LT9211C, +}; + struct lt9211 { struct drm_bridge bridge; struct device *dev; struct regmap *regmap; - struct mipi_dsi_device *dsi; + struct mipi_dsi_device *dsi; struct drm_bridge *panel_bridge; struct gpio_desc *reset_gpio; struct regulator *vccio; - bool lvds_dual_link; - bool lvds_dual_link_even_odd_swap; + bool lvds_dual_link; + bool lvds_dual_link_even_odd_swap; + /* LT9211C specific fields */ + enum lt9211_chip_type chip_type; + struct workqueue_struct *wq; + struct delayed_work lt9211_dw; + struct drm_display_mode mode; + bool bpp24; + bool jeida; + bool de; }; static const struct regmap_range lt9211_rw_ranges[] = { @@ -93,6 +113,49 @@ static const struct regmap_config lt9211_regmap_config = { .max_register = 0xda00, }; +static const struct regmap_range lt9211c_rw_ranges[] = { + regmap_reg_range(0xff, 0xff), + regmap_reg_range(0x8100, 0x8182), + regmap_reg_range(0x8200, 0x82aa), + regmap_reg_range(0x8500, 0x85ff), + regmap_reg_range(0x8600, 0x86a0), + regmap_reg_range(0x8700, 0x8746), + regmap_reg_range(0xd000, 0xd0a7), + regmap_reg_range(0xd400, 0xd42c), + regmap_reg_range(0xd800, 0xd838), + regmap_reg_range(0xd9c0, 0xd9d5), +}; + +static const struct regmap_access_table lt9211c_rw_table = { + .yes_ranges = lt9211c_rw_ranges, + .n_yes_ranges = ARRAY_SIZE(lt9211c_rw_ranges), +}; + +static const struct regmap_range_cfg lt9211c_range = { + .name = "lt9211c", + .range_min = 0x0000, + .range_max = 0xda00, + .selector_reg = REG_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, +}; + +static const struct regmap_config lt9211c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .rd_table = <9211c_rw_table, + .wr_table = <9211c_rw_table, + .volatile_table = <9211c_rw_table, + .ranges = <9211c_range, + .num_ranges = 1, + .cache_type = REGCACHE_RBTREE, + .max_register = 0xda00, +}; + +static void lt9211_delayed_work_func(struct work_struct *work); + static struct lt9211 *bridge_to_lt9211(struct drm_bridge *bridge) { return container_of(bridge, struct lt9211, bridge); @@ -120,14 +183,21 @@ static int lt9211_read_chipid(struct lt9211 *ctx) return ret; } - /* Test for known Chip ID. */ - if (chipid[0] != REG_CHIPID0_VALUE || chipid[1] != REG_CHIPID1_VALUE) { - dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x 0x%02x\n", - chipid[0], chipid[1], chipid[2]); - return -EINVAL; + /* Test for LT9211 Chip ID. */ + if (chipid[0] == REG_CHIPID0_VALUE && chipid[1] == REG_CHIPID1_VALUE) { + dev_dbg(ctx->dev, "Detected LT9211 chip\n"); + return 0; } - return 0; + /* Test for LT9211C Chip ID. */ + if (chipid[0] == REG_CHIPID0_LT9211C_VALUE && chipid[1] == REG_CHIPID1_LT9211C_VALUE) { + dev_dbg(ctx->dev, "Detected LT9211C chip\n"); + return 0; + } + + dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x\n", chipid[0], chipid[1]); + + return -EINVAL; } static int lt9211_system_init(struct lt9211 *ctx) @@ -504,8 +574,8 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge, lvds_format_24bpp = true; lvds_format_jeida = false; dev_warn(ctx->dev, - "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", - bridge_state->output_bus_cfg.format); + "Unsupported LVDS bus format 0x%04x, please check output bridge driver. Falling back to SPWG24.\n", + bridge_state->output_bus_cfg.format); break; } @@ -518,35 +588,42 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge, crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; crtc_state = drm_atomic_get_new_crtc_state(state, crtc); mode = &crtc_state->adjusted_mode; - ret = lt9211_read_chipid(ctx); if (ret) return; - ret = lt9211_system_init(ctx); - if (ret) + if (ctx->chip_type == LT9211C && ctx->wq) { + drm_mode_copy(&ctx->mode, mode); + /* LT9211C must enable after mipi clock enable */ + queue_delayed_work(ctx->wq, &ctx->lt9211_dw, + msecs_to_jiffies(100)); + dev_dbg(ctx->dev, "LT9211C enabled.\n"); return; + } + ret = lt9211_system_init(ctx); + if (ret) + return; - ret = lt9211_configure_rx(ctx); - if (ret) - return; + ret = lt9211_configure_rx(ctx); + if (ret) + return; - ret = lt9211_autodetect_rx(ctx, mode); - if (ret) - return; + ret = lt9211_autodetect_rx(ctx, mode); + if (ret) + return; - ret = lt9211_configure_timing(ctx, mode); - if (ret) - return; + ret = lt9211_configure_timing(ctx, mode); + if (ret) + return; - ret = lt9211_configure_plls(ctx, mode); - if (ret) - return; + ret = lt9211_configure_plls(ctx, mode); + if (ret) + return; ret = lt9211_configure_tx(ctx, lvds_format_jeida, lvds_format_24bpp, - bus_flags & DRM_BUS_FLAG_DE_HIGH); - if (ret) - return; + bus_flags & DRM_BUS_FLAG_DE_HIGH); + if (ret) + return; dev_dbg(ctx->dev, "LT9211 enabled.\n"); } @@ -671,11 +748,6 @@ static int lt9211_parse_dt(struct lt9211 *ctx) static int lt9211_host_attach(struct lt9211 *ctx) { - const struct mipi_dsi_device_info info = { - .type = "lt9211", - .channel = 0, - .node = NULL, - }; struct device *dev = ctx->dev; struct device_node *host_node; struct device_node *endpoint; @@ -684,6 +756,8 @@ static int lt9211_host_attach(struct lt9211 *ctx) int dsi_lanes; int ret; + /* Check if the compatible string matches lt9211c */ + endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); dsi_lanes = drm_of_get_data_lanes_count(endpoint, 1, 4); host_node = of_graph_get_remote_port_parent(endpoint); @@ -697,7 +771,22 @@ static int lt9211_host_attach(struct lt9211 *ctx) if (dsi_lanes < 0) return dsi_lanes; - dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (ctx->chip_type == LT9211C) { + const struct mipi_dsi_device_info info = { + .type = "lt9211c", + .channel = 0, + .node = NULL, + }; + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + } else { + const struct mipi_dsi_device_info info = { + .type = "lt9211", + .channel = 0, + .node = NULL, + }; + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + } + if (IS_ERR(dsi)) return dev_err_probe(dev, PTR_ERR(dsi), "failed to create dsi device\n"); @@ -706,10 +795,16 @@ static int lt9211_host_attach(struct lt9211 *ctx) dsi->lanes = dsi_lanes; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | - MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA | - MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | - MIPI_DSI_MODE_NO_EOT_PACKET; + + if (ctx->chip_type == LT9211C) { + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; + } else { + dsi->mode_flags = + MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA | + MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | + MIPI_DSI_MODE_NO_EOT_PACKET; + } ret = devm_mipi_dsi_attach(dev, dsi); if (ret < 0) { @@ -731,6 +826,7 @@ static int lt9211_probe(struct i2c_client *client) return PTR_ERR(ctx); ctx->dev = dev; + ctx->chip_type = LT9211; /* * Put the chip in reset, pull nRST line low, @@ -744,13 +840,29 @@ static int lt9211_probe(struct i2c_client *client) usleep_range(10000, 11000); /* Very long reset duration. */ ret = lt9211_parse_dt(ctx); + if (ret) return ret; - ctx->regmap = devm_regmap_init_i2c(client, <9211_regmap_config); + if (of_device_is_compatible(dev->of_node, "lontium,lt9211c")) { + ctx->chip_type = LT9211C; + ctx->regmap = + devm_regmap_init_i2c(client, <9211c_regmap_config); + } else { + ctx->chip_type = LT9211; + ctx->regmap = + devm_regmap_init_i2c(client, <9211_regmap_config); + } if (IS_ERR(ctx->regmap)) return PTR_ERR(ctx->regmap); + /* Initialize LT9211C-specific fields */ + ctx->wq = create_workqueue("lt9211_work"); + if (!ctx->wq) + return -ENOMEM; + + INIT_DELAYED_WORK(&ctx->lt9211_dw, lt9211_delayed_work_func); + dev_set_drvdata(dev, ctx); i2c_set_clientdata(client, ctx); @@ -768,17 +880,667 @@ static void lt9211_remove(struct i2c_client *client) { struct lt9211 *ctx = i2c_get_clientdata(client); + if (ctx->wq) + destroy_workqueue(ctx->wq); + drm_bridge_remove(&ctx->bridge); } +static int lt9211c_configure_rx(struct lt9211 *ctx) +{ + unsigned int pval; + + const struct reg_sequence lt9211c_rx_phy_seq[] = { + { REG_DSI_LANE, REG_DSI_LANE_COUNT(ctx->dsi->lanes) }, + { 0x8201, 0x11 }, + { 0x8218, 0x48 }, + { 0x8201, 0x91 }, + { 0x8202, 0x00 }, + { 0x8203, 0xee }, + { 0x8209, 0x21 }, + { 0x8204, 0x44 }, + { 0x8205, 0xc4 }, + { 0x8206, 0x44 }, + { 0x8213, 0x0c }, + + { 0xd001, 0x00 }, + { 0xd002, 0x0e }, + { 0xd005, 0x00 }, + { 0xd00a, 0x59 }, + { 0xd00b, 0x20 }, + }; + + const struct reg_sequence lt9211c_rx_phy_reset_seq[] = { + { 0x8109, 0xde }, + { 0x8109, 0xdf }, + }; + + const struct reg_sequence lt9211c_rx_clk_sel_seq[] = { + { 0x85e9, 0x88 }, + { 0x8180, 0x51 }, + { 0x8181, 0x10 }, + { 0x8632, 0x03 }, + }; + + const struct reg_sequence lt9211c_rx_input_sel_seq[] = { + { 0xd004, 0x00 }, + { 0xd021, 0x46 }, + }; + + const struct reg_sequence lt9211c_rx_dig_seq[] = { + { 0x853f, 0x08 }, + { 0x8540, 0x04 }, + { 0x8541, 0x03 }, + { 0x8542, 0x02 }, + { 0x8543, 0x01 }, + { 0x8545, 0x04 }, + { 0x8546, 0x03 }, + { 0x8547, 0x02 }, + { 0x8548, 0x01 }, + { 0x8544, 0x00 }, + { 0x8549, 0x00 }, + }; + + int ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_seq, + ARRAY_SIZE(lt9211c_rx_phy_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_reset_seq, + ARRAY_SIZE(lt9211c_rx_phy_reset_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_clk_sel_seq, + ARRAY_SIZE(lt9211c_rx_clk_sel_seq)); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8180, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x8180, ((pval & 0xfc) | 0x03)); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8680, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, (pval & 0xf8)); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x05); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8530, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x8530, ((pval & 0xf8) | 0x11)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_input_sel_seq, + ARRAY_SIZE(lt9211c_rx_input_sel_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_dig_seq, + ARRAY_SIZE(lt9211c_rx_dig_seq)); + if (ret) + return ret; + + /* Give the chip time to lock onto RX stream. */ + msleep(100); + + return 0; +} + +static int lt9211c_autodetect_rx(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + u16 width, height; + u8 buf[5]; + u8 format; + u8 sot[8]; + int ret; + + /* Read the SOT from the chip. */ + ret = regmap_bulk_read(ctx->regmap, 0xd088, sot, sizeof(sot)); + if (ret) + return ret; + + dev_dbg(ctx->dev, "Sot Num = 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", sot[0], + sot[2], sot[4], sot[6]); + + dev_dbg(ctx->dev, "Sot Data = 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", sot[1], + sot[3], sot[5], sot[7]); + /* HS Settle Set */ + if ((sot[0] > 0x10) && (sot[0] < 0x50)) + regmap_write(ctx->regmap, 0xd002, sot[0] - 5); + else + regmap_write(ctx->regmap, 0xd002, 0x08); + + /* Width/Height/Format Auto-detection */ + ret = regmap_bulk_read(ctx->regmap, 0xd082, buf, sizeof(buf)); + if (ret) + return ret; + + width = (buf[0] << 8) | buf[1]; + height = (buf[3] << 8) | buf[4]; + format = buf[2] & 0xf; + + if (format == 0x3) { /* YUV422 16bit */ + width /= 2; + } else if (format == 0xa) { /* RGB888 24bit */ + width /= 3; + } else { + dev_err(ctx->dev, "Unsupported DSI format 0x%01x\n", format); + return -EINVAL; + } + + if (width != mode->hdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI width (%d) does not match mode hdisplay (%d)\n", + width, mode->hdisplay); + return -EINVAL; + } + + if (height != mode->vdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI height (%d) does not match mode vdisplay (%d)\n", + height, mode->vdisplay); + return -EINVAL; + } + + dev_dbg(ctx->dev, "RX: %dx%d format=0x%01x\n", width, height, format); + return 0; +} + +static int lt9211c_configure_timing(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_timing[] = { + { 0xd00d, (mode->vtotal >> 8) & 0xff }, + { 0xd00e, mode->vtotal & 0xff }, + { 0xd00f, (mode->vdisplay >> 8) & 0xff }, + { 0xd010, mode->vdisplay & 0xff }, + { 0xd011, (mode->htotal >> 8) & 0xff }, + { 0xd012, mode->htotal & 0xff }, + { 0xd013, (mode->hdisplay >> 8) & 0xff }, + { 0xd014, mode->hdisplay & 0xff }, + { 0xd015, (mode->vsync_end - mode->vsync_start) & 0xff }, + { 0xd04c, ((mode->hsync_end - mode->hsync_start) >> 8) & 0xff }, + { 0xd016, (mode->hsync_end - mode->hsync_start) & 0xff }, + { 0xd017, ((mode->vsync_start - mode->vdisplay) >> 8) & 0xff }, + { 0xd018, (mode->vsync_start - mode->vdisplay) & 0xff }, + { 0xd019, ((mode->hsync_start - mode->hdisplay) >> 8) & 0xff }, + { 0xd01a, (mode->hsync_start - mode->hdisplay) & 0xff }, + }; + + return regmap_multi_reg_write(ctx->regmap, lt9211c_timing, + ARRAY_SIZE(lt9211c_timing)); +} + +static int lt9211c_configure_plls(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_dessc_pll_reset[] = { + { 0x8103, 0xfe, 2000 }, + { 0x8103, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_pcr_cali_seq[] = { + { 0xd00a, 0x5f }, + { 0xd01e, 0x51 }, + { 0xd023, 0x80 }, + { 0xd024, 0x70 }, + { 0xd025, 0x80 }, + { 0xd02a, 0x10 }, + { 0xd021, 0x4f }, + { 0xd022, 0xf0 }, + { 0xd038, 0x04 }, + { 0xd039, 0x08 }, + { 0xd03a, 0x10 }, + { 0xd03b, 0x20 }, + { 0xd03f, 0x04 }, + { 0xd040, 0x08 }, + { 0xd041, 0x10 }, + { 0xd042, 0x20 }, + { 0xd02b, 0xA0 }, + }; + + const struct reg_sequence lt9211c_pcr_reset_seq[] = { + { 0xd009, 0xdb }, + { 0xd009, 0xdf }, + { 0xd008, 0x80 }, + { 0xd008, 0x00 }, + }; + + unsigned int pval; + int ret; + u8 div; + u32 pcr_m; + u32 pcr_k; + u32 pcr_up; + u32 pcr_down; + + /* DeSSC PLL reference clock is 25 MHz XTal. */ + ret = regmap_write(ctx->regmap, 0x8226, 0x20); + if (ret) + return ret; + + /* Prediv = 0 */ + ret = regmap_write(ctx->regmap, 0x8227, 0x40); + if (ret) + return ret; + + if (mode->clock < 22000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x07); + ret |= regmap_write(ctx->regmap, 0x822c, 0x01); + div = 16; + } else if (mode->clock < 44000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x07); + div = 16; + } else if (mode->clock < 88000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x06); + div = 8; + } else if (mode->clock < 176000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x05); + div = 4; + } else { + ret = regmap_write(ctx->regmap, 0x822f, 0x04); + div = 2; + } + + if (ret) + return ret; + + pcr_m = (mode->clock * div) / 25; + pcr_k = pcr_m % 1000; + pcr_m /= 1000; + + pcr_up = pcr_m + 1; + pcr_down = pcr_m - 1; + + pcr_k <<= 14; + + ret = regmap_write(ctx->regmap, 0xd008, 0x00); + if (ret < 0) + return ret; + + /* 0xd026: pcr_m */ + ret = regmap_write(ctx->regmap, 0xd026, (0x80 | (u8)pcr_m) & 0x7f); + if (ret < 0) + return ret; + + /* 0xd027 0xd028 0xd029: pcr_k */ + ret = regmap_write(ctx->regmap, 0xd027, (pcr_k >> 16) & 0xff); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0xd028, (pcr_k >> 8) & 0xff); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0xd029, pcr_k & 0xff); + if (ret < 0) + return ret; + + /* 0xd02d: pcr_m overflow limit setting */ + ret = regmap_write(ctx->regmap, 0xd02d, pcr_up); + if (ret < 0) + return ret; + + /* 0xd031: pcr_m underflow limit setting */ + ret = regmap_write(ctx->regmap, 0xd031, pcr_down); + if (ret < 0) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_dessc_pll_reset, + ARRAY_SIZE(lt9211c_dessc_pll_reset)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_cali_seq, + ARRAY_SIZE(lt9211c_pcr_cali_seq)); + if (ret) + return ret; + + if (mode->clock < 44000) { + ret = regmap_write(ctx->regmap, 0xd00c, 0x60); + ret |= regmap_write(ctx->regmap, 0xd01b, 0x00); + ret |= regmap_write(ctx->regmap, 0xd01c, 0x60); + } else { + ret = regmap_write(ctx->regmap, 0xd00c, 0x40); + ret |= regmap_write(ctx->regmap, 0xd01b, 0x00); + ret |= regmap_write(ctx->regmap, 0xd01c, 0x40); + } + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_reset_seq, + ARRAY_SIZE(lt9211c_pcr_reset_seq)); + if (ret) + return ret; + + /* PCR stability test takes seconds. */ + ret = regmap_read_poll_timeout(ctx->regmap, 0xd087, pval, + ((pval & 0x18) == 0x18), 20000, 3000000); + if (ret) + dev_err(ctx->dev, "PCR unstable, ret=%i\n", ret); + + ret = regmap_write(ctx->regmap, 0x8180, 0x51); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x00); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x01); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(ctx->regmap, 0x8640, pval, + ((pval & 0x01) == 0x01), 50000, 250000); + if (ret) + dev_err(ctx->dev, "Video check not stable, ret=%i\n", ret); + + return ret; +} + +static int lt9211c_configure_tx(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_tx_phy_off_seq[] = { + { 0x8236, 0x00 }, + { 0x8237, 0x00 }, + { 0x8108, 0x6f }, + { 0x8103, 0xbf }, + }; + + const struct reg_sequence lt9211c_tx_phy_seq[] = { + { 0x8236, 0x03 }, + { 0x8237, 0x44 }, + { 0x8238, 0x14 }, + { 0x8239, 0x31 }, + { 0x823a, 0xc8 }, + { 0x823b, 0x00 }, + { 0x823c, 0x0f }, + { 0x8246, 0x40 }, + { 0x8247, 0x40 }, + { 0x8248, 0x40 }, + { 0x8249, 0x40 }, + { 0x824a, 0x40 }, + { 0x824b, 0x40 }, + { 0x824c, 0x40 }, + { 0x824d, 0x40 }, + { 0x824e, 0x40 }, + { 0x824f, 0x40 }, + { 0x8250, 0x40 }, + { 0x8251, 0x40 }, + }; + + const struct reg_sequence lt9211c_tx_mltx_reset[] = { + { 0x8103, 0xbf }, + { 0x8103, 0xff }, + }; + + const struct reg_sequence lt9211c_tx_dig_seq[] = { + { 0x854a, 0x01 }, + { 0x854b, 0x00 }, + { 0x854c, 0x10 }, + { 0x854d, 0x20 }, + { 0x854e, 0x50 }, + { 0x854f, 0x30 }, + { 0x8550, 0x46 }, + { 0x8551, 0x10 }, + { 0x8552, 0x20 }, + { 0x8553, 0x50 }, + { 0x8554, 0x30 }, + { 0x8555, 0x00 }, + { 0x8556, 0x20 }, + + { 0x8568, 0x00 }, + { 0x856e, 0x10 | (ctx->de ? BIT(6) : 0) }, + { 0x856f, 0x81 | (ctx->jeida ? BIT(6) : 0) | + (ctx->lvds_dual_link ? BIT(4) : 0) | + (ctx->bpp24 ? BIT(2) : 0) }, + }; + + const struct reg_sequence lt9211c_tx_ssc_seq[] = { + { 0x8234, 0x00 }, + { 0x856e, 0x10 }, + { 0x8181, 0x15 }, + { 0x871e, 0x00 }, + { 0x8717, 0x02 }, + { 0x8718, 0x04 }, + { 0x8719, 0xd4 }, + { 0x871A, 0x00 }, + { 0x871B, 0x12 }, + { 0x871C, 0x00 }, + { 0x871D, 0x24 }, + { 0x871F, 0x1c }, + { 0x8720, 0x00 }, + { 0x8721, 0x00 }, + { 0x871e, 0x02 }, + }; + + const struct reg_sequence lt9211c_tx_pll_reset_seq[] = { + { 0x810c, 0xfe, 2000 }, + { 0x810c, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_tx_sw_reset_seq[] = { + { 0x8108, 0x6f, 2000 }, + { 0x8108, 0x7f, 0 }, + }; + + unsigned int pval; + int ret; + u32 phy_clk; + u8 pixclk_div; + u8 pre_div; + u8 div_set; + u8 sericlk_div; + u8 val; + + dev_info(ctx->dev, + "dual_link=%d,even_odd_swap=%d,bpp24=%d,jeida=%d,de=%d\n", + ctx->lvds_dual_link, ctx->lvds_dual_link_even_odd_swap, + ctx->bpp24, ctx->jeida, ctx->de); + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_off_seq, + ARRAY_SIZE(lt9211c_tx_phy_off_seq)); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8530, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x8530, ((pval & 0x3f) | 0x40)); + if (ret) + return ret; + + /* [7]0:txpll normal work; txpll ref clk sel pix clk */ + ret = regmap_write(ctx->regmap, 0x8230, 0x00); + if (ret) + return ret; + + if (ctx->lvds_dual_link) + phy_clk = (u32)(mode->clock * 7 / 2); + else + phy_clk = (u32)(mode->clock * 7); + + /* 0x8231: prediv sel */ + if (mode->clock < 20000) { + val = 0x28; + pre_div = 1; + } else if (mode->clock < 40000) { + val = 0x28; + pre_div = 1; + } else if (mode->clock < 80000) { + val = 0x29; + pre_div = 2; + } else if (mode->clock < 160000) { + val = 0x2a; + pre_div = 4; + } else if (mode->clock < 320000) { + val = 0x2b; + pre_div = 8; + } else { + val = 0x2f; + pre_div = 16; + } + ret = regmap_write(ctx->regmap, 0x8231, val); + if (ret < 0) + return ret; + + /* 0x8232: serickdiv sel */ + if (phy_clk < 80000) { + val = 0x32; + sericlk_div = 16; + } else if (phy_clk < 160000) { + val = 0x22; + sericlk_div = 8; + } else if (phy_clk < 320000) { + val = 0x12; + sericlk_div = 4; + } else if (phy_clk < 640000) { + val = 0x02; + sericlk_div = 2; + } else { + val = 0x42; + sericlk_div = 1; + } + ret = regmap_write(ctx->regmap, 0x8232, val); + if (ret < 0) + return ret; + + /* 0x8233: pix_mux sel & pix_div sel + * To avoid floating point operations, The pixclk_div is enlarged by 10 times + */ + if (mode->clock > 150000) { + val = 0x04; + pixclk_div = 35; + } else { + pixclk_div = + (u8)((phy_clk * sericlk_div * 10) / (mode->clock * 7)); + if (pixclk_div <= 10) + val = 0x00; + else if (pixclk_div <= 20) + val = 0x01; + else if (pixclk_div <= 40) + val = 0x02; + else + val = 0x03; + } + ret = regmap_write(ctx->regmap, 0x8233, val); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0x8234, 0x01); + if (ret < 0) + return ret; + + /* 0x8235: div set */ + div_set = (u8)(phy_clk * sericlk_div / mode->clock / pre_div); + ret = regmap_write(ctx->regmap, 0x8235, div_set); + if (ret < 0) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_ssc_seq, + ARRAY_SIZE(lt9211c_tx_ssc_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_pll_reset_seq, + ARRAY_SIZE(lt9211c_tx_pll_reset_seq)); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(ctx->regmap, 0x8739, pval, pval & 0x04, + 10000, 1000000); + if (ret) { + dev_err(ctx->dev, "TX PLL unstable, ret=%i\n", ret); + return ret; + } + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_seq, + ARRAY_SIZE(lt9211c_tx_phy_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_mltx_reset, + ARRAY_SIZE(lt9211c_tx_mltx_reset)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_dig_seq, + ARRAY_SIZE(lt9211c_tx_dig_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_sw_reset_seq, + ARRAY_SIZE(lt9211c_tx_sw_reset_seq)); + if (ret) + return ret; + + return 0; +} + +static void lt9211_delayed_work_func(struct work_struct *work) +{ + struct delayed_work *dw = to_delayed_work(work); + struct lt9211 *ctx = container_of(dw, struct lt9211, lt9211_dw); + int ret; + const struct drm_display_mode *mode = &ctx->mode; + + /* For LT9211C */ + if (ctx->chip_type != LT9211C) { + dev_err(ctx->dev, "LT9211: Delayed work called for non-LT9211C chip\n"); + return; + } + ret = lt9211c_configure_rx(ctx); + if (ret) + return; + + ret = lt9211c_autodetect_rx(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_timing(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_plls(ctx, mode); + if (ret) + return; + + ret = lt9211c_configure_tx(ctx, mode); + if (ret) + return; + +} + static const struct i2c_device_id lt9211_id[] = { { "lontium,lt9211" }, + { "lontium,lt9211c" }, {}, }; MODULE_DEVICE_TABLE(i2c, lt9211_id); static const struct of_device_id lt9211_match_table[] = { { .compatible = "lontium,lt9211" }, + { .compatible = "lontium,lt9211c" }, {}, }; MODULE_DEVICE_TABLE(of, lt9211_match_table); diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c new file mode 100644 index 0000000000000..30828bb9b3b85 --- /dev/null +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -0,0 +1,1331 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026 Lontium Semiconductor, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FW_SIZE (64 * 1024) +#define LT_PAGE_SIZE 256 +#define FW_FILE "Lontium/lt9611c_fw.bin" +#define LT9611C_CRC_POLYNOMIAL 0x31 +#define LT9611C_PAGE_CONTROL 0xff + +enum lt9611_chip_type { + CHIP_LT9611C = 0, + CHIP_LT9611EX, + CHIP_LT9611UXD, +}; + +enum lt9611c_PORT_SELECT { + PORT_SELECT_A = 0, + PORT_SELECT_B = 1, + PORT_SELECT_AB = 2, +}; + +struct lt9611c { + struct device *dev; + struct i2c_client *client; + struct drm_bridge bridge; + struct regmap *regmap; + /* Protects all accesses to registers by stopping the on-chip MCU */ + struct mutex ocm_lock; + struct work_struct work; + struct device_node *dsi0_node; + struct device_node *dsi1_node; + struct mipi_dsi_device *dsi0; + struct mipi_dsi_device *dsi1; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[2]; + int fw_version; + /* Chip variant: C/EX/UXD */ + enum lt9611_chip_type chip_type; + /* HDMI cable connection status */ + bool hdmi_connected; + /* Selected DSI port configuration */ + int selected_port; +}; + +DECLARE_CRC8_TABLE(lt9611c_crc8_table); + +static const struct regmap_range_cfg lt9611c_ranges[] = { + { + .name = "register_range", + .range_min = 0, + .range_max = 0xfe9c, + .selector_reg = LT9611C_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct regmap_config lt9611c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xfe9c, + .ranges = lt9611c_ranges, + .num_ranges = ARRAY_SIZE(lt9611c_ranges), +}; + +static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params, + unsigned int param_count, u8 *return_buffer, + unsigned int return_count) +{ + int ret; + unsigned int i; + unsigned int temp; + unsigned int max_params = 0xe0dd - 0xe0b0 + 1; + + regmap_write(lt9611c->regmap, 0xe0de, 0x01); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x01, 1000, 200 * 1000); + if (ret) + return -ETIMEDOUT; + + for (i = 0; i < param_count && i < max_params; i++) + regmap_write(lt9611c->regmap, 0xe0b0 + i, params[i]); + + regmap_write(lt9611c->regmap, 0xe0de, 0x02); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x02, 1000, 200 * 1000); + if (ret) + return -ETIMEDOUT; + + return regmap_bulk_read(lt9611c->regmap, 0xe085, return_buffer, + return_count); +} + +static int lt9611c_select_port(struct lt9611c *lt9611c, int port_select) +{ + int ret; + u8 set_port_select_cmd[6] = {0x57, 0x4d, 0x31, 0x3a, 0x01, 0xc0}; + u8 set_port_select_ret[5]; + + if (port_select == PORT_SELECT_B) { + set_port_select_cmd[5] = 0x40; + } else if (port_select == PORT_SELECT_AB) { + set_port_select_cmd[4] = 0x02; + set_port_select_cmd[5] = 0xd0; + } else if (port_select != PORT_SELECT_A) { + return -EINVAL; + } + + /* MCU must be running (0xe0ee=0x00) for lt9611c_read_write_flow */ + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, set_port_select_cmd, + ARRAY_SIZE(set_port_select_cmd), + set_port_select_ret, + ARRAY_SIZE(set_port_select_ret)); + if (ret < 0 || set_port_select_ret[4] == 0) + return ret < 0 ? ret : -EIO; + + return 0; +} + +static void lt9611c_config_parameters(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write_paras[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe103, 0x3f), /*fifo rst*/ + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0xc1), + REG_SEQ0(0xe058, 0x00), + REG_SEQ0(0xe059, 0x50), + REG_SEQ0(0xe05a, 0x10), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write_paras, ARRAY_SIZE(seq_write_paras)); +} + +static void lt9611c_wren(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x04); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_wrdi(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x08); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_erase_op(struct lt9611c *lt9611c, u32 addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe05a, 0x04), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x01), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void read_flash_reg_status(struct lt9611c *lt9611c, unsigned int *status) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe103, 0x3f), + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0x40), + REG_SEQ0(0xe056, 0x05), + REG_SEQ0(0xe055, 0x25), + REG_SEQ0(0xe055, 0x01), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); + + regmap_read(lt9611c->regmap, 0xe05f, status); +} + +static void lt9611c_crc_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0x00), + REG_SEQ0(0xe055, 0xc0), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_data_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0xff), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_sram_to_flash(struct lt9611c *lt9611c, size_t addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x30), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_block_erase(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + int i; + unsigned int block_num; + unsigned int flash_status = 0; + u32 flash_addr = 0; + + for (block_num = 0; block_num < 2; block_num++) { + flash_addr = (block_num * 0x008000); + lt9611c_erase_op(lt9611c, flash_addr); + msleep(100); + i = 0; + while (1) { + read_flash_reg_status(lt9611c, &flash_status); + if ((flash_status & 0x01) == 0) + break; + + if (i > 50) + break; + + i++; + msleep(50); + } + } + + dev_dbg(dev, "erase flash done.\n"); +} + +static int lt9611c_write_data(struct lt9611c *lt9611c, const struct firmware *fw, size_t addr) +{ + struct device *dev = lt9611c->dev; + int ret; + unsigned int page = 0, num = 0, i = 0; + size_t size, index; + const u8 *data; + u8 value; + + data = fw->data; + size = fw->size; + page = (size + LT_PAGE_SIZE - 1) / LT_PAGE_SIZE; + if (page * LT_PAGE_SIZE > FW_SIZE) { + dev_err(dev, "firmware size out of range\n"); + return -EINVAL; + } + + dev_dbg(dev, "%u pages, total size %zu byte\n", page, size); + + for (num = 0; num < page; num++) { + lt9611c_data_to_sram(lt9611c); + + for (i = 0; i < LT_PAGE_SIZE; i++) { + index = num * LT_PAGE_SIZE + i; + value = (index < size) ? data[index] : 0xff; + + ret = regmap_write(lt9611c->regmap, 0xe059, value); + if (ret < 0) { + dev_err(dev, "write error at page %u, index %u\n", num, i); + return ret; + } + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + + addr += LT_PAGE_SIZE; + } + + lt9611c_wrdi(lt9611c); + + return 0; +} + +static int lt9611c_write_crc(struct lt9611c *lt9611c, u8 fw_crc, size_t addr) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c_crc_to_sram(lt9611c); + ret = regmap_write(lt9611c->regmap, 0xe059, fw_crc); + if (ret < 0) { + dev_err(dev, "failed to write crc\n"); + return ret; + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + lt9611c_wrdi(lt9611c); + + dev_dbg(dev, "crc 0x%02x written to flash at addr 0x%zx\n", fw_crc, addr); + + return 0; +} + +static void lt9611c_reset(struct lt9611c *lt9611c) +{ + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + msleep(20); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + msleep(20); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + msleep(400); + + dev_dbg(lt9611c->dev, "lt9611c reset"); +} + +static int lt9611c_upgrade_result(struct lt9611c *lt9611c, u8 fw_crc) +{ + struct device *dev = lt9611c->dev; + unsigned int crc_result; + + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + regmap_read(lt9611c->regmap, 0xe021, &crc_result); + + if (crc_result != fw_crc) { + dev_err(dev, "lt9611c fw upgrade failed, expected crc=0x%02x, read crc=0x%02x\n", + fw_crc, crc_result); + return -1; + } + + dev_dbg(dev, "lt9611c firmware upgrade success, crc=0x%02x\n", crc_result); + return 0; +} + +static int lt9611c_firmware_upgrade(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + const struct firmware *fw; + u8 *buffer; + size_t total_size = FW_SIZE - 1; + u8 fw_crc; + int ret; + + /* 1. load firmware */ + ret = request_firmware(&fw, FW_FILE, dev); + if (ret) + return dev_err_probe(dev, ret, "failed to load '%s'\n", FW_FILE); + + /* 2. check size */ + if (fw->size > total_size) { + dev_err(dev, "firmware too large (%zu > %zu)\n", fw->size, total_size); + ret = -EINVAL; + goto out_release_fw; + } + dev_dbg(dev, "firmware size: %zu bytes\n", fw->size); + + /* 3. calculate crc8 */ + buffer = kzalloc(total_size, GFP_KERNEL); + if (!buffer) { + ret = -ENOMEM; + goto out_release_fw; + } + + memset(buffer, 0xff, total_size); + memcpy(buffer, fw->data, fw->size); + + fw_crc = crc8(lt9611c_crc8_table, buffer, total_size, 0); + kfree(buffer); + + dev_dbg(dev, "firmware crc: 0x%02x\n", fw_crc); + dev_dbg(dev, "starting firmware upgrade, size: %zu bytes\n", fw->size); + + /* 4. firmware upgrade */ + lt9611c_config_parameters(lt9611c); + lt9611c_block_erase(lt9611c); + + ret = lt9611c_write_data(lt9611c, fw, 0); + if (ret < 0) { + dev_err(dev, "failed to write firmware data\n"); + goto out_release_fw; + } + + ret = lt9611c_write_crc(lt9611c, fw_crc, FW_SIZE - 1); + if (ret < 0) { + dev_err(dev, "failed to write firmware crc\n"); + goto out_release_fw; + } + + /* 5. check upgrade of result */ + lt9611c_reset(lt9611c); + ret = lt9611c_upgrade_result(lt9611c, fw_crc); + +out_release_fw: + release_firmware(fw); + return ret; +} + +static struct lt9611c *bridge_to_lt9611c(struct drm_bridge *bridge) +{ + return container_of(bridge, struct lt9611c, bridge); +} + +/*read only*/ +static const struct lt9611c *bridge_to_lt9611c_const(const struct drm_bridge *bridge) +{ + return container_of(bridge, const struct lt9611c, bridge); +} + +static void lt9611c_lock(struct lt9611c *lt9611c) +{ + mutex_lock(<9611c->ocm_lock); + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); +} + +static void lt9611c_unlock(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + mutex_unlock(<9611c->ocm_lock); +} + +static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) +{ + struct lt9611c *lt9611c = dev_id; + struct device *dev = lt9611c->dev; + int ret; + unsigned int irq_status; + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + + guard(mutex)(<9611c->ocm_lock); + + ret = regmap_read(lt9611c->regmap, 0xe084, &irq_status); + if (ret) { + dev_err(dev, "failed to read irq status: %d\n", ret); + return IRQ_HANDLED; + } + + if (!(irq_status & BIT(0))) + return IRQ_HANDLED; + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); + if (ret) { + dev_err(dev, "failed to read HPD status\n"); + } else { + lt9611c->hdmi_connected = (data[4] == 0x02); + dev_dbg(dev, "HDMI %s\n", lt9611c->hdmi_connected ? "connected" : "disconnected"); + } + + /*Clear interrupt: hardware requires two writes with delay*/ + regmap_write(lt9611c->regmap, 0xe0df, irq_status & BIT(0)); + usleep_range(10000, 12000); + regmap_write(lt9611c->regmap, 0xe0df, irq_status & (~BIT(0))); + + schedule_work(<9611c->work); + + return IRQ_HANDLED; +} + +static void lt9611c_hpd_work(struct work_struct *work) +{ + struct lt9611c *lt9611c = container_of(work, struct lt9611c, work); + bool connected; + + mutex_lock(<9611c->ocm_lock); + connected = lt9611c->hdmi_connected; + mutex_unlock(<9611c->ocm_lock); + + drm_bridge_hpd_notify(<9611c->bridge, + connected ? connector_status_connected : + connector_status_disconnected); +} + +static int lt9611c_regulator_init(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c->supplies[0].supply = "vcc"; + lt9611c->supplies[1].supply = "vdd"; + + ret = devm_regulator_bulk_get(dev, 2, lt9611c->supplies); + + return ret; +} + +static struct mipi_dsi_device *lt9611c_attach_dsi(struct lt9611c *lt9611c, + struct device_node *dsi_node) +{ + const struct mipi_dsi_device_info info = { "lt9611c", 0, NULL }; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + struct device *dev = lt9611c->dev; + int ret; + + host = of_find_mipi_dsi_host_by_node(dsi_node); + if (!host) + return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n")); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) + return ERR_PTR(dev_err_probe(dev, PTR_ERR(dsi), "failed to create dsi device\n")); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE; + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) + return ERR_PTR(dev_err_probe(dev, ret, "failed to attach dsi to host\n")); + + return dsi; +} + +static int lt9611c_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, + enum drm_bridge_attach_flags flags) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + return drm_bridge_attach(encoder, lt9611c->bridge.next_bridge, bridge, flags); +} + +static enum drm_mode_status +lt9611c_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) +{ + const struct lt9611c *lt9611c = bridge_to_lt9611c_const(bridge); + + if (lt9611c->chip_type == CHIP_LT9611UXD) { + if (tmds_rate > 600000000) + return MODE_CLOCK_HIGH; + + } else { + if (tmds_rate > 340000000) + return MODE_CLOCK_HIGH; + } + + if (tmds_rate < 25000000) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static void lt9611c_video_setup(struct lt9611c *lt9611c, + const struct drm_display_mode *mode) +{ + struct device *dev = lt9611c->dev; + int ret; + u32 h_total, hactive, hsync_len, hfront_porch, hback_porch; + u32 v_total, vactive, vsync_len, vfront_porch, vback_porch; + u8 timing_set_cmd[26] = {0x57, 0x4d, 0x33, 0x3a}; + u8 return_param[3]; + u8 framerate; + u8 vic = 0x00; + + guard(mutex)(<9611c->ocm_lock); + h_total = mode->htotal; + hactive = mode->hdisplay; + hsync_len = mode->hsync_end - mode->hsync_start; + hfront_porch = mode->hsync_start - mode->hdisplay; + hback_porch = mode->htotal - mode->hsync_end; + + v_total = mode->vtotal; + vactive = mode->vdisplay; + vsync_len = mode->vsync_end - mode->vsync_start; + vfront_porch = mode->vsync_start - mode->vdisplay; + vback_porch = mode->vtotal - mode->vsync_end; + framerate = drm_mode_vrefresh(mode); + vic = drm_match_cea_mode(mode); + + dev_dbg(dev, "hactive=%d, vactive=%d\n", hactive, vactive); + dev_dbg(dev, "framerate=%d\n", framerate); + dev_dbg(dev, "vic = 0x%02x\n", vic); + + timing_set_cmd[4] = (h_total >> 8) & 0xff; + timing_set_cmd[5] = h_total & 0xff; + timing_set_cmd[6] = (hactive >> 8) & 0xff; + timing_set_cmd[7] = hactive & 0xff; + timing_set_cmd[8] = (hfront_porch >> 8) & 0xff; + timing_set_cmd[9] = hfront_porch & 0xff; + timing_set_cmd[10] = (hsync_len >> 8) & 0xff; + timing_set_cmd[11] = hsync_len & 0xff; + timing_set_cmd[12] = (hback_porch >> 8) & 0xff; + timing_set_cmd[13] = hback_porch & 0xff; + timing_set_cmd[14] = (v_total >> 8) & 0xff; + timing_set_cmd[15] = v_total & 0xff; + timing_set_cmd[16] = (vactive >> 8) & 0xff; + timing_set_cmd[17] = vactive & 0xFF; + timing_set_cmd[18] = (vfront_porch >> 8) & 0xff; + timing_set_cmd[19] = vfront_porch & 0xff; + timing_set_cmd[20] = (vsync_len >> 8) & 0xff; + timing_set_cmd[21] = vsync_len & 0xff; + timing_set_cmd[22] = (vback_porch >> 8) & 0xff; + timing_set_cmd[23] = vback_porch & 0xff; + timing_set_cmd[24] = framerate; + timing_set_cmd[25] = vic; + + ret = lt9611c_read_write_flow(lt9611c, + timing_set_cmd, ARRAY_SIZE(timing_set_cmd), + return_param, ARRAY_SIZE(return_param)); + if (ret) + dev_err(dev, "video set failed\n"); +} + +static void lt9611c_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); +} + +static void lt9611c_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *mode; + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + mode = &crtc_state->adjusted_mode; + + lt9611c_video_setup(lt9611c, mode); +} + +static void lt9611c_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + int ret; + + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); +} + +static enum drm_connector_status +lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct device *dev = lt9611c->dev; + int ret; + bool connected = false; + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), data, ARRAY_SIZE(data)); + if (ret) { + dev_err(dev, "failed to read HPD status (err=%d)\n", ret); + connected = lt9611c->hdmi_connected; + } else { + connected = (data[4] == 0x02); + } + + lt9611c->hdmi_connected = connected; + + return connected ? connector_status_connected : + connector_status_disconnected; +} + +static int lt9611c_get_edid_block(void *data, u8 *buf, + unsigned int block, size_t len) +{ + struct lt9611c *lt9611c = data; + struct device *dev = lt9611c->dev; + u8 cmd[5] = {0x52, 0x48, 0x33, 0x3a, 0x00}; + u8 packet[37]; + int ret, i, offset = 0; + + if (len != 128) + return -EINVAL; + guard(mutex)(<9611c->ocm_lock); + + for (i = 0; i < 4; i++) { + cmd[4] = block * 4 + i; + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + packet, ARRAY_SIZE(packet)); + if (ret) { + dev_err(dev, "Failed to read EDID block %u packet %d\n", + block, i); + return ret; + } + memcpy(buf + offset, &packet[5], 32); + offset += 32; + } + + return 0; +} + +static const struct drm_edid *lt9611c_bridge_edid_read(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + return drm_edid_read_custom(connector, lt9611c_get_edid_block, lt9611c); +} + +static int lt9611c_hdmi_write_avi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 *cmd; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + cmd = kmalloc(5 + len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd[0] = 0x57; + cmd[1] = 0x48; + cmd[2] = 0x35; + cmd[3] = 0x3a; + cmd[4] = 0x01;/*write avi*/ + memcpy(cmd + 5, buffer, len); + + ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, + data, ARRAY_SIZE(data)); + kfree(cmd); + + if (ret < 0) { + dev_err(lt9611c->dev, "write avi infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x01}; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + + if (ret < 0) { + dev_err(lt9611c->dev, "clear avi infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + return 0; +} + +static int lt9611c_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge) +{ + return 0; +} + +static int lt9611c_hdmi_write_audio_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 *cmd; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + cmd = kmalloc(5 + len, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd[0] = 0x57; + cmd[1] = 0x48; + cmd[2] = 0x35; + cmd[3] = 0x3a; + cmd[4] = 0x02;/*write audio*/ + memcpy(cmd + 5, buffer, len); + + ret = lt9611c_read_write_flow(lt9611c, cmd, 5 + len, + data, ARRAY_SIZE(data)); + + kfree(cmd); + + if (ret < 0) { + dev_err(lt9611c->dev, "write audio infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_clear_audio_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x57, 0x48, 0x42, 0x3a, 0x02}; + u8 data[5]; + int ret; + + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + + if (ret < 0) { + dev_err(lt9611c->dev, "clear audio infoframe failed!\n"); + return ret; + } + + return 0; +} + +static int lt9611c_hdmi_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 audio_cmd[6] = {0x57, 0x48, 0x36, 0x3a}; + u8 data[5]; + int ret; + + if (hparms->sample_width == 32) + return -EINVAL; + + switch (fmt->fmt) { + case HDMI_I2S: + audio_cmd[4] = 0x01; + break; + case HDMI_SPDIF: + audio_cmd[4] = 0x02; + break; + default: + return -EINVAL; + } + + audio_cmd[5] = hparms->channels; + guard(mutex)(<9611c->ocm_lock); + + ret = lt9611c_read_write_flow(lt9611c, audio_cmd, sizeof(audio_cmd), + data, sizeof(data)); + if (ret < 0) { + dev_err(lt9611c->dev, "set audio info failed!\n"); + return ret; + } + + return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, + &hparms->cea); +} + +static void lt9611c_hdmi_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); +} + +static void lt9611c_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 cmd[5] = {0x52, 0x48, 0x31, 0x3a, 0x00}; + u8 data[5]; + int ret; + + mutex_lock(<9611c->ocm_lock); + ret = lt9611c_read_write_flow(lt9611c, cmd, ARRAY_SIZE(cmd), + data, ARRAY_SIZE(data)); + if (!ret) + lt9611c->hdmi_connected = (data[4] == 0x02); + mutex_unlock(<9611c->ocm_lock); + + schedule_work(<9611c->work); +} + +static int lt9611c_hdmi_audio_startup(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + return 0; +} + +static const struct drm_bridge_funcs lt9611c_bridge_funcs = { + .attach = lt9611c_bridge_attach, + .detect = lt9611c_bridge_detect, + .edid_read = lt9611c_bridge_edid_read, + .atomic_pre_enable = lt9611c_bridge_atomic_pre_enable, + .atomic_enable = lt9611c_bridge_atomic_enable, + .atomic_post_disable = lt9611c_bridge_atomic_post_disable, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .hpd_enable = lt9611c_bridge_hpd_enable, + + .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, + .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, + .hdmi_clear_avi_infoframe = lt9611c_hdmi_clear_avi_infoframe, + .hdmi_write_hdmi_infoframe = lt9611c_hdmi_write_hdmi_infoframe, + .hdmi_clear_hdmi_infoframe = lt9611c_hdmi_clear_hdmi_infoframe, + .hdmi_write_audio_infoframe = lt9611c_hdmi_write_audio_infoframe, + .hdmi_clear_audio_infoframe = lt9611c_hdmi_clear_audio_infoframe, + + .hdmi_audio_startup = lt9611c_hdmi_audio_startup, + .hdmi_audio_prepare = lt9611c_hdmi_audio_prepare, + .hdmi_audio_shutdown = lt9611c_hdmi_audio_shutdown, +}; + +static int lt9611c_parse_dt(struct device *dev, + struct lt9611c *lt9611c) +{ + int ret; + + lt9611c->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); + if (!lt9611c->dsi0_node) + return dev_err_probe(dev, -ENODEV, "failed to get remote node for primary dsi\n"); + + lt9611c->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); + + if (of_property_read_u32(dev->of_node, "lontium,port-select", + <9611c->selected_port)) + lt9611c->selected_port = 0; + + ret = drm_of_find_panel_or_bridge(dev->of_node, 2, -1, NULL, <9611c->bridge.next_bridge); + if (ret) { + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); + return ret; + } + drm_bridge_get(lt9611c->bridge.next_bridge); + return 0; +} + +static int lt9611c_gpio_init(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + + lt9611c->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(lt9611c->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(lt9611c->reset_gpio), + "failed to acquire reset gpio\n"); + + return 0; +} + +static int lt9611c_read_version(struct lt9611c *lt9611c) +{ + u8 buf[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe080, buf, ARRAY_SIZE(buf)); + if (ret) + return ret; + + return (buf[0] << 8) | buf[1]; +} + +static int lt9611c_read_chipid(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + u8 chipid[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe100, chipid, 2); + if (ret) + return ret; + + if (chipid[0] != 0x23 || chipid[1] != 0x06) { + dev_err(dev, "ChipID: 0x%02x 0x%02x\n", chipid[0], chipid[1]); + return -ENODEV; + } + + return 0; +} + +static ssize_t lt9611c_firmware_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + lt9611c_lock(lt9611c); + + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) + dev_err(dev, "upgrade failure\n"); + + lt9611c_unlock(lt9611c); + + return ret < 0 ? ret : len; +} + +static ssize_t lt9611c_firmware_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + + return sysfs_emit(buf, "0x%04x\n", lt9611c->fw_version); +} + +static DEVICE_ATTR_RW(lt9611c_firmware); + +static struct attribute *lt9611c_attrs[] = { + &dev_attr_lt9611c_firmware.attr, + NULL, +}; + +static const struct attribute_group lt9611c_attr_group = { + .attrs = lt9611c_attrs, +}; + +static const struct attribute_group *lt9611c_attr_groups[] = { + <9611c_attr_group, + NULL, +}; + +static int lt9611c_probe(struct i2c_client *client) +{ + const struct i2c_device_id *id = i2c_client_get_device_id(client); + struct lt9611c *lt9611c; + struct device *dev = &client->dev; + bool fw_updated = false; + int ret; + + crc8_populate_msb(lt9611c_crc8_table, LT9611C_CRC_POLYNOMIAL); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return dev_err_probe(dev, -ENODEV, "device doesn't support I2C\n"); + + lt9611c = devm_drm_bridge_alloc(dev, struct lt9611c, bridge, <9611c_bridge_funcs); + if (IS_ERR(lt9611c)) + return dev_err_probe(dev, PTR_ERR(lt9611c), "drm bridge alloc failed.\n"); + + lt9611c->dev = dev; + lt9611c->client = client; + + if (dev->of_node) { + lt9611c->chip_type = (uintptr_t)of_device_get_match_data(dev); + } else { + lt9611c->chip_type = id->driver_data; + } + + ret = devm_mutex_init(dev, <9611c->ocm_lock); + if (ret) + return dev_err_probe(dev, ret, "failed to init mutex\n"); + + lt9611c->regmap = devm_regmap_init_i2c(client, <9611c_regmap_config); + if (IS_ERR(lt9611c->regmap)) + return dev_err_probe(dev, PTR_ERR(lt9611c->regmap), "regmap i2c init failed\n"); + + ret = lt9611c_parse_dt(dev, lt9611c); + if (ret) + return dev_err_probe(dev, ret, "failed to parse device tree\n"); + + ret = lt9611c_gpio_init(lt9611c); + if (ret < 0) + goto err_of_put; + + ret = lt9611c_regulator_init(lt9611c); + if (ret < 0) + goto err_of_put; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) + goto err_of_put; + + lt9611c_reset(lt9611c); + + ret = lt9611c_select_port(lt9611c, lt9611c->selected_port); + if (ret < 0) + dev_err(lt9611c->dev, "failed to select port %d\n", lt9611c->selected_port); + + lt9611c_lock(lt9611c); + + ret = lt9611c_read_chipid(lt9611c); + if (ret < 0) { + dev_err(dev, "failed to read chip id.\n"); + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + +retry: + lt9611c->fw_version = lt9611c_read_version(lt9611c); + if (lt9611c->fw_version < 0) { + dev_err(dev, "failed to read fw version\n"); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + + } else if (lt9611c->fw_version == 0) { + if (!fw_updated) { + fw_updated = true; + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) { + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + + goto retry; + + } else { + dev_err(dev, "fw version 0x%04x, update failed\n", lt9611c->fw_version); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + } + + lt9611c_unlock(lt9611c); + dev_dbg(dev, "current version:0x%04x", lt9611c->fw_version); + + INIT_WORK(<9611c->work, lt9611c_hpd_work); + + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, + lt9611c_irq_thread_handler, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT | + IRQF_NO_AUTOEN, + "lt9611c", lt9611c); + if (ret) { + dev_err(dev, "failed to request irq\n"); + goto err_disable_regulators; + } + + lt9611c->bridge.of_node = client->dev.of_node; + lt9611c->bridge.ops = DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HPD | + DRM_BRIDGE_OP_HDMI | + DRM_BRIDGE_OP_HDMI_AUDIO; + lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA; + + lt9611c->bridge.vendor = "Lontium"; + lt9611c->bridge.product = "LT9611C"; + + lt9611c->bridge.hdmi_audio_dev = dev; + lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8; + lt9611c->bridge.hdmi_audio_dai_port = 2; + + devm_drm_bridge_add(dev, <9611c->bridge); + + /* Attach primary DSI */ + lt9611c->dsi0 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi0_node); + if (IS_ERR(lt9611c->dsi0)) { + ret = PTR_ERR(lt9611c->dsi0); + goto err_remove_bridge; + } + + /* Attach secondary DSI, if specified */ + if (lt9611c->dsi1_node) { + lt9611c->dsi1 = lt9611c_attach_dsi(lt9611c, lt9611c->dsi1_node); + if (IS_ERR(lt9611c->dsi1)) { + ret = PTR_ERR(lt9611c->dsi1); + goto err_remove_bridge; + } + } + + lt9611c->hdmi_connected = false; + i2c_set_clientdata(client, lt9611c); + enable_irq(client->irq); + + return 0; + +err_remove_bridge: + cancel_work_sync(<9611c->work); + +err_disable_regulators: + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + +err_of_put: + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); + + return ret; +} + +static void lt9611c_remove(struct i2c_client *client) +{ + struct lt9611c *lt9611c = i2c_get_clientdata(client); + + cancel_work_sync(<9611c->work); + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + of_node_put(lt9611c->dsi1_node); + of_node_put(lt9611c->dsi0_node); +} + +static int lt9611c_bridge_suspend(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + dev_dbg(lt9611c->dev, "suspend\n"); + disable_irq(lt9611c->client->irq); + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + return ret; + } + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + + return ret; +} + +static int lt9611c_bridge_resume(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + return ret; + } + enable_irq(lt9611c->client->irq); + lt9611c_reset(lt9611c); + dev_dbg(lt9611c->dev, "resume\n"); + + return ret; +} + +static const struct dev_pm_ops lt9611c_bridge_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(lt9611c_bridge_suspend, + lt9611c_bridge_resume) +}; + +static struct i2c_device_id lt9611c_id[] = { + /* chip_type */ + { "lontium,lt9611c", 0 }, + { "lontium,lt9611ex", 1 }, + { "lontium,lt9611uxd", 2 }, + { /* sentinel */ } +}; + +static const struct of_device_id lt9611c_match_table[] = { + { .compatible = "lontium,lt9611c", .data = (void *)CHIP_LT9611C }, + { .compatible = "lontium,lt9611ex", .data = (void *)CHIP_LT9611EX }, + { .compatible = "lontium,lt9611uxd", .data = (void *)CHIP_LT9611UXD }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lt9611c_match_table); + +static struct i2c_driver lt9611c_driver = { + .driver = { + .name = "lt9611c", + .of_match_table = lt9611c_match_table, + .pm = <9611c_bridge_pm_ops, + .dev_groups = lt9611c_attr_groups, + }, + .probe = lt9611c_probe, + .remove = lt9611c_remove, + .id_table = lt9611c_id, +}; +module_i2c_driver(lt9611c_driver); + +MODULE_AUTHOR("SunYun Yang "); +MODULE_DESCRIPTION("Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FW_FILE); + diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 9427cc2358ae1..3e8dff3175d36 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -87,7 +87,9 @@ static const struct regmap_config lt9611uxc_regmap_config = { struct lt9611uxc_mode { u16 hdisplay; + u16 htotal; u16 vdisplay; + u16 vtotal; u8 vrefresh; }; @@ -96,22 +98,23 @@ struct lt9611uxc_mode { * Enumerate them here to check whether the mode is supported. */ static struct lt9611uxc_mode lt9611uxc_modes[] = { - { 1920, 1080, 60 }, - { 1920, 1080, 30 }, - { 1920, 1080, 25 }, - { 1366, 768, 60 }, - { 1360, 768, 60 }, - { 1280, 1024, 60 }, - { 1280, 800, 60 }, - { 1280, 720, 60 }, - { 1280, 720, 50 }, - { 1280, 720, 30 }, - { 1152, 864, 60 }, - { 1024, 768, 60 }, - { 800, 600, 60 }, - { 720, 576, 50 }, - { 720, 480, 60 }, - { 640, 480, 60 }, + { 3840, 4400, 2160, 2250, 30 }, + { 1920, 2200, 1080, 1125, 60 }, + { 1920, 2200, 1080, 1125, 30 }, + { 1920, 2640, 1080, 1125, 25 }, + { 1366, 1792, 768, 798, 60 }, + { 1360, 1792, 768, 795, 60 }, + { 1280, 1688, 1024, 1066, 60 }, + { 1280, 1680, 800, 831, 60 }, + { 1280, 1650, 720, 750, 60 }, + { 1280, 1980, 720, 750, 50 }, + { 1280, 3300, 720, 750, 30 }, + { 1152, 1600, 864, 900, 60 }, + { 1024, 1344, 768, 806, 60 }, + { 800, 1056, 600, 628, 60 }, + { 720, 864, 576, 625, 50 }, + { 720, 858, 480, 525, 60 }, + { 640, 800, 480, 525, 60 }, }; static struct lt9611uxc *bridge_to_lt9611uxc(struct drm_bridge *bridge) @@ -169,6 +172,9 @@ static void lt9611uxc_hpd_work(struct work_struct *work) connected = lt9611uxc->hdmi_connected; mutex_unlock(<9611uxc->ocm_lock); + if (!connected) + lt9611uxc->edid_read = false; + drm_bridge_hpd_notify(<9611uxc->bridge, connected ? connector_status_connected : @@ -235,7 +241,9 @@ static struct lt9611uxc_mode *lt9611uxc_find_mode(const struct drm_display_mode for (i = 0; i < ARRAY_SIZE(lt9611uxc_modes); i++) { if (lt9611uxc_modes[i].hdisplay == mode->hdisplay && + lt9611uxc_modes[i].htotal == mode->htotal && lt9611uxc_modes[i].vdisplay == mode->vdisplay && + lt9611uxc_modes[i].vtotal == mode->vtotal && lt9611uxc_modes[i].vrefresh == drm_mode_vrefresh(mode)) { return <9611uxc_modes[i]; } @@ -380,7 +388,7 @@ lt9611uxc_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connect static int lt9611uxc_wait_for_edid(struct lt9611uxc *lt9611uxc) { return wait_event_interruptible_timeout(lt9611uxc->wq, lt9611uxc->edid_read, - msecs_to_jiffies(500)); + msecs_to_jiffies(1000)); } static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) @@ -429,7 +437,9 @@ static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *brid static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { const struct drm_edid *drm_edid; diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index bf4ab4eaf2697..e2eedaaa3552e 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -110,7 +110,8 @@ static void tfp410_hpd_work_func(struct work_struct *work) drm_helper_hpd_irq_event(dvi->bridge.dev); } -static void tfp410_hpd_callback(void *arg, enum drm_connector_status status) +static void tfp410_hpd_callback(void *arg, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct tfp410 *dvi = arg; diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 649969fca1413..82ed0dc450abc 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -141,7 +141,9 @@ struct drm_bridge_connector { */ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); @@ -149,38 +151,56 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, /* Notify all bridges in the pipeline of hotplug events. */ drm_for_each_bridge_in_chain_scoped(bridge_connector->encoder, bridge) { if (bridge->funcs->hpd_notify) - bridge->funcs->hpd_notify(bridge, connector, status); + bridge->funcs->hpd_notify(bridge, connector, status, + extra_status, send_hotplug); } } static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bridge_connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_connector *connector = &drm_bridge_connector->base; struct drm_device *dev = connector->dev; + bool send_hotplug = true; + + /* + * IRQ-only notification: extra_status carries the event but + * status is unknown — do not overwrite connector->status. + */ + if (status == connector_status_unknown && + extra_status != DRM_CONNECTOR_NO_EXTRA_STATUS) { + drm_bridge_connector_hpd_notify(connector, + connector->status, + extra_status, NULL); + return; + } mutex_lock(&dev->mode_config.mutex); connector->status = status; mutex_unlock(&dev->mode_config.mutex); - drm_bridge_connector_hpd_notify(connector, status); + drm_bridge_connector_hpd_notify(connector, status, extra_status, &send_hotplug); - drm_kms_helper_connector_hotplug_event(connector); + if (send_hotplug) + drm_kms_helper_connector_hotplug_event(connector); } static void drm_bridge_connector_hpd_cb(void *cb_data, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { - drm_bridge_connector_handle_hpd(cb_data, status); + drm_bridge_connector_handle_hpd(cb_data, status, extra_status); } static void drm_bridge_connector_oob_hotplug_event(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); - drm_bridge_connector_handle_hpd(bridge_connector, status); + drm_bridge_connector_handle_hpd(bridge_connector, status, extra_status); } static void drm_bridge_connector_enable_hpd(struct drm_connector *connector) @@ -223,7 +243,8 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force) if (hdmi) drm_atomic_helper_connector_hdmi_hotplug(connector, status); - drm_bridge_connector_hpd_notify(connector, status); + drm_bridge_connector_hpd_notify(connector, status, + DRM_CONNECTOR_NO_EXTRA_STATUS, NULL); } else { switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DPI: diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 687b36eea0c70..3fd3e7bac588c 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1445,7 +1445,8 @@ EXPORT_SYMBOL_GPL(drm_bridge_edid_read); */ void drm_bridge_hpd_enable(struct drm_bridge *bridge, void (*cb)(void *data, - enum drm_connector_status status), + enum drm_connector_status status, + enum drm_connector_status_extra extra_status), void *data) { if (!(bridge->ops & DRM_BRIDGE_OP_HPD)) @@ -1495,25 +1496,28 @@ void drm_bridge_hpd_disable(struct drm_bridge *bridge) EXPORT_SYMBOL_GPL(drm_bridge_hpd_disable); /** - * drm_bridge_hpd_notify - notify hot plug detection events + * drm_bridge_hpd_notify_extra - notify hot plug detection and sink IRQ events * @bridge: bridge control structure * @status: output connection status + * @extra_status: additional status recorded by the sink * * Bridge drivers shall call this function to report hot plug events when they - * detect a change in the output status, when hot plug detection has been - * enabled by drm_bridge_hpd_enable(). + * detect a change in the output status or when the sink has reported extra HPD + * status events (like the IRQ_HPD in case of the DisplayPort), when hot plug + * detection has been enabled by drm_bridge_hpd_enable(). * * This function shall be called in a context that can sleep. */ -void drm_bridge_hpd_notify(struct drm_bridge *bridge, - enum drm_connector_status status) +void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { mutex_lock(&bridge->hpd_mutex); if (bridge->hpd_cb) - bridge->hpd_cb(bridge->hpd_data, status); + bridge->hpd_cb(bridge->hpd_data, status, extra_status); mutex_unlock(&bridge->hpd_mutex); } -EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify); +EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify_extra); #ifdef CONFIG_OF /** diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 11646453aaac9..6bcd47439d5f8 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -3502,20 +3502,24 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) } /** - * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector + * drm_connector_dp_oob_status - Report out-of-band hotplug event to DisplayPort connector * @connector_fwnode: fwnode_handle to report the event on * @status: hot plug detect logical state + * @extra_status: additional information provided by the sink without changing + * the HPD state (or in addition to such a change). * - * On some hardware a hotplug event notification may come from outside the display - * driver / device. An example of this is some USB Type-C setups where the hardware - * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD - * status bit to the GPU's DP HPD pin. + * In some cases when DisplayPort signals are being routed through the USB + * Type-C port the hotplug event notifications come from outside of the display + * driver / device. In this case hardware muxes the DisplayPort data and + * AUX-lines but does not pass the altmode HPD status bit to the GPU's DP HPD + * pin. * * This function can be used to report these out-of-band events after obtaining * a drm_connector reference through calling drm_connector_find_by_fwnode(). */ -void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, - enum drm_connector_status status) +void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_connector *connector; @@ -3524,11 +3528,11 @@ void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, return; if (connector->funcs->oob_hotplug_event) - connector->funcs->oob_hotplug_event(connector, status); + connector->funcs->oob_hotplug_event(connector, status, extra_status); drm_connector_put(connector); } -EXPORT_SYMBOL(drm_connector_oob_hotplug_event); +EXPORT_SYMBOL(drm_connector_dp_oob_status); /** diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 85d3aa3b9894c..31acb31297233 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6990,7 +6990,8 @@ static int intel_dp_connector_atomic_check(struct drm_connector *_connector, } static void intel_dp_oob_hotplug_event(struct drm_connector *_connector, - enum drm_connector_status hpd_state) + enum drm_connector_status hpd_state, + enum drm_connector_status_extra extra_status) { struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(connector); diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index 55c0601df3c62..a67e7b365c5b3 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -323,7 +323,9 @@ static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge, static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index d0c3a4c6703be..31a15636958c8 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -145,7 +145,8 @@ msm-display-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_link.o \ dp/dp_panel.o \ dp/dp_audio.o \ - dp/dp_utils.o + dp/dp_utils.o \ + dp/dp_mst_drm.o msm-display-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 2c0bbac43c52b..f1df2514c6132 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1275,6 +1275,11 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu) status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR); if (priv->disable_err_irq) { + /* Turn off interrupts to avoid interrupt storm */ + gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, + A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | + A5XX_RBBM_INT_0_MASK_CP_SW); + status &= A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | A5XX_RBBM_INT_0_MASK_CP_SW; } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 2e5d7b53a0c38..a2f6918c4f7f2 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -642,7 +642,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu) int ret; u32 val; - if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status)) + if (!test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status)) return; if (adreno_is_a840(adreno_gpu)) @@ -1465,6 +1465,9 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) /* Stop the interrupts and mask the hardware */ a6xx_gmu_irq_disable(gmu); + /* Halt the gmu cm3 core */ + gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); + /* Tell RPMh to power off the GPU */ a6xx_rpmh_stop(gmu); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 8b3bb2fd433ba..9a4f9d0e17800 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1911,8 +1911,11 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu) gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status); - if (priv->disable_err_irq) + if (priv->disable_err_irq) { + /* Turn off interrupts to avoid interrupt storm */ + gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS); status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; + } if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) a6xx_fault_detect_irq(gpu); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 166365359fa6d..3ea8ff8c74044 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -1244,9 +1244,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], &a6xx_state->gmu_registers[1], true); - if (adreno_is_a621(adreno_gpu) || adreno_is_a623(adreno_gpu)) + if (adreno_is_a621(adreno_gpu)) _a6xx_get_gmu_registers(gpu, a6xx_state, &a621_gpucc_reg, &a6xx_state->gmu_registers[2], false); + else if (adreno_is_a623(adreno_gpu) || adreno_is_a663(adreno_gpu)) + _a6xx_get_gmu_registers(gpu, a6xx_state, &a623_gpucc_reg, + &a6xx_state->gmu_registers[2], false); else _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gpucc_reg, &a6xx_state->gmu_registers[2], false); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h index b49d8427b59e6..0a13a65f89ac8 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h @@ -377,6 +377,17 @@ static const u32 a6xx_gmu_gpucc_registers[] = { }; static const u32 a621_gmu_gpucc_registers[] = { + /* GPU CC */ + 0x24000, 0x2400e, 0x24400, 0x2440e, 0x24800, 0x24805, 0x24c00, 0x24cff, + 0x25800, 0x25804, 0x25c00, 0x25c04, 0x26000, 0x26004, 0x26400, 0x26405, + 0x26414, 0x2641d, 0x2642a, 0x26430, 0x26432, 0x26432, 0x26441, 0x26455, + 0x26466, 0x26468, 0x26478, 0x2647a, 0x26489, 0x2648a, 0x2649c, 0x2649e, + 0x264a0, 0x264a3, 0x264b3, 0x264b5, 0x264c5, 0x264c7, 0x264d6, 0x264d8, + 0x264e8, 0x264e9, 0x264f9, 0x264fc, 0x2650b, 0x2650c, 0x2651c, 0x2651e, + 0x26540, 0x26570, 0x26600, 0x26616, 0x26620, 0x2662d, +}; + +static const u32 a623_gmu_gpucc_registers[] = { /* GPU CC */ 0x24000, 0x2400e, 0x24400, 0x2440e, 0x25800, 0x25804, 0x25c00, 0x25c04, 0x26000, 0x26004, 0x26400, 0x26405, 0x26414, 0x2641d, 0x2642a, 0x26430, @@ -402,6 +413,7 @@ static const struct a6xx_registers a6xx_gmu_reglist[] = { static const struct a6xx_registers a6xx_gpucc_reg = REGS(a6xx_gmu_gpucc_registers, 0, 0); static const struct a6xx_registers a621_gpucc_reg = REGS(a621_gmu_gpucc_registers, 0, 0); +static const struct a6xx_registers a623_gpucc_reg = REGS(a623_gmu_gpucc_registers, 0, 0); static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); static u32 a7xx_get_cp_roq_size(struct msm_gpu *gpu); diff --git a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c index 9e44fd1ae6346..0f6fd35bd5878 100644 --- a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c @@ -1211,8 +1211,11 @@ irqreturn_t a8xx_irq(struct msm_gpu *gpu) gpu_write(gpu, REG_A8XX_RBBM_INT_CLEAR_CMD, status); - if (priv->disable_err_irq) + if (priv->disable_err_irq) { + /* Turn off interrupts to avoid interrupt storm */ + gpu_write(gpu, REG_A8XX_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS); status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS; + } if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT) a8xx_fault_detect_irq(gpu); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 778e231d49677..3adfaeaab71da 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1149,9 +1149,9 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc, } } -static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) +void dpu_encoder_atomic_mode_set(struct drm_encoder *drm_enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { struct dpu_encoder_virt *dpu_enc; struct msm_drm_private *priv; @@ -1334,8 +1334,8 @@ void dpu_encoder_virt_runtime_resume(struct drm_encoder *drm_enc) mutex_unlock(&dpu_enc->enc_lock); } -static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, - struct drm_atomic_commit *state) +void dpu_encoder_phys_enable(struct drm_encoder *drm_enc, + struct drm_atomic_commit *state) { struct dpu_encoder_virt *dpu_enc = NULL; int ret = 0; @@ -1381,8 +1381,8 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, mutex_unlock(&dpu_enc->enc_lock); } -static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc, - struct drm_atomic_commit *state) +void dpu_encoder_phys_disable(struct drm_encoder *drm_enc, + struct drm_atomic_commit *state) { struct dpu_encoder_virt *dpu_enc = NULL; struct drm_crtc *crtc; @@ -1438,18 +1438,21 @@ static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc, static struct dpu_hw_intf *dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog, struct dpu_rm *dpu_rm, - enum dpu_intf_type type, u32 controller_id) + struct msm_display_info *disp_info, u32 controller_id) { - int i = 0; + int i = 0, cnt = 0; + int stream_id = disp_info->stream_id; - if (type == INTF_WB) + if (disp_info->intf_type == INTF_WB) return NULL; + DPU_DEBUG("intf_type 0x%x controller_id %d stream_id %d\n", + disp_info->intf_type, controller_id, stream_id); for (i = 0; i < catalog->intf_count; i++) { - if (catalog->intf[i].type == type - && catalog->intf[i].controller_id == controller_id) { - return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id); - } + if (catalog->intf[i].type == disp_info->intf_type && + controller_id == catalog->intf[i].controller_id) + if (cnt++ == stream_id) + return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id); } return NULL; @@ -2675,8 +2678,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, i, controller_id, phys_params.split_role); phys_params.hw_intf = dpu_encoder_get_intf(dpu_kms->catalog, &dpu_kms->rm, - disp_info->intf_type, - controller_id); + disp_info, controller_id); if (disp_info->intf_type == INTF_WB && controller_id < WB_MAX) phys_params.hw_wb = dpu_rm_get_wb(&dpu_kms->rm, controller_id); @@ -2739,9 +2741,9 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) } static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { - .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, - .atomic_disable = dpu_encoder_virt_atomic_disable, - .atomic_enable = dpu_encoder_virt_atomic_enable, + .atomic_mode_set = dpu_encoder_atomic_mode_set, + .atomic_disable = dpu_encoder_phys_disable, + .atomic_enable = dpu_encoder_phys_enable, }; static const struct drm_encoder_funcs dpu_encoder_funcs = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 4942097e76137..861d69afbd763 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -28,6 +28,7 @@ * @h_tile_instance: Controller instance used per tile. Number of elements is * based on num_of_h_tiles * @is_cmd_mode Boolean to indicate if the CMD mode is requested + * @stream_id stream id for which the interface needs to be acquired * @vsync_source: Source of the TE signal for DSI CMD devices */ struct msm_display_info { @@ -35,6 +36,7 @@ struct msm_display_info { uint32_t num_of_h_tiles; uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; bool is_cmd_mode; + int stream_id; enum dpu_vsync_source vsync_source; }; @@ -98,4 +100,10 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc, bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc); void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc); + +void dpu_encoder_phys_enable(struct drm_encoder *enc, struct drm_atomic_commit *state); +void dpu_encoder_phys_disable(struct drm_encoder *enc, struct drm_atomic_commit *state); +void dpu_encoder_atomic_mode_set(struct drm_encoder *enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); #endif /* __DPU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index da3556eb6ecc2..b27fb266ef0f4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -52,7 +52,7 @@ #define DPU_DEBUGFS_DIR "msm_dpu" #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask" -bool dpu_use_virtual_planes = true; +bool dpu_use_virtual_planes; module_param(dpu_use_virtual_planes, bool, 0); static int dpu_kms_hw_init(struct msm_kms *kms); @@ -614,6 +614,7 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, info.h_tile_instance[info.num_of_h_tiles++] = other; info.is_cmd_mode = msm_dsi_is_cmd_mode(priv->kms->dsi[i]); + info.stream_id = 0; rc = dpu_kms_dsi_set_te_source(&info, priv->kms->dsi[i]); if (rc) { @@ -655,7 +656,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, struct msm_display_info info; bool yuv_supported; int rc; - int i; + int i, stream_id, stream_cnt; for (i = 0; i < ARRAY_SIZE(priv->kms->dp); i++) { if (!priv->kms->dp[i]) @@ -678,6 +679,31 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); return rc; } + + stream_cnt = msm_dp_get_mst_max_stream(priv->kms->dp[i]); + + if (stream_cnt > 1) { + rc = msm_dp_mst_register(priv->kms->dp[i]); + if (rc) { + DPU_ERROR("dp_mst_init failed for DP, rc = %d\n", rc); + return rc; + } + + for (stream_id = 0; stream_id < stream_cnt; stream_id++) { + info.stream_id = stream_id; + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DPMST, &info); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dp mst display\n"); + return PTR_ERR(encoder); + } + + rc = msm_dp_mst_attach_encoder(priv->kms->dp[i], encoder); + if (rc) { + DPU_ERROR("dp_mst attach_encoder failed, rc = %d\n", rc); + return rc; + } + } + } } return 0; @@ -698,6 +724,7 @@ static int _dpu_kms_initialize_hdmi(struct drm_device *dev, info.num_of_h_tiles = 1; info.h_tile_instance[0] = 0; info.intf_type = INTF_HDMI; + info.stream_id = 0; encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS, &info); if (IS_ERR(encoder)) { @@ -730,6 +757,7 @@ static int _dpu_kms_initialize_writeback(struct drm_device *dev, /* use only WB idx 2 instance for DPU */ info.h_tile_instance[0] = wb_idx; info.intf_type = INTF_WB; + info.stream_id = 0; maxlinewidth = dpu_rm_get_wb(&dpu_kms->rm, info.h_tile_instance[0])->caps->maxlinewidth; @@ -1496,6 +1524,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,sdm660-mdp5", .data = &dpu_sdm660_cfg, }, { .compatible = "qcom,sdm670-dpu", .data = &dpu_sdm670_cfg, }, { .compatible = "qcom,sdm845-dpu", .data = &dpu_sdm845_cfg, }, + { .compatible = "qcom,shikra-dpu", .data = &dpu_qcm2290_cfg, }, { .compatible = "qcom,sc7180-dpu", .data = &dpu_sc7180_cfg, }, { .compatible = "qcom,sc7280-dpu", .data = &dpu_sc7280_cfg, }, { .compatible = "qcom,sc8180x-dpu", .data = &dpu_sc8180x_cfg, }, diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 41018e82efa10..8118130a3220f 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -284,10 +284,8 @@ int msm_dp_audio_prepare(struct drm_bridge *bridge, * such cases check for connection status and bail out if not * connected. */ - if (!msm_dp_display->power_on) { - rc = -EINVAL; + if (!msm_dp_display->active_stream_cnt) goto end; - } audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 86ef8c89ad443..80116e19fbbf4 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -65,6 +65,11 @@ (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \ PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK) +#define DP_INTERRUPT_STATUS5 \ + (DP_INTR_DP0_VCPF_SENT | DP_INTR_DP1_VCPF_SENT) +#define DP_INTERRUPT_STATUS5_MASK \ + (DP_INTERRUPT_STATUS5 << DP_INTERRUPT_STATUS_MASK_SHIFT) + #define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) #define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) @@ -73,6 +78,7 @@ #define MR_LINK_PRBS7 0x100 #define MR_LINK_CUSTOM80 0x200 #define MR_LINK_TRAINING4 0x40 +#define DP_MAX_TIME_SLOTS 64 enum { DP_TRAINING_NONE, @@ -109,15 +115,21 @@ struct msm_dp_vc_tu_mapping_table { u8 tu_size_minus1; }; +struct msm_dp_mst_ch_slot_info { + u32 start_slot; + u32 tot_slots; +}; + struct msm_dp_ctrl_private { struct msm_dp_ctrl msm_dp_ctrl; struct drm_device *drm_dev; struct device *dev; struct drm_dp_aux *aux; - struct msm_dp_panel *panel; struct msm_dp_link *link; void __iomem *ahb_base; void __iomem *link_base; + void __iomem *mst2link_base; + void __iomem *mst3link_base; struct phy *phy; @@ -127,7 +139,8 @@ struct msm_dp_ctrl_private { unsigned int num_link_clks; struct clk_bulk_data *link_clks; - struct clk *pixel_clk; + struct clk *pixel_clk[DP_STREAM_MAX]; + unsigned int num_pixel_clks; union phy_configure_opts phy_opts; @@ -139,7 +152,10 @@ struct msm_dp_ctrl_private { bool core_clks_on; bool link_clks_on; - bool stream_clks_on; + bool stream_clks_on[DP_STREAM_MAX]; + bool mst_active; + + struct msm_dp_mst_ch_slot_info mst_ch_info[DP_STREAM_MAX]; }; static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset) @@ -172,6 +188,49 @@ static inline void msm_dp_write_link(struct msm_dp_ctrl_private *ctrl, writel(data, ctrl->link_base + offset); } +static inline u32 msm_dp_read_stream_link(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 offset) +{ + offset = msm_dp_stream_reg(stream_id, offset); + switch (stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + return readl_relaxed(ctrl->link_base + offset); + case DP_STREAM_2: + return readl_relaxed(ctrl->mst2link_base + offset); + case DP_STREAM_3: + return readl_relaxed(ctrl->mst3link_base + offset); + default: + DRM_ERROR("error stream_id\n"); + return 0; + } +} + +static inline void msm_dp_write_stream_link(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 offset, u32 data) +{ + /* + * To make sure link reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + offset = msm_dp_stream_reg(stream_id, offset); + switch (stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + writel(data, ctrl->link_base + offset); + break; + case DP_STREAM_2: + writel(data, ctrl->mst2link_base + offset); + break; + case DP_STREAM_3: + writel(data, ctrl->mst3link_base + offset); + break; + default: + DRM_ERROR("error stream_id\n"); + break; + } +} + static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, struct msm_dp_link_info *link) { @@ -199,10 +258,93 @@ static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, return err; } +int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) +{ + struct msm_dp_ctrl_private *ctrl; + const struct drm_display_mode *mode; + u32 frame_time_ms; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + return 0; + + mode = &panel->msm_dp_mode.drm_mode; + frame_time_ms = DIV_ROUND_UP((u64)mode->htotal * mode->vtotal, + mode->clock) + 1; + + msm_dp_write_link(ctrl, REG_DP_MST_ACT, 0x1); + /* make sure ACT signal is performed */ + wmb(); + + msleep(frame_time_ms); + + /* Hardware clears this bit after sending 4 ACT headers */ + if (msm_dp_read_link(ctrl, REG_DP_MST_ACT)) { + drm_dbg_dp(ctrl->drm_dev, "MST ACT trigger complete failed\n"); + return -EINVAL; + } + + return 0; +} + +static void msm_dp_ctrl_mst_config(struct msm_dp_ctrl_private *ctrl, bool enable) +{ + u32 mainlink_ctrl; + + mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + if (enable) + mainlink_ctrl |= DP_MAINLINK_CTRL_MST_EN; + else + mainlink_ctrl &= ~DP_MAINLINK_CTRL_MST_EN; + + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); +} + +static void msm_dp_ctrl_mst_channel_alloc(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 ch_start_slot, + u32 tot_slot_cnt) +{ + u32 slot_reg_1 = 0, slot_reg_2 = 0; + + if (ch_start_slot > DP_MAX_TIME_SLOTS || + (ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) { + DRM_ERROR("invalid slots start %d, tot %d\n", + ch_start_slot, tot_slot_cnt); + return; + } + + drm_dbg_dp(ctrl->drm_dev, "stream_id %d, start_slot %d, tot_slot %d\n", + stream_id, ch_start_slot, tot_slot_cnt); + + if (ch_start_slot && tot_slot_cnt) { + u64 mask = GENMASK_ULL(ch_start_slot + tot_slot_cnt - 2, ch_start_slot - 1); + + slot_reg_1 = mask & 0xFFFFFFFF; + slot_reg_2 = (mask >> 32) & 0xFFFFFFFF; + } + + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_TIMESLOT_1_32, slot_reg_1); + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_TIMESLOT_33_63, slot_reg_2); +} + +static void msm_dp_ctrl_update_rg(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 x_int, u32 y_frac_enum) +{ + u32 rg = y_frac_enum | (x_int << 16); + + drm_dbg_dp(ctrl->drm_dev, "stream_id: %d x_int:%d y_frac_enum:%d rg:%d\n", + stream_id, x_int, y_frac_enum, rg); + + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_RG, rg); +} + /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ -void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); @@ -219,7 +361,7 @@ void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl) if (!ctrl->hw_revision) { ctrl->hw_revision = msm_dp_read_ahb(ctrl, REG_DP_HW_VERSION); - ctrl->panel->hw_revision = ctrl->hw_revision; + panel->hw_revision = ctrl->hw_revision; } } @@ -261,6 +403,8 @@ void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl) DP_INTERRUPT_STATUS1_MASK); msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, DP_INTERRUPT_STATUS2_MASK); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, + DP_INTERRUPT_STATUS5_MASK); } void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl) @@ -270,6 +414,7 @@ void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl) msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS, 0x00); msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, 0x00); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, 0x00); } static u32 msm_dp_ctrl_get_psr_interrupt(struct msm_dp_ctrl_private *ctrl) @@ -289,6 +434,20 @@ static void msm_dp_ctrl_config_psr_interrupt(struct msm_dp_ctrl_private *ctrl) msm_dp_write_ahb(ctrl, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4); } +static u32 msm_dp_ctrl_get_mst_interrupt(struct msm_dp_ctrl_private *ctrl) +{ + u32 intr, intr_ack; + + intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS5); + intr &= ~DP_INTERRUPT_STATUS5_MASK; + intr_ack = (intr & DP_INTERRUPT_STATUS5) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, + intr_ack | DP_INTERRUPT_STATUS5_MASK); + + return intr; +} + static void msm_dp_ctrl_psr_mainlink_enable(struct msm_dp_ctrl_private *ctrl) { u32 val; @@ -388,26 +547,74 @@ void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "mainlink off\n"); } -static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl) +/* Must be called with msm_dp_mst::mst_lock held */ +void msm_dp_ctrl_push_vcpf(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_ctrl_private *ctrl; + u32 state = 0x0; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + state |= DP_STATE_CTRL_PUSH_IDLE; + else if (msm_dp_panel->stream_id == DP_STREAM_0) + state |= DP_DP0_PUSH_VCPF; + else if (msm_dp_panel->stream_id == DP_STREAM_1) + state |= DP_DP1_PUSH_VCPF; + else + state |= DP_MSTLINK_PUSH_VCPF; + + reinit_completion(&ctrl->idle_comp); + + msm_dp_write_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_STATE_CTRL, state); + + if (!wait_for_completion_timeout(&ctrl->idle_comp, + IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES)) + pr_warn("PUSH_VCPF pattern timedout\n"); + + drm_dbg_dp(ctrl->drm_dev, "vcpf sent\n"); +} + +static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *msm_dp_panel) { u32 config = 0, tbd; - const u8 *dpcd = ctrl->panel->dpcd; - /* Default-> LSCLK DIV: 1/4 LCLK */ - config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); + /* + * RMW: Called from atomic_enable(). Serialized by the DRM atomic framework. + */ + if (msm_dp_panel->stream_id == DP_STREAM_0) + config = msm_dp_read_link(ctrl, REG_DP_CONFIGURATION_CTRL); - if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) + if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420) config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */ - /* Scrambler reset enable */ - if (drm_dp_alternate_scrambler_reset_cap(dpcd)) - config |= DP_CONFIGURATION_CTRL_ASSR; - tbd = msm_dp_link_get_test_bits_depth(ctrl->link, - ctrl->panel->msm_dp_mode.bpp); + msm_dp_panel->msm_dp_mode.bpp); config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; + if (msm_dp_panel->psr_cap.version) + config |= DP_CONFIGURATION_CTRL_SEND_VSC; + + drm_dbg_dp(ctrl->drm_dev, "stream DP_CONFIGURATION_CTRL=0x%x\n", config); + + msm_dp_write_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_CONFIGURATION_CTRL, config); +} + +static void msm_dp_ctrl_config_ctrl_link(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) +{ + u32 config = 0; + const u8 *dpcd = panel->dpcd; + + /* Default-> LSCLK DIV: 1/4 LCLK */ + config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); + + /* Scrambler reset enable */ + if (drm_dp_alternate_scrambler_reset_cap(dpcd)) + config |= DP_CONFIGURATION_CTRL_ASSR; + /* Num of Lanes */ config |= ((ctrl->link->link_params.num_lanes - 1) << DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT); @@ -421,10 +628,7 @@ static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl) config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN; config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK; - if (ctrl->panel->psr_cap.version) - config |= DP_CONFIGURATION_CTRL_SEND_VSC; - - drm_dbg_dp(ctrl->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", config); + drm_dbg_dp(ctrl->drm_dev, "link DP_CONFIGURATION_CTRL=0x%x\n", config); msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config); } @@ -443,19 +647,16 @@ static void msm_dp_ctrl_lane_mapping(struct msm_dp_ctrl_private *ctrl) ln_mapping); } -static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_config_misc1_misc0(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *msm_dp_panel) { u32 colorimetry_cfg, test_bits_depth, misc_val; - msm_dp_ctrl_lane_mapping(ctrl); - msm_dp_setup_peripheral_flush(ctrl); - - msm_dp_ctrl_config_ctrl(ctrl); - - test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, ctrl->panel->msm_dp_mode.bpp); + test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, + msm_dp_panel->msm_dp_mode.bpp); colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link); - misc_val = msm_dp_read_link(ctrl, REG_DP_MISC1_MISC0); + misc_val = msm_dp_read_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_MISC1_MISC0); /* clear bpp bits */ misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT); @@ -465,9 +666,19 @@ static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl misc_val |= DP_MISC0_SYNCHRONOUS_CLK; drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val); - msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val); + msm_dp_write_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_MISC1_MISC0, misc_val); +} + +static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) +{ + msm_dp_ctrl_config_ctrl_streams(ctrl, panel); + + msm_dp_ctrl_config_misc1_misc0(ctrl, panel); + + msm_dp_panel_timing_cfg(panel, ctrl->msm_dp_ctrl.wide_bus_en); - msm_dp_panel_timing_cfg(ctrl->panel, ctrl->msm_dp_ctrl.wide_bus_en); + msm_dp_panel_mst_async_fifo(panel, ctrl->mst_active); } /* @@ -1237,20 +1448,21 @@ static void _dp_ctrl_calc_tu(struct msm_dp_ctrl_private *ctrl, } static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, struct msm_dp_vc_tu_mapping_table *tu_table) { struct msm_dp_tu_calc_input in; - struct drm_display_mode *drm_mode; + const struct drm_display_mode *drm_mode; - drm_mode = &ctrl->panel->msm_dp_mode.drm_mode; + drm_mode = &panel->msm_dp_mode.drm_mode; in.lclk = ctrl->link->link_params.rate / 1000; in.pclk_khz = drm_mode->clock; in.hactive = drm_mode->hdisplay; in.hporch = drm_mode->htotal - drm_mode->hdisplay; in.nlanes = ctrl->link->link_params.num_lanes; - in.bpp = ctrl->panel->msm_dp_mode.bpp; - in.pixel_enc = ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; + in.bpp = panel->msm_dp_mode.bpp; + in.pixel_enc = panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444; in.dsc_en = 0; in.async_en = 0; in.fec_en = 0; @@ -1260,14 +1472,15 @@ static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl, _dp_ctrl_calc_tu(ctrl, &in, tu_table); } -static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { u32 msm_dp_tu = 0x0; u32 valid_boundary = 0x0; u32 valid_boundary2 = 0x0; struct msm_dp_vc_tu_mapping_table tu_calc_table; - msm_dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table); + msm_dp_ctrl_calc_tu_parameters(ctrl, panel, &tu_calc_table); msm_dp_tu |= tu_calc_table.tu_size_minus1; valid_boundary |= tu_calc_table.valid_boundary_link; @@ -1419,6 +1632,7 @@ static int msm_dp_ctrl_set_pattern_state_bit(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step, enum drm_dp_phy dp_phy) { int delay_us; @@ -1427,7 +1641,7 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, int const maximum_retries = 4; delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, - ctrl->panel->dpcd, dp_phy, false); + panel->dpcd, dp_phy, false); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); @@ -1513,14 +1727,15 @@ static int msm_dp_ctrl_link_rate_down_shift(struct msm_dp_ctrl_private *ctrl) return ret; } -static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { if (ctrl->link->link_params.num_lanes == 1) return -1; ctrl->link->link_params.num_lanes /= 2; - ctrl->link->link_params.rate = ctrl->panel->link_info.rate; + ctrl->link->link_params.rate = panel->link_info.rate; ctrl->link->phy_params.p_level = 0; ctrl->link->phy_params.v_level = 0; @@ -1529,6 +1744,7 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) } static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, enum drm_dp_phy dp_phy) { int delay_us; @@ -1536,11 +1752,12 @@ static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, - ctrl->panel->dpcd, dp_phy, false); + panel->dpcd, dp_phy, false); fsleep(delay_us); } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step, enum drm_dp_phy dp_phy) { int delay_us; @@ -1551,16 +1768,16 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, u8 link_status[DP_LINK_STATUS_SIZE]; delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, - ctrl->panel->dpcd, dp_phy, false); + panel->dpcd, dp_phy, false); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0); *training_step = DP_TRAINING_2; - if (drm_dp_tps4_supported(ctrl->panel->dpcd)) { + if (drm_dp_tps4_supported(panel->dpcd)) { pattern = DP_TRAINING_PATTERN_4; state_ctrl_bit = 4; - } else if (drm_dp_tps3_supported(ctrl->panel->dpcd)) { + } else if (drm_dp_tps3_supported(panel->dpcd)) { pattern = DP_TRAINING_PATTERN_3; state_ctrl_bit = 3; } else { @@ -1597,18 +1814,19 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step, enum drm_dp_phy dp_phy) { int ret; - ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy); + ret = msm_dp_ctrl_link_train_1(ctrl, panel, training_step, dp_phy); if (ret) { DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); return ret; } drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); - ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy); + ret = msm_dp_ctrl_link_train_2(ctrl, panel, training_step, dp_phy); if (ret) { DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); return ret; @@ -1619,16 +1837,17 @@ static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step) { int i; int ret = 0; - const u8 *dpcd = ctrl->panel->dpcd; + const u8 *dpcd = panel->dpcd; u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; u8 assr; struct msm_dp_link_info link_info = {0}; - msm_dp_ctrl_config_ctrl(ctrl); + msm_dp_ctrl_config_ctrl_link(ctrl, panel); link_info.num_lanes = ctrl->link->link_params.num_lanes; link_info.rate = ctrl->link->link_params.rate; @@ -1651,8 +1870,8 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); - ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy); - msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); + ret = msm_dp_ctrl_link_train_1_2(ctrl, panel, training_step, dp_phy); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, dp_phy); if (ret) break; @@ -1663,7 +1882,7 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, goto end; } - ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX); + ret = msm_dp_ctrl_link_train_1_2(ctrl, panel, training_step, DP_PHY_DPRX); if (ret) { DRM_ERROR("link training on sink failed. ret=%d\n", ret); goto end; @@ -1676,6 +1895,7 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, } static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, int *training_step) { int ret = 0; @@ -1691,7 +1911,7 @@ static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl, * a link training pattern, we have to first do soft reset. */ - ret = msm_dp_ctrl_link_train(ctrl, training_step); + ret = msm_dp_ctrl_link_train(ctrl, panel, training_step); return ret; } @@ -1716,7 +1936,7 @@ int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "enable core clocks \n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); @@ -1735,7 +1955,7 @@ void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "disable core clocks \n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); } @@ -1766,7 +1986,7 @@ static int msm_dp_ctrl_link_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "enable link clocks\n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); @@ -1785,16 +2005,17 @@ static void msm_dp_ctrl_link_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "disabled link clocks\n"); drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n", - str_on_off(ctrl->stream_clks_on), + str_on_off(ctrl->stream_clks_on[DP_STREAM_0]), str_on_off(ctrl->link_clks_on), str_on_off(ctrl->core_clks_on)); } -static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int ret = 0; struct phy *phy = ctrl->phy; - const u8 *dpcd = ctrl->panel->dpcd; + const u8 *dpcd = panel->dpcd; ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes; ctrl->phy_opts.dp.link_rate = ctrl->link->link_params.rate / 100; @@ -1846,13 +2067,14 @@ static void msm_dp_ctrl_psr_exit(struct msm_dp_ctrl_private *ctrl) msm_dp_write_link(ctrl, REG_PSR_CMD, cmd); } -void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); u32 cfg; - if (!ctrl->panel->psr_cap.version) + if (!panel->psr_cap.version) return; /* enable PSR1 function */ @@ -1867,12 +2089,13 @@ void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl) drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1); } -void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enter) +void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, bool enter) { struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - if (!ctrl->panel->psr_cap.version) + if (!panel->psr_cap.version) return; /* @@ -1942,7 +2165,8 @@ void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl) phy_exit(phy); } -static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { struct phy *phy = ctrl->phy; int ret = 0; @@ -1963,7 +2187,7 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) /* hw recommended delay before re-enabling clocks */ msleep(20); - ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl); + ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); if (ret) { DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret); return ret; @@ -1972,7 +2196,8 @@ static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) return ret; } -static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { struct phy *phy; @@ -1980,7 +2205,7 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) msm_dp_ctrl_mainlink_disable(ctrl); - msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); @@ -1994,7 +2219,8 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl) return 0; } -static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int ret = 0; int training_step = DP_TRAINING_NONE; @@ -2004,11 +2230,11 @@ static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) ctrl->link->phy_params.p_level = 0; ctrl->link->phy_params.v_level = 0; - ret = msm_dp_ctrl_setup_main_link(ctrl, &training_step); + ret = msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); if (ret) goto end; - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); @@ -2152,7 +2378,44 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) return success; } -static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned long pixel_rate, + enum msm_dp_stream_id stream_id) +{ + int ret; + + ret = clk_set_rate(ctrl->pixel_clk[stream_id], pixel_rate * 1000); + if (ret) { + DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); + return ret; + } + + if (WARN_ON_ONCE(ctrl->stream_clks_on[stream_id])) + return 0; + + ret = clk_prepare_enable(ctrl->pixel_clk[stream_id]); + if (ret) { + DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + return ret; + } + ctrl->stream_clks_on[stream_id] = true; + + return ret; +} + +void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl, enum msm_dp_stream_id stream_id) +{ + struct msm_dp_ctrl_private *ctrl; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (ctrl->stream_clks_on[stream_id]) { + clk_disable_unprepare(ctrl->pixel_clk[stream_id]); + ctrl->stream_clks_on[stream_id] = false; + } +} + +static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int ret; unsigned long pixel_rate; @@ -2168,38 +2431,25 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl * running. Add the global reset just before disabling the * link clocks and core clocks. */ - msm_dp_ctrl_off(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_off_pixel_clk(&ctrl->msm_dp_ctrl, panel->stream_id); + msm_dp_ctrl_off_link(&ctrl->msm_dp_ctrl, panel); - ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl); + ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl, panel); if (ret) { DRM_ERROR("failed to enable DP link controller\n"); return ret; } - pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; - ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); - if (ret) { - DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); - return ret; - } - - if (ctrl->stream_clks_on) { - drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); - } else { - ret = clk_prepare_enable(ctrl->pixel_clk); - if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); - return ret; - } - ctrl->stream_clks_on = true; - } + pixel_rate = panel->msm_dp_mode.drm_mode.clock; + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate, panel->stream_id); msm_dp_ctrl_send_phy_test_pattern(ctrl); return 0; } -void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl; u32 sink_request = 0x0; @@ -2214,14 +2464,14 @@ void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { drm_dbg_dp(ctrl->drm_dev, "PHY_TEST_PATTERN request\n"); - if (msm_dp_ctrl_process_phy_test_request(ctrl)) { + if (msm_dp_ctrl_process_phy_test_request(ctrl, panel)) { DRM_ERROR("process phy_test_req failed\n"); return; } } if (sink_request & DP_LINK_STATUS_UPDATED) { - if (msm_dp_ctrl_link_maintenance(ctrl)) { + if (msm_dp_ctrl_link_maintenance(ctrl, panel)) { DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); return; } @@ -2229,7 +2479,7 @@ void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl) if (sink_request & DP_TEST_LINK_TRAINING) { msm_dp_link_send_test_response(ctrl->link); - if (msm_dp_ctrl_link_maintenance(ctrl)) { + if (msm_dp_ctrl_link_maintenance(ctrl, panel)) { DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); return; } @@ -2265,7 +2515,8 @@ static bool msm_dp_ctrl_channel_eq_ok(struct msm_dp_ctrl_private *ctrl) return drm_dp_channel_eq_ok(link_status, num_lanes); } -int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) +int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { int rc = 0; struct msm_dp_ctrl_private *ctrl; @@ -2281,8 +2532,8 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - rate = ctrl->panel->link_info.rate; - pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock; + rate = panel->link_info.rate; + pixel_rate = panel->msm_dp_mode.drm_mode.clock; msm_dp_ctrl_core_clk_enable(&ctrl->msm_dp_ctrl); @@ -2294,8 +2545,8 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } else { ctrl->link->link_params.rate = rate; ctrl->link->link_params.num_lanes = - ctrl->panel->link_info.num_lanes; - if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) + panel->link_info.num_lanes; + if (panel->msm_dp_mode.out_fmt_is_yuv_420) pixel_rate >>= 1; } @@ -2303,13 +2554,13 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, pixel_rate); - rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl); + rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); if (rc) return rc; while (--link_train_max_retries) { training_step = DP_TRAINING_NONE; - rc = msm_dp_ctrl_setup_main_link(ctrl, &training_step); + rc = msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); if (rc == 0) { /* training completed successfully */ break; @@ -2328,7 +2579,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * some lanes are ready, * reduce lane number */ - rc = msm_dp_ctrl_link_lane_down_shift(ctrl); + rc = msm_dp_ctrl_link_lane_down_shift(ctrl, panel); if (rc < 0) { /* lane == 1 already */ /* end with failure */ break; @@ -2349,7 +2600,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) ctrl->link->link_params.num_lanes)) rc = msm_dp_ctrl_link_rate_down_shift(ctrl); else - rc = msm_dp_ctrl_link_lane_down_shift(ctrl); + rc = msm_dp_ctrl_link_lane_down_shift(ctrl, panel); if (rc < 0) { /* end with failure */ @@ -2357,10 +2608,10 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } /* stop link training before start re training */ - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); } - rc = msm_dp_ctrl_reinitialize_mainlink(ctrl); + rc = msm_dp_ctrl_reinitialize_mainlink(ctrl, panel); if (rc) { DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc); break; @@ -2381,25 +2632,26 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * link training failed * end txing train pattern here */ - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); - msm_dp_ctrl_deinitialize_mainlink(ctrl); + msm_dp_ctrl_deinitialize_mainlink(ctrl, panel); rc = -ECONNRESET; } return rc; } -static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) { int training_step = DP_TRAINING_NONE; - return msm_dp_ctrl_setup_main_link(ctrl, &training_step); + return msm_dp_ctrl_setup_main_link(ctrl, panel, &training_step); } static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, - u32 rate, u32 stream_rate_khz, - bool is_ycbcr_420) + struct msm_dp_panel *panel, + u32 rate, u32 stream_rate_khz) { u32 pixel_m, pixel_n; u32 mvid, nvid, pixel_div, dispcc_input_rate; @@ -2451,7 +2703,7 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, nvid = temp; } - if (is_ycbcr_420) + if (panel->msm_dp_mode.out_fmt_is_yuv_420) mvid /= 2; if (link_rate_hbr2 == rate) @@ -2461,66 +2713,184 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, nvid *= 3; drm_dbg_dp(ctrl->drm_dev, "mvid=0x%x, nvid=0x%x\n", mvid, nvid); - msm_dp_write_link(ctrl, REG_DP_SOFTWARE_MVID, mvid); - msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid); + msm_dp_write_stream_link(ctrl, panel->stream_id, REG_DP_SOFTWARE_MVID, mvid); + msm_dp_write_stream_link(ctrl, panel->stream_id, REG_DP_SOFTWARE_NVID, nvid); +} + +/* + * Calculate MST Rate Governor parameters x_int and y_frac_enum (HPG 3.8.1.2). + * + * The RG paces symbol delivery per MTP via: M = x_int + y_frac_enum/256 + * where M is the target symbol count per MTP across all lanes. + * + * min_slot_cnt = (pclk * bpp/8) / (lclk * lanes) * 64 -- slots at 1.0x BW + * max_slot_cnt = pbn * 54 / (lclk * lanes) -- slots at PBN limit + * raw_target_sc = (min + max) / 2 -- midpoint (~1.003x) + * + * Quantize raw_target_sc to 1/(256*lanes) steps, then: + * M = Chosen_TARGET_Slot_Count * lanes + * x_int = INT(M) + * y_frac_enum = CEIL(256 * MOD(M, 1)) + */ +static void msm_dp_ctrl_mst_calculate_rg(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, + u32 *p_x_int, u32 *p_y_frac_enum) +{ + u64 min_slot_cnt, max_slot_cnt; + u64 raw_target_sc, target_sc_fixp; + u64 ts_denom, ts_enum, ts_int; + u64 pclk = panel->msm_dp_mode.drm_mode.clock; + u64 lclk = 0; + u64 lanes = ctrl->link->link_params.num_lanes; + u64 bpp = panel->msm_dp_mode.bpp; + u64 pbn = panel->pbn; + u64 numerator, denominator, temp, temp1, temp2; + u32 x_int = 0, y_frac_enum = 0; + u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp; + + lclk = ctrl->link->link_params.rate; + + /* min_slot_cnt */ + numerator = pclk * bpp * 64 * 1000; + denominator = lclk * lanes * 8 * 1000; + min_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* max_slot_cnt */ + numerator = pbn * 54 * 1000; + denominator = lclk * lanes; + max_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* raw_target_sc */ + numerator = max_slot_cnt + min_slot_cnt; + denominator = drm_fixp_from_fraction(2, 1); + raw_target_sc = drm_fixp_div(numerator, denominator); + + /* target_sc */ + temp = drm_fixp_from_fraction(256 * lanes, 1); + numerator = drm_fixp_mul(raw_target_sc, temp); + denominator = drm_fixp_from_fraction(256 * lanes, 1); + target_sc_fixp = drm_fixp_div(numerator, denominator); + + ts_enum = 256 * lanes; + ts_denom = drm_fixp_from_fraction(256 * lanes, 1); + ts_int = drm_fixp2int(target_sc_fixp); + + temp = drm_fixp2int_ceil(raw_target_sc); + if (temp != ts_int) { + temp = drm_fixp_from_fraction(ts_int, 1); + temp1 = raw_target_sc - temp; + temp2 = drm_fixp_mul(temp1, ts_denom); + ts_enum = drm_fixp2int(temp2); + } + + /* target_strm_sym */ + ts_int_fixp = drm_fixp_from_fraction(ts_int, 1); + ts_frac_fixp = drm_fixp_from_fraction(ts_enum, drm_fixp2int(ts_denom)); + temp = ts_int_fixp + ts_frac_fixp; + temp1 = drm_fixp_from_fraction(lanes, 1); + target_strm_sym = drm_fixp_mul(temp, temp1); + + /* x_int */ + x_int = drm_fixp2int(target_strm_sym); + + /* y_enum_frac */ + temp = drm_fixp_from_fraction(x_int, 1); + temp1 = target_strm_sym - temp; + temp2 = drm_fixp_from_fraction(256, 1); + y_frac_enum_fixp = drm_fixp_mul(temp1, temp2); + + temp1 = drm_fixp2int(y_frac_enum_fixp); + temp2 = drm_fixp2int_ceil(y_frac_enum_fixp); + + y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1); + + *p_x_int = x_int; + *p_y_frac_enum = y_frac_enum; + + drm_dbg_dp(ctrl->drm_dev, "MST lane_cnt:%llu, rate:%llu x_int:%d, y_frac:%d\n", + lanes, lclk, x_int, y_frac_enum); +} + +static void msm_dp_ctrl_mst_stream_setup(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) +{ + u32 x_int, y_frac_enum; + + if (!ctrl->mst_active) + return; + + drm_dbg_dp(ctrl->drm_dev, "MST stream channel allocation\n"); + + msm_dp_ctrl_mst_stream_channel_slot_setup(&ctrl->msm_dp_ctrl); + + msm_dp_ctrl_mst_calculate_rg(ctrl, panel, &x_int, &y_frac_enum); + + msm_dp_ctrl_update_rg(ctrl, panel->stream_id, x_int, y_frac_enum); } -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train) +int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, + bool force_link_train) { int ret = 0; - bool mainlink_ready = false; struct msm_dp_ctrl_private *ctrl; - unsigned long pixel_rate; - unsigned long pixel_rate_orig; if (!msm_dp_ctrl) return -EINVAL; ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - pixel_rate = pixel_rate_orig = ctrl->panel->msm_dp_mode.drm_mode.clock; + drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d\n", + ctrl->link->link_params.rate, + ctrl->link->link_params.num_lanes); - if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420) - pixel_rate >>= 1; - - drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n", - ctrl->link->link_params.rate, - ctrl->link->link_params.num_lanes, pixel_rate); - - drm_dbg_dp(ctrl->drm_dev, - "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n", - ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on); + drm_dbg_dp(ctrl->drm_dev, "core_clk_on=%d link_clk_on=%d\n", + ctrl->core_clks_on, ctrl->link_clks_on); if (!ctrl->link_clks_on) { /* link clk is off */ - ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl); + ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl, panel); if (ret) { DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); - goto end; - } - } - - ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000); - if (ret) { - DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret); - goto end; - } - - if (ctrl->stream_clks_on) { - drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n"); - } else { - ret = clk_prepare_enable(ctrl->pixel_clk); - if (ret) { - DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); - goto end; + return ret; } - ctrl->stream_clks_on = true; } if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl)) - msm_dp_ctrl_link_retrain(ctrl); + msm_dp_ctrl_link_retrain(ctrl, panel); /* stop txing train pattern to end link training */ - msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); + msm_dp_ctrl_clear_training_pattern(ctrl, panel, DP_PHY_DPRX); + + return ret; +} + +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, + bool mst_active) +{ + int ret = 0; + bool mainlink_ready = false; + struct msm_dp_ctrl_private *ctrl; + unsigned long pixel_rate; + unsigned long pixel_rate_orig; + + if (!msm_dp_ctrl) + return -EINVAL; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + ctrl->mst_active = mst_active; + + pixel_rate_orig = panel->msm_dp_mode.drm_mode.clock; + pixel_rate = pixel_rate_orig; + + if (msm_dp_ctrl->wide_bus_en || panel->msm_dp_mode.out_fmt_is_yuv_420) + pixel_rate >>= 1; + + drm_dbg_dp(ctrl->drm_dev, "pixel_rate=%lu\n", pixel_rate); + + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate, panel->stream_id); + if (ret) + return ret; /* * Set up transfer unit values and set controller state to send @@ -2528,19 +2898,33 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train */ reinit_completion(&ctrl->video_comp); - msm_dp_ctrl_configure_source_params(ctrl); + msm_dp_ctrl_lane_mapping(ctrl); + msm_dp_setup_peripheral_flush(ctrl); + if (ctrl->mst_active) + msm_dp_ctrl_mst_config(ctrl, true); + + if (panel->stream_id == DP_STREAM_0) + msm_dp_ctrl_config_ctrl_link(ctrl, panel); + + msm_dp_ctrl_configure_source_params(ctrl, panel); msm_dp_ctrl_config_msa(ctrl, - ctrl->link->link_params.rate, - pixel_rate_orig, - ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420); + panel, ctrl->link->link_params.rate, + pixel_rate_orig); + + msm_dp_panel_clear_dsc_dto(panel); - msm_dp_panel_clear_dsc_dto(ctrl->panel); + if (!ctrl->mst_active) + msm_dp_ctrl_setup_tr_unit(ctrl, panel); - msm_dp_ctrl_setup_tr_unit(ctrl); + msm_dp_ctrl_mst_stream_setup(ctrl, panel); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); + ret = msm_dp_ctrl_mst_send_act(msm_dp_ctrl, panel); + if (ret) + return ret; + ret = msm_dp_ctrl_wait4video_ready(ctrl); if (ret) return ret; @@ -2549,11 +2933,10 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train drm_dbg_dp(ctrl->drm_dev, "mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); -end: return ret; } -void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl) { struct msm_dp_ctrl_private *ctrl; struct phy *phy; @@ -2561,29 +2944,13 @@ void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_panel_disable_vsc_sdp(ctrl->panel); - - /* set dongle to D3 (power off) mode */ - msm_dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true); - - msm_dp_ctrl_mainlink_disable(ctrl); - - if (ctrl->stream_clks_on) { - clk_disable_unprepare(ctrl->pixel_clk); - ctrl->stream_clks_on = false; - } - - dev_pm_opp_set_rate(ctrl->dev, 0); - msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); - - phy_power_off(phy); - /* aux channel down, reinit phy */ phy_exit(phy); phy_init(phy); } -void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl; struct phy *phy; @@ -2591,16 +2958,12 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); phy = ctrl->phy; - msm_dp_panel_disable_vsc_sdp(ctrl->panel); - msm_dp_ctrl_mainlink_disable(ctrl); + msm_dp_ctrl_mst_config(ctrl, false); - msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl); + msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); - if (ctrl->stream_clks_on) { - clk_disable_unprepare(ctrl->pixel_clk); - ctrl->stream_clks_on = false; - } + ctrl->mst_active = false; dev_pm_opp_set_rate(ctrl->dev, 0); msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); @@ -2608,7 +2971,41 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl) phy_power_off(phy); } -irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) +void msm_dp_ctrl_set_mst_channel_info(struct msm_dp_ctrl *msm_dp_ctrl, + enum msm_dp_stream_id stream_id, + u32 start_slot, u32 tot_slots) +{ + struct msm_dp_ctrl_private *ctrl; + + if (!msm_dp_ctrl || stream_id >= DP_STREAM_MAX) { + DRM_ERROR("invalid input\n"); + return; + } + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + ctrl->mst_ch_info[stream_id].start_slot = start_slot; + ctrl->mst_ch_info[stream_id].tot_slots = tot_slots; +} + +void msm_dp_ctrl_mst_stream_channel_slot_setup(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl; + int i; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + return; + + for (i = DP_STREAM_0; i < ctrl->num_pixel_clks; i++) { + msm_dp_ctrl_mst_channel_alloc(ctrl, i, ctrl->mst_ch_info[i].start_slot, + ctrl->mst_ch_info[i].tot_slots); + } +} + +irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) { struct msm_dp_ctrl_private *ctrl; u32 isr; @@ -2619,7 +3016,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - if (ctrl->panel->psr_cap.version) { + if (panel->psr_cap.version) { isr = msm_dp_ctrl_get_psr_interrupt(ctrl); if (isr) @@ -2649,6 +3046,13 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl) ret = IRQ_HANDLED; } + isr = msm_dp_ctrl_get_mst_interrupt(ctrl); + if (isr & (DP_INTR_DP0_VCPF_SENT | DP_INTR_DP1_VCPF_SENT)) { + drm_dbg_dp(ctrl->drm_dev, "vcpf sent\n"); + complete(&ctrl->idle_comp); + ret = IRQ_HANDLED; + } + /* DP aux isr */ isr = msm_dp_ctrl_get_aux_interrupt(ctrl); if (isr) @@ -2667,6 +3071,13 @@ static const char *ctrl_clks[] = { "ctrl_link_iface", }; +static const char * const pixel_clks[] = { + "stream_pixel", + "stream_1_pixel", + "stream_2_pixel", + "stream_3_pixel", +}; + static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) { struct msm_dp_ctrl_private *ctrl; @@ -2700,23 +3111,47 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl) if (rc) return rc; - ctrl->pixel_clk = devm_clk_get(dev, "stream_pixel"); - if (IS_ERR(ctrl->pixel_clk)) - return PTR_ERR(ctrl->pixel_clk); + ctrl->num_pixel_clks = 0; + for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { + ctrl->pixel_clk[i] = devm_clk_get(dev, pixel_clks[i]); + + if (i == 0 && IS_ERR(ctrl->pixel_clk[i])) + return PTR_ERR(ctrl->pixel_clk[i]); + + if (IS_ERR(ctrl->pixel_clk[i])) { + if (PTR_ERR(ctrl->pixel_clk[i]) != -ENOENT) + return PTR_ERR(ctrl->pixel_clk[i]); + DRM_DEBUG_DP("stream %d pixel clock not found", i); + break; + } + + ctrl->num_pixel_clks++; + } return 0; } +int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + return ctrl->num_pixel_clks; +} + struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, - struct msm_dp_panel *panel, struct drm_dp_aux *aux, + struct drm_dp_aux *aux, struct phy *phy, void __iomem *ahb_base, - void __iomem *link_base) + void __iomem *link_base, + void __iomem *mst2link_base, + void __iomem *mst3link_base) { struct msm_dp_ctrl_private *ctrl; int ret; - if (!dev || !panel || !aux || !link) { + if (!dev || !aux || !link) { DRM_ERROR("invalid input\n"); return ERR_PTR(-EINVAL); } @@ -2744,13 +3179,15 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link init_completion(&ctrl->video_comp); /* in parameters */ - ctrl->panel = panel; ctrl->aux = aux; ctrl->link = link; ctrl->dev = dev; ctrl->phy = phy; ctrl->ahb_base = ahb_base; ctrl->link_base = link_base; + ctrl->mst2link_base = mst2link_base; + ctrl->mst3link_base = mst3link_base; + ctrl->mst_active = false; ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl); if (ret) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index f68bee62713f1..88a02d52f61c6 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -16,28 +16,41 @@ struct msm_dp_ctrl { struct phy; -int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl); -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train); -void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl); -void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl); +int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, + bool mst_active); +int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, + bool force_link_train); +void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); +void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl, enum msm_dp_stream_id stream_id); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); -irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl); -void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_push_vcpf(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); +irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); +void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, - struct msm_dp_panel *panel, struct drm_dp_aux *aux, struct phy *phy, void __iomem *ahb_base, - void __iomem *link_base); + void __iomem *link_base, + void __iomem *mst2link_base, + void __iomem *mst3link_base); -void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_irq_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl); -void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enable); -void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel, bool enable); +void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); @@ -45,4 +58,12 @@ void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); +int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *dp_ctrl); +int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); +void msm_dp_ctrl_mst_stream_channel_slot_setup(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_set_mst_channel_info(struct msm_dp_ctrl *msm_dp_ctrl, + enum msm_dp_stream_id stream_id, + u32 start_slot, u32 tot_slots); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index dc6f33809ca5f..6f21a60f251d7 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "msm_drv.h" @@ -27,6 +28,7 @@ #include "dp_drm.h" #include "dp_audio.h" #include "dp_debug.h" +#include "dp_mst_drm.h" static bool psr_enabled = false; module_param(psr_enabled, bool, 0); @@ -63,7 +65,6 @@ struct msm_dp_display_private { struct msm_dp_panel *panel; struct msm_dp_ctrl *ctrl; - struct msm_dp_display_mode msm_dp_mode; struct msm_dp msm_dp_display; /* wait for audio signaling */ @@ -86,8 +87,16 @@ struct msm_dp_display_private { void __iomem *link_base; size_t link_len; - void __iomem *p0_base; - size_t p0_len; + void __iomem *mst2link_base; + size_t mst2link_len; + + void __iomem *mst3link_base; + size_t mst3link_len; + + void __iomem *pixel_base[DP_STREAM_MAX]; + size_t pixel_len; + + int max_stream; }; struct msm_dp_desc { @@ -263,12 +272,38 @@ static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd return lttpr_count; } +static void msm_dp_display_mst_init(struct msm_dp_display_private *dp) +{ + u8 old_mstm_ctrl; + struct msm_dp *msm_dp = &dp->msm_dp_display; + int ret; + + /* clear sink MST state */ + drm_dp_dpcd_read_byte(dp->aux, DP_MSTM_CTRL, &old_mstm_ctrl); + + ret = drm_dp_dpcd_write_byte(dp->aux, DP_MSTM_CTRL, 0); + if (ret < 0) { + DRM_ERROR("failed to clear DP_MSTM_CTRL, ret=%d\n", ret); + return; + } + + ret = drm_dp_dpcd_write_byte(dp->aux, DP_MSTM_CTRL, + DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); + if (ret < 0) { + DRM_ERROR("sink MST enablement failed\n"); + return; + } + + msm_dp->mst_active = true; +} + static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) { struct drm_connector *connector = dp->msm_dp_display.connector; const struct drm_display_info *info = &connector->display_info; int rc = 0; u8 dpcd[DP_RECEIVER_CAP_SIZE]; + const struct drm_edid *drm_edid = NULL; rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); if (rc) @@ -276,10 +311,25 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) dp->link->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); - rc = msm_dp_panel_read_sink_caps(dp->panel, connector); + rc = msm_dp_panel_read_link_caps(dp->panel, connector); if (rc) goto end; + if (!(dp->max_stream > 1) || !drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) { + drm_edid = drm_edid_read_ddc(connector, &dp->aux->ddc); + drm_edid_connector_update(connector, drm_edid); + + if (!drm_edid) { + DRM_ERROR("panel edid read failed\n"); + /* check edid read fail is due to unplug */ + if (!msm_dp_aux_is_link_connected(dp->aux)) + return -ETIMEDOUT; + } + + if (rc) + goto end; + } + msm_dp_link_process_request(dp->link); if (!dp->msm_dp_display.is_edp) @@ -291,7 +341,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) dp->msm_dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled; dp->audio_supported = info->has_audio; - msm_dp_panel_handle_sink_request(dp->panel); + msm_dp_panel_handle_sink_request(dp->panel, drm_edid); /* * set sink to normal operation mode -- D0 @@ -299,9 +349,18 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) */ msm_dp_link_psm_config(dp->link, &dp->panel->link_info, false); + if (dp->max_stream > 1 && drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) + msm_dp_display_mst_init(dp); + + if (dp->msm_dp_display.mst_active) { + connector->status = connector_status_disconnected; + msm_dp_mst_display_set_mgr_state(&dp->msm_dp_display, true); + } + msm_dp_link_reset_phy_params_vx_px(dp->link); end: + drm_edid_free(drm_edid); return rc; } @@ -348,7 +407,7 @@ static void msm_dp_display_host_init(struct msm_dp_display_private *dp) dp->phy_initialized); msm_dp_ctrl_core_clk_enable(dp->ctrl); - msm_dp_ctrl_reset(dp->ctrl); + msm_dp_ctrl_reset(dp->ctrl, dp->panel); msm_dp_ctrl_enable_irq(dp->ctrl); msm_dp_aux_init(dp->aux); dp->core_initialized = true; @@ -360,7 +419,7 @@ static void msm_dp_display_host_deinit(struct msm_dp_display_private *dp) dp->msm_dp_display.connector_type, dp->core_initialized, dp->phy_initialized); - msm_dp_ctrl_reset(dp->ctrl); + msm_dp_ctrl_reset(dp->ctrl, dp->panel); msm_dp_ctrl_disable_irq(dp->ctrl); msm_dp_aux_deinit(dp->aux); msm_dp_ctrl_core_clk_disable(dp->ctrl); @@ -381,7 +440,7 @@ static int msm_dp_display_handle_irq_hpd(struct msm_dp_display_private *dp) drm_dbg_dp(dp->drm_dev, "%d\n", sink_request); - msm_dp_ctrl_handle_sink_request(dp->ctrl); + msm_dp_ctrl_handle_sink_request(dp->ctrl, dp->panel); if (sink_request & DP_TEST_LINK_VIDEO_PATTERN) msm_dp_display_handle_video_request(dp); @@ -398,6 +457,9 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp) dp->msm_dp_display.connector_type, dp->link->sink_count); + if (dp->plugged && dp->msm_dp_display.mst_active) + return 0; + guard(mutex)(&dp->plugged_lock); ret = pm_runtime_resume_and_get(&pdev->dev); @@ -453,7 +515,7 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp) /* Don't forget modes for eDP */ if (!dp->msm_dp_display.is_edp) - msm_dp_panel_unplugged(dp->panel, dp->msm_dp_display.connector); + drm_edid_connector_update(dp->msm_dp_display.connector, NULL); /* triggered by irq_hdp with sink_count = 0 */ if (dp->link->sink_count == 0) @@ -469,6 +531,11 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp) dp->panel->dpcd, dp->panel->downstream_ports); + if (dp->msm_dp_display.mst_active) { + msm_dp_mst_display_set_mgr_state(&dp->msm_dp_display, false); + dp->msm_dp_display.mst_active = false; + } + /* signal the disconnect event early to ensure proper teardown */ msm_dp_display_handle_plugged_change(&dp->msm_dp_display, false); @@ -488,12 +555,18 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) { u32 sink_request; int rc = 0; + struct msm_dp *msm_dp_display = &dp->msm_dp_display; /* irq_hpd can happen at either connected or disconnected state */ drm_dbg_dp(dp->drm_dev, "Before, type=%d, sink_count=%d\n", dp->msm_dp_display.connector_type, dp->link->sink_count); + if (msm_dp_display->mst_active) { + msm_dp_mst_display_hpd_irq(&dp->msm_dp_display); + return 0; + } + /* check for any test request issued by sink */ rc = msm_dp_link_process_request(dp->link); if (!rc) { @@ -512,10 +585,45 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) return rc; } +struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, + enum msm_dp_stream_id stream_id) +{ + struct msm_dp_display_private *dp; + struct msm_dp_panel *dp_panel; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + if (stream_id >= DP_STREAM_MAX || stream_id >= dp->max_stream) { + DRM_ERROR("invalid stream_id %d\n", stream_id); + return NULL; + } + + dp_panel = msm_dp_panel_get(&dp->msm_dp_display.pdev->dev, dp->aux, dp->link, + dp->link_base, dp->mst2link_base, dp->mst3link_base, + dp->pixel_base[stream_id]); + + if (IS_ERR(dp_panel)) { + DRM_ERROR("failed to initialize panel\n"); + return NULL; + } + + dp_panel->stream_id = stream_id; + + return dp_panel; +} + +void msm_dp_display_set_link_info(struct msm_dp *msm_dp_display, + struct msm_dp_link_info *dst) +{ + struct msm_dp_display_private *dp = + container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + memcpy(dst, &dp->panel->link_info, sizeof(*dst)); +} + static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) { msm_dp_audio_put(dp->audio); - msm_dp_panel_put(dp->panel); msm_dp_aux_put(dp->aux); } @@ -552,7 +660,8 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) goto error_link; } - dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, dp->p0_base); + dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->link_base, + dp->mst2link_base, dp->mst3link_base, dp->pixel_base[0]); if (IS_ERR(dp->panel)) { rc = PTR_ERR(dp->panel); DRM_ERROR("failed to initialize panel, rc = %d\n", rc); @@ -560,27 +669,27 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) goto error_link; } - dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, - phy, dp->ahb_base, dp->link_base); + dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->aux, + phy, dp->ahb_base, dp->link_base, + dp->mst2link_base, dp->mst3link_base); if (IS_ERR(dp->ctrl)) { rc = PTR_ERR(dp->ctrl); DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); dp->ctrl = NULL; - goto error_ctrl; + goto error_link; } + dp->max_stream = msm_dp_ctrl_get_stream_cnt(dp->ctrl); dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->link_base); if (IS_ERR(dp->audio)) { rc = PTR_ERR(dp->audio); pr_err("failed to initialize audio, rc = %d\n", rc); dp->audio = NULL; - goto error_ctrl; + goto error_link; } return rc; -error_ctrl: - msm_dp_panel_put(dp->panel); error_link: msm_dp_aux_put(dp->aux); error: @@ -588,33 +697,80 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp) } static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, - struct msm_dp_display_mode *mode) + const struct drm_display_mode *adjusted_mode, + struct msm_dp_panel *msm_dp_panel) { struct msm_dp_display_private *dp; + u32 bpp; dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - drm_mode_copy(&dp->panel->msm_dp_mode.drm_mode, &mode->drm_mode); - dp->panel->msm_dp_mode.bpp = mode->bpp; - dp->panel->msm_dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420; - msm_dp_panel_init_panel_info(dp->panel); + if (msm_dp_display_check_video_test(msm_dp_display)) + bpp = msm_dp_display_get_test_bpp(msm_dp_display); + else + bpp = msm_dp_panel->connector->display_info.bpc * 3; + + msm_dp_panel_init_panel_info(msm_dp_panel, adjusted_mode, bpp ? bpp : 24); + + /* populate wide_bus_support to different layers */ + dp->ctrl->wide_bus_en = + msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 ? false : dp->wide_bus_supported; return 0; } -static int msm_dp_display_enable(struct msm_dp_display_private *dp, bool force_link_train) +int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) { + struct msm_dp_display_private *dp; int rc = 0; - struct msm_dp *msm_dp_display = &dp->msm_dp_display; + bool force_link_train = false; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); - if (msm_dp_display->power_on) { - drm_dbg_dp(dp->drm_dev, "Link already setup, return\n"); + + if (msm_dp_display->is_edp) + msm_dp_hpd_plug_handle(dp); + + if (msm_dp_display->link_ready) return 0; + + rc = pm_runtime_resume_and_get(&msm_dp_display->pdev->dev); + if (rc) { + DRM_ERROR("failed to pm_runtime_resume\n"); + return rc; } - rc = msm_dp_ctrl_on_stream(dp->ctrl, force_link_train); + if (dp->link->sink_count == 0) + return rc; + + if (!msm_dp_display->active_stream_cnt) { + msm_dp_display_host_phy_init(dp); + force_link_train = true; + + rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); + if (rc) + DRM_ERROR("Failed link training (rc=%d)\n", rc); + // TODO: schedule drm_connector_set_link_status_property() + } + + rc = msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); if (!rc) - msm_dp_display->power_on = true; + msm_dp_display->link_ready = true; + + return rc; +} + +static int msm_dp_display_enable(struct msm_dp_display_private *dp, + struct msm_dp_panel *msm_dp_panel) +{ + int rc = 0; + struct msm_dp *msm_dp_display = &dp->msm_dp_display; + + drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); + + rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel, msm_dp_display->mst_active); + + msm_dp_display->active_stream_cnt++; return rc; } @@ -637,18 +793,15 @@ static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display) msm_dp_display_handle_plugged_change(msm_dp_display, true); if (msm_dp_display->psr_supported) - msm_dp_ctrl_config_psr(dp->ctrl); + msm_dp_ctrl_config_psr(dp->ctrl, dp->panel); return 0; } -static int msm_dp_display_disable(struct msm_dp_display_private *dp) +static void msm_dp_display_audio_notify_disable(struct msm_dp_display_private *dp) { struct msm_dp *msm_dp_display = &dp->msm_dp_display; - if (!msm_dp_display->power_on) - return 0; - /* wait only if audio was enabled */ if (msm_dp_display->audio_enabled) { /* signal the disconnect event */ @@ -659,48 +812,57 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) } msm_dp_display->audio_enabled = false; +} - if (dp->link->sink_count == 0) { - /* - * irq_hpd with sink_count = 0 - * hdmi unplugged out of dongle - */ - msm_dp_ctrl_off_link_stream(dp->ctrl); - } else { - /* - * unplugged interrupt - * dongle unplugged out of DUT - */ - msm_dp_ctrl_off(dp->ctrl); - msm_dp_display_host_phy_exit(dp); - } +static int msm_dp_display_disable(struct msm_dp_display_private *dp, + struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp *msm_dp_display = &dp->msm_dp_display; - msm_dp_display->power_on = false; + if (!msm_dp_display->active_stream_cnt) + return 0; + + msm_dp_panel_disable_vsc_sdp(msm_dp_panel); + + msm_dp_ctrl_off_pixel_clk(dp->ctrl, msm_dp_panel->stream_id); + + msm_dp_display->active_stream_cnt--; drm_dbg_dp(dp->drm_dev, "sink count: %d\n", dp->link->sink_count); return 0; } +int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, + u32 start_slot, u32 num_slots, u32 pbn) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_ctrl_set_mst_channel_info(dp->ctrl, panel->stream_id, start_slot, num_slots); + + panel->pbn = pbn; + + return 0; +} + /** * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid - * @bridge: Pointer to drm bridge structure + * @dp: Pointer to dp display structure * @info: display info * @mode: Pointer to drm mode structure * Returns: Validity status for specified mode */ -enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode) +enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, + const struct drm_display_info *info, + const struct drm_display_mode *mode) { const u32 num_components = 3, default_bpp = 24; struct msm_dp_display_private *msm_dp_display; struct msm_dp_link_info *link_info; u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; - struct msm_dp *dp; int mode_pclk_khz = mode->clock; - dp = to_dp_bridge(bridge)->msm_dp_display; - if (!dp || !mode_pclk_khz || !dp->connector) { DRM_ERROR("invalid params\n"); return -EINVAL; @@ -744,8 +906,7 @@ int msm_dp_display_get_modes(struct msm_dp *dp) msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - return msm_dp_panel_get_modes(msm_dp_display->panel, - dp->connector); + return drm_edid_connector_add_modes(msm_dp_display->panel->connector); } bool msm_dp_display_check_video_test(struct msm_dp *dp) @@ -782,10 +943,10 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) * if we are reading registers we need the link clocks to be on * however till DP cable is connected this will not happen as we * do not know the resolution to power up with. Hence check the - * power_on status before dumping DP registers to avoid crash due + * active_stream_cnt status before dumping DP registers to avoid crash due * to unclocked access */ - if (!dp->power_on) + if (!dp->active_stream_cnt) return; msm_disp_snapshot_add_block(disp_state, msm_dp_display->ahb_len, @@ -794,8 +955,18 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) msm_dp_display->aux_base, "dp_aux"); msm_disp_snapshot_add_block(disp_state, msm_dp_display->link_len, msm_dp_display->link_base, "dp_link"); - msm_disp_snapshot_add_block(disp_state, msm_dp_display->p0_len, - msm_dp_display->p0_base, "dp_p0"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->mst2link_len, + msm_dp_display->mst2link_base, "dp_mst2link"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->mst3link_len, + msm_dp_display->mst3link_base, "dp_mst3link"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[0], "dp_p0"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[1], "dp_p1"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[2], "dp_p2"); + msm_disp_snapshot_add_block(disp_state, msm_dp_display->pixel_len, + msm_dp_display->pixel_base[3], "dp_p3"); } void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter) @@ -808,7 +979,7 @@ void msm_dp_display_set_psr(struct msm_dp *msm_dp_display, bool enter) } dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - msm_dp_ctrl_set_psr(dp->ctrl, enter); + msm_dp_ctrl_set_psr(dp->ctrl, dp->panel, enter); } /** @@ -836,6 +1007,9 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, priv = container_of(dp, struct msm_dp_display_private, msm_dp_display); + if (dp->mst_active) + return status; + guard(mutex)(&priv->plugged_lock); ret = pm_runtime_resume_and_get(&dp->pdev->dev); if (ret) { @@ -881,6 +1055,10 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, status = connector_status_disconnected; } + /* skip for MST */ + if (priv->max_stream > 1 && drm_dp_read_mst_cap(priv->aux, dpcd)) + status = connector_status_disconnected; + end: /* * If we detected the DPRX, leave the controller on so that it doesn't @@ -918,7 +1096,7 @@ static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id) } /* DP controller isr */ - ret |= msm_dp_ctrl_isr(dp->ctrl); + ret |= msm_dp_ctrl_isr(dp->ctrl, dp->panel); return ret; } @@ -943,10 +1121,10 @@ static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id) drm_bridge_hpd_notify(dp->msm_dp_display.bridge, connector_status_connected); - /* Send HPD as connected and distinguish it in the notifier */ if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) - drm_bridge_hpd_notify(dp->msm_dp_display.bridge, - connector_status_connected); + drm_bridge_hpd_notify_extra(dp->msm_dp_display.bridge, + connector_status_unknown, + DRM_CONNECTOR_DP_IRQ_HPD); ret = IRQ_HANDLED; @@ -1075,6 +1253,7 @@ static void __iomem *msm_dp_ioremap(struct platform_device *pdev, int idx, size_ static int msm_dp_display_get_io(struct msm_dp_display_private *display) { struct platform_device *pdev = display->msm_dp_display.pdev; + int i; display->ahb_base = msm_dp_ioremap(pdev, 0, &display->ahb_len); if (IS_ERR(display->ahb_base)) @@ -1104,8 +1283,8 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display) display->aux_len = DP_DEFAULT_AUX_SIZE; display->link_base = display->ahb_base + DP_DEFAULT_LINK_OFFSET; display->link_len = DP_DEFAULT_LINK_SIZE; - display->p0_base = display->ahb_base + DP_DEFAULT_P0_OFFSET; - display->p0_len = DP_DEFAULT_P0_SIZE; + display->pixel_base[0] = display->ahb_base + DP_DEFAULT_P0_OFFSET; + display->pixel_len = DP_DEFAULT_P0_SIZE; return 0; } @@ -1116,15 +1295,43 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display) return PTR_ERR(display->link_base); } - display->p0_base = msm_dp_ioremap(pdev, 3, &display->p0_len); - if (IS_ERR(display->p0_base)) { - DRM_ERROR("unable to remap p0 region: %pe\n", display->p0_base); - return PTR_ERR(display->p0_base); + display->pixel_base[0] = msm_dp_ioremap(pdev, 3, &display->pixel_len); + if (IS_ERR(display->pixel_base[0])) { + DRM_ERROR("unable to remap p0 region: %pe\n", display->pixel_base[0]); + return PTR_ERR(display->pixel_base[0]); + } + + for (i = DP_STREAM_1; i < DP_STREAM_MAX; i++) { + /* pixels clk reg index start from 3*/ + display->pixel_base[i] = msm_dp_ioremap(pdev, i + 3, &display->pixel_len); + if (IS_ERR(display->pixel_base[i])) { + DRM_DEBUG_DP("unable to remap p%d region: %pe\n", i, + display->pixel_base[i]); + display->pixel_base[i] = NULL; + break; + } } + display->mst2link_base = msm_dp_ioremap(pdev, 7, &display->mst2link_len); + if (IS_ERR(display->mst2link_base)) + DRM_DEBUG_DP("unable to remap link region: %pe\n", display->mst2link_base); + + display->mst3link_base = msm_dp_ioremap(pdev, 8, &display->mst3link_len); + if (IS_ERR(display->mst3link_base)) + DRM_DEBUG_DP("unable to remap link region: %pe\n", display->mst3link_base); + return 0; } +int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + return dp->max_stream; +} + static int msm_dp_display_probe(struct platform_device *pdev) { int rc = 0; @@ -1301,7 +1508,7 @@ bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display) dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - if (dp->msm_dp_mode.out_fmt_is_yuv_420) + if (dp->panel->msm_dp_mode.out_fmt_is_yuv_420) return false; return dp->wide_bus_supported; @@ -1352,129 +1559,168 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, return 0; } -void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state) +int msm_dp_mst_register(struct msm_dp *msm_dp_display) { - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; - int rc = 0; - struct msm_dp_display_private *msm_dp_display; - bool force_link_train = false; + struct msm_dp_display_private *dp; - msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - if (!msm_dp_display->msm_dp_mode.drm_mode.clock) { - DRM_ERROR("invalid params\n"); - return; - } + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - if (dp->is_edp) - msm_dp_hpd_plug_handle(msm_dp_display); + return msm_dp_mst_init(msm_dp_display, dp->max_stream, dp->aux); +} - if (pm_runtime_resume_and_get(&dp->pdev->dev)) { - DRM_ERROR("failed to pm_runtime_resume\n"); - return; - } +int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state, + struct drm_encoder *drm_encoder, + struct msm_dp_panel *msm_dp_panel) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; - if (msm_dp_display->link->sink_count == 0) - return; + crtc = drm_atomic_get_new_crtc_for_encoder(state, drm_encoder); + if (!crtc) + return 0; + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + return msm_dp_display_set_mode(msm_dp_display, &crtc_state->adjusted_mode, msm_dp_panel); +} - rc = msm_dp_display_set_mode(dp, &msm_dp_display->msm_dp_mode); +void msm_dp_display_atomic_prepare(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state) +{ + int rc = 0; + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + rc = msm_dp_display_set_mode_helper(msm_dp_display, state, + msm_dp_display->bridge->encoder, dp->panel); if (rc) { DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); return; } - if (!dp->power_on) { - msm_dp_display_host_phy_init(msm_dp_display); - force_link_train = true; - } + rc = msm_dp_display_prepare_link(msm_dp_display); + if (rc) + DRM_ERROR("DP display prepare failed, rc=%d\n", rc); +} - rc = msm_dp_ctrl_on_link(msm_dp_display->ctrl); - if (rc) { - DRM_ERROR("Failed link training (rc=%d)\n", rc); - // TODO: schedule drm_connector_set_link_status_property() - return; +void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_display_private *dp; + int rc = 0; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + if (msm_dp_display->link_ready) { + rc = msm_dp_display_enable(dp, msm_dp_panel); + if (rc) + DRM_ERROR("DP display enable failed, rc=%d\n", rc); + + rc = msm_dp_display_post_enable(msm_dp_display); + if (rc) { + DRM_ERROR("DP display post enable failed, rc=%d\n", rc); + msm_dp_display_disable(dp, msm_dp_panel); + } } - msm_dp_display_enable(msm_dp_display, force_link_train); + drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); +} - rc = msm_dp_display_post_enable(dp); - if (rc) { - DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - msm_dp_display_disable(msm_dp_display); +void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_display_set_stream_info(msm_dp_display, dp->panel, 0, 0, 0); + + msm_dp_display_enable_helper(msm_dp_display, dp->panel); +} + +void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + if (!msm_dp_display->active_stream_cnt) { + drm_dbg_dp(dp->drm_dev, "no active streams\n"); + return; } - drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); + msm_dp_ctrl_push_vcpf(dp->ctrl, msm_dp_panel); + msm_dp_ctrl_mst_stream_channel_slot_setup(dp->ctrl); + msm_dp_ctrl_mst_send_act(dp->ctrl, msm_dp_panel); } -void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state) +void msm_dp_display_atomic_disable(struct msm_dp *dp) { - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; struct msm_dp_display_private *msm_dp_display; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - msm_dp_ctrl_push_idle(msm_dp_display->ctrl); + msm_dp_display_disable_helper(dp, msm_dp_display->panel); } -void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state) +void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) { - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; - struct msm_dp_display_private *msm_dp_display; + struct msm_dp_display_private *dp; - msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - if (dp->is_edp) - msm_dp_hpd_unplug_handle(msm_dp_display); + if (!msm_dp_display->link_ready) { + drm_dbg_dp(dp->drm_dev, "Link already setup, return\n"); + return; + } + + if (msm_dp_display->active_stream_cnt) { + drm_dbg_dp(dp->drm_dev, "stream still active, return\n"); + return; + } + + /* dongle is still connected but sinks are disconnected */ + if (dp->link->sink_count == 0) + msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); - msm_dp_display_disable(msm_dp_display); + msm_dp_ctrl_off_link(dp->ctrl, dp->panel); - drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); + if (dp->link->sink_count == 0) + /* re-init the PHY so that we can listen to Dongle disconnect */ + msm_dp_ctrl_reinit_phy(dp->ctrl); + else + msm_dp_display_host_phy_exit(dp); - pm_runtime_put_sync(&dp->pdev->dev); + pm_runtime_put_sync(&msm_dp_display->pdev->dev); + + msm_dp_display->link_ready = false; } -void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode) +void msm_dp_display_atomic_post_disable_helper(struct msm_dp *dp, struct msm_dp_panel *msm_dp_panel) { - struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); - struct msm_dp *dp = msm_dp_bridge->msm_dp_display; struct msm_dp_display_private *msm_dp_display; - struct msm_dp_panel *msm_dp_panel; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - msm_dp_panel = msm_dp_display->panel; - memset(&msm_dp_display->msm_dp_mode, 0x0, sizeof(struct msm_dp_display_mode)); + if (dp->is_edp) + msm_dp_hpd_unplug_handle(msm_dp_display); - if (msm_dp_display_check_video_test(dp)) - msm_dp_display->msm_dp_mode.bpp = msm_dp_display_get_test_bpp(dp); - else /* Default num_components per pixel = 3 */ - msm_dp_display->msm_dp_mode.bpp = dp->connector->display_info.bpc * 3; + msm_dp_display_audio_notify_disable(msm_dp_display); - if (!msm_dp_display->msm_dp_mode.bpp) - msm_dp_display->msm_dp_mode.bpp = 24; /* Default bpp */ + msm_dp_display_disable(msm_dp_display, msm_dp_panel); - drm_mode_copy(&msm_dp_display->msm_dp_mode.drm_mode, adjusted_mode); + drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); +} - msm_dp_display->msm_dp_mode.v_active_low = - !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NVSYNC); +void msm_dp_display_atomic_post_disable(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; - msm_dp_display->msm_dp_mode.h_active_low = - !!(msm_dp_display->msm_dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC); + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 = - drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) && - msm_dp_panel->vsc_sdp_supported; + msm_dp_display_atomic_post_disable_helper(msm_dp_display, dp->panel); - /* populate wide_bus_support to different layers */ - msm_dp_display->ctrl->wide_bus_en = - msm_dp_display->msm_dp_mode.out_fmt_is_yuv_420 ? false : msm_dp_display->wide_bus_supported; + msm_dp_display_unprepare(msm_dp_display); } void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge) @@ -1514,7 +1760,9 @@ void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge) void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge); struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display; @@ -1531,17 +1779,26 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, drm_dbg_dp(dp->drm_dev, "type=%d link hpd_link_status=0x%x, status=%d\n", msm_dp_display->connector_type, hpd_link_status, status); - if (status == connector_status_connected) { + if (extra_status == DRM_CONNECTOR_DP_IRQ_HPD || + hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT) { + msm_dp_irq_hpd_handle(dp); + } else if (status == connector_status_connected) { if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { msm_dp_hpd_unplug_handle(dp); msm_dp_hpd_plug_handle(dp); - } else if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT) { - msm_dp_irq_hpd_handle(dp); } else { msm_dp_hpd_plug_handle(dp); + /* mst_active is set in plug_handle; suppress SST hotplug */ + if (send_hotplug && msm_dp_display->mst_active) + *send_hotplug = false; } } else { - msm_dp_hpd_unplug_handle(dp); + if (!msm_dp_display->mst_active) { + msm_dp_hpd_unplug_handle(dp); + } else if (send_hotplug) { + msm_dp_hpd_unplug_handle(dp); + *send_hotplug = false; + } } pm_runtime_put_sync(&msm_dp_display->pdev->dev); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 0b65e16c790da..fb6bdd372b52f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -18,14 +18,19 @@ struct msm_dp { struct drm_bridge *next_bridge; struct drm_bridge *bridge; bool audio_enabled; - bool power_on; + u32 active_stream_cnt; + bool mst_active; unsigned int connector_type; bool is_edp; + bool link_ready; + + void *msm_dp_mst; struct msm_dp_audio *msm_dp_audio; bool psr_supported; }; +int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display); int msm_dp_display_get_modes(struct msm_dp *msm_dp_display); bool msm_dp_display_check_video_test(struct msm_dp *msm_dp_display); int msm_dp_display_get_test_bpp(struct msm_dp *msm_dp_display); @@ -33,5 +38,31 @@ void msm_dp_display_signal_audio_start(struct msm_dp *msm_dp_display); void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display); void msm_dp_display_set_psr(struct msm_dp *dp, bool enter); void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *dentry, bool is_edp); +void msm_dp_display_atomic_post_disable(struct msm_dp *dp_display); +void msm_dp_display_atomic_disable(struct msm_dp *dp_display); +void msm_dp_display_atomic_prepare(struct msm_dp *dp_display, + struct drm_atomic_commit *state); +void msm_dp_display_atomic_enable(struct msm_dp *dp_display); +enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, + const struct drm_display_info *info, + const struct drm_display_mode *mode); +int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, + u32 start_slot, u32 num_slots, u32 pbn); +void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +void msm_dp_display_atomic_post_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state, + struct drm_encoder *drm_encoder, + struct msm_dp_panel *msm_dp_panel); +int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display); +void msm_dp_display_unprepare(struct msm_dp *dp); +struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, + enum msm_dp_stream_id stream_id); +void msm_dp_display_set_link_info(struct msm_dp *msm_dp_display, + struct msm_dp_link_info *dst); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index b659d22f5f284..4bf1a5b7c3f97 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -49,6 +49,44 @@ static void msm_dp_bridge_debugfs_init(struct drm_bridge *bridge, struct dentry msm_dp_display_debugfs_init(dp, root, false); } +static void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, + struct drm_atomic_commit *state) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + msm_dp_display_atomic_prepare(dp, state); + msm_dp_display_atomic_enable(dp); +} + +static void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, + struct drm_atomic_commit *state) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + msm_dp_display_atomic_disable(dp); +} + +static void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, + struct drm_atomic_commit *state) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + msm_dp_display_atomic_post_disable(dp); +} + +static enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *drm_bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge); + struct msm_dp *dp = dp_bridge->msm_dp_display; + + return msm_dp_display_mode_valid(dp, info, mode); +} + static const struct drm_bridge_funcs msm_dp_bridge_ops = { .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, @@ -56,7 +94,6 @@ static const struct drm_bridge_funcs msm_dp_bridge_ops = { .atomic_enable = msm_dp_bridge_atomic_enable, .atomic_disable = msm_dp_bridge_atomic_disable, .atomic_post_disable = msm_dp_bridge_atomic_post_disable, - .mode_set = msm_dp_bridge_mode_set, .mode_valid = msm_dp_bridge_mode_valid, .get_modes = msm_dp_bridge_get_modes, .detect = msm_dp_bridge_detect, @@ -116,7 +153,8 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; } - msm_dp_bridge_atomic_enable(drm_bridge, state); + msm_dp_display_atomic_prepare(dp, state); + msm_dp_display_atomic_enable(dp); } static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, @@ -233,7 +271,6 @@ static const struct drm_bridge_funcs msm_edp_bridge_ops = { .atomic_enable = msm_edp_bridge_atomic_enable, .atomic_disable = msm_edp_bridge_atomic_disable, .atomic_post_disable = msm_edp_bridge_atomic_post_disable, - .mode_set = msm_dp_bridge_mode_set, .mode_valid = msm_edp_bridge_mode_valid, .atomic_reset = drm_atomic_helper_bridge_reset, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 041aa026ae2ee..07ddcd0559626 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -27,22 +27,12 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector); -void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state); -void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state); -void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_atomic_commit *state); -enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode); -void msm_dp_bridge_mode_set(struct drm_bridge *drm_bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode); void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status, + bool *send_hotplug); #endif /* _DP_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c new file mode 100644 index 0000000000000..56f7a84e77d15 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "dp_mst_drm.h" +#include "dp_panel.h" +#include "dpu_encoder.h" + +#define to_dp_mst_connector(x) \ + container_of((x), struct msm_dp_mst_connector, connector) + +struct msm_dp_mst_encoder { + struct drm_encoder *enc; + int stream_id; + struct msm_dp_panel *dp_panel; +}; + +struct msm_dp_mst_connector { + struct drm_connector connector; + struct drm_dp_mst_port *mst_port; + struct msm_dp_mst *dp_mst; +}; + + +struct msm_dp_mst { + struct drm_dp_mst_topology_mgr mst_mgr; + struct msm_dp_mst_encoder mst_encoders[DP_STREAM_MAX]; + struct msm_dp *msm_dp; + struct drm_dp_aux *dp_aux; + u32 max_streams; + struct mutex mst_lock; + /* Serializes HPD IRQ handling between IRQ handler and poll_hpd_irq. */ + struct mutex hpd_irq_lock; + struct msm_dp_link_info link_info; +}; + +static struct msm_dp_panel *msm_dp_mst_panel_from_encoder(struct msm_dp_mst *mst, + struct drm_encoder *enc) +{ + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (mst->mst_encoders[i].enc == enc) + return mst->mst_encoders[i].dp_panel; + } + return NULL; +} + +static int msm_dp_mst_encoder_stream_id(struct msm_dp_mst *mst, + struct drm_encoder *enc) +{ + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (mst->mst_encoders[i].enc == enc) + return mst->mst_encoders[i].stream_id; + } + return -1; +} + +static void msm_dp_mst_update_timeslots(struct msm_dp_mst *mst, + struct msm_dp_panel *panel, + struct drm_dp_mst_atomic_payload *payload) +{ + if (payload->vc_start_slot < 0) + msm_dp_display_set_stream_info(mst->msm_dp, panel, 1, 0, 0); + else + msm_dp_display_set_stream_info(mst->msm_dp, panel, + payload->vc_start_slot, + payload->time_slots, payload->pbn); + + drm_dbg_kms(mst->msm_dp->drm_dev, + "[MST] stream:%u timeslots vc_start:%d slots:%d pbn:%d\n", + panel->stream_id, payload->vc_start_slot, + payload->time_slots, payload->pbn); +} + +static void msm_dp_mst_stream_enable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = + drm_atomic_get_new_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp *dp_display = mst->msm_dp; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + struct drm_dp_mst_port *port = mst_conn->mst_port; + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_new_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_atomic_payload *payload = + drm_atomic_get_mst_payload_state(mst_state, port); + int rc; + + panel->connector = connector; + + guard(mutex)(&mst->mst_lock); + + rc = msm_dp_display_set_mode_helper(dp_display, state, encoder, panel); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] stream:%u set_mode failed rc=%d\n", panel->stream_id, rc); + goto out; + } + + rc = msm_dp_display_prepare_link(dp_display); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] stream:%u prepare_link failed rc=%d\n", panel->stream_id, rc); + msm_dp_display_unprepare(dp_display); + goto out; + } + + drm_dp_mst_update_slots(mst_state, DP_CAP_ANSI_8B10B); + + rc = drm_dp_add_payload_part1(&mst->mst_mgr, mst_state, payload); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] payload allocation failure for conn:%d\n", connector->base.id); + msm_dp_display_unprepare(dp_display); + goto out; + } + + msm_dp_mst_update_timeslots(mst, panel, payload); + + msm_dp_display_enable_helper(dp_display, panel); + + drm_dp_check_act_status(&mst->mst_mgr); + + drm_dp_add_payload_part2(&mst->mst_mgr, payload); + +out: + drm_connector_get(connector); +} + +static void msm_dp_mst_stream_disable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + struct drm_dp_mst_topology_state *old_mst_state = + drm_atomic_get_old_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_topology_state *new_mst_state = + drm_atomic_get_new_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_atomic_payload *old_payload = + drm_atomic_get_mst_payload_state(old_mst_state, mst_conn->mst_port); + struct drm_dp_mst_atomic_payload *new_payload = + drm_atomic_get_mst_payload_state(new_mst_state, mst_conn->mst_port); + + guard(mutex)(&mst->mst_lock); + + drm_dp_remove_payload_part1(&mst->mst_mgr, new_mst_state, new_payload); + + drm_dp_remove_payload_part2(&mst->mst_mgr, new_mst_state, old_payload, new_payload); + + msm_dp_mst_update_timeslots(mst, panel, new_payload); + + msm_dp_display_disable_helper(mst->msm_dp, panel); + + drm_dp_check_act_status(&mst->mst_mgr); +} + +static void msm_dp_mst_stream_post_disable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + + guard(mutex)(&mst->mst_lock); + + msm_dp_display_atomic_post_disable_helper(mst->msm_dp, panel); + + if (!mst->msm_dp->mst_active) + msm_dp_display_unprepare(mst->msm_dp); + + panel->connector = NULL; + + drm_connector_put(connector); +} + +static int msm_dp_mst_enc_atomic_check(struct drm_encoder *enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(conn_state->connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct drm_dp_mst_topology_state *mst_state; + int bpp, pbn, slots; + + if (!conn_state->crtc) + return 0; + + if (!drm_atomic_crtc_needs_modeset(crtc_state) || !crtc_state->active) + return 0; + + bpp = (conn_state->connector->display_info.bpc * 3) ?: 24; /* fallback: assume 8bpc */ + pbn = drm_dp_calc_pbn_mode(crtc_state->mode.clock, bpp << 4); + + mst_state = drm_atomic_get_mst_topology_state(crtc_state->state, &mst->mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + if (!dfixed_trunc(mst_state->pbn_div)) { + mst_state->pbn_div = + drm_dp_get_vc_payload_bw(mst->link_info.rate, + mst->link_info.num_lanes); + } + + slots = drm_dp_atomic_find_time_slots(crtc_state->state, &mst->mst_mgr, + mst_conn->mst_port, pbn); + if (slots < 0) + return slots; + + return 0; +} + +static void msm_dp_mst_enc_atomic_enable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + msm_dp_mst_stream_enable(enc, state); + dpu_encoder_phys_enable(enc, state); +} + +static void msm_dp_mst_enc_atomic_disable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + msm_dp_mst_stream_disable(enc, state); + dpu_encoder_phys_disable(enc, state); + msm_dp_mst_stream_post_disable(enc, state); +} + +static const struct drm_encoder_helper_funcs msm_dp_mst_encoder_helper_funcs = { + .atomic_check = msm_dp_mst_enc_atomic_check, + .atomic_mode_set = dpu_encoder_atomic_mode_set, + .atomic_enable = msm_dp_mst_enc_atomic_enable, + .atomic_disable = msm_dp_mst_enc_atomic_disable, +}; + +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, struct drm_encoder *encoder) +{ + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + struct msm_dp_panel *dp_panel; + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (!mst->mst_encoders[i].enc) + break; + } + + dp_panel = msm_dp_display_get_panel(dp_display, i); + if (!dp_panel) { + drm_err(dp_display->drm_dev, + "[MST] failed to allocate panel for stream %d\n", i); + return -ENOMEM; + } + + mst->mst_encoders[i].enc = encoder; + mst->mst_encoders[i].stream_id = i; + mst->mst_encoders[i].dp_panel = dp_panel; + drm_encoder_helper_add(encoder, &msm_dp_mst_encoder_helper_funcs); + + return 0; +} + +int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state) +{ + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + int rc; + + rc = drm_dp_mst_topology_mgr_set_mst(&mst->mst_mgr, state); + if (rc < 0) { + drm_err(dp_display->drm_dev, + "[MST] failed to set topology mgr state to %d rc:%d\n", state, rc); + } + + if (state) + msm_dp_display_set_link_info(dp_display, &mst->link_info); + + drm_dbg_kms(dp_display->drm_dev, "[MST] set_mgr_state state:%d\n", state); + return rc; +} + +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display) +{ + int rc; + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + u8 ack[8] = {}; + u8 esi[4]; + unsigned int esi_res = DP_SINK_COUNT_ESI + 1; + bool handled; + + guard(mutex)(&mst->hpd_irq_lock); + + rc = drm_dp_dpcd_read_data(mst->dp_aux, DP_SINK_COUNT_ESI, esi, 4); + if (rc < 0) { + DRM_ERROR("DPCD sink status read failed, rlen=%d\n", rc); + return; + } + + drm_dbg_dp(dp_display->drm_dev, "MST irq: esi1[0x%x] esi2[0x%x] esi3[%x]\n", + esi[1], esi[2], esi[3]); + + rc = drm_dp_mst_hpd_irq_handle_event(&mst->mst_mgr, esi, ack, &handled); + + /* ack the request */ + if (handled) { + rc = drm_dp_dpcd_write_byte(mst->dp_aux, esi_res, ack[1]); + if (rc < 0) { + DRM_ERROR("DPCD esi_res failed. rc=%d\n", rc); + return; + } + + drm_dp_mst_hpd_irq_send_new_request(&mst->mst_mgr); + } + drm_dbg_dp(dp_display->drm_dev, "MST display hpd_irq handled:%d rc:%d\n", handled, rc); +} + +/* DP MST Connector OPs */ +static int +msm_dp_mst_connector_detect(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp *dp_display = mst->msm_dp; + struct device *dev = dp_display->drm_dev->dev; + enum drm_connector_status status = connector_status_disconnected; + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return status; + + if (dp_display->mst_active) + status = drm_dp_mst_detect_port(connector, + ctx, &mst->mst_mgr, mst_conn->mst_port); + + pm_runtime_put_autosuspend(dev); + + return status; +} + +static int msm_dp_mst_connector_get_modes(struct drm_connector *connector) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + const struct drm_edid *drm_edid; + int rc; + + drm_edid = drm_dp_mst_edid_read(connector, &mst->mst_mgr, mst_conn->mst_port); + drm_edid_connector_update(connector, drm_edid); + + rc = drm_edid_connector_add_modes(connector); + + drm_edid_free(drm_edid); + + return rc; +} + +static enum drm_mode_status msm_dp_mst_connector_mode_valid(struct drm_connector *connector, + const struct drm_display_mode *mode) +{ + struct msm_dp_mst_connector *mst_conn; + struct drm_dp_mst_port *mst_port; + struct msm_dp *dp_display; + int required_pbn; + + if (drm_connector_is_unregistered(connector)) + return 0; + + mst_conn = to_dp_mst_connector(connector); + mst_port = mst_conn->mst_port; + dp_display = mst_conn->dp_mst->msm_dp; + + /* FIXME: use negotiated bpp (DSC, YUV 4:2:0, etc.); for now use + * 18bpp (6bpc) as a conservative lower bound like i915/nouveau. + */ + required_pbn = drm_dp_calc_pbn_mode(mode->clock, (6 * 3) << 4); + + if (required_pbn > mst_port->full_pbn) { + drm_dbg_dp(dp_display->drm_dev, "mode:%s not supported.\n", mode->name); + return MODE_CLOCK_HIGH; + } + + return msm_dp_display_mode_valid(dp_display, &connector->display_info, mode); +} + +static const struct drm_connector_funcs msm_dp_drm_mst_connector_funcs; + +static struct drm_encoder * +msm_dp_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_atomic_commit *state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct drm_connector_state *conn_state; + struct drm_connector *iter; + struct drm_connector_list_iter conn_iter; + u32 stream_mask = 0; + u32 i; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return NULL; + + if (conn_state->best_encoder) + return conn_state->best_encoder; + + drm_connector_list_iter_begin(connector->dev, &conn_iter); + drm_for_each_connector_iter(iter, &conn_iter) { + struct drm_connector_state *peer_state; + int stream_id; + + if (iter == connector || + iter->funcs != &msm_dp_drm_mst_connector_funcs || + to_dp_mst_connector(iter)->dp_mst != mst) + continue; + + peer_state = drm_atomic_get_new_connector_state(state, iter) ?: iter->state; + if (!peer_state || !peer_state->crtc || !peer_state->best_encoder) + continue; + + stream_id = msm_dp_mst_encoder_stream_id(mst, peer_state->best_encoder); + if (stream_id >= 0 && stream_id < mst->max_streams) + stream_mask |= BIT(stream_id); + } + drm_connector_list_iter_end(&conn_iter); + + for (i = 0; i < mst->max_streams; i++) { + if (!(stream_mask & BIT(i))) { + conn_state->best_encoder = mst->mst_encoders[i].enc; + return mst->mst_encoders[i].enc; + } + } + + return NULL; +} + +static int msm_dp_mst_connector_atomic_check(struct drm_connector *connector, + struct drm_atomic_commit *state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + + return drm_dp_atomic_release_time_slots(state, &mst->mst_mgr, mst_conn->mst_port); +} + +static void dp_mst_connector_destroy(struct drm_connector *connector) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + + drm_connector_cleanup(connector); + drm_dp_mst_put_port_malloc(mst_conn->mst_port); + kfree(mst_conn); +} + +/* DRM MST callbacks */ +static const struct drm_connector_helper_funcs msm_dp_drm_mst_connector_helper_funcs = { + .get_modes = msm_dp_mst_connector_get_modes, + .detect_ctx = msm_dp_mst_connector_detect, + .mode_valid = msm_dp_mst_connector_mode_valid, + .atomic_best_encoder = msm_dp_mst_atomic_best_encoder, + .atomic_check = msm_dp_mst_connector_atomic_check, +}; + +static const struct drm_connector_funcs msm_dp_drm_mst_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .destroy = dp_mst_connector_destroy, + .fill_modes = drm_helper_probe_single_connector_modes, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static struct drm_connector * +msm_dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, const char *pathprop) +{ + struct msm_dp_mst *mst = container_of(mgr, struct msm_dp_mst, mst_mgr); + struct drm_device *dev = mst->msm_dp->drm_dev; + struct msm_dp_mst_connector *mst_conn; + struct drm_connector *connector; + int rc, i; + + mst_conn = kzalloc_obj(*mst_conn); + if (!mst_conn) + return NULL; + + connector = &mst_conn->connector; + rc = drm_connector_dynamic_init(dev, connector, + &msm_dp_drm_mst_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort, NULL); + if (rc) + goto err_free; + + mst_conn->dp_mst = mst; + + drm_connector_helper_add(connector, &msm_dp_drm_mst_connector_helper_funcs); + connector->funcs->reset(connector); + + /* add all encoders as possible encoders */ + for (i = 0; i < mst->max_streams; i++) { + rc = drm_connector_attach_encoder(connector, mst->mst_encoders[i].enc); + if (rc) { + drm_err(dev, "[MST] failed to attach encoder:%u to conn:%d rc:%d\n", + mst->mst_encoders[i].enc->base.id, + connector->base.id, rc); + goto err_connector; + } + } + + mst_conn->mst_port = port; + drm_dp_mst_get_port_malloc(port); + + drm_object_attach_property(&connector->base, + dev->mode_config.path_property, 0); + drm_object_attach_property(&connector->base, + dev->mode_config.tile_property, 0); + drm_connector_set_path_property(connector, pathprop); + + drm_dbg_kms(dev, "[MST] add_connector done conn:%d max_streams:%u\n", + connector->base.id, mst->max_streams); + + return connector; + +err_connector: + drm_connector_cleanup(connector); +err_free: + kfree(mst_conn); + return NULL; +} + +static void msm_dp_mst_poll_hpd_irq(struct drm_dp_mst_topology_mgr *mgr) +{ + struct msm_dp_mst *mst = container_of(mgr, struct msm_dp_mst, mst_mgr); + + msm_dp_mst_display_hpd_irq(mst->msm_dp); +} + +static const struct drm_dp_mst_topology_cbs msm_dp_mst_drm_cbs = { + .add_connector = msm_dp_mst_add_connector, + .poll_hpd_irq = msm_dp_mst_poll_hpd_irq, +}; + +int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux) +{ + struct drm_device *dev = dp_display->drm_dev; + struct msm_dp_mst *mst; + int ret; + + mst = devm_kzalloc(dev->dev, sizeof(*mst), GFP_KERNEL); + if (!mst) + return -ENOMEM; + + mst->mst_mgr.cbs = &msm_dp_mst_drm_cbs; + mst->msm_dp = dp_display; + mst->max_streams = max_streams; + mst->dp_aux = drm_aux; + + ret = drm_dp_mst_topology_mgr_init(&mst->mst_mgr, dev, + drm_aux, + 16, + max_streams, + dp_display->connector->base.id); + if (ret) { + drm_err(dev, "[MST] topology manager init failed\n"); + return ret; + } + + mutex_init(&mst->mst_lock); + mutex_init(&mst->hpd_irq_lock); + dp_display->msm_dp_mst = mst; + return 0; +} diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h new file mode 100644 index 0000000000000..08e145399cfc7 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DP_MST_DRM_H_ +#define _DP_MST_DRM_H_ + +#include "dp_display.h" + +int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux); +int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state); +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display); + +#endif /* _DP_MST_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 6bb021820d7c5..ba5ee2ad8924b 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -25,13 +25,92 @@ struct msm_dp_panel_private { struct drm_dp_aux *aux; struct msm_dp_link *link; void __iomem *link_base; - void __iomem *p0_base; + void __iomem *mst2link_base; + void __iomem *mst3link_base; + void __iomem *pixel_base; bool panel_on; }; +u32 msm_dp_stream_reg(enum msm_dp_stream_id id, u32 reg) +{ + bool is_s1 = (id == DP_STREAM_1); + + if (id == DP_STREAM_0) + return reg; + + switch (reg) { + case REG_DP_STATE_CTRL: + return is_s1 ? REG_DP_STATE_CTRL : REG_DP_MSTLINK_STATE_CTRL; + case REG_DP_CONFIGURATION_CTRL: + return is_s1 ? REG_DP1_CONFIGURATION_CTRL : REG_DP_MSTLINK_CONFIGURATION_CTRL; + case REG_DP_SOFTWARE_MVID: + return is_s1 ? REG_DP1_SOFTWARE_MVID : REG_MSTLINK_SOFTWARE_MVID; + case REG_DP_SOFTWARE_NVID: + return is_s1 ? REG_DP1_SOFTWARE_NVID : REG_MSTLINK_SOFTWARE_NVID; + case REG_DP_TOTAL_HOR_VER: + return is_s1 ? REG_DP1_TOTAL_HOR_VER : REG_DP_MSTLINK_TOTAL_HOR_VER; + case REG_DP_START_HOR_VER_FROM_SYNC: + return is_s1 ? REG_DP1_START_HOR_VER_FROM_SYNC + : REG_DP_MSTLINK_START_HOR_VER_FROM_SYNC; + case REG_DP_HSYNC_VSYNC_WIDTH_POLARITY: + return is_s1 ? REG_DP1_HSYNC_VSYNC_WIDTH_POLARITY + : REG_DP_MSTLINK_HSYNC_VSYNC_WIDTH_POLARITY; + case REG_DP_ACTIVE_HOR_VER: + return is_s1 ? REG_DP1_ACTIVE_HOR_VER : REG_DP_MSTLINK_ACTIVE_HOR_VER; + case REG_DP_MISC1_MISC0: + return is_s1 ? REG_DP1_MISC1_MISC0 : REG_DP_MSTLINK_MISC1_MISC0; + case REG_DP_DP0_TIMESLOT_1_32: + return is_s1 ? REG_DP_DP1_TIMESLOT_1_32 : REG_DP_MSTLINK_TIMESLOT_1_32; + case REG_DP_DP0_TIMESLOT_33_63: + return is_s1 ? REG_DP_DP1_TIMESLOT_33_63 : REG_DP_MSTLINK_TIMESLOT_33_63; + case REG_DP_DP0_RG: + return is_s1 ? REG_DP_DP1_RG : REG_DP_MSTLINK_DP_RG; + case MMSS_DP_SDP_CFG: + return is_s1 ? MMSS_DP1_SDP_CFG : MMSS_DP_MSTLINK_SDP_CFG; + case MMSS_DP_SDP_CFG2: + return is_s1 ? MMSS_DP1_SDP_CFG2 : MMSS_DP_MSTLINK_SDP_CFG2; + case MMSS_DP_SDP_CFG3: + return is_s1 ? MMSS_DP1_SDP_CFG3 : MMSS_DP_MSTLINK_SDP_CFG3; + case MMSS_DP_GENERIC0_0: + return is_s1 ? MMSS_DP1_GENERIC0_0 : MMSS_DP_MSTLINK_GENERIC0_0; + case MMSS_DP_GENERIC0_1: + return is_s1 ? MMSS_DP1_GENERIC0_1 : MMSS_DP_MSTLINK_GENERIC0_1; + case MMSS_DP_GENERIC0_2: + return is_s1 ? MMSS_DP1_GENERIC0_2 : MMSS_DP_MSTLINK_GENERIC0_2; + case MMSS_DP_GENERIC0_3: + return is_s1 ? MMSS_DP1_GENERIC0_3 : MMSS_DP_MSTLINK_GENERIC0_3; + case MMSS_DP_GENERIC0_4: + return is_s1 ? MMSS_DP1_GENERIC0_4 : MMSS_DP_MSTLINK_GENERIC0_4; + case MMSS_DP_GENERIC0_5: + return is_s1 ? MMSS_DP1_GENERIC0_5 : MMSS_DP_MSTLINK_GENERIC0_5; + case MMSS_DP_GENERIC0_6: + return is_s1 ? MMSS_DP1_GENERIC0_6 : MMSS_DP_MSTLINK_GENERIC0_6; + case MMSS_DP_GENERIC0_7: + return is_s1 ? MMSS_DP1_GENERIC0_7 : MMSS_DP_MSTLINK_GENERIC0_7; + case MMSS_DP_GENERIC0_8: + return is_s1 ? MMSS_DP1_GENERIC0_8 : MMSS_DP_MSTLINK_GENERIC0_8; + case MMSS_DP_GENERIC0_9: + return is_s1 ? MMSS_DP1_GENERIC0_9 : MMSS_DP_MSTLINK_GENERIC0_9; + default: + return reg; + } +} + static inline u32 msm_dp_read_link(struct msm_dp_panel_private *panel, u32 offset) { - return readl_relaxed(panel->link_base + offset); + offset = msm_dp_stream_reg(panel->msm_dp_panel.stream_id, offset); + switch (panel->msm_dp_panel.stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + return readl_relaxed(panel->link_base + offset); + case DP_STREAM_2: + return readl_relaxed(panel->mst2link_base + offset); + case DP_STREAM_3: + return readl_relaxed(panel->mst3link_base + offset); + default: + DRM_ERROR("error stream_id\n"); + return 0; + } } static inline void msm_dp_write_link(struct msm_dp_panel_private *panel, @@ -41,27 +120,42 @@ static inline void msm_dp_write_link(struct msm_dp_panel_private *panel, * To make sure link reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, panel->link_base + offset); + offset = msm_dp_stream_reg(panel->msm_dp_panel.stream_id, offset); + switch (panel->msm_dp_panel.stream_id) { + case DP_STREAM_0: + case DP_STREAM_1: + writel(data, panel->link_base + offset); + break; + case DP_STREAM_2: + writel(data, panel->mst2link_base + offset); + break; + case DP_STREAM_3: + writel(data, panel->mst3link_base + offset); + break; + default: + DRM_ERROR("error stream_id\n"); + break; + } } -static inline void msm_dp_write_p0(struct msm_dp_panel_private *panel, - u32 offset, u32 data) +static inline void msm_dp_write_pn(struct msm_dp_panel_private *panel, + u32 offset, u32 data) { /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, panel->p0_base + offset); + writel(data, panel->pixel_base + offset); } -static inline u32 msm_dp_read_p0(struct msm_dp_panel_private *panel, - u32 offset) +static inline u32 msm_dp_read_pn(struct msm_dp_panel_private *panel, + u32 offset) { /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - return readl_relaxed(panel->p0_base + offset); + return readl_relaxed(panel->pixel_base + offset); } static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel) @@ -232,8 +326,8 @@ static u32 msm_dp_panel_get_supported_bpp(struct msm_dp_panel *msm_dp_panel, return min_supported_bpp; } -int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector) +int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, + struct drm_connector *connector) { int rc, bw_code; int count; @@ -271,36 +365,9 @@ int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, rc = drm_dp_read_downstream_info(panel->aux, msm_dp_panel->dpcd, msm_dp_panel->downstream_ports); - if (rc) - return rc; - - drm_edid_free(msm_dp_panel->drm_edid); - - msm_dp_panel->drm_edid = drm_edid_read_ddc(connector, &panel->aux->ddc); - - drm_edid_connector_update(connector, msm_dp_panel->drm_edid); - - if (!msm_dp_panel->drm_edid) { - DRM_ERROR("panel edid read failed\n"); - /* check edid read fail is due to unplug */ - if (!msm_dp_aux_is_link_connected(panel->aux)) { - rc = -ETIMEDOUT; - goto end; - } - } - -end: return rc; } -void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector) -{ - drm_edid_connector_update(connector, NULL); - drm_edid_free(msm_dp_panel->drm_edid); - msm_dp_panel->drm_edid = NULL; -} - u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_edid_bpp, u32 mode_pclk_khz) { @@ -324,20 +391,6 @@ u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, return bpp; } -int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector) -{ - if (!msm_dp_panel) { - DRM_ERROR("invalid input\n"); - return -EINVAL; - } - - if (msm_dp_panel->drm_edid) - return drm_edid_connector_add_modes(connector); - - return 0; -} - static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) { edid += edid->extensions; @@ -345,7 +398,8 @@ static u8 msm_dp_panel_get_edid_checksum(const struct edid *edid) return edid->checksum; } -void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel) +void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel, + const struct drm_edid *drm_edid) { struct msm_dp_panel_private *panel; @@ -358,7 +412,7 @@ void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel) if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) { /* FIXME: get rid of drm_edid_raw() */ - const struct edid *edid = drm_edid_raw(msm_dp_panel->drm_edid); + const struct edid *edid = drm_edid_raw(drm_edid); u8 checksum; if (edid) @@ -407,34 +461,34 @@ static void msm_dp_panel_tpg_enable(struct msm_dp_panel *msm_dp_panel, display_hctl = (hsync_end_x << 16) | hsync_start_x; - msm_dp_write_p0(panel, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * + msm_dp_write_pn(panel, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * hsync_period); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_HCTL, 0); - msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); - msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); - msm_dp_write_p0(panel, MMSS_INTF_DISPLAY_V_START_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); - msm_dp_write_p0(panel, MMSS_DP_INTF_POLARITY_CTL, 0); - - msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL, - DP_TPG_CHECKERED_RECT_PATTERN); - msm_dp_write_p0(panel, MMSS_DP_TPG_VIDEO_CONFIG, - DP_TPG_VIDEO_CONFIG_BPP_8BIT | - DP_TPG_VIDEO_CONFIG_RGB); - msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE, - DP_BIST_ENABLE_DPBIST_EN); - msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN, - DP_TIMING_ENGINE_EN_EN); + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_HCTL, 0); + msm_dp_write_pn(panel, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); + msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); + msm_dp_write_pn(panel, MMSS_INTF_DISPLAY_V_START_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); + msm_dp_write_pn(panel, MMSS_DP_INTF_POLARITY_CTL, 0); + + msm_dp_write_pn(panel, MMSS_DP_TPG_MAIN_CONTROL, + DP_TPG_CHECKERED_RECT_PATTERN); + msm_dp_write_pn(panel, MMSS_DP_TPG_VIDEO_CONFIG, + DP_TPG_VIDEO_CONFIG_BPP_8BIT | + DP_TPG_VIDEO_CONFIG_RGB); + msm_dp_write_pn(panel, MMSS_DP_BIST_ENABLE, + DP_BIST_ENABLE_DPBIST_EN); + msm_dp_write_pn(panel, MMSS_DP_TIMING_ENGINE_EN, + DP_TIMING_ENGINE_EN_EN); drm_dbg_dp(panel->drm_dev, "%s: enabled tpg\n", __func__); } @@ -443,9 +497,9 @@ static void msm_dp_panel_tpg_disable(struct msm_dp_panel *msm_dp_panel) struct msm_dp_panel_private *panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - msm_dp_write_p0(panel, MMSS_DP_TPG_MAIN_CONTROL, 0x0); - msm_dp_write_p0(panel, MMSS_DP_BIST_ENABLE, 0x0); - msm_dp_write_p0(panel, MMSS_DP_TIMING_ENGINE_EN, 0x0); + msm_dp_write_pn(panel, MMSS_DP_TPG_MAIN_CONTROL, 0x0); + msm_dp_write_pn(panel, MMSS_DP_BIST_ENABLE, 0x0); + msm_dp_write_pn(panel, MMSS_DP_TIMING_ENGINE_EN, 0x0); } void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable) @@ -479,7 +533,7 @@ void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel) struct msm_dp_panel_private *panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); - msm_dp_write_p0(panel, MMSS_DP_DSC_DTO, 0x0); + msm_dp_write_pn(panel, MMSS_DP_DSC_DTO, 0x0); } static void msm_dp_panel_send_vsc_sdp(struct msm_dp_panel_private *panel, struct dp_sdp *vsc_sdp) @@ -669,7 +723,7 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) msm_dp_write_link(panel, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, width_blanking); msm_dp_write_link(panel, REG_DP_ACTIVE_HOR_VER, msm_dp_active); - reg = msm_dp_read_p0(panel, MMSS_DP_INTF_CONFIG); + reg = msm_dp_read_pn(panel, MMSS_DP_INTF_CONFIG); if (wide_bus_en) reg |= DP_INTF_CONFIG_DATABUS_WIDEN; else @@ -677,7 +731,7 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) drm_dbg_dp(panel->drm_dev, "wide_bus_en=%d reg=%#x\n", wide_bus_en, reg); - msm_dp_write_p0(panel, MMSS_DP_INTF_CONFIG, reg); + msm_dp_write_pn(panel, MMSS_DP_INTF_CONFIG, reg); if (msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420) msm_dp_panel_setup_vsc_sdp_yuv_420(msm_dp_panel); @@ -687,15 +741,39 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) return 0; } -int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel) +void msm_dp_panel_mst_async_fifo(struct msm_dp_panel *msm_dp_panel, bool mst_en) { - struct drm_display_mode *drm_mode; struct msm_dp_panel_private *panel; - drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; + panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + + if (mst_en) + msm_dp_write_pn(panel, MMSS_DP_ASYNC_FIFO_CONFIG, 0x01); + else + msm_dp_write_pn(panel, MMSS_DP_ASYNC_FIFO_CONFIG, 0x00); +} + +int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, + const struct drm_display_mode *adjusted_mode, + u32 bpp) +{ + struct drm_display_mode *drm_mode; + struct msm_dp_panel_private *panel; panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + drm_mode_copy(&msm_dp_panel->msm_dp_mode.drm_mode, adjusted_mode); + msm_dp_panel->msm_dp_mode.bpp = bpp; + msm_dp_panel->msm_dp_mode.v_active_low = + !!(adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC); + msm_dp_panel->msm_dp_mode.h_active_low = + !!(adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC); + msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 = + drm_mode_is_420_only(&msm_dp_panel->connector->display_info, adjusted_mode) && + msm_dp_panel->vsc_sdp_supported; + + drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; + /* * print resolution info as this is a result * of user initiated action of cable connection @@ -729,7 +807,9 @@ int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel) struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, struct msm_dp_link *link, void __iomem *link_base, - void __iomem *p0_base) + void __iomem *mst2link_base, + void __iomem *mst3link_base, + void __iomem *pixel_base) { struct msm_dp_panel_private *panel; struct msm_dp_panel *msm_dp_panel; @@ -747,18 +827,14 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux panel->aux = aux; panel->link = link; panel->link_base = link_base; - panel->p0_base = p0_base; + panel->pixel_base = pixel_base; + panel->mst2link_base = mst2link_base; + panel->mst3link_base = mst3link_base; msm_dp_panel = &panel->msm_dp_panel; msm_dp_panel->max_bw_code = DP_LINK_BW_8_1; + msm_dp_panel->stream_id = DP_STREAM_0; return msm_dp_panel; } -void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel) -{ - if (!msm_dp_panel) - return; - - drm_edid_free(msm_dp_panel->drm_edid); -} diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 9173e90a50530..edc39ee5268ef 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -27,13 +27,21 @@ struct msm_dp_panel_psr { u8 capabilities; }; +/* stream id */ +enum msm_dp_stream_id { + DP_STREAM_0, + DP_STREAM_1, + DP_STREAM_2, + DP_STREAM_3, + DP_STREAM_MAX, +}; + struct msm_dp_panel { /* dpcd raw data */ u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct msm_dp_link_info link_info; - const struct drm_edid *drm_edid; struct drm_connector *connector; struct msm_dp_display_mode msm_dp_mode; struct msm_dp_panel_psr psr_cap; @@ -41,21 +49,23 @@ struct msm_dp_panel { bool vsc_sdp_supported; u32 hw_revision; + enum msm_dp_stream_id stream_id; + u32 pbn; + u32 max_bw_code; }; -int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel); +int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, + const struct drm_display_mode *adjusted_mode, + u32 bpp); int msm_dp_panel_deinit(struct msm_dp_panel *msm_dp_panel); int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en); -int msm_dp_panel_read_sink_caps(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector); -void msm_dp_panel_unplugged(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector); +int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, + struct drm_connector *connector); u32 msm_dp_panel_get_mode_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_max_bpp, u32 mode_pclk_khz); -int msm_dp_panel_get_modes(struct msm_dp_panel *msm_dp_panel, - struct drm_connector *connector); -void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel); +void msm_dp_panel_handle_sink_request(struct msm_dp_panel *msm_dp_panel, + const struct drm_edid *drm_edid); void msm_dp_panel_tpg_config(struct msm_dp_panel *msm_dp_panel, bool enable); void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); @@ -63,6 +73,8 @@ void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); void msm_dp_panel_enable_vsc_sdp(struct msm_dp_panel *msm_dp_panel, struct dp_sdp *vsc_sdp); void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel); +void msm_dp_panel_mst_async_fifo(struct msm_dp_panel *msm_dp_panel, bool mst_en); + /** * is_link_rate_valid() - validates the link rate * @bw_code: link rate requested by the sink @@ -90,9 +102,12 @@ static inline bool is_lane_count_valid(u32 lane_count) lane_count == 4); } +u32 msm_dp_stream_reg(enum msm_dp_stream_id id, u32 reg); + struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux, struct msm_dp_link *link, void __iomem *link_base, - void __iomem *p0_base); -void msm_dp_panel_put(struct msm_dp_panel *msm_dp_panel); + void __iomem *mst2link_base, + void __iomem *mst3link_base, + void __iomem *pixel_base); #endif /* _DP_PANEL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 3689642b7fc06..ade7b362d650c 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -42,9 +42,13 @@ #define DP_INTR_FRAME_END BIT(6) #define DP_INTR_CRC_UPDATED BIT(9) +#define DP_INTR_DP0_VCPF_SENT BIT(0) +#define DP_INTR_DP1_VCPF_SENT BIT(3) + #define REG_DP_INTR_STATUS3 (0x00000028) #define REG_DP_INTR_STATUS4 (0x0000002C) +#define REG_DP_INTR_STATUS5 (0x00000034) #define PSR_UPDATE_INT (0x00000001) #define PSR_CAPTURE_INT (0x00000004) #define PSR_EXIT_INT (0x00000010) @@ -128,6 +132,10 @@ #define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 1) #define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 3) #define DP_MAINLINK_FB_BOUNDARY_SEL (0x02000000) +#define DP_MAINLINK_CTRL_ECF_MODE BIT(26) +#define DP_MAINLINK_CTRL_MST_ACTIVE BIT(8) +#define DP_MAINLINK_CTRL_MST_EN (DP_MAINLINK_CTRL_ECF_MODE | \ + DP_MAINLINK_CTRL_MST_ACTIVE) #define REG_DP_STATE_CTRL (0x00000004) #define DP_STATE_CTRL_LINK_TRAINING_PATTERN1 (0x00000001) @@ -139,6 +147,8 @@ #define DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN (0x00000040) #define DP_STATE_CTRL_SEND_VIDEO (0x00000080) #define DP_STATE_CTRL_PUSH_IDLE (0x00000100) +#define DP_DP0_PUSH_VCPF BIT(12) +#define DP_DP1_PUSH_VCPF BIT(14) #define REG_DP_CONFIGURATION_CTRL (0x00000008) #define DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK (0x00000001) @@ -156,6 +166,8 @@ #define DP_CONFIGURATION_CTRL_BPC_SHIFT (0x08) #define DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT (0x0D) +#define REG_DP_MST_ACT (0x00000500) + #define REG_DP_SOFTWARE_MVID (0x00000010) #define REG_DP_SOFTWARE_NVID (0x00000018) #define REG_DP_TOTAL_HOR_VER (0x0000001C) @@ -332,6 +344,62 @@ #define DP_TPG_VIDEO_CONFIG_BPP_8BIT (0x00000001) #define DP_TPG_VIDEO_CONFIG_RGB (0x00000004) + +#define REG_DP_MSTLINK_DP_RG (0X0000011C) +#define REG_DP1_CONFIGURATION_CTRL (0x00000400) +#define REG_DP_DP0_TIMESLOT_1_32 (0x00000404) +#define REG_DP_DP0_TIMESLOT_33_63 (0x00000408) +#define REG_DP_DP1_TIMESLOT_1_32 (0x0000040C) +#define REG_DP_DP1_TIMESLOT_33_63 (0x00000410) +#define REG_DP1_SOFTWARE_MVID (0x00000414) +#define REG_DP1_SOFTWARE_NVID (0x00000418) +#define REG_DP1_TOTAL_HOR_VER (0x0000041C) +#define REG_DP1_START_HOR_VER_FROM_SYNC (0x00000420) +#define REG_DP1_HSYNC_VSYNC_WIDTH_POLARITY (0x00000424) +#define REG_DP1_ACTIVE_HOR_VER (0x00000428) +#define REG_DP1_MISC1_MISC0 (0x0000042C) +#define MMSS_DP1_GENERIC0_0 (0x00000490) +#define MMSS_DP1_GENERIC0_1 (0x00000494) +#define MMSS_DP1_GENERIC0_2 (0x00000498) +#define MMSS_DP1_GENERIC0_3 (0x0000049C) +#define MMSS_DP1_GENERIC0_4 (0x000004A0) +#define MMSS_DP1_GENERIC0_5 (0x000004A4) +#define MMSS_DP1_GENERIC0_6 (0x000004A8) +#define MMSS_DP1_GENERIC0_7 (0x000004AC) +#define MMSS_DP1_GENERIC0_8 (0x000004B0) +#define MMSS_DP1_GENERIC0_9 (0x000004B4) +#define MMSS_DP1_SDP_CFG (0x000004E0) +#define MMSS_DP1_SDP_CFG2 (0x000004E4) +#define MMSS_DP1_SDP_CFG3 (0x000004E8) +#define REG_DP_DP0_RG (0x000004F8) +#define REG_DP_DP1_RG (0x000004FC) + +#define REG_DP_MSTLINK_STATE_CTRL (0x00000000) +#define DP_MSTLINK_PUSH_VCPF BIT(12) +#define REG_DP_MSTLINK_CONFIGURATION_CTRL (0x00000034) +#define REG_DP_MSTLINK_TIMESLOT_1_32 (0x00000038) +#define REG_DP_MSTLINK_TIMESLOT_33_63 (0x0000003C) +#define REG_MSTLINK_SOFTWARE_MVID (0x00000040) +#define REG_MSTLINK_SOFTWARE_NVID (0x00000044) +#define REG_DP_MSTLINK_TOTAL_HOR_VER (0x00000048) +#define REG_DP_MSTLINK_START_HOR_VER_FROM_SYNC (0x0000004C) +#define REG_DP_MSTLINK_HSYNC_VSYNC_WIDTH_POLARITY (0x00000050) +#define REG_DP_MSTLINK_ACTIVE_HOR_VER (0x00000054) +#define REG_DP_MSTLINK_MISC1_MISC0 (0x00000058) +#define MMSS_DP_MSTLINK_GENERIC0_0 (0x000000BC) +#define MMSS_DP_MSTLINK_GENERIC0_1 (0x000000C0) +#define MMSS_DP_MSTLINK_GENERIC0_2 (0x000000C4) +#define MMSS_DP_MSTLINK_GENERIC0_3 (0x000000C8) +#define MMSS_DP_MSTLINK_GENERIC0_4 (0x000000CC) +#define MMSS_DP_MSTLINK_GENERIC0_5 (0x000000D0) +#define MMSS_DP_MSTLINK_GENERIC0_6 (0x000000D4) +#define MMSS_DP_MSTLINK_GENERIC0_7 (0x000000D8) +#define MMSS_DP_MSTLINK_GENERIC0_8 (0x000000DC) +#define MMSS_DP_MSTLINK_GENERIC0_9 (0x000000E0) +#define MMSS_DP_MSTLINK_SDP_CFG (0x0000010c) +#define MMSS_DP_MSTLINK_SDP_CFG2 (0x0000011c) +#define MMSS_DP_MSTLINK_SDP_CFG3 (0x00000114) + #define MMSS_DP_ASYNC_FIFO_CONFIG (0x00000088) #define REG_DP_PHY_AUX_INTERRUPT_CLEAR (0x0000004C) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index a8babf1dbe0d3..e70e5088cfe53 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -4,6 +4,7 @@ * Author: Rob Clark */ +#include #include #include @@ -207,7 +208,11 @@ int msm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state) if (ret) return ret; - return drm_atomic_helper_check(dev, state); + ret = drm_atomic_helper_check(dev, state); + if (ret) + return ret; + + return drm_dp_mst_atomic_check(state); } void msm_atomic_commit_tail(struct drm_atomic_commit *state) @@ -221,6 +226,8 @@ void msm_atomic_commit_tail(struct drm_atomic_commit *state) trace_msm_atomic_commit_tail_start(async, crtc_mask); + drm_dp_mst_atomic_wait_for_dependencies(state); + kms->funcs->enable_commit(kms); /* @@ -322,3 +329,8 @@ void msm_atomic_commit_tail(struct drm_atomic_commit *state) trace_msm_atomic_commit_tail_finish(async, crtc_mask); } + +int msm_atomic_commit_setup(struct drm_atomic_commit *state) +{ + return drm_dp_mst_atomic_setup_commit(state); +} diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 3787db8770ada..f599ebe670190 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -211,6 +211,7 @@ int msm_atomic_init_pending_timer(struct msm_pending_timer *timer, struct msm_kms *kms, int crtc_idx); void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer); void msm_atomic_commit_tail(struct drm_atomic_commit *state); +int msm_atomic_commit_setup(struct drm_atomic_commit *state); int msm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state); struct drm_atomic_commit *msm_atomic_state_alloc(struct drm_device *dev); @@ -361,6 +362,9 @@ bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display, bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, const struct drm_display_mode *mode); bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); +int msm_dp_get_mst_max_stream(struct msm_dp *dp_display); +int msm_dp_mst_register(struct msm_dp *dp_display); +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, struct drm_encoder *encoder); #else static inline int __init msm_dp_register(void) @@ -378,6 +382,21 @@ static inline int msm_dp_modeset_init(struct msm_dp *dp_display, return -EINVAL; } +static inline int msm_dp_get_mst_max_stream(struct msm_dp *dp_display) +{ + return -EINVAL; +} + +static inline int msm_dp_mst_register(struct msm_dp *dp_display) +{ + return -EINVAL; +} + +static inline int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, struct drm_encoder *encoder) +{ + return -EINVAL; +} + static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display) { } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 18ed00e5f143b..03c0578560658 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -505,6 +505,8 @@ static void recover_worker(struct kthread_work *work) */ if (!vm->managed) msm_gem_vm_unusable(submit->vm); + + put_task_struct(task); } noreclaim_flag = memalloc_noreclaim_save(); @@ -552,11 +554,13 @@ static void recover_worker(struct kthread_work *work) msm_update_fence(ring->fctx, fence); } - /* retire completed submits, plus the one that hung: */ - retire_submits(gpu); + priv->disable_err_irq = false; gpu->funcs->recover(gpu); + /* retire completed submits, plus the one that hung: */ + retire_submits(gpu); + /* * Replay all remaining submits starting with highest priority * ring diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index e5d0ea6294484..33ab30300e16d 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -29,6 +29,7 @@ static const struct drm_mode_config_funcs mode_config_funcs = { static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = { .atomic_commit_tail = msm_atomic_commit_tail, + .atomic_commit_setup = msm_atomic_commit_setup, }; static irqreturn_t msm_irq(int irq, void *arg) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 9087c4b290dba..03f27e6b0ae7b 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -537,6 +537,7 @@ static const struct of_device_id mdss_dt_match[] = { { .compatible = "qcom,sar2130p-mdss", .data = &data_74k }, { .compatible = "qcom,sdm670-mdss", .data = &data_76k8 }, { .compatible = "qcom,sdm845-mdss", .data = &data_76k8 }, + { .compatible = "qcom,shikra-mdss", .data = &data_76k8 }, { .compatible = "qcom,sc7180-mdss", .data = &data_76k8 }, { .compatible = "qcom,sc7280-mdss", .data = &data_74k }, { .compatible = "qcom,sc8180x-mdss", .data = &data_76k8 }, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index e306247ed8a05..ad659cef16f58 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -429,7 +429,9 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge, static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status, + bool *send_hotplug) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7450b27622a23..4354b51cbc53d 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -116,6 +116,17 @@ config DRM_PANEL_CHIPWEALTH_CH13726A Say Y here if you want to enable support for ChipWealth CH13726A-based display panels. +config DRM_PANEL_DLC0697 + tristate "DLC0697 1080x1920 video mode DSI panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for the DLC DLC0697 + 1080x1920 60Hz MIPI-DSI video mode panel found on Qualcomm + Shikra (QCM2290-based) EVK boards. The panel supports hardware + backlight control via the MIPI DCS brightness command. + config DRM_PANEL_EBBG_FT8719 tristate "EBBG FT8719 panel driver" depends on GPIOLIB diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index c2c5cf8171163..3a8314b438361 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_LL2) += panel-boe-tv101wum-ll2.o obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o obj-$(CONFIG_DRM_PANEL_CHIPWEALTH_CH13726A) += panel-chipwealth-ch13726a.o obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o +obj-$(CONFIG_DRM_PANEL_DLC0697) += panel-dlc0697.o obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o obj-$(CONFIG_DRM_PANEL_EDP) += panel-edp.o diff --git a/drivers/gpu/drm/panel/panel-dlc0697.c b/drivers/gpu/drm/panel/panel-dlc0697.c new file mode 100644 index 0000000000000..f0ef07cb0160f --- /dev/null +++ b/drivers/gpu/drm/panel/panel-dlc0697.c @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +/* + * DRM panel driver for DLC0697 1080x1920 60Hz video-mode DSI panel + * + * Derived from downstream Qualcomm panel DT data. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct dlc0697 { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; + struct gpio_desc *enable_gpio; + + struct pinctrl *pinctrl; + struct pinctrl_state *state_active; + struct pinctrl_state *state_suspend; +}; + +static const struct regulator_bulk_data dlc0697_supplies[] = { + { .supply = "vddio" }, + { .supply = "bias" }, +}; + +static inline struct dlc0697 *to_dlc0697(struct drm_panel *panel) +{ + return container_of(panel, struct dlc0697, panel); +} + +static const struct drm_display_mode dlc0697_mode = { + .clock = 131911, + + .hdisplay = 1080, + .hsync_start = 1080 + 18, + .hsync_end = 1080 + 18 + 2, + .htotal = 1080 + 18 + 2 + 16, + + .vdisplay = 1920, + .vsync_start = 1920 + 26, + .vsync_end = 1920 + 26 + 4, + .vtotal = 1920 + 26 + 4 + 20, + + .width_mm = 0, + .height_mm = 0, +}; + +static void dlc0697_reset(struct dlc0697 *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); +} + +static int dlc0697_on(struct dlc0697 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_soft_reset_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xff, 0x78, 0x07, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x09, 0x99); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x24); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x3f, 0xff); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + if (dsi_ctx.accum_err) + dev_err(&ctx->dsi->dev, "panel on sequence failed: %d\n", dsi_ctx.accum_err); + + return dsi_ctx.accum_err; +} + +static int dlc0697_off(struct dlc0697 *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + if (dsi_ctx.accum_err) + dev_err(&ctx->dsi->dev, "panel off sequence failed: %d\n", dsi_ctx.accum_err); + + return dsi_ctx.accum_err; +} + +static int dlc0697_enable(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + + if (ctx->enable_gpio) + gpiod_set_value_cansleep(ctx->enable_gpio, 1); + + return 0; +} + +static int dlc0697_disable(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + + if (ctx->enable_gpio) + gpiod_set_value_cansleep(ctx->enable_gpio, 0); + + return 0; +} + +static int dlc0697_prepare(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + int ret; + + if (ctx->pinctrl && ctx->state_active) { + ret = pinctrl_select_state(ctx->pinctrl, ctx->state_active); + if (ret < 0) + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(dlc0697_supplies), ctx->supplies); + if (ret < 0) { + dev_err(ctx->panel.dev, "failed to enable regulators: %d\n", ret); + return ret; + } + + /* qcom,supply-post-on-sleep = <20> */ + msleep(20); + + dlc0697_reset(ctx); + + ret = dlc0697_on(ctx); + if (ret < 0) + goto err; + + return 0; + +err: + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + + if (ctx->pinctrl && ctx->state_suspend) + pinctrl_select_state(ctx->pinctrl, ctx->state_suspend); + + regulator_bulk_disable(ARRAY_SIZE(dlc0697_supplies), ctx->supplies); + + return ret; +} + +static int dlc0697_unprepare(struct drm_panel *panel) +{ + struct dlc0697 *ctx = to_dlc0697(panel); + + dlc0697_off(ctx); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + + if (ctx->pinctrl && ctx->state_suspend) + pinctrl_select_state(ctx->pinctrl, ctx->state_suspend); + + regulator_bulk_disable(ARRAY_SIZE(dlc0697_supplies), ctx->supplies); + + return 0; +} + +static int dlc0697_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &dlc0697_mode); +} + +static const struct drm_panel_funcs dlc0697_panel_funcs = { + .prepare = dlc0697_prepare, + .unprepare = dlc0697_unprepare, + .enable = dlc0697_enable, + .disable = dlc0697_disable, + .get_modes = dlc0697_get_modes, +}; + +static int dlc0697_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness = backlight_get_brightness(bl); + int ret; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + return 0; +} + +static const struct backlight_ops dlc0697_bl_ops = { + .update_status = dlc0697_bl_update_status, +}; + +static struct backlight_device *dlc0697_create_backlight(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + const struct backlight_properties props = { + .type = BACKLIGHT_RAW, + .brightness = 4095, + .max_brightness = 4095, + }; + + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, + &dlc0697_bl_ops, &props); +} + +static int dlc0697_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct dlc0697 *ctx; + int ret; + + ctx = devm_drm_panel_alloc(dev, struct dlc0697, panel, + &dlc0697_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(dlc0697_supplies), + dlc0697_supplies, &ctx->supplies); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get regulators\n"); + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "failed to get reset gpio\n"); + + ctx->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(ctx->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), + "failed to get enable gpio\n"); + + ctx->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(ctx->pinctrl)) { + if (PTR_ERR(ctx->pinctrl) == -ENODEV) { + ctx->pinctrl = NULL; + } else { + return dev_err_probe(dev, PTR_ERR(ctx->pinctrl), + "failed to get pinctrl\n"); + } + } + + if (ctx->pinctrl) { + ctx->state_active = pinctrl_lookup_state(ctx->pinctrl, "default"); + if (IS_ERR(ctx->state_active)) + ctx->state_active = NULL; + + ctx->state_suspend = pinctrl_lookup_state(ctx->pinctrl, "sleep"); + if (IS_ERR(ctx->state_suspend)) + ctx->state_suspend = NULL; + } + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST; + + ctx->panel.prepare_prev_first = true; + + ctx->panel.backlight = dlc0697_create_backlight(dsi); + if (IS_ERR(ctx->panel.backlight)) + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), + "failed to create backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "failed to attach dsi\n"); + } + + return 0; +} + +static void dlc0697_remove(struct mipi_dsi_device *dsi) +{ + drm_panel_remove(mipi_dsi_get_drvdata(dsi)); +} + +static const struct of_device_id dlc0697_of_match[] = { + { .compatible = "dlc,dlc0697" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dlc0697_of_match); + +static struct mipi_dsi_driver dlc0697_driver = { + .probe = dlc0697_probe, + .remove = dlc0697_remove, + .driver = { + .name = "panel-dlc0697", + .of_match_table = dlc0697_of_match, + }, +}; +module_mipi_dsi_driver(dlc0697_driver); + +MODULE_AUTHOR("Arpit Saini "); +MODULE_DESCRIPTION("DLC0697 1080x1920 video mode DSI panel"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5c2d3ff5fce82..251f5cc900b3b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1939,6 +1939,15 @@ config SENSORS_PWM_FAN This driver can also be built as a module. If so, the module will be called pwm-fan. +config SENSORS_QCOM_BCL + tristate "Qualcomm BCL hardware monitoring" + help + Say yes here to enable support for Qualcomm battery over current + and under voltage alarms monitor. + + This driver can also be built as a module. If so, the module + will be called qcom-bcl-hwmon. + config SENSORS_QNAP_MCU_HWMON tristate "QNAP MCU hardware monitoring" depends on MFD_QNAP_MCU diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 63effc0ab8d11..e0293c14a7cba 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -202,6 +202,7 @@ obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o obj-$(CONFIG_SENSORS_PROM21_XHCI) += prom21-xhci.o obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o +obj-$(CONFIG_SENSORS_QCOM_BCL) += qcom-bcl-hwmon.o obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o diff --git a/drivers/hwmon/qcom-bcl-hwmon.c b/drivers/hwmon/qcom-bcl-hwmon.c new file mode 100644 index 0000000000000..9894b1d14d124 --- /dev/null +++ b/drivers/hwmon/qcom-bcl-hwmon.c @@ -0,0 +1,982 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm pmic BCL hardware driver for battery overcurrent and + * battery or system under voltage monitor + * + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qcom-bcl-hwmon.h" + +ADD_BCL_HWMON_ALARM_MAPS(in, min, lcrit); +ADD_BCL_HWMON_ALARM_MAPS(curr, max, crit); + +/* Interrupt names for each alarm level */ +static const char * const bcl_int_names[ALARM_MAX] = { + [LVL0] = "bcl-max-min", + [LVL1] = "bcl-critical", +}; + +static const char * const bcl_channel_label[CHANNEL_MAX] = { + "BCL Voltage", + "BCL Current", +}; + +/* Common Reg Fields */ +static const struct reg_field common_reg_fields[COMMON_FIELD_MAX] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), +}; + +/* BCL Version/Modes specific fields */ +static const struct reg_field bcl_v1_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(MODE_CTL1, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(VADC_CONV_REQ, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(IADC_CONV_REQ, 0, 0), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v2_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 1), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(VADC_CONV_REQ, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(IADC_CONV_REQ, 0, 0), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v3_bmx_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v3_wb_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 3), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_v3_core_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VCMP_L0_THR, 0, 5), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), +}; + +static const struct reg_field bcl_v4_bmx_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 15), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 15), +}; + +static const struct reg_field bcl_v4_wb_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 6), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 15), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 4), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 15), +}; + +static const struct reg_field bcl_v4_core_reg_fields[] = { + [F_IN_MON_EN] = REG_FIELD(VCMP_CTL, 0, 2), + [F_IN_L0_THR] = REG_FIELD(VCMP_L0_THR, 0, 6), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 6), + [F_IN_INPUT_EN] = REG_FIELD(PARAM_1, 0, 0), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 15), + [F_CURR_MON_EN] = REG_FIELD(PARAM_1, 1, 1), +}; + +/* V1 BMX and core */ +static const struct bcl_desc pm7250b_data = { + .reg_fields = bcl_v1_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 7, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 10000, + .default_scale_nu = 305180, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V2 BMX and core */ +static const struct bcl_desc pm8350_data = { + .reg_fields = bcl_v2_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 10000, + .default_scale_nu = 305180, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V3 BMX */ +static const struct bcl_desc pm8550b_data = { + .reg_fields = bcl_v3_bmx_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 12000, + .default_scale_nu = 366220, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V3 WB */ +static const struct bcl_desc pmw5100_data = { + .reg_fields = bcl_v3_wb_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .base = 800, + .max = 2000, + .step = 100, + .default_scale_nu = 61035, + .thresh_type = {ADC, INDEX}, + }, +}; + +/* V3 CORE */ +static const struct bcl_desc pm8550_data = { + .reg_fields = bcl_v3_core_reg_fields, + .num_reg_fields = F_CURR_MON_EN + 1, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .thresh_type = {INDEX, INDEX}, + }, +}; + +/* V4 BMX */ +static const struct bcl_desc pmih010_data = { + .reg_fields = bcl_v4_bmx_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 20000, + .default_scale_nu = 610370, + .thresh_type = {ADC, ADC}, + }, +}; + +/* V4 WB */ +static const struct bcl_desc pmw6100_data = { + .reg_fields = bcl_v4_wb_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 1500, + .max = 4000, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .base = 900, + .max = 3300, + .step = 150, + .default_scale_nu = 152586, + .thresh_type = {ADC, INDEX}, + }, +}; + +/* V4 CORE */ +static const struct bcl_desc pmh010_data = { + .reg_fields = bcl_v4_core_reg_fields, + .num_reg_fields = F_CURR_MON_EN + 1, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 1500, + .max = 4000, + .step = 25, + .thresh_type = {INDEX, INDEX}, + }, +}; + +/* V4 BMX with different scale */ +static const struct bcl_desc pmv010_data = { + .reg_fields = bcl_v4_bmx_reg_fields, + .num_reg_fields = F_MAX_FIELDS, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .channel[IN] = { + .base = 2250, + .max = 3600, + .step = 25, + .default_scale_nu = 194637, + .thresh_type = {ADC, INDEX}, + }, + .channel[CURR] = { + .max = 12000, + .default_scale_nu = 366220, + .thresh_type = {ADC, ADC}, + }, +}; + +/** + * bcl_convert_raw_to_milliunit - Convert raw value to milli unit + * @desc: BCL device descriptor + * @raw_val: Raw ADC value from hardware + * @type: type of the channel, in or curr + * @field_width: bits size for data or threshold field + * + * Return: value in milli unit + */ +static unsigned int bcl_convert_raw_to_milliunit(const struct bcl_desc *desc, int raw_val, + enum bcl_channel_type type, u8 field_width) +{ + u32 def_scale = desc->channel[type].default_scale_nu; + u32 lsb_weight = field_width > 8 ? 1 : 1 << field_width; + u32 scaling_factor = def_scale * lsb_weight; + + return div_s64((s64)raw_val * scaling_factor, 1000000); +} + +/** + * bcl_convert_milliunit_to_raw - Convert milli unit to raw value + * @desc: BCL device descriptor + * @ma_val: threshold value in milli unit + * @type: type of the channel, in or curr + * @field_width: bits size for data or threshold field + * + * Return: Raw ADC value for hardware + */ +static unsigned int bcl_convert_milliunit_to_raw(const struct bcl_desc *desc, int mval, + enum bcl_channel_type type, u8 field_width) +{ + u32 def_scale = desc->channel[type].default_scale_nu; + u32 lsb_weight = field_width > 8 ? 1 : 1 << field_width; + u32 scaling_factor = def_scale * lsb_weight; + + return div_s64((s64)mval * 1000000, scaling_factor); +} + +/** + * bcl_convert_milliunit_to_index - Convert milliunit to in or curr index + * @desc: BCL device descriptor + * @val: in or curr value in milli unit + * @type: type of the channel, in or curr + * + * Converts a value in milli unit to an index for BCL that use indexed thresholds. + * + * Return: Voltage index value + */ +static unsigned int bcl_convert_milliunit_to_index(const struct bcl_desc *desc, int val, + enum bcl_channel_type type) +{ + return div_s64((s64)val - desc->channel[type].base, desc->channel[type].step); +} + +/** + * bcl_convert_index_to_milliunit - Convert in or curr index to milli unit + * @desc: BCL device descriptor + * @val: index value + * @type: type of the channel, in or curr + * + * Converts an index value to milli unit for BCL that use indexed thresholds. + * + * Return: Voltage value in millivolts + */ +static unsigned int bcl_convert_index_to_milliunit(const struct bcl_desc *desc, int val, + enum bcl_channel_type type) +{ + return desc->channel[type].base + val * desc->channel[type].step; +} + +static int bcl_in_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl) +{ + const struct bcl_desc *desc = bcl->desc; + u32 raw_val; + + int thresh = clamp_val(value, desc->channel[IN].base, desc->channel[IN].max); + + if (desc->channel[IN].thresh_type[lvl] == ADC) + raw_val = bcl_convert_milliunit_to_raw(desc, thresh, IN, + desc->thresh_field_bits_size); + else + raw_val = bcl_convert_milliunit_to_index(desc, thresh, IN); + + return regmap_field_write(bcl->fields[F_IN_L0_THR + lvl], raw_val); +} + +static int bcl_curr_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl) +{ + const struct bcl_desc *desc = bcl->desc; + u32 raw_val; + + /* Clamp only to curr max */ + int thresh = clamp_val(value, value, desc->channel[CURR].max); + + if (desc->channel[CURR].thresh_type[lvl] == ADC) + raw_val = bcl_convert_milliunit_to_raw(desc, thresh, CURR, + desc->thresh_field_bits_size); + else + raw_val = bcl_convert_milliunit_to_index(desc, thresh, CURR); + + return regmap_field_write(bcl->fields[F_CURR_H0_THR + lvl], raw_val); +} + +static int bcl_in_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out) +{ + int ret, thresh; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_IN_L0_THR + lvl, &raw_val); + if (ret) + return ret; + + if (desc->channel[IN].thresh_type[lvl] == ADC) + thresh = bcl_convert_raw_to_milliunit(desc, raw_val, IN, + desc->thresh_field_bits_size); + else + thresh = bcl_convert_index_to_milliunit(desc, raw_val, IN); + + *out = thresh; + + return 0; +} + +static int bcl_curr_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out) +{ + int ret, thresh; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_CURR_H0_THR + lvl, &raw_val); + if (ret) + return ret; + + if (desc->channel[CURR].thresh_type[lvl] == ADC) + thresh = bcl_convert_raw_to_milliunit(desc, raw_val, CURR, + desc->thresh_field_bits_size); + else + thresh = bcl_convert_index_to_milliunit(desc, raw_val, CURR); + + *out = thresh; + + return 0; +} + +static int bcl_curr_input_read(struct bcl_device *bcl, long *out) +{ + int ret; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_CURR_INPUT, &raw_val); + if (ret) + return ret; + + /* + * The sensor sometime can read a value 0 if there are + * consecutive reads + */ + if (raw_val != 0) + bcl->last_curr_input = + bcl_convert_raw_to_milliunit(desc, raw_val, CURR, + desc->data_field_bits_size); + + *out = bcl->last_curr_input; + + return 0; +} + +static int bcl_in_input_read(struct bcl_device *bcl, long *out) +{ + int ret; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = bcl_read_field_value(bcl, F_IN_INPUT, &raw_val); + if (ret) + return ret; + + if (raw_val < GENMASK(desc->data_field_bits_size - 1, 0)) + bcl->last_in_input = + bcl_convert_raw_to_milliunit(desc, raw_val, IN, + desc->data_field_bits_size); + + *out = bcl->last_in_input; + + return 0; +} + +static int bcl_read_alarm_status(struct bcl_device *bcl, + enum bcl_limit_alarm lvl, long *status) +{ + int ret; + u32 raw_val = 0; + + ret = bcl_read_field_value(bcl, F_LVL0_ALARM + lvl, &raw_val); + if (ret) + return ret; + + *status = raw_val; + + return 0; +} + +static unsigned int bcl_get_version_major(const struct bcl_device *bcl) +{ + u32 raw_val = 0; + + bcl_read_field_value(bcl, F_V_MAJOR, &raw_val); + + return raw_val; +} + +static unsigned int bcl_get_version_minor(const struct bcl_device *bcl) +{ + u32 raw_val = 0; + + bcl_read_field_value(bcl, F_V_MINOR, &raw_val); + + return raw_val; +} + +static void bcl_hwmon_notify_event(struct bcl_device *bcl, enum bcl_limit_alarm alarm) +{ + if (bcl->in_mon_enabled) + hwmon_notify_event(bcl->hwmon_dev, hwmon_in, + in_lvl_to_attr_map[alarm], 0); + if (bcl->curr_mon_enabled) + hwmon_notify_event(bcl->hwmon_dev, hwmon_curr, + curr_lvl_to_attr_map[alarm], 0); +} + +static void bcl_alarm_enable_poll(struct work_struct *work) +{ + struct bcl_alarm_data *alarm = container_of(work, struct bcl_alarm_data, + alarm_poll_work.work); + struct bcl_device *bcl = alarm->device; + long status; + + guard(mutex)(&bcl->lock); + + if (bcl_read_alarm_status(bcl, alarm->type, &status)) + goto re_schedule; + + if (!status & !alarm->irq_enabled) { + bcl_enable_irq(alarm); + bcl_hwmon_notify_event(bcl, alarm->type); + return; + } + +re_schedule: + schedule_delayed_work(&alarm->alarm_poll_work, + msecs_to_jiffies(BCL_ALARM_POLLING_MS)); +} + +static irqreturn_t bcl_handle_alarm(int irq, void *data) +{ + struct bcl_alarm_data *alarm = data; + struct bcl_device *bcl = alarm->device; + long status; + + guard(mutex)(&bcl->lock); + + if (bcl_read_alarm_status(bcl, alarm->type, &status) || !status) + return IRQ_HANDLED; + + if (!bcl->hwmon_dev) + return IRQ_HANDLED; + + bcl_hwmon_notify_event(bcl, alarm->type); + + bcl_disable_irq(alarm); + schedule_delayed_work(&alarm->alarm_poll_work, + msecs_to_jiffies(BCL_ALARM_POLLING_MS)); + + dev_dbg(bcl->dev, "Irq:%d triggered for bcl type:%d\n", + irq, alarm->type); + + return IRQ_HANDLED; +} + +static umode_t bcl_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct bcl_device *bcl = data; + + switch (type) { + case hwmon_in: + if (!bcl->in_mon_enabled) + return 0; + switch (attr) { + case hwmon_in_input: + return bcl->in_input_enabled ? 0444 : 0; + case hwmon_in_label: + case hwmon_in_min_alarm: + case hwmon_in_lcrit_alarm: + return 0444; + case hwmon_in_min: + case hwmon_in_lcrit: + return 0644; + default: + return 0; + } + case hwmon_curr: + if (!bcl->curr_mon_enabled) + return 0; + switch (attr) { + case hwmon_curr_input: + case hwmon_curr_label: + case hwmon_curr_max_alarm: + case hwmon_curr_crit_alarm: + return 0444; + case hwmon_curr_max: + case hwmon_curr_crit: + return 0644; + default: + return 0; + } + default: + return 0; + } +} + +static int bcl_hwmon_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct bcl_device *bcl = dev_get_drvdata(dev); + int ret = -EOPNOTSUPP; + + guard(mutex)(&bcl->lock); + + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_min: + case hwmon_in_lcrit: + ret = bcl_in_thresh_write(bcl, val, in_attr_to_lvl_map[attr]); + break; + default: + ret = -EOPNOTSUPP; + } + break; + case hwmon_curr: + switch (attr) { + case hwmon_curr_max: + case hwmon_curr_crit: + ret = bcl_curr_thresh_write(bcl, val, curr_attr_to_lvl_map[attr]); + break; + default: + ret = -EOPNOTSUPP; + } + break; + default: + break; + } + + return ret; +} + +static int bcl_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *value) +{ + struct bcl_device *bcl = dev_get_drvdata(dev); + int ret; + + guard(mutex)(&bcl->lock); + + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_input: + ret = bcl_in_input_read(bcl, value); + break; + case hwmon_in_min: + case hwmon_in_lcrit: + ret = bcl_in_thresh_read(bcl, in_attr_to_lvl_map[attr], value); + break; + case hwmon_in_min_alarm: + case hwmon_in_lcrit_alarm: + ret = bcl_read_alarm_status(bcl, in_attr_to_lvl_map[attr], value); + break; + default: + ret = -EOPNOTSUPP; + } + break; + case hwmon_curr: + switch (attr) { + case hwmon_curr_input: + ret = bcl_curr_input_read(bcl, value); + break; + case hwmon_curr_max: + case hwmon_curr_crit: + ret = bcl_curr_thresh_read(bcl, curr_attr_to_lvl_map[attr], value); + break; + case hwmon_curr_max_alarm: + case hwmon_curr_crit_alarm: + ret = bcl_read_alarm_status(bcl, curr_attr_to_lvl_map[attr], value); + break; + default: + ret = -EOPNOTSUPP; + } + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int bcl_hwmon_read_string(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + switch (type) { + case hwmon_in: + if (attr != hwmon_in_label) + break; + *str = bcl_channel_label[IN]; + return 0; + case hwmon_curr: + if (attr != hwmon_curr_label) + break; + *str = bcl_channel_label[CURR]; + return 0; + default: + break; + } + + return -EOPNOTSUPP; +} + +static const struct hwmon_ops bcl_hwmon_ops = { + .is_visible = bcl_hwmon_is_visible, + .read = bcl_hwmon_read, + .read_string = bcl_hwmon_read_string, + .write = bcl_hwmon_write, +}; + +static const struct hwmon_channel_info *bcl_hwmon_info[] = { + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_MIN | + HWMON_I_LCRIT | HWMON_I_MIN_ALARM | + HWMON_I_LCRIT_ALARM), + HWMON_CHANNEL_INFO(curr, + HWMON_C_INPUT | HWMON_C_LABEL | HWMON_C_MAX | + HWMON_C_CRIT | HWMON_C_MAX_ALARM | + HWMON_C_CRIT_ALARM), + NULL, +}; + +static const struct hwmon_chip_info bcl_hwmon_chip_info = { + .ops = &bcl_hwmon_ops, + .info = bcl_hwmon_info, +}; + +static int bcl_curr_thresh_update(struct bcl_device *bcl) +{ + int ret, i; + + if (!bcl->curr_thresholds[0]) + return 0; + + for (i = 0; i < ALARM_MAX; i++) { + ret = bcl_curr_thresh_write(bcl, bcl->curr_thresholds[i], i); + if (ret < 0) + return ret; + } + + return 0; +} + +static void bcl_hw_channel_mon_init(struct bcl_device *bcl) +{ + bcl->in_mon_enabled = bcl_in_monitor_enabled(bcl); + bcl->in_input_enabled = bcl_in_input_enabled(bcl); + bcl->curr_mon_enabled = bcl_curr_monitor_enabled(bcl); +} + +static int bcl_alarm_irq_init(struct platform_device *pdev, + struct bcl_device *bcl) +{ + int ret = 0, irq_num = 0, i = 0; + struct bcl_alarm_data *alarm; + + for (i = LVL0; i < ALARM_MAX; i++) { + alarm = &bcl->bcl_alarms[i]; + alarm->type = i; + alarm->device = bcl; + + ret = devm_delayed_work_autocancel(bcl->dev, &alarm->alarm_poll_work, + bcl_alarm_enable_poll); + if (ret) + return ret; + + irq_num = platform_get_irq_byname(pdev, bcl_int_names[i]); + if (irq_num <= 0) + continue; + + ret = devm_request_threaded_irq(&pdev->dev, irq_num, NULL, + bcl_handle_alarm, IRQF_ONESHOT, + bcl_int_names[i], alarm); + if (ret) { + dev_err(&pdev->dev, "Error requesting irq(%s).err:%d\n", + bcl_int_names[i], ret); + return ret; + } + alarm->irq = irq_num; + enable_irq_wake(alarm->irq); + alarm->irq_enabled = true; + } + + return 0; +} + +static int bcl_regmap_field_init(struct device *dev, struct bcl_device *bcl, + const struct bcl_desc *data) +{ + int i; + struct reg_field fields[F_MAX_FIELDS]; + + BUILD_BUG_ON(ARRAY_SIZE(common_reg_fields) != COMMON_FIELD_MAX); + + for (i = 0; i < data->num_reg_fields; i++) { + if (i < COMMON_FIELD_MAX) + fields[i] = common_reg_fields[i]; + else + fields[i] = data->reg_fields[i]; + + /* Need to adjust BCL base from regmap dynamically */ + fields[i].reg += bcl->base; + } + + return devm_regmap_field_bulk_alloc(dev, bcl->regmap, bcl->fields, + fields, data->num_reg_fields); +} + +static int bcl_get_device_property_data(struct platform_device *pdev, + struct bcl_device *bcl) +{ + struct device *dev = &pdev->dev; + int ret; + u32 reg; + + ret = device_property_read_u32(dev, "reg", ®); + if (ret < 0) + return ret; + + bcl->base = reg; + + device_property_read_u32_array(dev, "overcurrent-thresholds-milliamp", + bcl->curr_thresholds, 2); + return 0; +} + +static int bcl_probe(struct platform_device *pdev) +{ + struct bcl_device *bcl; + int ret; + + bcl = devm_kzalloc(&pdev->dev, sizeof(*bcl), GFP_KERNEL); + if (!bcl) + return -ENOMEM; + + bcl->dev = &pdev->dev; + bcl->desc = device_get_match_data(&pdev->dev); + if (!bcl->desc) + return -EINVAL; + + ret = devm_mutex_init(bcl->dev, &bcl->lock); + if (ret) + return ret; + + bcl->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!bcl->regmap) { + dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); + return -EINVAL; + } + + ret = bcl_get_device_property_data(pdev, bcl); + if (ret < 0) + return ret; + + ret = bcl_regmap_field_init(bcl->dev, bcl, bcl->desc); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to allocate regmap fields, err:%d\n", ret); + return ret; + } + + if (!bcl_hw_is_enabled(bcl)) + return -ENODEV; + + ret = bcl_curr_thresh_update(bcl); + if (ret < 0) + return ret; + + ret = bcl_alarm_irq_init(pdev, bcl); + if (ret < 0) + return ret; + + bcl_hw_channel_mon_init(bcl); + + dev_set_drvdata(&pdev->dev, bcl); + + bcl->hwmon_name = devm_hwmon_sanitize_name(&pdev->dev, + dev_name(bcl->dev)); + if (IS_ERR(bcl->hwmon_name)) { + dev_err(&pdev->dev, "Failed to sanitize hwmon name\n"); + return PTR_ERR(bcl->hwmon_name); + } + + bcl->hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, + bcl->hwmon_name, + bcl, + &bcl_hwmon_chip_info, + NULL); + if (IS_ERR(bcl->hwmon_dev)) { + dev_err(&pdev->dev, "Failed to register hwmon device: %ld\n", + PTR_ERR(bcl->hwmon_dev)); + return PTR_ERR(bcl->hwmon_dev); + } + + dev_dbg(&pdev->dev, "BCL hwmon device with version: %u.%u registered\n", + bcl_get_version_major(bcl), bcl_get_version_minor(bcl)); + + return 0; +} + +static const struct of_device_id bcl_match[] = { + { + .compatible = "qcom,bcl-v1", + .data = &pm7250b_data, + }, { + .compatible = "qcom,bcl-v2", + .data = &pm8350_data, + }, { + .compatible = "qcom,bcl-v3-bmx", + .data = &pm8550b_data, + }, { + .compatible = "qcom,bcl-v3-wb", + .data = &pmw5100_data, + }, { + .compatible = "qcom,bcl-v3-core", + .data = &pm8550_data, + }, { + .compatible = "qcom,bcl-v4-bmx", + .data = &pmih010_data, + }, { + .compatible = "qcom,bcl-v4-wb", + .data = &pmw6100_data, + }, { + .compatible = "qcom,bcl-v4-core", + .data = &pmh010_data, + }, { + .compatible = "qcom,bcl-v4-pmv010", + .data = &pmv010_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, bcl_match); + +static struct platform_driver bcl_driver = { + .probe = bcl_probe, + .driver = { + .name = BCL_DRIVER_NAME, + .of_match_table = bcl_match, + }, +}; + +MODULE_AUTHOR("Manaf Meethalavalappu Pallikunhi "); +MODULE_DESCRIPTION("QCOM BCL HWMON driver"); +module_platform_driver(bcl_driver); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/qcom-bcl-hwmon.h b/drivers/hwmon/qcom-bcl-hwmon.h new file mode 100644 index 0000000000000..28a7154d9486a --- /dev/null +++ b/drivers/hwmon/qcom-bcl-hwmon.h @@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2026, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __QCOM_BCL_HWMON_H__ +#define __QCOM_BCL_HWMON_H__ + +#define BCL_DRIVER_NAME "qcom-bcl-hwmon" + +/* BCL common regmap offset */ +#define REVISION1 0x0 +#define REVISION2 0x1 +#define STATUS 0x8 +#define INT_RT_STS 0x10 +#define EN_CTL1 0x46 + +/* BCL GEN1 regmap offsets */ +#define MODE_CTL1 0x41 +#define VADC_L0_THR 0x48 +#define VCMP_L1_THR 0x49 +#define IADC_H0_THR 0x4b +#define IADC_H1_THR 0x4c +#define VADC_CONV_REQ 0x72 +#define IADC_CONV_REQ 0x82 +#define VADC_DATA1 0x76 +#define IADC_DATA1 0x86 + +/* BCL GEN3 regmap offsets */ +#define VCMP_CTL 0x44 +#define VCMP_L0_THR 0x47 +#define PARAM_1 0x0e +#define IADC_H1_THR_GEN3 0x4d + +#define BCL_IN_INC_MV 25 +#define BCL_ALARM_POLLING_MS 50 + +/** + * enum bcl_limit_alarm - BCL alarm threshold levels + * @LVL0: Level 0 alarm threshold (mapped to in_min_alarm or curr_max_alarm) + * @LVL1: Level 1 alarm threshold (mapped to in_lcrit_alarm or curr_crit_alarm) + * @ALARM_MAX: sentinel value + * + * Defines the three threshold levels for BCL monitoring. Each level corresponds + * to different severity of in or curr conditions. + */ +enum bcl_limit_alarm { + LVL0, + LVL1, + + ALARM_MAX, +}; + +/** + * enum bcl_channel_type - BCL supported sensor channel type + * @IN: in (voltage) channel + * @CURR: curr (current) channel + * @CHANNEL_MAX: sentinel value + * + * Defines the supported channel types for bcl. + */ +enum bcl_channel_type { + IN, + CURR, + + CHANNEL_MAX, +}; + +/** + * enum bcl_thresh_type - voltage or current threshold representation type + * @ADC: Raw ADC value representation + * @INDEX: Index-based voltage or current representation + * + * Specifies how voltage or current thresholds are stored and interpreted in + * registers. Some PMICs use raw ADC values while others use indexed values. + */ +enum bcl_thresh_type { + ADC, + INDEX, +}; + +/** + * enum bcl_fields - BCL register field identifiers + * @F_V_MAJOR: Major revision info field + * @F_V_MINOR: Minor revision info field + * @F_CTL_EN: Monitor enable control field + * @F_LVL0_ALARM: Level 0 alarm status field + * @F_LVL1_ALARM: Level 1 alarm status field + * @COMMON_FIELD_MAX: sentinel value for common fields + * @F_IN_MON_EN: voltage monitor enable control field + * @F_IN_L0_THR: voltage level 0 threshold field + * @F_IN_L1_THR: voltage level 1 threshold field + * @F_IN_INPUT_EN: voltage input enable control field + * @F_IN_INPUT: voltage input data field + * @F_CURR_MON_EN: current monitor enable control field + * @F_CURR_H0_THR: current level 0 threshold field + * @F_CURR_H1_THR: current level 1 threshold field + * @F_CURR_INPUT: current input data field + * @F_MAX_FIELDS: sentinel value + * + * Enumeration of all register fields used by the BCL driver for accessing + * registers through regmap fields. + */ +enum bcl_fields { + F_V_MAJOR, + F_V_MINOR, + + F_CTL_EN, + + /* common alarm for in and curr channel */ + F_LVL0_ALARM, + F_LVL1_ALARM, + + COMMON_FIELD_MAX, + + F_IN_MON_EN = COMMON_FIELD_MAX, + F_IN_L0_THR, + F_IN_L1_THR, + + F_IN_INPUT_EN, + F_IN_INPUT, + + F_CURR_MON_EN, + F_CURR_H0_THR, + F_CURR_H1_THR, + + F_CURR_INPUT, + + F_MAX_FIELDS +}; + +#define ADD_BCL_HWMON_ALARM_MAPS(_type, lvl0_attr, lvl1_attr) \ + \ +static const u8 _type##_attr_to_lvl_map[] = { \ + [hwmon_##_type##_##lvl0_attr] = LVL0, \ + [hwmon_##_type##_##lvl1_attr] = LVL1, \ + [hwmon_##_type##_##lvl0_attr##_alarm] = LVL0, \ + [hwmon_##_type##_##lvl1_attr##_alarm] = LVL1, \ +}; \ + \ +static const u8 _type##_lvl_to_attr_map[ALARM_MAX] = { \ + [LVL0] = hwmon_##_type##_##lvl0_attr##_alarm, \ + [LVL1] = hwmon_##_type##_##lvl1_attr##_alarm, \ +} + +/** + * struct bcl_channel_cfg - BCL channel related configuration + * @default_scale_nu: Default scaling factor in nano unit + * @base: Base threshold value in milli unit + * @max: Maximum threshold value in milli unit + * @step: step increment value between two indexed threshold value + * @thresh_type: Array specifying threshold representation type for each alarm level + * + * Contains hardware-specific configuration and scaling parameters for different + * channel(voltage and current).. + */ + +struct bcl_channel_cfg { + u32 default_scale_nu; + u32 base; + u32 max; + u32 step; + u8 thresh_type[ALARM_MAX]; +}; + +/** + * struct bcl_desc - BCL device descriptor + * @reg_fields: Array of register field definitions for this device variant + * @channel: Each channel specific(voltage or current) configuration + * @num_reg_fields: Number of register field definitions for this device variant + * @data_field_bits_size: data read register bit size + * @thresh_field_bits_size: lsb bit size those are not included in threshold register + * + * Contains hardware-specific configuration and scaling parameters for different + * BCL variants. Each PMIC model may have different register layouts and + * conversion factors. + */ + +struct bcl_desc { + const struct reg_field *reg_fields; + struct bcl_channel_cfg channel[CHANNEL_MAX]; + u8 num_reg_fields; + u8 data_field_bits_size; + u8 thresh_field_bits_size; +}; + +struct bcl_device; + +/** + * struct bcl_alarm_data - BCL alarm interrupt data + * @irq: IRQ number assigned to this alarm + * @irq_enabled: Flag indicating if IRQ is enabled + * @type: Alarm level type (LVL0, or LVL1) + * @device: Pointer to parent BCL device structure + * @alarm_poll_work: delayed_work to poll alarm status + * + * Stores interrupt-related information for each alarm threshold level. + * Used by the IRQ handler to identify which alarm triggered. + */ +struct bcl_alarm_data { + int irq; + bool irq_enabled; + enum bcl_limit_alarm type; + struct bcl_device *device; + struct delayed_work alarm_poll_work; +}; + +/** + * struct bcl_device - Main BCL device structure + * @dev: Pointer to device structure + * @regmap: Regmap for accessing PMIC registers + * @fields: Array of regmap fields for register access + * @bcl_alarms: Array of alarm data structures for each threshold level + * @lock: Mutex for protecting concurrent hardware access + * @in_mon_enabled: Flag indicating if voltage monitoring is enabled + * @curr_mon_enabled: Flag indicating if current monitoring is enabled + * @curr_thresholds: Current threshold values in milliamps from dt-binding(LVL0 and LVL1) + * @base: the BCL regbase offset from regmap + * @in_input_enabled: Flag indicating if voltage input reading is enabled + * @last_in_input: Last valid voltage input reading in millivolts + * @last_curr_input: Last valid current input reading in milliamps + * @desc: Pointer to device descriptor with hardware-specific parameters + * @hwmon_dev: Pointer to registered hwmon device + * @hwmon_name: Sanitized name for hwmon device + * + * Main driver structure containing all state and configuration for a BCL + * monitoring instance. Manages voltage and current monitoring, thresholds, + * and alarm handling. + */ +struct bcl_device { + struct device *dev; + struct regmap *regmap; + u16 base; + struct regmap_field *fields[F_MAX_FIELDS]; + struct bcl_alarm_data bcl_alarms[ALARM_MAX]; + struct mutex lock; + u32 curr_thresholds[ALARM_MAX]; + u32 last_in_input; + u32 last_curr_input; + bool in_mon_enabled; + bool curr_mon_enabled; + bool in_input_enabled; + const struct bcl_desc *desc; + struct device *hwmon_dev; + char *hwmon_name; +}; + +/** + * bcl_read_field_value - Read alarm status for a given level + * @bcl: BCL device structure + * @id: Index in bcl->fields[] + * @val: Pointer to store val + * + * Return: 0 on success or regmap error code + */ +static inline int bcl_read_field_value(const struct bcl_device *bcl, enum bcl_fields id, u32 *val) +{ + return regmap_field_read(bcl->fields[id], val); +} + +/** + * bcl_field_enabled - Generic helper to check if a regmap field is enabled + * @bcl: BCL device structure + * @field: Index in bcl->fields[] + * + * Return: true if field is non-zero, false otherwise + */ +static inline bool bcl_field_enabled(const struct bcl_device *bcl, enum bcl_fields id) +{ + int ret; + u32 val = 0; + + ret = regmap_field_read(bcl->fields[id], &val); + if (ret) + return false; + + return !!val; +} + +#define bcl_in_input_enabled(bcl) bcl_field_enabled(bcl, F_IN_INPUT_EN) +#define bcl_curr_monitor_enabled(bcl) bcl_field_enabled(bcl, F_CURR_MON_EN) +#define bcl_in_monitor_enabled(bcl) bcl_field_enabled(bcl, F_IN_MON_EN) +#define bcl_hw_is_enabled(bcl) bcl_field_enabled(bcl, F_CTL_EN) + +/** + * bcl_enable_irq - Generic helper to enable alarm irq + * @alarm: BCL level alarm data + */ +static inline void bcl_enable_irq(struct bcl_alarm_data *alarm) +{ + if (alarm->irq_enabled) + return; + alarm->irq_enabled = true; + enable_irq(alarm->irq); + enable_irq_wake(alarm->irq); +} + +/** + * bcl_disable_irq - Generic helper to disable alarm irq + * @alarm: BCL level alarm data + */ +static inline void bcl_disable_irq(struct bcl_alarm_data *alarm) +{ + if (!alarm->irq_enabled) + return; + alarm->irq_enabled = false; + disable_irq_nosync(alarm->irq); + disable_irq_wake(alarm->irq); +} + +#endif /* __QCOM_BCL_HWMON_H__ */ diff --git a/drivers/hwtracing/Kconfig b/drivers/hwtracing/Kconfig index 911ee977103c0..8a640218eed84 100644 --- a/drivers/hwtracing/Kconfig +++ b/drivers/hwtracing/Kconfig @@ -7,4 +7,6 @@ source "drivers/hwtracing/intel_th/Kconfig" source "drivers/hwtracing/ptt/Kconfig" +source "drivers/hwtracing/qcom/Kconfig" + endmenu diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index ab16d06783a57..821a1b06b20c2 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -55,5 +55,5 @@ coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o -coresight-ctcu-y := coresight-ctcu-core.o +coresight-ctcu-y := coresight-ctcu-core.o coresight-ctcu-byte-cntr.o obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 6d65c43d574fd..0dc80a2acdfac 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -415,7 +415,8 @@ static void coresight_disable_sink(struct coresight_device *csdev) static int coresight_enable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child, - struct coresight_device *source) + struct coresight_device *source, + enum cs_mode mode) { int link_subtype; struct coresight_connection *inconn, *outconn; @@ -432,7 +433,7 @@ static int coresight_enable_link(struct coresight_device *csdev, if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn)) return PTR_ERR(outconn); - return link_ops(csdev)->enable(csdev, inconn, outconn); + return link_ops(csdev)->enable(csdev, inconn, outconn, mode); } static void coresight_disable_link(struct coresight_device *csdev, @@ -716,7 +717,7 @@ static int coresight_enable_path_from_to(struct coresight_path *path, parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; ret = coresight_enable_link(csdev, parent, child, - coresight_get_source(path)); + coresight_get_source(path), mode); if (ret) goto err_disable_helpers; break; @@ -773,6 +774,33 @@ struct coresight_device *coresight_get_sink(struct coresight_path *path) } EXPORT_SYMBOL_GPL(coresight_get_sink); +/** + * coresight_get_in_port: Find the input port number at @remote where the @csdev + * device is connected to. + * + * @csdev: csdev of the device. + * @remote: csdev of the remote device which is connected to @csdev. + * + * Return: port number upon success or -EINVAL for fail. + */ +int coresight_get_in_port(struct coresight_device *csdev, + struct coresight_device *remote) +{ + struct coresight_platform_data *pdata = remote->pdata; + int i; + + for (i = 0; i < pdata->nr_inconns; ++i) { + if (!pdata->in_conns[i]) + continue; + + if (pdata->in_conns[i]->src_dev == csdev) + return pdata->in_conns[i]->dest_port; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(coresight_get_in_port); + u32 coresight_get_sink_id(struct coresight_device *csdev) { if (!csdev->ea) diff --git a/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c new file mode 100644 index 0000000000000..5ab97a71f02f6 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-ctcu-byte-cntr.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include + +#include "coresight-ctcu.h" +#include "coresight-priv.h" +#include "coresight-tmc.h" + +static irqreturn_t byte_cntr_handler(int irq, void *data) +{ + struct ctcu_byte_cntr *byte_cntr_data = data; + + atomic_inc(&byte_cntr_data->irq_cnt); + wake_up(&byte_cntr_data->wq); + + return IRQ_HANDLED; +} + +static void ctcu_cfg_byte_cntr_reg(struct ctcu_drvdata *drvdata, u32 val, + u32 offset) +{ + /* A one value for IRQCTRL register represents 8 bytes */ + ctcu_program_register(drvdata, val / 8, offset); +} + +static struct ctcu_byte_cntr *ctcu_get_byte_cntr(struct coresight_device *ctcu, + struct coresight_device *etr) +{ + struct ctcu_drvdata *drvdata = dev_get_drvdata(ctcu->dev.parent); + int port; + + port = coresight_get_in_port(etr, ctcu); + if (port < 0 || port > 1) + return NULL; + + return &drvdata->byte_cntr_data[port]; +} + +static bool ctcu_byte_cntr_switch_buffer(struct tmc_drvdata *etr_drvdata, + struct ctcu_byte_cntr *byte_cntr_data) +{ + struct etr_buf_node *nd, *next, *curr_node = NULL, *picked_node = NULL; + struct etr_buf *curr_buf = etr_drvdata->sysfs_buf; + bool found_free_buf = false; + unsigned long flags; + + if (WARN_ON(!etr_drvdata || !byte_cntr_data)) + return false; + + /* Stop the ETR before initiating the switch */ + if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_DISABLED) + tmc_etr_enable_disable_hw(etr_drvdata, false); + + /* + * Serialise the sysfs_buf/etr_buf swap against the ETR sink + * enable/disable paths which also touch these fields under the + * spinlock. tmc_etr_enable_disable_hw() takes the same lock, so it + * must be called outside this critical section. + */ + raw_spin_lock_irqsave(&etr_drvdata->spinlock, flags); + list_for_each_entry_safe(nd, next, &etr_drvdata->etr_buf_list, link) { + /* curr_buf is free for next round */ + if (nd->sysfs_buf == curr_buf) { + nd->is_free = true; + curr_node = nd; + } else if (!found_free_buf && nd->is_free) { + picked_node = nd; + found_free_buf = true; + } + } + + if (found_free_buf) { + curr_node->pos = 0; + curr_node->reading = true; + byte_cntr_data->buf_node = curr_node; + etr_drvdata->sysfs_buf = picked_node->sysfs_buf; + etr_drvdata->etr_buf = picked_node->sysfs_buf; + picked_node->is_free = false; + /* Reset irq_cnt for next etr_buf */ + atomic_set(&byte_cntr_data->irq_cnt, 0); + } + raw_spin_unlock_irqrestore(&etr_drvdata->spinlock, flags); + + /* Restart the ETR once a free buffer is available */ + if (found_free_buf && + coresight_get_mode(etr_drvdata->csdev) != CS_MODE_DISABLED) + tmc_etr_enable_disable_hw(etr_drvdata, true); + + return found_free_buf; +} + +/* + * ctcu_byte_cntr_get_data() - reads data from the deactivated and filled buffer. + * The byte-cntr reading work reads data from the deactivated and filled buffer. + * The read operation waits for a buffer to become available, either filled or + * upon timeout, and then reads trace data from the synced buffer. + */ +static ssize_t tmc_byte_cntr_get_data(struct tmc_drvdata *etr_drvdata, loff_t pos, + size_t len, char **bufpp) +{ + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata); + struct device *dev = &etr_drvdata->csdev->dev; + struct ctcu_byte_cntr *byte_cntr_data; + struct etr_buf *sysfs_buf; + atomic_t *irq_cnt; + ssize_t actual; + int ret; + + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev); + if (!byte_cntr_data || !byte_cntr_data->irq_enabled) + return -EINVAL; + + irq_cnt = &byte_cntr_data->irq_cnt; + +wait_buffer: + if (!byte_cntr_data->buf_node) { + ret = wait_event_interruptible_timeout(byte_cntr_data->wq, + (atomic_read(irq_cnt) >= MAX_IRQ_CNT - 1) || + !byte_cntr_data->enable, + BYTE_CNTR_TIMEOUT); + if (ret < 0) + return ret; + /* + * The current etr_buf is almost full or timeout is triggered, + * so switch the buffer and mark the switched buffer as reading. + */ + if (byte_cntr_data->enable) { + if (!ctcu_byte_cntr_switch_buffer(etr_drvdata, byte_cntr_data)) { + dev_err(dev, "Switch buffer failed for the byte-cntr\n"); + return -ENOMEM; + } + } else { + /* Exit byte-cntr reading */ + return 0; + } + } + + /* Check the status of current etr_buf */ + if (atomic_read(irq_cnt) >= MAX_IRQ_CNT) + dev_warn(dev, "Data overwrite happened\n"); + + pos = byte_cntr_data->buf_node->pos; + sysfs_buf = byte_cntr_data->buf_node->sysfs_buf; + actual = tmc_etr_read_sysfs_buf(sysfs_buf, pos, len, bufpp); + if (actual <= 0) { + /* Reset buf_node upon reading is finished or failed */ + byte_cntr_data->buf_node->reading = false; + byte_cntr_data->buf_node = NULL; + + /* + * Nothing in the buffer, waiting for the next buffer + * to be filled. + */ + if (actual == 0) + goto wait_buffer; + } + + return actual; +} + +static int tmc_read_prepare_byte_cntr(struct tmc_drvdata *etr_drvdata) +{ + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata); + struct ctcu_byte_cntr *byte_cntr_data; + unsigned long flags; + int ret = 0; + + /* byte-cntr is operating with SYSFS mode being enabled only */ + if (coresight_get_mode(etr_drvdata->csdev) != CS_MODE_SYSFS) + return -EINVAL; + + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev); + if (!byte_cntr_data || !byte_cntr_data->irq_enabled) + return -EINVAL; + + raw_spin_lock_irqsave(&byte_cntr_data->spin_lock, flags); + if (byte_cntr_data->reading) { + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + return -EBUSY; + } + + /* byte_cntr_data->enable may race with ctcu_platform_remove() */ + if (!byte_cntr_data->enable) { + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + return -ENODEV; + } + + byte_cntr_data->reading = true; + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + /* Setup an available etr_buf_list for byte-cntr */ + ret = tmc_create_etr_buf_list(etr_drvdata, 2); + if (ret) { + byte_cntr_data->reading = false; + return ret; + } + + scoped_guard(raw_spinlock_irqsave, &byte_cntr_data->spin_lock) { + atomic_set(&byte_cntr_data->irq_cnt, 0); + /* + * Configure the byte-cntr register to enable IRQ. The + * configured size is 5% of the buffer_size. + */ + ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata, + etr_drvdata->size / MAX_IRQ_CNT, + byte_cntr_data->irq_ctrl_offset); + byte_cntr_data->buf_node = NULL; + } + /* enable_irq_wake() may sleep on slow-bus irqchips, call it unlocked */ + enable_irq_wake(byte_cntr_data->irq); + + return 0; +} + +static int tmc_read_unprepare_byte_cntr(struct tmc_drvdata *etr_drvdata) +{ + struct coresight_device *ctcu = tmc_etr_get_ctcu_device(etr_drvdata); + struct ctcu_byte_cntr *byte_cntr_data; + + /* + * Do the unprepare operation only when the byte_cntr_data->reading + * is truly set + */ + byte_cntr_data = ctcu_get_byte_cntr(ctcu, etr_drvdata->csdev); + if (!byte_cntr_data || !byte_cntr_data->irq_enabled || + !byte_cntr_data->reading) + return -EINVAL; + + tmc_clean_etr_buf_list(etr_drvdata); + scoped_guard(raw_spinlock_irqsave, &byte_cntr_data->spin_lock) { + /* Configure the byte-cntr register to disable IRQ */ + ctcu_cfg_byte_cntr_reg(byte_cntr_data->ctcu_drvdata, 0, + byte_cntr_data->irq_ctrl_offset); + byte_cntr_data->buf_node = NULL; + byte_cntr_data->reading = false; + } + /* + * The threshold IRQ is already disabled by the register write above, + * so no wake event can arrive here. disable_irq_wake() may sleep on + * slow-bus irqchips, so call it outside the spin_lock. + */ + disable_irq_wake(byte_cntr_data->irq); + wake_up(&byte_cntr_data->wq); + + return 0; +} + +const struct tmc_sysfs_ops byte_cntr_sysfs_ops = { + .read_prepare = tmc_read_prepare_byte_cntr, + .read_unprepare = tmc_read_unprepare_byte_cntr, + .get_trace_data = tmc_byte_cntr_get_data, +}; + +/* Start the byte-cntr function when the path is enabled. */ +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path) +{ + struct coresight_device *sink = coresight_get_sink(path); + struct ctcu_byte_cntr *byte_cntr_data; + + byte_cntr_data = ctcu_get_byte_cntr(csdev, sink); + if (!byte_cntr_data) + return; + + /* Don't start byte-cntr function when irq_enabled is not set. */ + if (!byte_cntr_data->irq_enabled || byte_cntr_data->enable) + return; + + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock); + byte_cntr_data->enable = true; +} + +/* Stop the byte-cntr function when the path is disabled. */ +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path) +{ + struct coresight_device *sink = coresight_get_sink(path); + struct ctcu_byte_cntr *byte_cntr_data; + + if (coresight_get_mode(sink) == CS_MODE_SYSFS) + return; + + byte_cntr_data = ctcu_get_byte_cntr(csdev, sink); + if (!byte_cntr_data) + return; + + guard(raw_spinlock_irqsave)(&byte_cntr_data->spin_lock); + byte_cntr_data->enable = false; +} + +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int etr_num) +{ + struct ctcu_byte_cntr *byte_cntr_data; + struct device_node *nd = dev->of_node; + int irq_num, ret, i, irq_registered = 0; + + for (i = 0; i < etr_num; i++) { + byte_cntr_data = &drvdata->byte_cntr_data[i]; + irq_num = of_irq_get(nd, i); + if (irq_num < 0) { + dev_err(dev, "Failed to get IRQ from DT for port%d\n", i); + continue; + } + + ret = devm_request_irq(dev, irq_num, byte_cntr_handler, + IRQF_TRIGGER_RISING | IRQF_SHARED, + dev_name(dev), byte_cntr_data); + if (ret) { + dev_err(dev, "Failed to register IRQ for port%d\n", i); + continue; + } + + byte_cntr_data->irq = irq_num; + byte_cntr_data->ctcu_drvdata = drvdata; + init_waitqueue_head(&byte_cntr_data->wq); + raw_spin_lock_init(&byte_cntr_data->spin_lock); + irq_registered++; + } + + if (irq_registered) + tmc_etr_set_byte_cntr_sysfs_ops(&byte_cntr_sysfs_ops); +} diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c index 9043cad42f01e..2da1a6f3d29f4 100644 --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -18,6 +19,7 @@ #include "coresight-ctcu.h" #include "coresight-priv.h" +#include "coresight-tmc.h" #define ctcu_writel(drvdata, val, offset) __raw_writel((val), drvdata->base + offset) #define ctcu_readl(drvdata, offset) __raw_readl(drvdata->base + offset) @@ -43,17 +45,21 @@ #define CTCU_ATID_REG_BIT(traceid) (traceid % 32) #define CTCU_ATID_REG_SIZE 0x10 +#define CTCU_ETR0_IRQCTRL 0x6c +#define CTCU_ETR1_IRQCTRL 0x70 #define CTCU_ETR0_ATID0 0xf8 #define CTCU_ETR1_ATID0 0x108 static const struct ctcu_etr_config sa8775p_etr_cfgs[] = { { - .atid_offset = CTCU_ETR0_ATID0, - .port_num = 0, + .atid_offset = CTCU_ETR0_ATID0, + .irq_ctrl_offset = CTCU_ETR0_IRQCTRL, + .port_num = 0, }, { - .atid_offset = CTCU_ETR1_ATID0, - .port_num = 1, + .atid_offset = CTCU_ETR1_ATID0, + .irq_ctrl_offset = CTCU_ETR1_IRQCTRL, + .port_num = 1, }, }; @@ -62,6 +68,85 @@ static const struct ctcu_config sa8775p_cfgs = { .num_etr_config = ARRAY_SIZE(sa8775p_etr_cfgs), }; +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset) +{ + CS_UNLOCK(drvdata->base); + ctcu_writel(drvdata, val, offset); + CS_LOCK(drvdata->base); +} + +static ssize_t irq_enabled_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ctcu_byte_cntr_irq_attribute *irq_attr = + container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr); + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent); + u8 port = irq_attr->port; + + if (!drvdata->byte_cntr_data[port].irq_ctrl_offset) + return -EINVAL; + + return sysfs_emit(buf, "%u\n", + (unsigned int)drvdata->byte_cntr_data[port].irq_enabled); +} + +static ssize_t irq_enabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct ctcu_byte_cntr_irq_attribute *irq_attr = + container_of(attr, struct ctcu_byte_cntr_irq_attribute, attr); + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent); + u8 port = irq_attr->port; + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + guard(raw_spinlock_irqsave)(&drvdata->byte_cntr_data[port].spin_lock); + if (drvdata->byte_cntr_data[port].reading) + return -EBUSY; + else if (drvdata->byte_cntr_data[port].irq_ctrl_offset) + drvdata->byte_cntr_data[port].irq_enabled = !!val; + + return size; +} + +static umode_t irq_enabled_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device_attribute *dev_attr = + container_of(attr, struct device_attribute, attr); + struct ctcu_byte_cntr_irq_attribute *irq_attr = + container_of(dev_attr, struct ctcu_byte_cntr_irq_attribute, attr); + struct device *dev = kobj_to_dev(kobj); + struct ctcu_drvdata *drvdata = dev_get_drvdata(dev->parent); + u8 port = irq_attr->port; + + if (drvdata && drvdata->byte_cntr_data[port].irq_ctrl_offset) + return attr->mode; + + return 0; +} + +static struct attribute *ctcu_attrs[] = { + ctcu_byte_cntr_irq_rw(0), + ctcu_byte_cntr_irq_rw(1), + NULL, +}; + +static struct attribute_group ctcu_attr_grp = { + .attrs = ctcu_attrs, + .is_visible = irq_enabled_is_visible, +}; + +static const struct attribute_group *ctcu_attr_grps[] = { + &ctcu_attr_grp, + NULL, +}; + static void ctcu_program_atid_register(struct ctcu_drvdata *drvdata, u32 reg_offset, u8 bit, bool enable) { @@ -116,23 +201,6 @@ static int __ctcu_set_etr_traceid(struct coresight_device *csdev, u8 traceid, in return 0; } -/* - * Searching the sink device from helper's view in case there are multiple helper devices - * connected to the sink device. - */ -static int ctcu_get_active_port(struct coresight_device *sink, struct coresight_device *helper) -{ - struct coresight_platform_data *pdata = helper->pdata; - int i; - - for (i = 0; i < pdata->nr_inconns; ++i) { - if (pdata->in_conns[i]->src_dev == sink) - return pdata->in_conns[i]->dest_port; - } - - return -EINVAL; -} - static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight_path *path, bool enable) { @@ -145,7 +213,7 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight return -EINVAL; } - port_num = ctcu_get_active_port(sink, csdev); + port_num = coresight_get_in_port(sink, csdev); if (port_num < 0) return -EINVAL; @@ -157,11 +225,15 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, struct coresight_path *path) { + ctcu_byte_cntr_start(csdev, path); + return ctcu_set_etr_traceid(csdev, path, true); } static int ctcu_disable(struct coresight_device *csdev, struct coresight_path *path) { + ctcu_byte_cntr_stop(csdev, path); + return ctcu_set_etr_traceid(csdev, path, false); } @@ -212,7 +284,10 @@ static int ctcu_probe(struct platform_device *pdev) for (i = 0; i < cfgs->num_etr_config; i++) { etr_cfg = &cfgs->etr_cfgs[i]; drvdata->atid_offset[i] = etr_cfg->atid_offset; + drvdata->byte_cntr_data[i].irq_ctrl_offset = + etr_cfg->irq_ctrl_offset; } + ctcu_byte_cntr_init(dev, drvdata, cfgs->num_etr_config); } } @@ -226,6 +301,7 @@ static int ctcu_probe(struct platform_device *pdev) desc.dev = dev; desc.ops = &ctcu_ops; desc.access = CSDEV_ACCESS_IOMEM(base); + desc.groups = ctcu_attr_grps; raw_spin_lock_init(&drvdata->spin_lock); drvdata->csdev = coresight_register(&desc); @@ -261,10 +337,34 @@ static int ctcu_platform_probe(struct platform_device *pdev) static void ctcu_platform_remove(struct platform_device *pdev) { struct ctcu_drvdata *drvdata = platform_get_drvdata(pdev); + struct ctcu_byte_cntr *byte_cntr_data; + unsigned long flags; + int i; if (WARN_ON(!drvdata)) return; + /* + * Signal all active byte-cntr readers to exit, then wait for them to + * finish before resetting the ops pointer and freeing driver data. + * Without this, a reader blocked in wait_event_interruptible_timeout() + * would access the freed ctcu_drvdata wait-queue head (use-after-free). + */ + for (i = 0; i < ETR_MAX_NUM; i++) { + byte_cntr_data = &drvdata->byte_cntr_data[i]; + raw_spin_lock_irqsave(&byte_cntr_data->spin_lock, flags); + /* Set enable=false for all ports to signal teardown to racing readers */ + byte_cntr_data->enable = false; + if (!byte_cntr_data->reading) { + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + continue; + } + raw_spin_unlock_irqrestore(&byte_cntr_data->spin_lock, flags); + wake_up_all(&byte_cntr_data->wq); + wait_event(byte_cntr_data->wq, !byte_cntr_data->reading); + } + + tmc_etr_reset_byte_cntr_sysfs_ops(); ctcu_remove(pdev); pm_runtime_disable(&pdev->dev); } diff --git a/drivers/hwtracing/coresight/coresight-ctcu.h b/drivers/hwtracing/coresight/coresight-ctcu.h index e9594c38dd91c..a2ae0a0d91d0f 100644 --- a/drivers/hwtracing/coresight/coresight-ctcu.h +++ b/drivers/hwtracing/coresight/coresight-ctcu.h @@ -1,23 +1,31 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2024-2026 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef _CORESIGHT_CTCU_H #define _CORESIGHT_CTCU_H + +#include #include "coresight-trace-id.h" /* Maximum number of supported ETR devices for a single CTCU. */ #define ETR_MAX_NUM 2 +#define BYTE_CNTR_TIMEOUT (3 * HZ) +#define MAX_IRQ_CNT 20 + /** * struct ctcu_etr_config * @atid_offset: offset to the ATID0 Register. - * @port_num: in-port number of CTCU device that connected to ETR. + * @port_num: in-port number of the CTCU device that connected to ETR. + * @irq_ctrl_offset: offset to the BYTECNTRVAL register. */ struct ctcu_etr_config { const u32 atid_offset; const u32 port_num; + const u32 irq_ctrl_offset; }; struct ctcu_config { @@ -25,15 +33,68 @@ struct ctcu_config { int num_etr_config; }; -struct ctcu_drvdata { - void __iomem *base; - struct clk *apb_clk; - struct device *dev; - struct coresight_device *csdev; +/** + * struct ctcu_byte_cntr + * @enable: indicates that byte_cntr function is enabled or not. + * @irq_enabled: indicates that the interruption is enabled. + * @reading: indicates that byte_cntr is reading. + * @irq: allocated number of the IRQ. + * @irq_cnt: IRQ count number of the triggered interruptions. + * @wq: waitqueue for reading data from ETR buffer. + * @spin_lock: spinlock of the byte_cntr_data. + * @irq_ctrl_offset: offset to the BYTECNTVAL Register. + * @ctcu_drvdata: drvdata of the CTCU device. + * @buf_node: etr_buf_node for reading. + */ +struct ctcu_byte_cntr { + bool enable; + bool irq_enabled; + bool reading; + int irq; + atomic_t irq_cnt; + wait_queue_head_t wq; raw_spinlock_t spin_lock; - u32 atid_offset[ETR_MAX_NUM]; + u32 irq_ctrl_offset; + struct ctcu_drvdata *ctcu_drvdata; + struct etr_buf_node *buf_node; +}; + +struct ctcu_drvdata { + void __iomem *base; + struct clk *apb_clk; + struct device *dev; + struct coresight_device *csdev; + struct ctcu_byte_cntr byte_cntr_data[ETR_MAX_NUM]; + raw_spinlock_t spin_lock; + u32 atid_offset[ETR_MAX_NUM]; /* refcnt for each traceid of each sink */ - u8 traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP]; + u8 traceid_refcnt[ETR_MAX_NUM][CORESIGHT_TRACE_ID_RES_TOP]; }; +/** + * struct ctcu_byte_cntr_irq_attribute + * @attr: The device attribute. + * @port: port number. + */ +struct ctcu_byte_cntr_irq_attribute { + struct device_attribute attr; + u8 port; +}; + +#define ctcu_byte_cntr_irq_rw(port) \ + (&((struct ctcu_byte_cntr_irq_attribute[]) { \ + { \ + __ATTR(irq_enabled##port, 0644, irq_enabled_show, \ + irq_enabled_store), \ + port, \ + } \ + })[0].attr.attr) + +void ctcu_program_register(struct ctcu_drvdata *drvdata, u32 val, u32 offset); + +/* Byte-cntr functions */ +void ctcu_byte_cntr_start(struct coresight_device *csdev, struct coresight_path *path); +void ctcu_byte_cntr_stop(struct coresight_device *csdev, struct coresight_path *path); +void ctcu_byte_cntr_init(struct device *dev, struct ctcu_drvdata *drvdata, int port_num); + #endif diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index b2c9a4db13b4e..5b83dd4e603bd 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -55,16 +55,17 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) /* write the CTI trigger registers */ for (i = 0; i < config->nr_trig_max; i++) { - writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i)); + writel_relaxed(config->ctiinen[i], + reg_index_addr(drvdata, CTIINEN, i)); writel_relaxed(config->ctiouten[i], - drvdata->base + CTIOUTEN(i)); + reg_index_addr(drvdata, CTIOUTEN, i)); } /* other regs */ - writel_relaxed(config->ctigate, drvdata->base + CTIGATE); + writel_relaxed(config->ctigate, reg_addr(drvdata, CTIGATE)); if (config->asicctl_impl) - writel_relaxed(config->asicctl, drvdata->base + ASICCTL); - writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET); + writel_relaxed(config->asicctl, reg_addr(drvdata, ASICCTL)); + writel_relaxed(config->ctiappset, reg_addr(drvdata, CTIAPPSET)); /* re-enable CTI */ writel_relaxed(1, drvdata->base + CTICONTROL); @@ -72,6 +73,35 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) CS_LOCK(drvdata->base); } +/* + * Qualcomm CTIs do not implement the CoreSight Claim tag protocol, so + * bypass coresight_clear_self_claim_tag() for them. + */ +static void cti_clear_self_claim_tag(struct cti_drvdata *drvdata, + struct csdev_access *csa) +{ + if (drvdata->is_qcom_cti) + return; + + coresight_clear_self_claim_tag(csa); +} + +static int cti_claim_device(struct cti_drvdata *drvdata) +{ + if (drvdata->is_qcom_cti) + return 0; + + return coresight_claim_device(drvdata->csdev); +} + +static void cti_unclaim_device_unlocked(struct cti_drvdata *drvdata) +{ + if (drvdata->is_qcom_cti) + return; + + coresight_disclaim_device_unlocked(drvdata->csdev); +} + /* write regs to hardware and enable */ static int cti_enable_hw(struct cti_drvdata *drvdata) { @@ -85,7 +115,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) goto cti_state_unchanged; /* claim the device */ - rc = coresight_claim_device(drvdata->csdev); + rc = cti_claim_device(drvdata); if (rc) return rc; @@ -100,7 +130,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - struct coresight_device *csdev = drvdata->csdev; guard(raw_spinlock_irqsave)(&drvdata->spinlock); @@ -117,29 +146,11 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) /* disable CTI */ writel_relaxed(0, drvdata->base + CTICONTROL); - coresight_disclaim_device_unlocked(csdev); + cti_unclaim_device_unlocked(drvdata); CS_LOCK(drvdata->base); return 0; } -u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset) -{ - int val; - - CS_UNLOCK(drvdata->base); - val = readl_relaxed(drvdata->base + offset); - CS_LOCK(drvdata->base); - - return val; -} - -void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value) -{ - CS_UNLOCK(drvdata->base); - writel_relaxed(value, drvdata->base + offset); - CS_LOCK(drvdata->base); -} - void cti_write_intack(struct device *dev, u32 ackval) { struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); @@ -161,8 +172,11 @@ void cti_write_intack(struct device *dev, u32 ackval) /* DEVID[19:16] - number of CTM channels */ #define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19)) -static void cti_set_default_config(struct device *dev, - struct cti_drvdata *drvdata) +/* DEVARCH[31:21] - ARCHITECT */ +#define CTI_DEVARCH_ARCHITECT(devarch_val) ((int)BMVAL(devarch_val, 21, 31)) + +static int cti_set_default_config(struct device *dev, + struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; u32 devid; @@ -181,6 +195,31 @@ static void cti_set_default_config(struct device *dev, config->nr_trig_max = CTIINOUTEN_MAX; } + config->trig_in_use = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_in_use) + return -ENOMEM; + + config->trig_out_use = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_out_use) + return -ENOMEM; + + config->trig_out_filter = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_out_filter) + return -ENOMEM; + + config->ctiinen = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), + GFP_KERNEL); + if (!config->ctiinen) + return -ENOMEM; + + config->ctiouten = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), + GFP_KERNEL); + if (!config->ctiouten) + return -ENOMEM; + config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid); /* Most regs default to 0 as zalloc'ed except...*/ @@ -189,6 +228,7 @@ static void cti_set_default_config(struct device *dev, config->enable_req_count = 0; config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid); + return 0; } /* @@ -219,8 +259,10 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata, cti_dev->nr_trig_con++; /* add connection usage bit info to overall info */ - drvdata->config.trig_in_use |= tc->con_in->used_mask; - drvdata->config.trig_out_use |= tc->con_out->used_mask; + bitmap_or(drvdata->config.trig_in_use, drvdata->config.trig_in_use, + tc->con_in->used_mask, drvdata->config.nr_trig_max); + bitmap_or(drvdata->config.trig_out_use, drvdata->config.trig_out_use, + tc->con_out->used_mask, drvdata->config.nr_trig_max); return 0; } @@ -231,6 +273,14 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, { struct cti_trig_con *tc = NULL; struct cti_trig_grp *in = NULL, *out = NULL; + struct cti_drvdata *drvdata = dev_get_drvdata(dev); + int n_trigs = drvdata->config.nr_trig_max; + + if (in_sigs > n_trigs || out_sigs > n_trigs) { + dev_err(dev, "trigger signal is out of range: in=%d out=%d nr_max=%d\n", + in_sigs, out_sigs, n_trigs); + return NULL; + } tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL); if (!tc) @@ -242,12 +292,20 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, if (!in) return NULL; + in->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL); + if (!in->used_mask) + return NULL; + out = devm_kzalloc(dev, offsetof(struct cti_trig_grp, sig_types[out_sigs]), GFP_KERNEL); if (!out) return NULL; + out->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL); + if (!out->used_mask) + return NULL; + tc->con_in = in; tc->con_out = out; tc->con_in->nr_sigs = in_sigs; @@ -263,7 +321,6 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) { int ret = 0; int n_trigs = drvdata->config.nr_trig_max; - u32 n_trig_mask = GENMASK(n_trigs - 1, 0); struct cti_trig_con *tc = NULL; /* @@ -274,8 +331,8 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) if (!tc) return -ENOMEM; - tc->con_in->used_mask = n_trig_mask; - tc->con_out->used_mask = n_trig_mask; + bitmap_fill(tc->con_in->used_mask, n_trigs); + bitmap_fill(tc->con_out->used_mask, n_trigs); ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default"); return ret; } @@ -288,35 +345,31 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, { struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config; - u32 trig_bitmask; u32 chan_bitmask; u32 reg_value; - int reg_offset; + u32 reg_offset; /* ensure indexes in range */ if ((channel_idx >= config->nr_ctm_channels) || (trigger_idx >= config->nr_trig_max)) return -EINVAL; - trig_bitmask = BIT(trigger_idx); - /* ensure registered triggers and not out filtered */ if (direction == CTI_TRIG_IN) { - if (!(trig_bitmask & config->trig_in_use)) + if (!(test_bit(trigger_idx, config->trig_in_use))) return -EINVAL; } else { - if (!(trig_bitmask & config->trig_out_use)) + if (!(test_bit(trigger_idx, config->trig_out_use))) return -EINVAL; if ((config->trig_filter_enable) && - (config->trig_out_filter & trig_bitmask)) + test_bit(trigger_idx, config->trig_out_filter)) return -EINVAL; } /* update the local register values */ chan_bitmask = BIT(channel_idx); - reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) : - CTIOUTEN(trigger_idx)); + reg_offset = (direction == CTI_TRIG_IN ? CTIINEN : CTIOUTEN); guard(raw_spinlock_irqsave)(&drvdata->spinlock); @@ -336,7 +389,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, reg_offset, reg_value); + cti_write_single_reg_index(drvdata, reg_offset, trigger_idx, reg_value); return 0; } @@ -662,6 +715,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_desc cti_desc = { 0 }; struct coresight_platform_data *pdata = NULL; struct resource *res = &adev->res; + u32 devarch; /* driver data*/ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -686,8 +740,14 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) raw_spin_lock_init(&drvdata->spinlock); + devarch = readl_relaxed(drvdata->base + CORESIGHT_DEVARCH); + if (CTI_DEVARCH_ARCHITECT(devarch) == QCOM_ARCHITECT) + drvdata->is_qcom_cti = true; + /* initialise CTI driver config values */ - cti_set_default_config(dev, drvdata); + ret = cti_set_default_config(dev, drvdata); + if (ret) + return ret; pdata = coresight_cti_get_platform_data(dev); if (IS_ERR(pdata)) { @@ -729,7 +789,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) cti_desc.groups = drvdata->ctidev.con_groups; cti_desc.dev = dev; - coresight_clear_self_claim_tag(&cti_desc.access); + cti_clear_self_claim_tag(drvdata, &cti_desc.access); drvdata->csdev = coresight_register(&cti_desc); if (IS_ERR(drvdata->csdev)) return PTR_ERR(drvdata->csdev); @@ -743,7 +803,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) /* all done - dec pm refcount */ pm_runtime_put(&adev->dev); - dev_info(&drvdata->csdev->dev, "CTI initialized\n"); + dev_info(&drvdata->csdev->dev, + "%sCTI initialized\n", drvdata->is_qcom_cti ? "QCOM " : ""); return 0; } diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c index d6d5388705c3e..ba5a7e4b6bff0 100644 --- a/drivers/hwtracing/coresight/coresight-cti-platform.c +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -136,8 +136,8 @@ static int cti_plat_create_v8_etm_connection(struct device *dev, goto create_v8_etm_out; /* build connection data */ - tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */ - tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */ + bitmap_set(tc->con_in->used_mask, 4, 4); /* sigs <4,5,6,7> */ + bitmap_set(tc->con_out->used_mask, 4, 4); /* sigs <4,5,6,7> */ /* * The EXTOUT type signals from the ETM are connected to a set of input @@ -194,10 +194,10 @@ static int cti_plat_create_v8_connections(struct device *dev, goto of_create_v8_out; /* Set the v8 PE CTI connection data */ - tc->con_in->used_mask = 0x3; /* sigs <0 1> */ + bitmap_set(tc->con_in->used_mask, 0, 2); /* sigs <0 1> */ tc->con_in->sig_types[0] = PE_DBGTRIGGER; tc->con_in->sig_types[1] = PE_PMUIRQ; - tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */ + bitmap_set(tc->con_out->used_mask, 0, 3); /* sigs <0 1 2 > */ tc->con_out->sig_types[0] = PE_EDBGREQ; tc->con_out->sig_types[1] = PE_DBGRESTART; tc->con_out->sig_types[2] = PE_CTIIRQ; @@ -213,7 +213,7 @@ static int cti_plat_create_v8_connections(struct device *dev, goto of_create_v8_out; /* filter pe_edbgreq - PE trigout sig <0> */ - drvdata->config.trig_out_filter |= 0x1; + set_bit(0, drvdata->config.trig_out_filter); of_create_v8_out: return ret; @@ -257,7 +257,7 @@ static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp, if (!err) { /* set the signal usage mask */ for (idx = 0; idx < tgrp->nr_sigs; idx++) - tgrp->used_mask |= BIT(values[idx]); + set_bit(values[idx], tgrp->used_mask); } kfree(values); @@ -316,24 +316,34 @@ static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata, { struct cti_trig_grp *tg = NULL; int err = 0, nr_filter_sigs; + int nr_trigs = drvdata->config.nr_trig_max; nr_filter_sigs = cti_plat_count_sig_elements(fwnode, CTI_DT_FILTER_OUT_SIGS); if (nr_filter_sigs == 0) return 0; - if (nr_filter_sigs > drvdata->config.nr_trig_max) + if (nr_filter_sigs > nr_trigs) return -EINVAL; tg = kzalloc_obj(*tg); if (!tg) return -ENOMEM; + tg->used_mask = bitmap_zalloc(nr_trigs, GFP_KERNEL); + if (!tg->used_mask) { + kfree(tg); + return -ENOMEM; + } + tg->nr_sigs = nr_filter_sigs; err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS); if (!err) - drvdata->config.trig_out_filter |= tg->used_mask; + bitmap_or(drvdata->config.trig_out_filter, + drvdata->config.trig_out_filter, + tg->used_mask, nr_trigs); + bitmap_free(tg->used_mask); kfree(tg); return err; } diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 3fe2c916d2288..175f20d69232d 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -171,7 +171,7 @@ static ssize_t coresight_cti_reg_show(struct device *dev, pm_runtime_get_sync(dev->parent); scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) - val = cti_read_single_reg(drvdata, cti_attr->off); + val = cti_read_single_reg_index(drvdata, cti_attr->off, cti_attr->index); pm_runtime_put_sync(dev->parent); return sysfs_emit(buf, "0x%x\n", val); @@ -192,7 +192,7 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, pm_runtime_get_sync(dev->parent); scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) - cti_write_single_reg(drvdata, cti_attr->off, val); + cti_write_single_reg_index(drvdata, cti_attr->off, cti_attr->index, val); pm_runtime_put_sync(dev->parent); return size; @@ -202,7 +202,17 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0444, coresight_cti_reg_show, NULL), \ - offset \ + offset, \ + 0 \ + } \ + })[0].attr.attr) + +#define coresight_cti_reg_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_cti_reg_show, NULL), \ + offset, \ + idx \ } \ })[0].attr.attr) @@ -211,7 +221,18 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, { \ __ATTR(name, 0644, coresight_cti_reg_show, \ coresight_cti_reg_store), \ - offset \ + offset, \ + 0 \ + } \ + })[0].attr.attr) + +#define coresight_cti_reg_rw_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0644, coresight_cti_reg_show, \ + coresight_cti_reg_store), \ + offset, \ + idx \ } \ })[0].attr.attr) @@ -219,7 +240,17 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0200, NULL, coresight_cti_reg_store), \ - offset \ + offset, \ + 0 \ + } \ + })[0].attr.attr) + +#define coresight_cti_reg_wo_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0200, NULL, coresight_cti_reg_store), \ + offset, \ + idx \ } \ })[0].attr.attr) @@ -386,7 +417,7 @@ static ssize_t inen_store(struct device *dev, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, CTIINEN(index), val); + cti_write_single_reg_index(drvdata, CTIINEN, index, val); return size; } @@ -427,7 +458,7 @@ static ssize_t outen_store(struct device *dev, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, CTIOUTEN(index), val); + cti_write_single_reg_index(drvdata, CTIOUTEN, index, val); return size; } @@ -512,18 +543,36 @@ static struct attribute *coresight_cti_regs_attrs[] = { &dev_attr_appclear.attr, &dev_attr_apppulse.attr, coresight_cti_reg(triginstatus, CTITRIGINSTATUS), + coresight_cti_reg_index(triginstatus1, CTITRIGINSTATUS, 1), + coresight_cti_reg_index(triginstatus2, CTITRIGINSTATUS, 2), + coresight_cti_reg_index(triginstatus3, CTITRIGINSTATUS, 3), coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS), + coresight_cti_reg_index(trigoutstatus1, CTITRIGOUTSTATUS, 1), + coresight_cti_reg_index(trigoutstatus2, CTITRIGOUTSTATUS, 2), + coresight_cti_reg_index(trigoutstatus3, CTITRIGOUTSTATUS, 3), coresight_cti_reg(chinstatus, CTICHINSTATUS), coresight_cti_reg(choutstatus, CTICHOUTSTATUS), #ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL), coresight_cti_reg(ittrigin, ITTRIGIN), + coresight_cti_reg_index(ittrigin1, ITTRIGIN, 1), + coresight_cti_reg_index(ittrigin2, ITTRIGIN, 2), + coresight_cti_reg_index(ittrigin3, ITTRIGIN, 3), coresight_cti_reg(itchin, ITCHIN), coresight_cti_reg_rw(ittrigout, ITTRIGOUT), + coresight_cti_reg_rw_index(ittrigout1, ITTRIGOUT, 1), + coresight_cti_reg_rw_index(ittrigout2, ITTRIGOUT, 2), + coresight_cti_reg_rw_index(ittrigout3, ITTRIGOUT, 3), coresight_cti_reg_rw(itchout, ITCHOUT), coresight_cti_reg(itchoutack, ITCHOUTACK), coresight_cti_reg(ittrigoutack, ITTRIGOUTACK), + coresight_cti_reg_index(ittrigoutack1, ITTRIGOUTACK, 1), + coresight_cti_reg_index(ittrigoutack2, ITTRIGOUTACK, 2), + coresight_cti_reg_index(ittrigoutack3, ITTRIGOUTACK, 3), coresight_cti_reg_wo(ittriginack, ITTRIGINACK), + coresight_cti_reg_wo_index(ittriginack1, ITTRIGINACK, 1), + coresight_cti_reg_wo_index(ittriginack2, ITTRIGINACK, 2), + coresight_cti_reg_wo_index(ittriginack3, ITTRIGINACK, 3), coresight_cti_reg_wo(itchinack, ITCHINACK), #endif NULL, @@ -534,10 +583,22 @@ static umode_t coresight_cti_regs_is_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct device_attribute *dev_attr; + struct cs_off_attribute *cti_attr; + int max_bank; if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl) return 0; + dev_attr = container_of(attr, struct device_attribute, attr); + if (dev_attr->show == coresight_cti_reg_show || + dev_attr->store == coresight_cti_reg_store) { + cti_attr = container_of(dev_attr, struct cs_off_attribute, attr); + max_bank = DIV_ROUND_UP(drvdata->config.nr_trig_max, 32); + if (cti_attr->index >= max_bank) + return 0; + } + return attr->mode; } @@ -719,12 +780,12 @@ static ssize_t trigout_filtered_show(struct device *dev, struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; int nr_trig_max = cfg->nr_trig_max; - unsigned long mask = cfg->trig_out_filter; + unsigned long *mask = cfg->trig_out_filter; - if (mask == 0) + if (bitmap_empty(mask, nr_trig_max)) return 0; - return sysfs_emit(buf, "%*pbl\n", nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", nr_trig_max, mask); } static DEVICE_ATTR_RO(trigout_filtered); @@ -931,9 +992,9 @@ static ssize_t trigin_sig_show(struct device *dev, struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; - unsigned long mask = con->con_in->used_mask; + unsigned long *mask = con->con_in->used_mask; - return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask); } static ssize_t trigout_sig_show(struct device *dev, @@ -945,9 +1006,9 @@ static ssize_t trigout_sig_show(struct device *dev, struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; - unsigned long mask = con->con_out->used_mask; + unsigned long *mask = con->con_out->used_mask; - return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask); } /* convert a sig type id to a name */ diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index c5f9e79fabc60..4b6fd6b551142 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -30,8 +30,8 @@ struct fwnode_handle; #define CTIAPPSET 0x014 #define CTIAPPCLEAR 0x018 #define CTIAPPPULSE 0x01C -#define CTIINEN(n) (0x020 + (4 * n)) -#define CTIOUTEN(n) (0x0A0 + (4 * n)) +#define CTIINEN 0x020 +#define CTIOUTEN 0x0A0 #define CTITRIGINSTATUS 0x130 #define CTITRIGOUTSTATUS 0x134 #define CTICHINSTATUS 0x138 @@ -54,10 +54,36 @@ struct fwnode_handle; /* * CTI CSSoc 600 has a max of 32 trigger signals per direction. * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def. + * QCOM CTI support up to 128 trigger signals per direction. * Max of in and out defined in the DEVID register. * - pick up actual number used from .dts parameters if present. */ -#define CTIINOUTEN_MAX 32 +#define CTIINOUTEN_MAX 128 + +/* QCOM CTI extension */ +#define QCOM_ARCHITECT 0x477 + +#define QCOM_CTIINTACK 0x020 +#define QCOM_CTIAPPSET 0x004 +#define QCOM_CTIAPPCLEAR 0x008 +#define QCOM_CTIAPPPULSE 0x00C +#define QCOM_CTIINEN 0x400 +#define QCOM_CTIOUTEN 0x800 +#define QCOM_CTITRIGINSTATUS 0x040 +#define QCOM_CTITRIGOUTSTATUS 0x060 +#define QCOM_CTICHINSTATUS 0x080 +#define QCOM_CTICHOUTSTATUS 0x084 +#define QCOM_CTIGATE 0x088 +#define QCOM_ASICCTL 0x08C +/* Integration test registers */ +#define QCOM_ITCHINACK 0xE70 +#define QCOM_ITTRIGINACK 0xE80 +#define QCOM_ITCHOUT 0xE74 +#define QCOM_ITTRIGOUT 0xEA0 +#define QCOM_ITCHOUTACK 0xE78 +#define QCOM_ITTRIGOUTACK 0xEC0 +#define QCOM_ITCHIN 0xE7C +#define QCOM_ITTRIGIN 0xEE0 /** * Group of related trigger signals @@ -68,7 +94,7 @@ struct fwnode_handle; */ struct cti_trig_grp { int nr_sigs; - u32 used_mask; + unsigned long *used_mask; int sig_types[]; }; @@ -145,17 +171,17 @@ struct cti_config { int enable_req_count; /* registered triggers and filtering */ - u32 trig_in_use; - u32 trig_out_use; - u32 trig_out_filter; + unsigned long *trig_in_use; + unsigned long *trig_out_use; + unsigned long *trig_out_filter; bool trig_filter_enable; u8 xtrig_rchan_sel; /* cti cross trig programmable regs */ u32 ctiappset; u8 ctiinout_sel; - u32 ctiinen[CTIINOUTEN_MAX]; - u32 ctiouten[CTIINOUTEN_MAX]; + u32 *ctiinen; + u32 *ctiouten; u32 ctigate; u32 asicctl; }; @@ -168,6 +194,9 @@ struct cti_config { * @spinlock: Control data access to one at a time. * @config: Configuration data for this CTI device. * @node: List entry of this device in the list of CTI devices. + * @is_qcom_cti: True if this CTI is a Qualcomm vendor-specific + * variant that requires register offset translation + * via cti_qcom_reg_off(). */ struct cti_drvdata { void __iomem *base; @@ -176,6 +205,7 @@ struct cti_drvdata { raw_spinlock_t spinlock; struct cti_config config; struct list_head node; + bool is_qcom_cti; }; /* @@ -217,8 +247,6 @@ int cti_enable(struct coresight_device *csdev, enum cs_mode mode, int cti_disable(struct coresight_device *csdev, struct coresight_path *path); void cti_write_all_hw_regs(struct cti_drvdata *drvdata); void cti_write_intack(struct device *dev, u32 ackval); -void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value); -u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset); int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, enum cti_trig_dir direction, u32 channel_idx, u32 trigger_idx); @@ -231,6 +259,78 @@ struct coresight_platform_data * coresight_cti_get_platform_data(struct device *dev); const char *cti_plat_get_node_name(struct fwnode_handle *fwnode); +static inline u32 cti_qcom_reg_off(u32 offset) +{ + switch (offset) { + case CTIINTACK: return QCOM_CTIINTACK; + case CTIAPPSET: return QCOM_CTIAPPSET; + case CTIAPPCLEAR: return QCOM_CTIAPPCLEAR; + case CTIAPPPULSE: return QCOM_CTIAPPPULSE; + case CTIINEN: return QCOM_CTIINEN; + case CTIOUTEN: return QCOM_CTIOUTEN; + case CTITRIGINSTATUS: return QCOM_CTITRIGINSTATUS; + case CTITRIGOUTSTATUS: return QCOM_CTITRIGOUTSTATUS; + case CTICHINSTATUS: return QCOM_CTICHINSTATUS; + case CTICHOUTSTATUS: return QCOM_CTICHOUTSTATUS; + case CTIGATE: return QCOM_CTIGATE; + case ASICCTL: return QCOM_ASICCTL; + case ITCHINACK: return QCOM_ITCHINACK; + case ITTRIGINACK: return QCOM_ITTRIGINACK; + case ITCHOUT: return QCOM_ITCHOUT; + case ITTRIGOUT: return QCOM_ITTRIGOUT; + case ITCHOUTACK: return QCOM_ITCHOUTACK; + case ITTRIGOUTACK: return QCOM_ITTRIGOUTACK; + case ITCHIN: return QCOM_ITCHIN; + case ITTRIGIN: return QCOM_ITTRIGIN; + + default: + return offset; + } +} + +static inline void __iomem *__reg_addr(struct cti_drvdata *drvdata, + u32 off, u32 index) +{ + if (unlikely(drvdata->is_qcom_cti)) + off = cti_qcom_reg_off(off); + + return drvdata->base + off + index * sizeof(u32); +} + +#define reg_addr(drvdata, off) __reg_addr((drvdata), (off), 0) +#define reg_index_addr(drvdata, off, i) __reg_addr((drvdata), (off), (i)) + +static inline u32 cti_read_single_reg_index(struct cti_drvdata *drvdata, + u32 off, u32 index) +{ + u32 val; + + CS_UNLOCK(drvdata->base); + val = readl_relaxed(reg_index_addr(drvdata, off, index)); + CS_LOCK(drvdata->base); + + return val; +} + +static inline u32 cti_read_single_reg(struct cti_drvdata *drvdata, u32 off) +{ + return cti_read_single_reg_index(drvdata, off, 0); +} + +static inline void cti_write_single_reg_index(struct cti_drvdata *drvdata, + u32 off, u32 index, u32 value) +{ + CS_UNLOCK(drvdata->base); + writel_relaxed(value, reg_index_addr(drvdata, off, index)); + CS_LOCK(drvdata->base); +} + +static inline void cti_write_single_reg(struct cti_drvdata *drvdata, + u32 off, u32 value) +{ + cti_write_single_reg_index(drvdata, off, 0, value); +} + /* Check if a cti device is enabled */ static inline bool cti_is_active(struct cti_config *cfg) { diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 0abc11f0690c5..b175f8db4210f 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,10 @@ #define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT) #define FUNNEL_ENSx_MASK 0xff +static LIST_HEAD(funnel_delay_probe); +static enum cpuhp_state hp_online; +static DEFINE_SPINLOCK(delay_lock); + /** * struct funnel_drvdata - specifics associated to a funnel component * @base: memory mapped base address for this component. @@ -38,6 +43,9 @@ * @csdev: component vitals needed by the framework. * @priority: port selection order. * @spinlock: serialize enable/disable operations. + * @supported_cpus: Represent the CPUs related to this funnel. + * @dev: pointer to the device associated with this funnel. + * @link: list node for adding this funnel to the delayed probe list. */ struct funnel_drvdata { void __iomem *base; @@ -46,6 +54,15 @@ struct funnel_drvdata { struct coresight_device *csdev; unsigned long priority; raw_spinlock_t spinlock; + struct cpumask *supported_cpus; + struct device *dev; + struct list_head link; +}; + +struct funnel_smp_arg { + struct funnel_drvdata *drvdata; + int port; + int rc; }; static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) @@ -74,9 +91,37 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) return rc; } +static void funnel_enable_hw_smp_call(void *info) +{ + struct funnel_smp_arg *arg = info; + + arg->rc = dynamic_funnel_enable_hw(arg->drvdata, arg->port); +} + +static int funnel_enable_hw(struct funnel_drvdata *drvdata, int port) +{ + int cpu, ret; + struct funnel_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return dynamic_funnel_enable_hw(drvdata, port); + + arg.drvdata = drvdata; + arg.port = port; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + funnel_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + return ret; +} + static int funnel_enable(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { int rc = 0; struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -84,19 +129,41 @@ static int funnel_enable(struct coresight_device *csdev, bool first_enable = false; raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (in->dest_refcnt == 0) { - if (drvdata->base) - rc = dynamic_funnel_enable_hw(drvdata, in->dest_port); - if (!rc) - first_enable = true; - } - if (!rc) + + if (in->dest_refcnt == 0) + first_enable = true; + else in->dest_refcnt++; + + if (mode == CS_MODE_PERF) { + if (first_enable) { + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) { + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } + + if (drvdata->base) + rc = dynamic_funnel_enable_hw(drvdata, in->dest_port); + if (!rc) + in->dest_refcnt++; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return rc; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (first_enable) - dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", - in->dest_port); + if (first_enable) { + if (drvdata->base) + rc = funnel_enable_hw(drvdata, in->dest_port); + if (!rc) { + in->dest_refcnt++; + dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", + in->dest_port); + } + } + return rc; } @@ -133,6 +200,7 @@ static void funnel_disable(struct coresight_device *csdev, dynamic_funnel_disable_hw(drvdata, in->dest_port); last_disable = true; } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) @@ -186,15 +254,39 @@ static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata) return functl; } +static void get_funnel_ctrl_smp_call(void *info) +{ + struct funnel_smp_arg *arg = info; + + arg->rc = get_funnel_ctrl_hw(arg->drvdata); +} + static ssize_t funnel_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf) { u32 val; + int cpu, ret; struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct funnel_smp_arg arg = { 0 }; pm_runtime_get_sync(dev->parent); - - val = get_funnel_ctrl_hw(drvdata); + if (!drvdata->supported_cpus) { + val = get_funnel_ctrl_hw(drvdata); + } else { + arg.drvdata = drvdata; + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + get_funnel_ctrl_smp_call, &arg, 1); + if (!ret) + break; + } + if (!ret) { + val = arg.rc; + } else { + pm_runtime_put(dev->parent); + return ret; + } + } pm_runtime_put(dev->parent); @@ -209,22 +301,68 @@ static struct attribute *coresight_funnel_attrs[] = { }; ATTRIBUTE_GROUPS(coresight_funnel); +static void funnel_clear_self_claim_tag(struct funnel_drvdata *drvdata) +{ + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + coresight_clear_self_claim_tag(&access); +} + +static void funnel_init_on_cpu(void *info) +{ + struct funnel_drvdata *drvdata = info; + + funnel_clear_self_claim_tag(drvdata); +} + +static int funnel_add_coresight_dev(struct device *dev) +{ + struct coresight_desc desc = { 0 }; + struct funnel_drvdata *drvdata = dev_get_drvdata(dev); + + if (drvdata->base) { + desc.groups = coresight_funnel_groups; + desc.access = CSDEV_ACCESS_IOMEM(drvdata->base); + } + + desc.name = coresight_alloc_device_name("funnel", dev); + if (!desc.name) + return -ENOMEM; + + desc.type = CORESIGHT_DEV_TYPE_LINK; + desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; + desc.ops = &funnel_cs_ops; + desc.pdata = dev->platform_data; + desc.dev = dev; + + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) + return PTR_ERR(drvdata->csdev); + return 0; +} + +static struct cpumask *funnel_get_supported_cpus(struct device *dev) +{ + struct generic_pm_domain *pd; + + pd = pd_to_genpd(dev->pm_domain); + if (pd) + return pd->cpus; + + return NULL; +} + static int funnel_probe(struct device *dev, struct resource *res) { void __iomem *base; struct coresight_platform_data *pdata = NULL; struct funnel_drvdata *drvdata; - struct coresight_desc desc = { 0 }; - int ret; + int cpu, ret; if (is_of_node(dev_fwnode(dev)) && of_device_is_compatible(dev->of_node, "arm,coresight-funnel")) dev_warn_once(dev, "Uses OBSOLETE CoreSight funnel binding\n"); - desc.name = coresight_alloc_device_name("funnel", dev); - if (!desc.name) - return -ENOMEM; - drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -242,9 +380,6 @@ static int funnel_probe(struct device *dev, struct resource *res) if (IS_ERR(base)) return PTR_ERR(base); drvdata->base = base; - desc.groups = coresight_funnel_groups; - desc.access = CSDEV_ACCESS_IOMEM(base); - coresight_clear_self_claim_tag(&desc.access); } dev_set_drvdata(dev, drvdata); @@ -256,24 +391,45 @@ static int funnel_probe(struct device *dev, struct resource *res) dev->platform_data = pdata; raw_spin_lock_init(&drvdata->spinlock); - desc.type = CORESIGHT_DEV_TYPE_LINK; - desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; - desc.ops = &funnel_cs_ops; - desc.pdata = pdata; - desc.dev = dev; - drvdata->csdev = coresight_register(&desc); - if (IS_ERR(drvdata->csdev)) - return PTR_ERR(drvdata->csdev); - return 0; + if (fwnode_property_present(dev_fwnode(dev), "qcom,cpu-bound-components")) { + drvdata->supported_cpus = funnel_get_supported_cpus(dev); + if (!drvdata->supported_cpus) + return -EINVAL; + drvdata->dev = dev; + cpus_read_lock(); + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + funnel_init_on_cpu, drvdata, 1); + if (!ret) + break; + } + + if (ret) { + scoped_guard(spinlock, &delay_lock) + list_add(&drvdata->link, &funnel_delay_probe); + cpus_read_unlock(); + return 0; + } + + cpus_read_unlock(); + } else if (res) { + funnel_clear_self_claim_tag(drvdata); + } + + return funnel_add_coresight_dev(dev); } static int funnel_remove(struct device *dev) { struct funnel_drvdata *drvdata = dev_get_drvdata(dev); - coresight_unregister(drvdata->csdev); - + if (drvdata->csdev) { + coresight_unregister(drvdata->csdev); + } else { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + } return 0; } @@ -410,14 +566,51 @@ static struct amba_driver dynamic_funnel_driver = { .id_table = dynamic_funnel_ids, }; +static int funnel_online_cpu(unsigned int cpu) +{ + struct funnel_drvdata *drvdata, *tmp; + int ret; + + list_for_each_entry_safe(drvdata, tmp, &funnel_delay_probe, link) { + if (cpumask_test_cpu(cpu, drvdata->supported_cpus)) { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret < 0) + return 0; + + funnel_clear_self_claim_tag(drvdata); + funnel_add_coresight_dev(drvdata->dev); + pm_runtime_put(drvdata->dev); + } + } + return 0; +} + static int __init funnel_init(void) { + int ret; + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight-funnel:online", + funnel_online_cpu, NULL); + + if (ret > 0) + hp_online = ret; + else + return ret; + return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver); } static void __exit funnel_exit(void) { coresight_remove_driver(&dynamic_funnel_driver, &funnel_driver); + if (hp_online) { + cpuhp_remove_state_nocalls(hp_online); + hp_online = 0; + } } module_init(funnel_init); diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index dddac946659fc..46284eb9b300e 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -58,6 +58,7 @@ struct cs_pair_attribute { struct cs_off_attribute { struct device_attribute attr; u32 off; + u32 index; }; ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf); @@ -67,7 +68,8 @@ ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0444, coresight_simple_show32, NULL), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) @@ -155,6 +157,8 @@ void coresight_remove_links(struct coresight_device *orig, u32 coresight_get_sink_id(struct coresight_device *csdev); int coresight_path_assign_trace_id(struct coresight_path *path, enum cs_mode mode); +int coresight_get_in_port(struct coresight_device *csdev, + struct coresight_device *remote); #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X) int etm_readl_cp14(u32 off, unsigned int *val); diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 2f382de357ee4..9f488ed103087 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,10 @@ #define REPLICATOR_IDFILTER0 0x000 #define REPLICATOR_IDFILTER1 0x004 +static LIST_HEAD(replicator_delay_probe); +static enum cpuhp_state hp_online; +static DEFINE_SPINLOCK(delay_lock); + /** * struct replicator_drvdata - specifics associated to a replicator component * @base: memory mapped base address for this component. Also indicates @@ -33,6 +38,9 @@ * @csdev: component vitals needed by the framework * @spinlock: serialize enable/disable operations. * @check_idfilter_val: check if the context is lost upon clock removal. + * @supported_cpus: Represent the CPUs related to this funnel. + * @dev: pointer to the device associated with this replicator. + * @link: link to the delay_probed list. */ struct replicator_drvdata { void __iomem *base; @@ -41,18 +49,64 @@ struct replicator_drvdata { struct coresight_device *csdev; raw_spinlock_t spinlock; bool check_idfilter_val; + struct cpumask *supported_cpus; + struct device *dev; + struct list_head link; }; -static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) +struct replicator_smp_arg { + struct replicator_drvdata *drvdata; + int outport; + u32 offset; + int rc; +}; + +static void replicator_clear_self_claim_tag(struct replicator_drvdata *drvdata) +{ + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + coresight_clear_self_claim_tag(&access); +} + +static int replicator_claim_device_unlocked(struct replicator_drvdata *drvdata) +{ + struct coresight_device *csdev = drvdata->csdev; + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + u32 claim_tag; + + if (csdev) + return coresight_claim_device_unlocked(csdev); + + writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, drvdata->base + CORESIGHT_CLAIMSET); + + claim_tag = readl_relaxed(drvdata->base + CORESIGHT_CLAIMCLR); + if (claim_tag != CORESIGHT_CLAIM_SELF_HOSTED) { + coresight_clear_self_claim_tag_unlocked(&access); + return -EBUSY; + } + + return 0; +} + +static void replicator_disclaim_device_unlocked(struct replicator_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + if (csdev) + return coresight_disclaim_device_unlocked(csdev); + coresight_clear_self_claim_tag_unlocked(&access); +} + +static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) +{ CS_UNLOCK(drvdata->base); - if (!coresight_claim_device_unlocked(csdev)) { + if (!replicator_claim_device_unlocked(drvdata)) { writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1); - coresight_disclaim_device_unlocked(csdev); + replicator_disclaim_device_unlocked(drvdata); } CS_LOCK(drvdata->base); @@ -114,9 +168,38 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, return rc; } +static void replicator_enable_hw_smp_call(void *info) +{ + struct replicator_smp_arg *arg = info; + + arg->rc = dynamic_replicator_enable(arg->drvdata, 0, arg->outport); +} + +static int replicator_enable_hw(struct replicator_drvdata *drvdata, + int inport, int outport) +{ + int cpu, ret; + struct replicator_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return dynamic_replicator_enable(drvdata, 0, outport); + + arg.drvdata = drvdata; + arg.outport = outport; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, replicator_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + + return ret; +} + static int replicator_enable(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { int rc = 0; struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -124,19 +207,43 @@ static int replicator_enable(struct coresight_device *csdev, bool first_enable = false; raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (out->src_refcnt == 0) { - if (drvdata->base) - rc = dynamic_replicator_enable(drvdata, in->dest_port, - out->src_port); - if (!rc) - first_enable = true; - } - if (!rc) + + if (out->src_refcnt == 0) + first_enable = true; + else out->src_refcnt++; + + if (mode == CS_MODE_PERF) { + if (first_enable) { + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) { + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } + + if (drvdata->base) + rc = dynamic_replicator_enable(drvdata, in->dest_port, + out->src_port); + if (!rc) + out->src_refcnt++; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return rc; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (first_enable) - dev_dbg(&csdev->dev, "REPLICATOR enabled\n"); + if (first_enable) { + if (drvdata->base) + rc = replicator_enable_hw(drvdata, in->dest_port, + out->src_port); + if (!rc) { + out->src_refcnt++; + dev_dbg(&csdev->dev, "REPLICATOR enabled\n"); + return rc; + } + } + return rc; } @@ -184,6 +291,7 @@ static void replicator_disable(struct coresight_device *csdev, out->src_port); last_disable = true; } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); if (last_disable) @@ -199,9 +307,65 @@ static const struct coresight_ops replicator_cs_ops = { .link_ops = &replicator_link_ops, }; +static void replicator_read_register_smp_call(void *info) +{ + struct replicator_smp_arg *arg = info; + + arg->rc = readl_relaxed(arg->drvdata->base + arg->offset); +} + +static ssize_t coresight_replicator_reg32_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct replicator_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); + unsigned long flags; + struct replicator_smp_arg arg = { 0 }; + u32 val; + int ret, cpu; + + pm_runtime_get_sync(dev->parent); + + if (!drvdata->supported_cpus) { + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + val = readl_relaxed(drvdata->base + cs_attr->off); + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + } else { + arg.drvdata = drvdata; + arg.offset = cs_attr->off; + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + replicator_read_register_smp_call, + &arg, 1); + if (!ret) + break; + } + if (!ret) { + val = arg.rc; + } else { + pm_runtime_put_sync(dev->parent); + return ret; + } + } + + pm_runtime_put_sync(dev->parent); + + return sysfs_emit(buf, "0x%x\n", val); +} + +#define coresight_replicator_reg32(name, offset) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_replicator_reg32_show, NULL), \ + offset \ + } \ + })[0].attr.attr) + static struct attribute *replicator_mgmt_attrs[] = { - coresight_simple_reg32(idfilter0, REPLICATOR_IDFILTER0), - coresight_simple_reg32(idfilter1, REPLICATOR_IDFILTER1), + coresight_replicator_reg32(idfilter0, REPLICATOR_IDFILTER0), + coresight_replicator_reg32(idfilter1, REPLICATOR_IDFILTER1), NULL, }; @@ -215,23 +379,69 @@ static const struct attribute_group *replicator_groups[] = { NULL, }; +static int replicator_add_coresight_dev(struct device *dev) +{ + struct coresight_desc desc = { 0 }; + struct replicator_drvdata *drvdata = dev_get_drvdata(dev); + + if (drvdata->base) { + desc.groups = replicator_groups; + desc.access = CSDEV_ACCESS_IOMEM(drvdata->base); + } + + desc.name = coresight_alloc_device_name("replicator", dev); + if (!desc.name) + return -ENOMEM; + + desc.type = CORESIGHT_DEV_TYPE_LINK; + desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; + desc.ops = &replicator_cs_ops; + desc.pdata = dev->platform_data; + desc.dev = dev; + + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) + return PTR_ERR(drvdata->csdev); + + return 0; +} + +static void replicator_init_hw(struct replicator_drvdata *drvdata) +{ + replicator_clear_self_claim_tag(drvdata); + replicator_reset(drvdata); +} + +static void replicator_init_on_cpu(void *info) +{ + struct replicator_drvdata *drvdata = info; + + replicator_init_hw(drvdata); +} + +static struct cpumask *replicator_get_supported_cpus(struct device *dev) +{ + struct generic_pm_domain *pd; + + pd = pd_to_genpd(dev->pm_domain); + if (pd) + return pd->cpus; + + return NULL; +} + static int replicator_probe(struct device *dev, struct resource *res) { struct coresight_platform_data *pdata = NULL; struct replicator_drvdata *drvdata; - struct coresight_desc desc = { 0 }; void __iomem *base; - int ret; + int cpu, ret; if (is_of_node(dev_fwnode(dev)) && of_device_is_compatible(dev->of_node, "arm,coresight-replicator")) dev_warn_once(dev, "Uses OBSOLETE CoreSight replicator binding\n"); - desc.name = coresight_alloc_device_name("replicator", dev); - if (!desc.name) - return -ENOMEM; - drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -249,9 +459,6 @@ static int replicator_probe(struct device *dev, struct resource *res) if (IS_ERR(base)) return PTR_ERR(base); drvdata->base = base; - desc.groups = replicator_groups; - desc.access = CSDEV_ACCESS_IOMEM(base); - coresight_clear_self_claim_tag(&desc.access); } if (fwnode_property_present(dev_fwnode(dev), @@ -266,25 +473,48 @@ static int replicator_probe(struct device *dev, struct resource *res) dev->platform_data = pdata; raw_spin_lock_init(&drvdata->spinlock); - desc.type = CORESIGHT_DEV_TYPE_LINK; - desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; - desc.ops = &replicator_cs_ops; - desc.pdata = dev->platform_data; - desc.dev = dev; - drvdata->csdev = coresight_register(&desc); - if (IS_ERR(drvdata->csdev)) - return PTR_ERR(drvdata->csdev); + if (fwnode_property_present(dev_fwnode(dev), "qcom,cpu-bound-components")) { + drvdata->supported_cpus = replicator_get_supported_cpus(dev); + if (!drvdata->supported_cpus) + return -EINVAL; + drvdata->dev = dev; + cpus_read_lock(); + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + replicator_init_on_cpu, drvdata, 1); + if (!ret) + break; + } - replicator_reset(drvdata); - return 0; + if (ret) { + scoped_guard(spinlock, &delay_lock) + list_add(&drvdata->link, &replicator_delay_probe); + cpus_read_unlock(); + return 0; + } + + cpus_read_unlock(); + } else if (res) { + replicator_init_hw(drvdata); + } + + ret = replicator_add_coresight_dev(dev); + + return ret; } static int replicator_remove(struct device *dev) { struct replicator_drvdata *drvdata = dev_get_drvdata(dev); - coresight_unregister(drvdata->csdev); + if (drvdata->csdev) { + coresight_unregister(drvdata->csdev); + } else { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + } + return 0; } @@ -416,14 +646,54 @@ static struct amba_driver dynamic_replicator_driver = { .id_table = dynamic_replicator_ids, }; +static int replicator_online_cpu(unsigned int cpu) +{ + struct replicator_drvdata *drvdata, *tmp; + int ret; + + spin_lock(&delay_lock); + list_for_each_entry_safe(drvdata, tmp, &replicator_delay_probe, link) { + if (cpumask_test_cpu(cpu, drvdata->supported_cpus)) { + list_del(&drvdata->link); + spin_unlock(&delay_lock); + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret < 0) + return 0; + + replicator_clear_self_claim_tag(drvdata); + replicator_reset(drvdata); + replicator_add_coresight_dev(drvdata->dev); + pm_runtime_put(drvdata->dev); + spin_lock(&delay_lock); + } + } + spin_unlock(&delay_lock); + return 0; +} + static int __init replicator_init(void) { + int ret; + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight-replicator:online", + replicator_online_cpu, NULL); + + if (ret > 0) + hp_online = ret; + else + return ret; + return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver); } static void __exit replicator_exit(void) { coresight_remove_driver(&dynamic_replicator_driver, &replicator_driver); + if (hp_online) { + cpuhp_remove_state_nocalls(hp_online); + hp_online = 0; + } } module_init(replicator_init); diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index bc5a133ada3e3..190cade689094 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,10 @@ #include "coresight-priv.h" #include "coresight-tmc.h" +static LIST_HEAD(tmc_delay_probe); +static enum cpuhp_state hp_online; +static DEFINE_SPINLOCK(delay_lock); + int tmc_wait_for_tmcready(struct tmc_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; @@ -228,17 +233,10 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata) { int ret = 0; - switch (drvdata->config_type) { - case TMC_CONFIG_TYPE_ETB: - case TMC_CONFIG_TYPE_ETF: - ret = tmc_read_prepare_etb(drvdata); - break; - case TMC_CONFIG_TYPE_ETR: - ret = tmc_read_prepare_etr(drvdata); - break; - default: + if (drvdata->sysfs_ops) + ret = drvdata->sysfs_ops->read_prepare(drvdata); + else ret = -EINVAL; - } if (!ret) dev_dbg(&drvdata->csdev->dev, "TMC read start\n"); @@ -250,17 +248,10 @@ static int tmc_read_unprepare(struct tmc_drvdata *drvdata) { int ret = 0; - switch (drvdata->config_type) { - case TMC_CONFIG_TYPE_ETB: - case TMC_CONFIG_TYPE_ETF: - ret = tmc_read_unprepare_etb(drvdata); - break; - case TMC_CONFIG_TYPE_ETR: - ret = tmc_read_unprepare_etr(drvdata); - break; - default: + if (drvdata->sysfs_ops) + ret = drvdata->sysfs_ops->read_unprepare(drvdata); + else ret = -EINVAL; - } if (!ret) dev_dbg(&drvdata->csdev->dev, "TMC read end\n"); @@ -287,15 +278,7 @@ static int tmc_open(struct inode *inode, struct file *file) static ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata, loff_t pos, size_t len, char **bufpp) { - switch (drvdata->config_type) { - case TMC_CONFIG_TYPE_ETB: - case TMC_CONFIG_TYPE_ETF: - return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp); - case TMC_CONFIG_TYPE_ETR: - return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp); - } - - return -EINVAL; + return drvdata->sysfs_ops->get_trace_data(drvdata, pos, len, bufpp); } static ssize_t tmc_read(struct file *file, char __user *data, size_t len, @@ -315,7 +298,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, return -EFAULT; } - *ppos += actual; + if (!tmc_etr_update_buf_node_pos(drvdata, actual)) + *ppos += actual; dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual); return actual; @@ -452,21 +436,130 @@ static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid) return memwidth; } +struct tmc_smp_arg { + struct tmc_drvdata *drvdata; + u32 offset; + int rc; +}; + +static void tmc_read_reg_smp_call(void *info) +{ + struct tmc_smp_arg *arg = info; + + arg->rc = readl_relaxed(arg->drvdata->base + arg->offset); +} + +static u32 cpu_tmc_read_reg(struct tmc_drvdata *drvdata, u32 offset) +{ + struct tmc_smp_arg arg = { + .drvdata = drvdata, + .offset = offset, + }; + int cpu, ret = 0; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_read_reg_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + + return ret; +} + +static ssize_t coresight_tmc_reg32_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); + int ret; + u32 val; + + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; + + if (!drvdata->supported_cpus) + val = readl_relaxed(drvdata->base + cs_attr->off); + else + val = cpu_tmc_read_reg(drvdata, cs_attr->off); + + pm_runtime_put(dev->parent); + + if (ret < 0) + return ret; + else + return sysfs_emit(buf, "0x%x\n", val); +} + +static ssize_t coresight_tmc_reg64_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr); + int ret; + u64 val; + + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; + if (!drvdata->supported_cpus) { + val = readl_relaxed(drvdata->base + cs_attr->lo_off) | + ((u64)readl_relaxed(drvdata->base + cs_attr->hi_off) << 32); + } else { + ret = cpu_tmc_read_reg(drvdata, cs_attr->lo_off); + + if (ret < 0) + goto out; + + val = ret; + + ret = cpu_tmc_read_reg(drvdata, cs_attr->hi_off); + if (ret < 0) + goto out; + + val |= ((u64)ret << 32); + } + +out: + pm_runtime_put_sync(dev->parent); + if (ret < 0) + return ret; + else + return sysfs_emit(buf, "0x%llx\n", val); +} + +#define coresight_tmc_reg32(name, offset) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_tmc_reg32_show, NULL), \ + offset \ + } \ + })[0].attr.attr) +#define coresight_tmc_reg64(name, lo_off, hi_off) \ + (&((struct cs_pair_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_tmc_reg64_show, NULL), \ + lo_off, hi_off \ + } \ + })[0].attr.attr) static struct attribute *coresight_tmc_mgmt_attrs[] = { - coresight_simple_reg32(rsz, TMC_RSZ), - coresight_simple_reg32(sts, TMC_STS), - coresight_simple_reg64(rrp, TMC_RRP, TMC_RRPHI), - coresight_simple_reg64(rwp, TMC_RWP, TMC_RWPHI), - coresight_simple_reg32(trg, TMC_TRG), - coresight_simple_reg32(ctl, TMC_CTL), - coresight_simple_reg32(ffsr, TMC_FFSR), - coresight_simple_reg32(ffcr, TMC_FFCR), - coresight_simple_reg32(mode, TMC_MODE), - coresight_simple_reg32(pscr, TMC_PSCR), - coresight_simple_reg32(devid, CORESIGHT_DEVID), - coresight_simple_reg64(dba, TMC_DBALO, TMC_DBAHI), - coresight_simple_reg32(axictl, TMC_AXICTL), - coresight_simple_reg32(authstatus, TMC_AUTHSTATUS), + coresight_tmc_reg32(rsz, TMC_RSZ), + coresight_tmc_reg32(sts, TMC_STS), + coresight_tmc_reg64(rrp, TMC_RRP, TMC_RRPHI), + coresight_tmc_reg64(rwp, TMC_RWP, TMC_RWPHI), + coresight_tmc_reg32(trg, TMC_TRG), + coresight_tmc_reg32(ctl, TMC_CTL), + coresight_tmc_reg32(ffsr, TMC_FFSR), + coresight_tmc_reg32(ffcr, TMC_FFCR), + coresight_tmc_reg32(mode, TMC_MODE), + coresight_tmc_reg32(pscr, TMC_PSCR), + coresight_tmc_reg32(devid, CORESIGHT_DEVID), + coresight_tmc_reg64(dba, TMC_DBALO, TMC_DBAHI), + coresight_tmc_reg32(axictl, TMC_AXICTL), + coresight_tmc_reg32(authstatus, TMC_AUTHSTATUS), NULL, }; @@ -764,56 +857,26 @@ static void register_crash_dev_interface(struct tmc_drvdata *drvdata, "Valid crash tracedata found\n"); } -static int __tmc_probe(struct device *dev, struct resource *res) +static const struct tmc_sysfs_ops etb_sysfs_ops = { + .read_prepare = tmc_read_prepare_etb, + .read_unprepare = tmc_read_unprepare_etb, + .get_trace_data = tmc_etb_get_sysfs_trace, +}; + +static const struct tmc_sysfs_ops etr_sysfs_ops = { + .read_prepare = tmc_read_prepare_etr, + .read_unprepare = tmc_read_unprepare_etr, + .get_trace_data = tmc_etr_get_sysfs_trace, +}; + +static int tmc_add_coresight_dev(struct device *dev) { - int ret = 0; - u32 devid; - void __iomem *base; - struct coresight_platform_data *pdata = NULL; - struct tmc_drvdata *drvdata; + struct tmc_drvdata *drvdata = dev_get_drvdata(dev); struct coresight_desc desc = { 0 }; const char *dev_list = NULL; + int ret = 0; - drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - - dev_set_drvdata(dev, drvdata); - - ret = coresight_get_enable_clocks(dev, &drvdata->pclk, &drvdata->atclk); - if (ret) - return ret; - - ret = -ENOMEM; - - /* Validity for the resource is already checked by the AMBA core */ - base = devm_ioremap_resource(dev, res); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - goto out; - } - - drvdata->base = base; - desc.access = CSDEV_ACCESS_IOMEM(base); - - raw_spin_lock_init(&drvdata->spinlock); - - devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); - drvdata->config_type = BMVAL(devid, 6, 7); - drvdata->memwidth = tmc_get_memwidth(devid); - /* This device is not associated with a session */ - drvdata->pid = -1; - drvdata->etr_mode = ETR_MODE_AUTO; - - if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { - drvdata->size = tmc_etr_get_default_buffer_size(dev); - drvdata->max_burst_size = tmc_etr_get_max_burst_size(dev); - } else { - drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4; - } - - tmc_get_reserved_region(dev); - + desc.access = CSDEV_ACCESS_IOMEM(drvdata->base); desc.dev = dev; switch (drvdata->config_type) { @@ -823,18 +886,21 @@ static int __tmc_probe(struct device *dev, struct resource *res) desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc.ops = &tmc_etb_cs_ops; dev_list = "tmc_etb"; + drvdata->sysfs_ops = &etb_sysfs_ops; break; case TMC_CONFIG_TYPE_ETR: desc.groups = coresight_etr_groups; desc.type = CORESIGHT_DEV_TYPE_SINK; desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM; desc.ops = &tmc_etr_cs_ops; - ret = tmc_etr_setup_caps(dev, devid, &desc.access); + ret = tmc_etr_setup_caps(dev, drvdata->devid, &desc.access); if (ret) - goto out; + return ret; idr_init(&drvdata->idr); mutex_init(&drvdata->idr_mutex); dev_list = "tmc_etr"; + drvdata->sysfs_ops = &etr_sysfs_ops; + INIT_LIST_HEAD(&drvdata->etr_buf_list); break; case TMC_CONFIG_TYPE_ETF: desc.groups = coresight_etf_groups; @@ -843,47 +909,152 @@ static int __tmc_probe(struct device *dev, struct resource *res) desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; desc.ops = &tmc_etf_cs_ops; dev_list = "tmc_etf"; + drvdata->sysfs_ops = &etb_sysfs_ops; break; default: pr_err("%s: Unsupported TMC config\n", desc.name); - ret = -EINVAL; - goto out; + return -EINVAL; } desc.name = coresight_alloc_device_name(dev_list, dev); - if (!desc.name) { - ret = -ENOMEM; + if (!desc.name) + return -ENOMEM; + + drvdata->desc_name = desc.name; + + desc.pdata = dev->platform_data; + + drvdata->csdev = coresight_register(&desc); + if (IS_ERR(drvdata->csdev)) + return PTR_ERR(drvdata->csdev); + + drvdata->miscdev.name = desc.name; + drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; + drvdata->miscdev.fops = &tmc_fops; + ret = misc_register(&drvdata->miscdev); + if (ret) + coresight_unregister(drvdata->csdev); + + return ret; +} + +static void tmc_clear_self_claim_tag(struct tmc_drvdata *drvdata) +{ + struct csdev_access access = CSDEV_ACCESS_IOMEM(drvdata->base); + + coresight_clear_self_claim_tag(&access); +} + +static void tmc_init_hw_config(struct tmc_drvdata *drvdata) +{ + u32 devid; + + devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); + drvdata->config_type = BMVAL(devid, 6, 7); + drvdata->memwidth = tmc_get_memwidth(devid); + drvdata->devid = devid; + drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4; + tmc_clear_self_claim_tag(drvdata); +} + +static void tmc_init_on_cpu(void *info) +{ + struct tmc_drvdata *drvdata = info; + + tmc_init_hw_config(drvdata); +} + +static struct cpumask *tmc_get_supported_cpus(struct device *dev) +{ + struct generic_pm_domain *pd; + + pd = pd_to_genpd(dev->pm_domain); + if (pd) + return pd->cpus; + + return NULL; +} + +static int __tmc_probe(struct device *dev, struct resource *res) +{ + int cpu, ret = 0; + void __iomem *base; + struct coresight_platform_data *pdata = NULL; + struct tmc_drvdata *drvdata; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + dev_set_drvdata(dev, drvdata); + + ret = coresight_get_enable_clocks(dev, &drvdata->pclk, &drvdata->atclk); + if (ret) + return ret; + + ret = -ENOMEM; + + /* Validity for the resource is already checked by the AMBA core */ + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) { + ret = PTR_ERR(base); goto out; } + drvdata->base = base; + + raw_spin_lock_init(&drvdata->spinlock); + /* This device is not associated with a session */ + drvdata->pid = -1; + drvdata->etr_mode = ETR_MODE_AUTO; + tmc_get_reserved_region(dev); + pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata)) { ret = PTR_ERR(pdata); goto out; } dev->platform_data = pdata; - desc.pdata = pdata; - coresight_clear_self_claim_tag(&desc.access); - drvdata->csdev = coresight_register(&desc); - if (IS_ERR(drvdata->csdev)) { - ret = PTR_ERR(drvdata->csdev); - goto out; + if (fwnode_property_present(dev_fwnode(dev), "qcom,cpu-bound-components")) { + drvdata->supported_cpus = tmc_get_supported_cpus(dev); + if (!drvdata->supported_cpus) + return -EINVAL; + + drvdata->dev = dev; + + cpus_read_lock(); + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_init_on_cpu, drvdata, 1); + if (!ret) + break; + } + + if (ret) { + scoped_guard(spinlock, &delay_lock) + list_add(&drvdata->link, &tmc_delay_probe); + cpus_read_unlock(); + ret = 0; + goto out; + } + + cpus_read_unlock(); + } else { + tmc_init_hw_config(drvdata); } - drvdata->miscdev.name = desc.name; - drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; - drvdata->miscdev.fops = &tmc_fops; - ret = misc_register(&drvdata->miscdev); - if (ret) { - coresight_unregister(drvdata->csdev); - goto out; + if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { + drvdata->size = tmc_etr_get_default_buffer_size(dev); + drvdata->max_burst_size = tmc_etr_get_max_burst_size(dev); } + ret = tmc_add_coresight_dev(dev); + out: if (is_tmc_crashdata_valid(drvdata) && !tmc_prepare_crashdata(drvdata)) - register_crash_dev_interface(drvdata, desc.name); + register_crash_dev_interface(drvdata, drvdata->desc_name); return ret; } @@ -929,10 +1100,16 @@ static void __tmc_remove(struct device *dev) * etb fops in this case, device is there until last file * handler to this device is closed. */ - misc_deregister(&drvdata->miscdev); + if (!drvdata->supported_cpus) + misc_deregister(&drvdata->miscdev); if (drvdata->crashdev.fops) misc_deregister(&drvdata->crashdev); - coresight_unregister(drvdata->csdev); + if (drvdata->csdev) { + coresight_unregister(drvdata->csdev); + } else { + scoped_guard(spinlock, &delay_lock) + list_del(&drvdata->link); + } } static void tmc_remove(struct amba_device *adev) @@ -987,7 +1164,6 @@ static void tmc_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; - __tmc_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); } @@ -1044,14 +1220,55 @@ static struct platform_driver tmc_platform_driver = { }, }; +static int tmc_online_cpu(unsigned int cpu) +{ + struct tmc_drvdata *drvdata, *tmp; + int ret; + + spin_lock(&delay_lock); + list_for_each_entry_safe(drvdata, tmp, &tmc_delay_probe, link) { + if (cpumask_test_cpu(cpu, drvdata->supported_cpus)) { + list_del(&drvdata->link); + + spin_unlock(&delay_lock); + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret < 0) + return 0; + + tmc_init_hw_config(drvdata); + tmc_clear_self_claim_tag(drvdata); + tmc_add_coresight_dev(drvdata->dev); + pm_runtime_put(drvdata->dev); + spin_lock(&delay_lock); + } + } + spin_unlock(&delay_lock); + return 0; +} + static int __init tmc_init(void) { + int ret; + + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight-tmc:online", + tmc_online_cpu, NULL); + + if (ret > 0) + hp_online = ret; + else + return ret; + return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver); } static void __exit tmc_exit(void) { coresight_remove_driver(&tmc_driver, &tmc_platform_driver); + if (hp_online) { + cpuhp_remove_state_nocalls(hp_online); + hp_online = 0; + } } module_init(tmc_init); module_exit(tmc_exit); diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 8882b1c4cdc05..f1b8264b4e5c8 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -47,7 +47,7 @@ static int __tmc_etb_enable_hw(struct tmc_drvdata *drvdata) return rc; } -static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) +static int tmc_etb_enable_hw_local(struct tmc_drvdata *drvdata) { int rc = coresight_claim_device(drvdata->csdev); @@ -60,6 +60,36 @@ static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) return rc; } +struct tmc_smp_arg { + struct tmc_drvdata *drvdata; + int rc; +}; + +static void tmc_etb_enable_hw_smp_call(void *info) +{ + struct tmc_smp_arg *arg = info; + + arg->rc = tmc_etb_enable_hw_local(arg->drvdata); +} + +static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) +{ + int cpu, ret; + struct tmc_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return tmc_etb_enable_hw_local(drvdata); + + arg.drvdata = drvdata; + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_etb_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + return ret; +} + static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata) { char *bufp; @@ -130,7 +160,7 @@ static int __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) return rc; } -static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) +static int tmc_etf_enable_hw_local(struct tmc_drvdata *drvdata) { int rc = coresight_claim_device(drvdata->csdev); @@ -143,6 +173,32 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) return rc; } +static void tmc_etf_enable_hw_smp_call(void *info) +{ + struct tmc_smp_arg *arg = info; + + arg->rc = tmc_etf_enable_hw_local(arg->drvdata); +} + +static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) +{ + int cpu, ret; + struct tmc_smp_arg arg = { 0 }; + + if (!drvdata->supported_cpus) + return tmc_etf_enable_hw_local(drvdata); + + arg.drvdata = drvdata; + + for_each_cpu(cpu, drvdata->supported_cpus) { + ret = smp_call_function_single(cpu, + tmc_etf_enable_hw_smp_call, &arg, 1); + if (!ret) + return arg.rc; + } + return ret; +} + static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; @@ -228,7 +284,11 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) used = true; drvdata->buf = buf; } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + ret = tmc_etb_enable_hw(drvdata); + + raw_spin_lock_irqsave(&drvdata->spinlock, flags); if (!ret) { coresight_set_mode(csdev, CS_MODE_SYSFS); csdev->refcnt++; @@ -291,7 +351,11 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, break; } - ret = tmc_etb_enable_hw(drvdata); + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) + break; + + ret = tmc_etb_enable_hw_local(drvdata); if (!ret) { /* Associate with monitored process. */ drvdata->pid = pid; @@ -363,7 +427,8 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) static int tmc_enable_etf_link(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { int ret = 0; unsigned long flags; @@ -376,19 +441,38 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, return -EBUSY; } - if (csdev->refcnt == 0) { + if (csdev->refcnt == 0) + first_enable = true; + + if (!first_enable) + csdev->refcnt++; + + if (mode == CS_MODE_PERF) { + if (first_enable) { + if (drvdata->supported_cpus && + !cpumask_test_cpu(smp_processor_id(), drvdata->supported_cpus)) { + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } + + ret = tmc_etf_enable_hw_local(drvdata); + if (!ret) + csdev->refcnt++; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return ret; + } + + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + if (first_enable) { ret = tmc_etf_enable_hw(drvdata); if (!ret) { coresight_set_mode(csdev, CS_MODE_SYSFS); - first_enable = true; + csdev->refcnt++; + dev_dbg(&csdev->dev, "TMC-ETF enabled\n"); } } - if (!ret) - csdev->refcnt++; - raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); - if (first_enable) - dev_dbg(&csdev->dev, "TMC-ETF enabled\n"); return ret; } diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 361a433e6f0c5..e78f8891f11e0 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -865,6 +865,30 @@ tmc_etr_get_catu_device(struct tmc_drvdata *drvdata) } EXPORT_SYMBOL_GPL(tmc_etr_get_catu_device); +/* + * TMC ETR could be connected to a CTCU device, which can provide ATID filter + * and byte-cntr service. This is represented by the output port of the TMC + * (ETR) connected to the input port of the CTCU. + * + * Returns : coresight_device ptr for the CTCU device if a CTCU is found. + * : NULL otherwise. + */ +struct coresight_device * +tmc_etr_get_ctcu_device(struct tmc_drvdata *drvdata) +{ + struct coresight_device *etr = drvdata->csdev; + union coresight_dev_subtype ctcu_subtype = { + .helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CTCU + }; + + if (!IS_ENABLED(CONFIG_CORESIGHT_CTCU)) + return NULL; + + return coresight_find_output_type(etr->pdata, CORESIGHT_DEV_TYPE_HELPER, + ctcu_subtype); +} +EXPORT_SYMBOL_GPL(tmc_etr_get_ctcu_device); + static const struct etr_buf_operations *etr_buf_ops[] = { [ETR_MODE_FLAT] = &etr_flat_buf_ops, [ETR_MODE_ETR_SG] = &etr_sg_buf_ops, @@ -1144,6 +1168,9 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, return rc; } +/* Assumes a single CTCU instance per system, as on all current Qualcomm SoCs. */ +static const struct tmc_sysfs_ops *byte_cntr_sysfs_ops; + /* * Return the available trace data in the buffer (starts at etr_buf->offset, * limited by etr_buf->len) from @pos, with a maximum limit of @len, @@ -1154,23 +1181,39 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, * We are protected here by drvdata->reading != 0, which ensures the * sysfs_buf stays alive. */ -ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, - loff_t pos, size_t len, char **bufpp) +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos, + size_t len, char **bufpp) { s64 offset; ssize_t actual = len; - struct etr_buf *etr_buf = drvdata->sysfs_buf; - if (pos + actual > etr_buf->len) - actual = etr_buf->len - pos; + if (pos + actual > sysfs_buf->len) + actual = sysfs_buf->len - pos; if (actual <= 0) return actual; /* Compute the offset from which we read the data */ - offset = etr_buf->offset + pos; - if (offset >= etr_buf->size) - offset -= etr_buf->size; - return tmc_etr_buf_get_data(etr_buf, offset, actual, bufpp); + offset = sysfs_buf->offset + pos; + if (offset >= sysfs_buf->size) + offset -= sysfs_buf->size; + return tmc_etr_buf_get_data(sysfs_buf, offset, actual, bufpp); +} +EXPORT_SYMBOL_GPL(tmc_etr_read_sysfs_buf); + +ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, + loff_t pos, size_t len, char **bufpp) +{ + ssize_t ret; + const struct tmc_sysfs_ops *byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops); + + if (byte_cntr_ops) { + ret = byte_cntr_ops->get_trace_data(drvdata, pos, len, bufpp); + /* Return the filled buffer */ + if (ret > 0 || ret == -ENOMEM) + return ret; + } + + return tmc_etr_read_sysfs_buf(drvdata->sysfs_buf, pos, len, bufpp); } static struct etr_buf * @@ -1224,6 +1267,39 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) } +static void tmc_etr_reset_sysfs_buf(struct tmc_drvdata *drvdata) +{ + u32 sts; + + CS_UNLOCK(drvdata->base); + tmc_write_rrp(drvdata, drvdata->sysfs_buf->hwaddr); + tmc_write_rwp(drvdata, drvdata->sysfs_buf->hwaddr); + sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL; + writel_relaxed(sts, drvdata->base + TMC_STS); + CS_LOCK(drvdata->base); +} + +/** + * tmc_etr_enable_disable_hw - enable/disable the ETR hw. + * @drvdata: drvdata of the TMC device. + * @enable: indicates enable/disable. + */ +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + if (enable) { + tmc_etr_reset_sysfs_buf(drvdata); + __tmc_etr_enable_hw(drvdata); + } else { + __tmc_etr_disable_hw(drvdata); + } + + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); +} +EXPORT_SYMBOL_GPL(tmc_etr_enable_disable_hw); + void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) { __tmc_etr_disable_hw(drvdata); @@ -1918,15 +1994,180 @@ const struct coresight_ops tmc_etr_cs_ops = { .panic_ops = &tmc_etr_sync_ops, }; +/** + * tmc_clean_etr_buf_list - clean the etr_buf_list. + * @drvdata: driver data of the TMC device. + * + * Remove all nodes from @drvdata->etr_buf_list and free their buffers. + * If a node holds the live sysfs_buf and the device is active, the node is + * removed but the buffer is not freed; ownership stays with drvdata->sysfs_buf. + * + * Locking: callers must guarantee exclusive access to @drvdata->etr_buf_list + * and must not hold @drvdata->spinlock. The spinlock is taken internally only + * to serialise the @drvdata->sysfs_buf accesses against the ETR sink + * enable/disable paths. Must be called from process context: buffers are freed + * with the lock released. + */ +void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata) +{ + struct etr_buf_node *nd, *next; + unsigned long flags; + + list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, link) { + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + if (nd->sysfs_buf == drvdata->sysfs_buf) { + if (coresight_get_mode(drvdata->csdev) != CS_MODE_DISABLED) + /* + * The device is still active. Keep the live + * buffer owned by drvdata->sysfs_buf and only + * drop the list's reference to it. + */ + nd->sysfs_buf = NULL; + else + /* Free the buffer below through nd->sysfs_buf */ + drvdata->sysfs_buf = NULL; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + /* Free the buffer (NULL is ignored) and the node out of the lock */ + tmc_etr_free_sysfs_buf(nd->sysfs_buf); + list_del(&nd->link); + kfree(nd); + } +} +EXPORT_SYMBOL_GPL(tmc_clean_etr_buf_list); + +/** + * tmc_create_etr_buf_list - create a list to manage the etr_buf_node. + * @drvdata: driver data of the TMC device. + * @num_nodes: number of nodes want to create with the list. + * + * Locking: callers must guarantee exclusive access to @drvdata->etr_buf_list + * and must not hold @drvdata->spinlock. The spinlock is taken internally only + * to serialise the @drvdata->sysfs_buf accesses against the ETR sink + * enable/disable paths. Must be called from process context: buffers and nodes + * are allocated with the lock released. + * + * Return 0 upon success and return the error number if fail. + */ +int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes) +{ + struct etr_buf_node *new_node; + struct etr_buf *sysfs_buf; + unsigned long flags; + int i = 0, ret = 0; + + /* We don't need a list if there is only one node */ + if (num_nodes < 2) + return -EINVAL; + + /* + * We expect that sysfs_buf in drvdata has already been allocated. + * Wrap the live sysfs_buf into the first node so the captured trace + * data is preserved. The list is owned by the caller, so no lock is + * needed to read sysfs_buf or to add the node here. + */ + if (drvdata->sysfs_buf) { + new_node = kzalloc_obj(*new_node, GFP_KERNEL); + if (!new_node) + return -ENOMEM; + + new_node->sysfs_buf = drvdata->sysfs_buf; + new_node->is_free = false; + list_add(&new_node->link, &drvdata->etr_buf_list); + i++; + } + + while (i < num_nodes) { + new_node = kzalloc_obj(*new_node, GFP_KERNEL); + if (!new_node) { + ret = -ENOMEM; + break; + } + + /* Allocate the buffer with the lock released */ + sysfs_buf = tmc_alloc_etr_buf(drvdata, drvdata->size, 0, cpu_to_node(0), NULL); + if (IS_ERR(sysfs_buf)) { + kfree(new_node); + ret = PTR_ERR(sysfs_buf); + break; + } + + new_node->sysfs_buf = sysfs_buf; + /* + * Only the drvdata->sysfs_buf write needs the spinlock, to + * serialise against the ETR sink enable/disable paths. + */ + raw_spin_lock_irqsave(&drvdata->spinlock, flags); + /* We don't have an available sysfs_buf in drvdata, set one up */ + if (!drvdata->sysfs_buf) { + drvdata->sysfs_buf = sysfs_buf; + new_node->is_free = false; + } else { + new_node->is_free = true; + } + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + list_add_tail(&new_node->link, &drvdata->etr_buf_list); + i++; + } + + /* Clean the list if there is an error */ + if (ret) + tmc_clean_etr_buf_list(drvdata); + + return ret; +} +EXPORT_SYMBOL_GPL(tmc_create_etr_buf_list); + +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops) +{ + WRITE_ONCE(byte_cntr_sysfs_ops, sysfs_ops); +} +EXPORT_SYMBOL_GPL(tmc_etr_set_byte_cntr_sysfs_ops); + +void tmc_etr_reset_byte_cntr_sysfs_ops(void) +{ + WRITE_ONCE(byte_cntr_sysfs_ops, NULL); +} +EXPORT_SYMBOL_GPL(tmc_etr_reset_byte_cntr_sysfs_ops); + +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size) +{ + struct etr_buf_node *nd, *next; + + if (drvdata->config_type != TMC_CONFIG_TYPE_ETR) + return false; + + list_for_each_entry_safe(nd, next, &drvdata->etr_buf_list, link) { + if (nd && nd->reading) { + nd->pos += size; + return true; + } + } + + return false; +} + int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) { int ret = 0; unsigned long flags; + const struct tmc_sysfs_ops *byte_cntr_ops; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) return -EINVAL; + byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops); + if (byte_cntr_ops) { + ret = byte_cntr_ops->read_prepare(drvdata); + if (!ret || ret == -EBUSY) + return ret; + + ret = 0; + } + raw_spin_lock_irqsave(&drvdata->spinlock, flags); if (drvdata->reading) { ret = -EBUSY; @@ -1958,11 +2199,17 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) { unsigned long flags; struct etr_buf *sysfs_buf = NULL; + const struct tmc_sysfs_ops *byte_cntr_ops; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) return -EINVAL; + byte_cntr_ops = READ_ONCE(byte_cntr_sysfs_ops); + if (byte_cntr_ops) + if (!byte_cntr_ops->read_unprepare(drvdata)) + return 0; + raw_spin_lock_irqsave(&drvdata->spinlock, flags); /* RE-enable the TMC if need be */ diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 319a354ede9fc..1898da4ad6988 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -208,6 +208,22 @@ struct tmc_resrv_buf { s64 len; }; +/** + * @sysfs_buf: Allocated sysfs_buf. + * @is_free: Indicates whether the buffer is free to choose. + * @reading: Indicates byte_cntr is reading the buffer attached to + * the node. + * @pos: Offset to the start of the buffer. + * @link: list_head of the node. + */ +struct etr_buf_node { + struct etr_buf *sysfs_buf; + bool is_free; + bool reading; + loff_t pos; + struct list_head link; +}; + /** * struct tmc_drvdata - specifics associated to an TMC component * @atclk: optional clock for the core parts of the TMC. @@ -245,6 +261,13 @@ struct tmc_resrv_buf { * (after crash) by default. * @crash_mdata: Reserved memory for storing tmc crash metadata. * Used by ETR/ETF. + * @etr_buf_list: List that is used to manage allocated etr_buf. + * @sysfs_ops: Read operations for the sysfs mode. + * @supported_cpus: Represent the CPUs related to this TMC. + * @devid: TMC variant ID inferred from the device configuration register. + * @desc_name: Name to be used while creating crash interface. + * @dev: pointer to the device associated with this TMC. + * @link: link to the delay_probed list. */ struct tmc_drvdata { struct clk *atclk; @@ -275,6 +298,26 @@ struct tmc_drvdata { struct etr_buf *perf_buf; struct tmc_resrv_buf resrv_buf; struct tmc_resrv_buf crash_mdata; + struct list_head etr_buf_list; + const struct tmc_sysfs_ops *sysfs_ops; + struct cpumask *supported_cpus; + u32 devid; + const char *desc_name; + struct device *dev; + struct list_head link; +}; + +/** + * struct tmc_sysfs_ops - read operations for TMC and its helper devices + * @read_prepare: prepare operation. + * @read_unprepare: unprepare operation. + * @get_trace_data: read operation. + */ +struct tmc_sysfs_ops { + int (*read_prepare)(struct tmc_drvdata *drvdata); + int (*read_unprepare)(struct tmc_drvdata *drvdata); + ssize_t (*get_trace_data)(struct tmc_drvdata *drvdata, loff_t pos, + size_t len, char **bufpp); }; struct etr_buf_operations { @@ -440,6 +483,7 @@ static inline uint32_t find_crash_tracedata_crc(struct tmc_drvdata *drvdata, } struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata); +struct coresight_device *tmc_etr_get_ctcu_device(struct tmc_drvdata *drvdata); void tmc_etr_set_catu_ops(const struct etr_buf_operations *catu); void tmc_etr_remove_catu_ops(void); @@ -447,5 +491,13 @@ struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, enum cs_mode mode, struct coresight_path *path); extern const struct attribute_group coresight_etr_group; +void tmc_clean_etr_buf_list(struct tmc_drvdata *drvdata); +int tmc_create_etr_buf_list(struct tmc_drvdata *drvdata, int num_nodes); +void tmc_etr_set_byte_cntr_sysfs_ops(const struct tmc_sysfs_ops *sysfs_ops); +void tmc_etr_reset_byte_cntr_sysfs_ops(void); +void tmc_etr_enable_disable_hw(struct tmc_drvdata *drvdata, bool enable); +bool tmc_etr_update_buf_node_pos(struct tmc_drvdata *drvdata, ssize_t size); +ssize_t tmc_etr_read_sysfs_buf(struct etr_buf *sysfs_buf, loff_t pos, + size_t len, char **bufpp); #endif diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c index 9e8de4323d285..5fb27291984fa 100644 --- a/drivers/hwtracing/coresight/coresight-tnoc.c +++ b/drivers/hwtracing/coresight/coresight-tnoc.c @@ -79,7 +79,8 @@ static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata) } static int trace_noc_enable(struct coresight_device *csdev, struct coresight_connection *inport, - struct coresight_connection *outport) + struct coresight_connection *outport, + enum cs_mode mode) { struct trace_noc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c index 89c8f71f0aff0..e0084eed4843f 100644 --- a/drivers/hwtracing/coresight/coresight-tpda.c +++ b/drivers/hwtracing/coresight/coresight-tpda.c @@ -222,7 +222,8 @@ static int __tpda_enable(struct tpda_drvdata *drvdata, int port) static int tpda_enable(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out) + struct coresight_connection *out, + enum cs_mode mode) { struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); int ret = 0; diff --git a/drivers/hwtracing/qcom/Kconfig b/drivers/hwtracing/qcom/Kconfig new file mode 100644 index 0000000000000..5c94c75ffa396 --- /dev/null +++ b/drivers/hwtracing/qcom/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# QCOM specific hwtracing drivers +# +menu "Qualcomm specific hwtracing drivers" + +config QCOM_TGU + tristate "QCOM Trigger Generation Unit driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on ARM_AMBA + help + This driver provides support for Trigger Generation Unit that is + used to detect patterns or sequences on a given set of signals. + TGU is used to monitor a particular bus within a given region to + detect illegal transaction sequences or slave responses. It is also + used to monitor a data stream to detect protocol violations and to + provide a trigger point for centering data around a specific event + within the trace data buffer. + +endmenu diff --git a/drivers/hwtracing/qcom/Makefile b/drivers/hwtracing/qcom/Makefile new file mode 100644 index 0000000000000..5a0a868c1ea0d --- /dev/null +++ b/drivers/hwtracing/qcom/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_QCOM_TGU) += tgu.o diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c new file mode 100644 index 0000000000000..9fb51f2a912f9 --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.c @@ -0,0 +1,704 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tgu.h" + +static int calculate_array_location(struct tgu_drvdata *drvdata, + int step_index, int operation_index, + int reg_index) +{ + switch (operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + return operation_index * (drvdata->num_step) * + (drvdata->num_reg) + + step_index * (drvdata->num_reg) + reg_index; + case TGU_CONDITION_DECODE: + return step_index * (drvdata->num_condition_decode) + + reg_index; + case TGU_CONDITION_SELECT: + return step_index * (drvdata->num_condition_select) + + reg_index; + case TGU_COUNTER: + return step_index * (drvdata->num_counter) + reg_index; + case TGU_TIMER: + return step_index * (drvdata->num_timer) + reg_index; + default: + break; + } + + return -EINVAL; +} + +static int check_array_location(struct tgu_drvdata *drvdata, int step, + int ops, int reg) +{ + int result = calculate_array_location(drvdata, step, ops, reg); + + if (result == -EINVAL) + dev_err(drvdata->dev, "check array location - Fail\n"); + + return result; +} + +static ssize_t tgu_dataset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + int index; + + index = check_array_location(drvdata, tgu_attr->step_index, + tgu_attr->operation_index, tgu_attr->reg_num); + + if (index == -EINVAL) + return index; + + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->priority[index]); + case TGU_CONDITION_DECODE: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_decode[index]); + case TGU_CONDITION_SELECT: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_select[index]); + case TGU_TIMER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->timer[index]); + case TGU_COUNTER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->counter[index]); + default: + break; + } + return -EINVAL; +} + +static ssize_t tgu_dataset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct tgu_drvdata *tgu_drvdata = dev_get_drvdata(dev); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + unsigned long val; + int index; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + + guard(spinlock)(&tgu_drvdata->lock); + index = check_array_location(tgu_drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num); + + if (index == -EINVAL) + return index; + + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + tgu_drvdata->value_table->priority[index] = val; + ret = size; + break; + case TGU_CONDITION_DECODE: + tgu_drvdata->value_table->condition_decode[index] = val; + ret = size; + break; + case TGU_CONDITION_SELECT: + tgu_drvdata->value_table->condition_select[index] = val; + ret = size; + break; + case TGU_TIMER: + tgu_drvdata->value_table->timer[index] = val; + ret = size; + break; + case TGU_COUNTER: + tgu_drvdata->value_table->counter[index] = val; + ret = size; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static umode_t tgu_node_visible(struct kobject *kobject, + struct attribute *attr, + int n) +{ + struct device *dev = kobj_to_dev(kobject); + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct device_attribute *dev_attr = + container_of(attr, struct device_attribute, attr); + struct tgu_attribute *tgu_attr = + container_of(dev_attr, struct tgu_attribute, attr); + + if (tgu_attr->step_index >= drvdata->num_step) + return SYSFS_GROUP_INVISIBLE; + + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + if (tgu_attr->reg_num < drvdata->num_reg) + return attr->mode; + break; + case TGU_CONDITION_DECODE: + if (tgu_attr->reg_num < drvdata->num_condition_decode) + return attr->mode; + break; + case TGU_CONDITION_SELECT: + /* 'default' register is at the end of 'select' region */ + if (tgu_attr->reg_num == drvdata->num_condition_select - 1) + attr->name = "default"; + if (tgu_attr->reg_num < drvdata->num_condition_select) + return attr->mode; + break; + case TGU_COUNTER: + if (!drvdata->num_counter) + break; + if (tgu_attr->reg_num < drvdata->num_counter) + return attr->mode; + break; + case TGU_TIMER: + if (!drvdata->num_timer) + break; + if (tgu_attr->reg_num < drvdata->num_timer) + return attr->mode; + break; + default: + break; + } + + return 0; +} + +static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) +{ + int i, j, k, index; + + TGU_UNLOCK(drvdata->base); + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < MAX_PRIORITY; j++) { + for (k = 0; k < drvdata->num_reg; k++) { + index = check_array_location( + drvdata, i, j, k); + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->priority[index], + drvdata->base + + PRIORITY_REG_STEP(i, j, k)); + } + } + } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_decode; j++) { + index = check_array_location(drvdata, i, + TGU_CONDITION_DECODE, j); + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->condition_decode[index], + drvdata->base + CONDITION_DECODE_STEP(i, j)); + } + } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_select; j++) { + index = check_array_location(drvdata, i, + TGU_CONDITION_SELECT, j); + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->condition_select[index], + drvdata->base + CONDITION_SELECT_STEP(i, j)); + } + } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_timer; j++) { + index = check_array_location(drvdata, i, TGU_TIMER, j); + + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->timer[index], + drvdata->base + TIMER_COMPARE_STEP(i, j)); + } + } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_counter; j++) { + index = check_array_location(drvdata, i, TGU_COUNTER, j); + + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->counter[index], + drvdata->base + COUNTER_COMPARE_STEP(i, j)); + } + } + /* Enable TGU to program the triggers */ + writel(1, drvdata->base + TGU_CONTROL); +exit: + TGU_LOCK(drvdata->base); + return index >= 0 ? 0 : -EINVAL; +} + +static void tgu_set_reg_number(struct tgu_drvdata *drvdata) +{ + int num_sense_input; + int num_reg; + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + + num_sense_input = TGU_DEVID_SENSE_INPUT(devid); + num_reg = (num_sense_input * TGU_BITS_PER_SIGNAL) / LENGTH_REGISTER; + + if ((num_sense_input * TGU_BITS_PER_SIGNAL) % LENGTH_REGISTER) + num_reg++; + + drvdata->num_reg = num_reg; +} + +static void tgu_set_steps(struct tgu_drvdata *drvdata) +{ + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + + drvdata->num_step = TGU_DEVID_STEPS(devid); +} + +static void tgu_set_conditions(struct tgu_drvdata *drvdata) +{ + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + drvdata->num_condition_decode = TGU_DEVID_CONDITIONS(devid); + /* select region has an additional 'default' register */ + drvdata->num_condition_select = TGU_DEVID_CONDITIONS(devid) + 1; +} + +static void tgu_set_timer_counter(struct tgu_drvdata *drvdata) +{ + int num_timers = 0, num_counters = 0; + u32 devid2; + + devid2 = readl(drvdata->base + CORESIGHT_DEVID2); + + if (TGU_DEVID2_TIMER0(devid2)) + num_timers++; + if (TGU_DEVID2_TIMER1(devid2)) + num_timers++; + + if (TGU_DEVID2_COUNTER0(devid2)) + num_counters++; + if (TGU_DEVID2_COUNTER1(devid2)) + num_counters++; + + drvdata->num_timer = num_timers; + drvdata->num_counter = num_counters; +} + +static int tgu_enable(struct device *dev) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + int ret; + + guard(spinlock)(&drvdata->lock); + + ret = tgu_write_all_hw_regs(drvdata); + if (!ret) + drvdata->enabled = true; + + return ret; +} + +static void tgu_do_disable(struct tgu_drvdata *drvdata) +{ + TGU_UNLOCK(drvdata->base); + writel(0, drvdata->base + TGU_CONTROL); + TGU_LOCK(drvdata->base); + + drvdata->enabled = false; +} + +static void tgu_disable(struct device *dev) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + + guard(spinlock)(&drvdata->lock); + if (!drvdata->enabled) + return; + + tgu_do_disable(drvdata); +} + +static ssize_t enable_tgu_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + bool enabled; + + guard(spinlock)(&drvdata->lock); + enabled = drvdata->enabled; + + return sysfs_emit(buf, "%d\n", !!enabled); +} + +/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */ +static ssize_t enable_tgu_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret || val > 1) + return -EINVAL; + + if (val) { + scoped_guard(spinlock, &drvdata->lock) { + if (drvdata->enabled) + return -EBUSY; + } + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret = tgu_enable(dev); + if (ret) { + pm_runtime_put(dev); + return ret; + } + } else { + scoped_guard(spinlock, &drvdata->lock) { + if (!drvdata->enabled) + return -EINVAL; + } + + tgu_disable(dev); + pm_runtime_put(dev); + } + + return size; +} +static DEVICE_ATTR_RW(enable_tgu); + +/* reset_tgu_store - Reset Trace and Gating Unit (TGU) configuration. */ +static ssize_t reset_tgu_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct value_table *vt = drvdata->value_table; + u32 *cond_decode = drvdata->value_table->condition_decode; + unsigned long value; + int i, j, ret; + + if (kstrtoul(buf, 0, &value) || value != 1) + return -EINVAL; + + spin_lock(&drvdata->lock); + if (!drvdata->enabled) { + spin_unlock(&drvdata->lock); + ret = pm_runtime_resume_and_get(drvdata->dev); + if (ret) + return ret; + spin_lock(&drvdata->lock); + } + + tgu_do_disable(drvdata); + + if (vt->priority) { + size_t size = MAX_PRIORITY * drvdata->num_step * + drvdata->num_reg * sizeof(unsigned int); + memset(vt->priority, 0, size); + } + + if (vt->condition_decode) { + size_t size = drvdata->num_condition_decode * + drvdata->num_step * sizeof(unsigned int); + memset(vt->condition_decode, 0, size); + } + + /* Initialize all condition registers to NOT(value=0x1000000) */ + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_decode; j++) { + cond_decode[calculate_array_location(drvdata, i, + TGU_CONDITION_DECODE, j)] = 0x1000000; + } + } + + if (vt->condition_select) { + size_t size = drvdata->num_condition_select * + drvdata->num_step * sizeof(unsigned int); + memset(vt->condition_select, 0, size); + } + + if (vt->timer) { + size_t size = (drvdata->num_step) * (drvdata->num_timer) * + sizeof(unsigned int); + memset(vt->timer, 0, size); + } + + if (vt->counter) { + size_t size = (drvdata->num_step) * (drvdata->num_counter) * + sizeof(unsigned int); + memset(vt->counter, 0, size); + } + + spin_unlock(&drvdata->lock); + + dev_dbg(dev, "Qualcomm-TGU reset complete\n"); + + pm_runtime_put(drvdata->dev); + + return size; +} +static DEVICE_ATTR_WO(reset_tgu); + +static struct attribute *tgu_common_attrs[] = { + &dev_attr_enable_tgu.attr, + &dev_attr_reset_tgu.attr, + NULL, +}; + +static const struct attribute_group tgu_common_grp = { + .attrs = tgu_common_attrs, + NULL, +}; + +static const struct attribute_group *tgu_attr_groups[] = { + &tgu_common_grp, + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(0, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(1, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(2, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(3, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(4, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(5, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(6, 3), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 0), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2), + PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(0), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(1), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(2), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(3), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(4), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(5), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(6), + CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(7), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(0), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(1), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(2), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(3), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(4), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(5), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(6), + CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(7), + TIMER_ATTRIBUTE_GROUP_INIT(0), + TIMER_ATTRIBUTE_GROUP_INIT(1), + TIMER_ATTRIBUTE_GROUP_INIT(2), + TIMER_ATTRIBUTE_GROUP_INIT(3), + TIMER_ATTRIBUTE_GROUP_INIT(4), + TIMER_ATTRIBUTE_GROUP_INIT(5), + TIMER_ATTRIBUTE_GROUP_INIT(6), + TIMER_ATTRIBUTE_GROUP_INIT(7), + COUNTER_ATTRIBUTE_GROUP_INIT(0), + COUNTER_ATTRIBUTE_GROUP_INIT(1), + COUNTER_ATTRIBUTE_GROUP_INIT(2), + COUNTER_ATTRIBUTE_GROUP_INIT(3), + COUNTER_ATTRIBUTE_GROUP_INIT(4), + COUNTER_ATTRIBUTE_GROUP_INIT(5), + COUNTER_ATTRIBUTE_GROUP_INIT(6), + COUNTER_ATTRIBUTE_GROUP_INIT(7), + NULL, +}; + +static int tgu_probe(struct amba_device *adev, const struct amba_id *id) +{ + struct device *dev = &adev->dev; + struct tgu_drvdata *drvdata; + unsigned int *priority, *condition, *select, *timer, *counter; + size_t priority_size, condition_size, select_size, timer_size, counter_size; + int ret; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &adev->dev; + dev_set_drvdata(dev, drvdata); + + drvdata->base = devm_ioremap_resource(dev, &adev->res); + if (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); + + spin_lock_init(&drvdata->lock); + + tgu_set_reg_number(drvdata); + tgu_set_steps(drvdata); + tgu_set_conditions(drvdata); + tgu_set_timer_counter(drvdata); + + ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups); + if (ret) { + dev_err(dev, "failed to create sysfs groups: %d\n", ret); + return ret; + } + + drvdata->value_table = + devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL); + if (!drvdata->value_table) + return -ENOMEM; + + priority_size = MAX_PRIORITY * drvdata->num_reg * drvdata->num_step; + + priority = devm_kcalloc(dev, priority_size, + sizeof(*drvdata->value_table->priority), + GFP_KERNEL); + if (!priority) + return -ENOMEM; + + drvdata->value_table->priority = priority; + + condition_size = drvdata->num_condition_decode * drvdata->num_step; + + condition = devm_kcalloc(dev, condition_size, + sizeof(*(drvdata->value_table->condition_decode)), + GFP_KERNEL); + if (!condition) + return -ENOMEM; + + drvdata->value_table->condition_decode = condition; + + select_size = drvdata->num_condition_select * drvdata->num_step; + + select = devm_kcalloc(dev, select_size, + sizeof(*(drvdata->value_table->condition_select)), + GFP_KERNEL); + if (!select) + return -ENOMEM; + + drvdata->value_table->condition_select = select; + + timer_size = drvdata->num_step * drvdata->num_timer; + + timer = devm_kcalloc(dev, timer_size, + sizeof(*(drvdata->value_table->timer)), + GFP_KERNEL); + if (!timer) + return -ENOMEM; + + drvdata->value_table->timer = timer; + + counter_size = drvdata->num_step * drvdata->num_counter; + + counter = devm_kcalloc(dev, counter_size, + sizeof(*(drvdata->value_table->counter)), + GFP_KERNEL); + if (!counter) + return -ENOMEM; + + drvdata->value_table->counter = counter; + + drvdata->enabled = false; + + pm_runtime_put(&adev->dev); + + return 0; +} + +static void tgu_remove(struct amba_device *adev) +{ + struct device *dev = &adev->dev; + + sysfs_remove_groups(&dev->kobj, tgu_attr_groups); + + tgu_disable(dev); +} + +static const struct amba_id tgu_ids[] = { + { + .id = 0x000f0e00, + .mask = 0x000fffff, + }, + { 0, 0, NULL }, +}; + +MODULE_DEVICE_TABLE(amba, tgu_ids); + +static struct amba_driver tgu_driver = { + .drv = { + .name = "qcom-tgu", + .suppress_bind_attrs = true, + }, + .probe = tgu_probe, + .remove = tgu_remove, + .id_table = tgu_ids, +}; + +module_amba_driver(tgu_driver); + +MODULE_AUTHOR("Songwei Chai "); +MODULE_AUTHOR("Jinlong Mao "); +MODULE_DESCRIPTION("Qualcomm Trigger Generation Unit driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h new file mode 100644 index 0000000000000..1bcbc99169def --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.h @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_TGU_H +#define _QCOM_TGU_H + +/* Register addresses */ +#define TGU_CONTROL 0x0000 +#define TGU_LAR 0xfb0 +#define TGU_UNLOCK_OFFSET 0xc5acce55 +#define TGU_DEVID 0xfc8 +#define CORESIGHT_DEVID2 0xfc0 + +#define TGU_DEVID_SENSE_INPUT(devid_val) \ + ((int)FIELD_GET(GENMASK(17, 10), devid_val)) +#define TGU_DEVID_STEPS(devid_val) \ + ((int)FIELD_GET(GENMASK(6, 3), devid_val)) +#define TGU_DEVID_CONDITIONS(devid_val) \ + ((int)FIELD_GET(GENMASK(2, 0), devid_val)) +#define TGU_DEVID2_TIMER0(devid_val) \ + ((int)FIELD_GET(GENMASK(23, 18), devid_val)) +#define TGU_DEVID2_TIMER1(devid_val) \ + ((int)FIELD_GET(GENMASK(17, 13), devid_val)) +#define TGU_DEVID2_COUNTER0(devid_val) \ + ((int)FIELD_GET(GENMASK(11, 6), devid_val)) +#define TGU_DEVID2_COUNTER1(devid_val) \ + ((int)FIELD_GET(GENMASK(5, 0), devid_val)) + + +#define TGU_BITS_PER_SIGNAL 4 +#define LENGTH_REGISTER 32 + +/* + * TGU configuration space Step configuration + * offset table space layout + * x-------------------------x$ x-------------x$ + * | |$ | |$ + * | | | reserve |$ + * | | | |$ + * |coresight management | |-------------|base+n*0x1D8+0x1F4$ + * | registers | |---> |priority[3] |$ + * | | | |-------------|base+n*0x1D8+0x194$ + * | | | |priority[2] |$ + * |-------------------------| | |-------------|base+n*0x1D8+0x134$ + * | | | |priority[1] |$ + * | step[7] | | |-------------|base+n*0x1D8+0xD4$ + * |-------------------------|->base+0x40+7*0x1D8 | |priority[0] |$ + * | | | |-------------|base+n*0x1D8+0x74$ + * | ... | | | condition |$ + * | | | | select |$ + * |-------------------------|->base+0x40+1*0x1D8 | |-------------|base+n*0x1D8+0x60$ + * | | | | condition |$ + * | step[0] |--------------------> | decode |$ + * |-------------------------|-> base+0x40 |-------------|base+n*0x1D8+0x50$ + * | | | |$ + * | Control and status space| |Timer/Counter|$ + * | space | | |$ + * x-------------------------x->base x-------------x base+n*0x1D8+0x40$ + * + */ +#define STEP_OFFSET 0x1D8 +#define PRIORITY_START_OFFSET 0x0074 +#define CONDITION_DECODE_OFFSET 0x0050 +#define CONDITION_SELECT_OFFSET 0x0060 +#define TIMER_START_OFFSET 0x0040 +#define COUNTER_START_OFFSET 0x0048 +#define PRIORITY_OFFSET 0x60 +#define REG_OFFSET 0x4 + +/* Calculate compare step addresses */ +#define PRIORITY_REG_STEP(step, priority, reg)\ + (PRIORITY_START_OFFSET + PRIORITY_OFFSET * priority +\ + REG_OFFSET * reg + STEP_OFFSET * step) + +#define CONDITION_DECODE_STEP(step, decode) \ + (CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step) + +#define CONDITION_SELECT_STEP(step, select) \ + (CONDITION_SELECT_OFFSET + REG_OFFSET * select + STEP_OFFSET * step) + +#define TIMER_COMPARE_STEP(step, timer) \ + (TIMER_START_OFFSET + REG_OFFSET * timer + STEP_OFFSET * step) + +#define COUNTER_COMPARE_STEP(step, counter) \ + (COUNTER_START_OFFSET + REG_OFFSET * counter + STEP_OFFSET * step) + +#define tgu_dataset_rw(name, step_index, type, reg_num) \ + (&((struct tgu_attribute[]){ { \ + __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ + step_index, \ + type, \ + reg_num, \ + } })[0].attr.attr) + +#define STEP_PRIORITY(step_index, reg_num, priority) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \ + reg_num) +#define STEP_DECODE(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num) +#define STEP_SELECT(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_SELECT, reg_num) +#define STEP_TIMER(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_TIMER, reg_num) +#define STEP_COUNTER(step_index, reg_num) \ + tgu_dataset_rw(reg##reg_num, step_index, TGU_COUNTER, reg_num) + +#define STEP_PRIORITY_LIST(step_index, priority) \ + {STEP_PRIORITY(step_index, 0, priority), \ + STEP_PRIORITY(step_index, 1, priority), \ + STEP_PRIORITY(step_index, 2, priority), \ + STEP_PRIORITY(step_index, 3, priority), \ + STEP_PRIORITY(step_index, 4, priority), \ + STEP_PRIORITY(step_index, 5, priority), \ + STEP_PRIORITY(step_index, 6, priority), \ + STEP_PRIORITY(step_index, 7, priority), \ + STEP_PRIORITY(step_index, 8, priority), \ + STEP_PRIORITY(step_index, 9, priority), \ + STEP_PRIORITY(step_index, 10, priority), \ + STEP_PRIORITY(step_index, 11, priority), \ + STEP_PRIORITY(step_index, 12, priority), \ + STEP_PRIORITY(step_index, 13, priority), \ + STEP_PRIORITY(step_index, 14, priority), \ + STEP_PRIORITY(step_index, 15, priority), \ + STEP_PRIORITY(step_index, 16, priority), \ + STEP_PRIORITY(step_index, 17, priority), \ + NULL \ + } + +#define STEP_DECODE_LIST(n) \ + {STEP_DECODE(n, 0), \ + STEP_DECODE(n, 1), \ + STEP_DECODE(n, 2), \ + STEP_DECODE(n, 3), \ + NULL \ + } + +#define STEP_SELECT_LIST(n) \ + {STEP_SELECT(n, 0), \ + STEP_SELECT(n, 1), \ + STEP_SELECT(n, 2), \ + STEP_SELECT(n, 3), \ + STEP_SELECT(n, 4), \ + NULL \ + } + +#define STEP_TIMER_LIST(n) \ + {STEP_TIMER(n, 0), \ + STEP_TIMER(n, 1), \ + NULL \ + } + +#define STEP_COUNTER_LIST(n) \ + {STEP_COUNTER(n, 0), \ + STEP_COUNTER(n, 1), \ + NULL \ + } + +#define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_priority" #priority \ + }) + +#define CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_DECODE_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_condition_decode" \ + }) + +#define CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_SELECT_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_condition_select" \ + }) + +#define TIMER_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_TIMER_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_timer" \ + }) + +#define COUNTER_ATTRIBUTE_GROUP_INIT(step)\ + (&(const struct attribute_group){\ + .attrs = (struct attribute*[])STEP_COUNTER_LIST(step),\ + .is_visible = tgu_node_visible,\ + .name = "step" #step "_counter" \ + }) + +enum operation_index { + TGU_PRIORITY0, + TGU_PRIORITY1, + TGU_PRIORITY2, + TGU_PRIORITY3, + TGU_CONDITION_DECODE, + TGU_CONDITION_SELECT, + TGU_TIMER, + TGU_COUNTER, +}; + +/* Maximum priority that TGU supports */ +#define MAX_PRIORITY 4 + +struct tgu_attribute { + struct device_attribute attr; + u32 step_index; + enum operation_index operation_index; + u32 reg_num; +}; + +struct value_table { + unsigned int *priority; + unsigned int *condition_decode; + unsigned int *condition_select; + unsigned int *timer; + unsigned int *counter; +}; + +static inline void TGU_LOCK(void __iomem *addr) +{ + do { + /* Wait for things to settle */ + mb(); + writel_relaxed(0x0, addr + TGU_LAR); + } while (0); +} + +static inline void TGU_UNLOCK(void __iomem *addr) +{ + do { + writel_relaxed(TGU_UNLOCK_OFFSET, addr + TGU_LAR); + /* Make sure everyone has seen this */ + mb(); + } while (0); +} + +/** + * struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit) + * @base: Memory-mapped base address of the TGU device + * @dev: Pointer to the associated device structure + * @lock: Spinlock for handling concurrent access to private data + * @enabled: Flag indicating whether the TGU device is enabled + * @value_table: Store given value based on relevant parameters + * @num_reg: Maximum number of registers + * @num_step: Maximum step size + * @num_condition_decode: Maximum number of condition_decode + * @num_condition_select: Maximum number of condition_select + * @num_timer: Maximum number of timers + * @num_counter: Maximum number of counters + * + * This structure defines the data associated with a TGU device, + * including its base address, device pointers, clock, spinlock for + * synchronization, trigger data pointers, maximum limits for various + * trigger-related parameters, and enable status. + */ +struct tgu_drvdata { + void __iomem *base; + struct device *dev; + spinlock_t lock; + bool enabled; + struct value_table *value_table; + int num_reg; + int num_step; + int num_condition_decode; + int num_condition_select; + int num_timer; + int num_counter; +}; + +#endif diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig index cd7f0b0f3fbeb..4c83da5d95a05 100644 --- a/drivers/hwtracing/stm/Kconfig +++ b/drivers/hwtracing/stm/Kconfig @@ -40,6 +40,20 @@ config STM_PROTO_SYS_T If you don't know what this is, say N. +config STM_PROTO_OST + tristate "MIPI OST STM framing protocol driver" + default STM + help + This is an implementation of MIPI OST protocol to be used + over the STP transport. In addition to the data payload, it + also carries additional metadata for entity, better + means of trace source identification, etc. + + The receiving side must be able to decode this protocol in + addition to the MIPI STP, in order to extract the data. + + If you don't know what this is, say N. + config STM_DUMMY tristate "Dummy STM driver" help diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile index 1692fcd292779..d9c8615849b95 100644 --- a/drivers/hwtracing/stm/Makefile +++ b/drivers/hwtracing/stm/Makefile @@ -5,9 +5,11 @@ stm_core-y := core.o policy.o obj-$(CONFIG_STM_PROTO_BASIC) += stm_p_basic.o obj-$(CONFIG_STM_PROTO_SYS_T) += stm_p_sys-t.o +obj-$(CONFIG_STM_PROTO_OST) += stm_p_ost.o stm_p_basic-y := p_basic.o stm_p_sys-t-y := p_sys-t.o +stm_p_ost-y := p_ost.o obj-$(CONFIG_STM_DUMMY) += dummy_stm.o diff --git a/drivers/hwtracing/stm/p_ost.c b/drivers/hwtracing/stm/p_ost.c new file mode 100644 index 0000000000000..d2174872b7615 --- /dev/null +++ b/drivers/hwtracing/stm/p_ost.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * MIPI OST framing protocol for STM devices. + */ + +#include +#include +#include +#include +#include "stm.h" + +/* + * OST Base Protocol Header + * + * Position Bits Field Name + * 0 8 STARTSIMPLE + * 1 8 Version + * 2 8 Entity ID + * 3 8 Protocol ID + */ +#define OST_FIELD_STARTSIMPLE 0 +#define OST_FIELD_VERSION 8 +#define OST_FIELD_ENTITY 16 +#define OST_FIELD_PROTOCOL 24 + +#define OST_TOKEN_STARTSIMPLE 0x10 +#define OST_VERSION_MIPI1 0x10 + +/* entity id to identify the source */ +#define OST_ENTITY_FTRACE 0x01 +#define OST_ENTITY_CONSOLE 0x02 +#define OST_ENTITY_DIAG 0xEE + +#define OST_CONTROL_PROTOCOL 0x0 + +#define DATA_HEADER ((OST_TOKEN_STARTSIMPLE << OST_FIELD_STARTSIMPLE) | \ + (OST_VERSION_MIPI1 << OST_FIELD_VERSION) | \ + (OST_CONTROL_PROTOCOL << OST_FIELD_PROTOCOL)) + +#define STM_MAKE_VERSION(ma, mi) (((ma) << 8) | (mi)) +#define STM_HEADER_MAGIC (0x5953) + +enum ost_entity_type { + OST_ENTITY_TYPE_NONE, + OST_ENTITY_TYPE_FTRACE, + OST_ENTITY_TYPE_CONSOLE, + OST_ENTITY_TYPE_DIAG, +}; + +static const char * const str_ost_entity_type[] = { + [OST_ENTITY_TYPE_NONE] = "none", + [OST_ENTITY_TYPE_FTRACE] = "ftrace", + [OST_ENTITY_TYPE_CONSOLE] = "console", + [OST_ENTITY_TYPE_DIAG] = "diag", +}; + +static const u32 ost_entity_value[] = { + [OST_ENTITY_TYPE_NONE] = 0, + [OST_ENTITY_TYPE_FTRACE] = OST_ENTITY_FTRACE, + [OST_ENTITY_TYPE_CONSOLE] = OST_ENTITY_CONSOLE, + [OST_ENTITY_TYPE_DIAG] = OST_ENTITY_DIAG, +}; + +struct ost_policy_node { + enum ost_entity_type entity_type; +}; + +struct ost_output { + struct ost_policy_node node; +}; + +/* Set default entity type as none */ +static void ost_policy_node_init(void *priv) +{ + struct ost_policy_node *pn = priv; + + pn->entity_type = OST_ENTITY_TYPE_NONE; +} + +static int ost_output_open(void *priv, struct stm_output *output) +{ + struct ost_policy_node *pn = priv; + struct ost_output *opriv; + + opriv = kzalloc_obj(*opriv, GFP_ATOMIC); + if (!opriv) + return -ENOMEM; + + memcpy(&opriv->node, pn, sizeof(opriv->node)); + output->pdrv_private = opriv; + return 0; +} + +static void ost_output_close(struct stm_output *output) +{ + kfree(output->pdrv_private); +} + +static ssize_t ost_t_policy_entity_show(struct config_item *item, + char *page) +{ + struct ost_policy_node *pn = to_pdrv_policy_node(item); + ssize_t sz = 0; + int i; + + for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) { + if (i == pn->entity_type) + sz += sysfs_emit_at(page, sz, "[%s] ", str_ost_entity_type[i]); + else + sz += sysfs_emit_at(page, sz, "%s ", str_ost_entity_type[i]); + } + + sz += sysfs_emit_at(page, sz, "\n"); + return sz; +} + +static int entity_index(const char *str) +{ + int i; + + for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) { + if (sysfs_streq(str, str_ost_entity_type[i])) + return i; + } + + return 0; +} + +static ssize_t +ost_t_policy_entity_store(struct config_item *item, const char *page, + size_t count) +{ + struct mutex *mutexp = &item->ci_group->cg_subsys->su_mutex; + struct ost_policy_node *pn = to_pdrv_policy_node(item); + int i; + + i = entity_index(page); + if (i) { + mutex_lock(mutexp); + pn->entity_type = i; + mutex_unlock(mutexp); + } else { + return -EINVAL; + } + + return count; +} +CONFIGFS_ATTR(ost_t_policy_, entity); + +static struct configfs_attribute *ost_t_policy_attrs[] = { + &ost_t_policy_attr_entity, + NULL, +}; + +static ssize_t +notrace ost_write(struct stm_data *data, struct stm_output *output, + unsigned int chan, const char *buf, size_t count, + struct stm_source_data *source) +{ + struct ost_output *op = output->pdrv_private; + unsigned int c = output->channel + chan; + unsigned int m = output->master; + const unsigned char nil = 0; + u32 header = DATA_HEADER; + struct trc_hdr { + u16 version; + u16 magic; + u32 cpu; + u64 timestamp; + u64 tgid; + } hdr; + ssize_t sz; + + /* + * Identify the source by entity type. + * If entity type is not set, return error value. + */ + if (op->node.entity_type) + header |= (ost_entity_value[op->node.entity_type] << OST_FIELD_ENTITY); + else + return -EINVAL; + + /* + * STP framing rules for OST frames: + * * the first packet of the OST frame is marked; + * * the last packet is a FLAG with timestamped tag. + */ + /* Message layout: HEADER / DATA / TAIL */ + /* HEADER */ + sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_MARKED, + 4, (u8 *)&header); + if (sz <= 0) + return sz; + + /* DATA */ + hdr.version = STM_MAKE_VERSION(0, 3); + hdr.magic = STM_HEADER_MAGIC; + hdr.cpu = raw_smp_processor_id(); + hdr.timestamp = sched_clock(); + hdr.tgid = task_tgid_nr(current); + sz = stm_data_write(data, m, c, false, &hdr, sizeof(hdr)); + if (sz <= 0) + return sz; + + sz = stm_data_write(data, m, c, false, buf, count); + + /* TAIL */ + if (sz > 0) + data->packet(data, m, c, STP_PACKET_FLAG, + STP_PACKET_TIMESTAMPED, 0, &nil); + + return sz; +} + +static const struct stm_protocol_driver ost_pdrv = { + .owner = THIS_MODULE, + .name = "p_ost", + .priv_sz = sizeof(struct ost_policy_node), + .write = ost_write, + .policy_attr = ost_t_policy_attrs, + .output_open = ost_output_open, + .output_close = ost_output_close, + .policy_node_init = ost_policy_node_init, +}; + +static int ost_stm_init(void) +{ + return stm_register_protocol(&ost_pdrv); +} +module_init(ost_stm_init); + +static void ost_stm_exit(void) +{ + stm_unregister_protocol(&ost_pdrv); +} +module_exit(ost_stm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MIPI Open System Trace STM framing protocol driver"); diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 4d64895a9e9e4..bdeda3979c481 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -492,24 +492,8 @@ static int __maybe_unused cci_resume_runtime(struct device *dev) return 0; } -static int __maybe_unused cci_suspend(struct device *dev) -{ - if (!pm_runtime_suspended(dev)) - return cci_suspend_runtime(dev); - - return 0; -} - -static int __maybe_unused cci_resume(struct device *dev) -{ - cci_resume_runtime(dev); - pm_request_autosuspend(dev); - - return 0; -} - static const struct dev_pm_ops qcom_cci_pm = { - SET_SYSTEM_SLEEP_PM_OPS(cci_suspend, cci_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) SET_RUNTIME_PM_OPS(cci_suspend_runtime, cci_resume_runtime, NULL) }; diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index d2f5055b0b108..cb4e7446f0755 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -828,6 +828,14 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i if (i < num - 1) peripheral.stretch = 1; + peripheral.lock_action = GPI_LOCK_NONE; + if (gi2c->se.multi_owner) { + if (i == 0) + peripheral.lock_action = GPI_LOCK_ACQUIRE; + else if (i == num - 1) + peripheral.lock_action = GPI_LOCK_RELEASE; + } + peripheral.addr = msgs[i].addr; if (i > 0 && (!(msgs[i].flags & I2C_M_RD))) peripheral.multi_msg = false; @@ -913,6 +921,10 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, gi2c->err = 0; reinit_completion(&gi2c->done); ret = pm_runtime_get_sync(gi2c->se.dev); + if (ret == -EACCES) { + dev_warn(gi2c->se.dev, "Runtime PM is disabled:%d\n", ret); + ret = 0; + } if (ret < 0) { dev_err(gi2c->se.dev, "error turning SE resources:%d\n", ret); pm_runtime_put_noidle(gi2c->se.dev); @@ -1027,6 +1039,17 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->clk_freq_out = I2C_MAX_STANDARD_MODE_FREQ; } + if (of_property_read_bool(pdev->dev.of_node, "qcom,qup-multi-owner")) { + /* + * Multi-owner controller configuration: the controller may be + * used by another system processor. Mark the SE as shared so + * common GENI resource handling can avoid pin state changes + * that would disrupt the other user. + */ + gi2c->se.multi_owner = true; + dev_dbg(&pdev->dev, "I2C controller is shared with another system processor\n"); + } + if (has_acpi_companion(dev)) ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(dev)); @@ -1045,7 +1068,8 @@ static int geni_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gi2c); /* Keep interrupts disabled initially to allow for low-power modes */ - ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN, + ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, + IRQF_NO_AUTOEN | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME, dev_name(dev), gi2c); if (ret) return dev_err_probe(dev, ret, @@ -1102,7 +1126,9 @@ static int geni_i2c_probe(struct platform_device *pdev) } if (fifo_disable) { - /* FIFO is disabled, so we can only use GPI DMA */ + /* FIFO is disabled, so we can only use GPI DMA. + * SE can be shared in GSI mode between subsystems, each SS owns a GPII. + */ gi2c->gpi_mode = true; ret = setup_gpi_dma(gi2c); if (ret) @@ -1111,6 +1137,10 @@ static int geni_i2c_probe(struct platform_device *pdev) dev_dbg(dev, "Using GPI DMA mode for I2C\n"); } else { gi2c->gpi_mode = false; + + if (gi2c->se.multi_owner) + dev_err_probe(dev, -EINVAL, "I2C sharing not supported in non GSI mode\n"); + tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se); /* I2C Master Hub Serial Elements doesn't have the HW_PARAM_0 register */ @@ -1257,7 +1287,12 @@ static int __maybe_unused geni_i2c_resume_noirq(struct device *dev) if (ret) return ret; + /* Enforced disable_depth = 0 to actually enable runtime PM during noirq phase */ + if (!pm_runtime_enabled(dev)) + pm_runtime_enable(dev); + i2c_mark_adapter_resumed(&gi2c->adap); + return 0; } diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c index 48c793b18d11e..f354532a17f0c 100644 --- a/drivers/iio/adc/qcom-spmi-adc5-gen3.c +++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c @@ -56,9 +56,6 @@ struct adc5_channel_prop { * requests from multiple clients. * @data: software configuration data. * @n_tm_channels: number of ADC channels used for TM measurements. - * @handler: TM callback to be called for threshold violation interrupt - * on first SDAM. - * @tm_aux: pointer to auxiliary TM device. */ struct adc5_chip { struct device *dev; @@ -70,8 +67,6 @@ struct adc5_chip { struct mutex lock; const struct adc5_data *data; unsigned int n_tm_channels; - void (*handler)(struct auxiliary_device *tm_aux); - struct auxiliary_device *tm_aux; }; int adc5_gen3_read(struct adc5_device_data *adc, unsigned int sdam_index, @@ -287,23 +282,21 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id) { struct adc5_chip *adc = dev_id; struct device *dev = adc->dev; - struct auxiliary_device *adev; u8 status, eoc_status, val; - u8 tm_status[2]; int ret; ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_STATUS1, &status, sizeof(status)); if (ret) { dev_err(dev, "adc read status1 failed with %d\n", ret); - return IRQ_HANDLED; + return IRQ_NONE; } ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_EOC_STS, &eoc_status, sizeof(eoc_status)); if (ret) { dev_err(dev, "adc read eoc status failed with %d\n", ret); - return IRQ_HANDLED; + return IRQ_NONE; } if (status & ADC5_GEN3_STATUS1_CONV_FAULT) { @@ -316,30 +309,13 @@ static irqreturn_t adc5_gen3_isr(int irq, void *dev_id) return IRQ_HANDLED; } - /* CHAN0 is the preconfigured channel for immediate conversion */ - if (eoc_status & ADC5_GEN3_EOC_CHAN_0) - complete(&adc->complete); - - ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, - ADC5_GEN3_TM_HIGH_STS, tm_status, sizeof(tm_status)); - if (ret) { - dev_err(dev, "adc read TM status failed with %d\n", ret); - return IRQ_HANDLED; - } - - dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x, high:%#x, low:%#x\n", - status, eoc_status, tm_status[0], tm_status[1]); + dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x\n", status, eoc_status); - if (tm_status[0] || tm_status[1]) { - adev = adc->tm_aux; - if (!adev || !adev->dev.driver) { - dev_err(dev, "adc_tm auxiliary device not initialized\n"); - return IRQ_HANDLED; - } - - adc->handler(adev); - } + /* CHAN0 is the preconfigured channel for immediate conversion */ + if (!(eoc_status & ADC5_GEN3_EOC_CHAN_0)) + return IRQ_NONE; + complete(&adc->complete); return IRQ_HANDLED; } @@ -684,8 +660,6 @@ static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc) if (ret) return ret; - adc->tm_aux = &aux_device->aux_dev; - return 0; } @@ -741,16 +715,6 @@ int adc5_gen3_therm_code_to_temp(struct device *dev, } EXPORT_SYMBOL_NS_GPL(adc5_gen3_therm_code_to_temp, "QCOM_SPMI_ADC5_GEN3"); -void adc5_gen3_register_tm_event_notifier(struct device *dev, - void (*handler)(struct auxiliary_device *)) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); - struct adc5_chip *adc = iio_priv(indio_dev); - - adc->handler = handler; -} -EXPORT_SYMBOL_NS_GPL(adc5_gen3_register_tm_event_notifier, "QCOM_SPMI_ADC5_GEN3"); - static int adc5_gen3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -817,10 +781,18 @@ static int adc5_gen3_probe(struct platform_device *pdev) return -ENOMEM; } - ret = devm_request_irq(dev, adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq, - adc5_gen3_isr, 0, - adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq_name, - adc); + /* + * This interrupt is shared with the ADC_TM auxiliary driver, which + * is threaded and uses IRQF_ONESHOT. Since shared interrupts need + * to agree on IRQF_ONESHOT configuration and there is a kernel + * warning for using IRQF_ONESHOT with non-threaded interrupts, + * make this also a threaded IRQ. + */ + + ret = devm_request_threaded_irq(dev, adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq, + NULL, adc5_gen3_isr, IRQF_ONESHOT | IRQF_SHARED, + adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq_name, + adc); if (ret) return dev_err_probe(dev, ret, "Failed to request SDAM%d irq\n", diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index 5b8a094ca4ede..baec7eb4c24be 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -333,6 +333,7 @@ config INTERCONNECT_QCOM_SHIKRA tristate "Qualcomm SHIKRA interconnect driver" depends on INTERCONNECT_QCOM depends on QCOM_SMD_RPM + default ARCH_QCOM select INTERCONNECT_QCOM_SMD_RPM help This is a driver for the Qualcomm Network-on-Chip on shikra-based diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c index b33f00da1880d..ecad636b53e06 100644 --- a/drivers/interconnect/qcom/osm-l3.c +++ b/drivers/interconnect/qcom/osm-l3.c @@ -60,6 +60,7 @@ struct qcom_osm_l3_desc { unsigned int lut_row_size; unsigned int reg_freq_lut; unsigned int reg_perf_state; + unsigned int lut_max_entries; }; #define DEFINE_QNODE(_name, _buswidth) \ @@ -90,6 +91,7 @@ static const struct qcom_osm_l3_desc osm_l3 = { .lut_row_size = OSM_LUT_ROW_SIZE, .reg_freq_lut = OSM_REG_FREQ_LUT, .reg_perf_state = OSM_REG_PERF_STATE, + .lut_max_entries = LUT_MAX_ENTRIES, }; static const struct qcom_osm_l3_desc epss_l3_perf_state = { @@ -98,6 +100,16 @@ static const struct qcom_osm_l3_desc epss_l3_perf_state = { .lut_row_size = EPSS_LUT_ROW_SIZE, .reg_freq_lut = EPSS_REG_FREQ_LUT, .reg_perf_state = EPSS_REG_PERF_STATE, + .lut_max_entries = LUT_MAX_ENTRIES, +}; + +static const struct qcom_osm_l3_desc shikra_epss_l3_perf_state = { + .nodes = epss_l3_nodes, + .num_nodes = ARRAY_SIZE(epss_l3_nodes), + .lut_row_size = EPSS_LUT_ROW_SIZE, + .reg_freq_lut = EPSS_REG_FREQ_LUT, + .reg_perf_state = EPSS_REG_PERF_STATE, + .lut_max_entries = 12, }; static const struct qcom_osm_l3_desc epss_l3_l3_vote = { @@ -106,6 +118,7 @@ static const struct qcom_osm_l3_desc epss_l3_l3_vote = { .lut_row_size = EPSS_LUT_ROW_SIZE, .reg_freq_lut = EPSS_REG_FREQ_LUT, .reg_perf_state = EPSS_REG_L3_VOTE, + .lut_max_entries = LUT_MAX_ENTRIES, }; static int qcom_osm_l3_set(struct icc_node *src, struct icc_node *dst) @@ -189,7 +202,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) qp->reg_perf_state = desc->reg_perf_state; - for (i = 0; i < LUT_MAX_ENTRIES; i++) { + for (i = 0; i < desc->lut_max_entries; i++) { info = readl_relaxed(qp->base + desc->reg_freq_lut + i * desc->lut_row_size); src = FIELD_GET(LUT_SRC, info); @@ -272,6 +285,7 @@ static const struct of_device_id osm_l3_of_match[] = { { .compatible = "qcom,sc7180-osm-l3", .data = &osm_l3 }, { .compatible = "qcom,sc7280-epss-l3", .data = &epss_l3_perf_state }, { .compatible = "qcom,sdm845-osm-l3", .data = &osm_l3 }, + { .compatible = "qcom,shikra-epss-l3", .data = &shikra_epss_l3_perf_state }, { .compatible = "qcom,sm8150-osm-l3", .data = &osm_l3 }, { .compatible = "qcom,sc8180x-osm-l3", .data = &osm_l3 }, { .compatible = "qcom,sm8250-epss-l3", .data = &epss_l3_perf_state }, diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index e2c914fccd6fc..f95b7d3b7a965 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -55,6 +55,8 @@ static const struct of_device_id qcom_smmu_actlr_client_of_match[] = { .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, { .compatible = "qcom,sc8280xp-mdss", .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, + { .compatible = "qcom,shikra-mdss", + .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, { .compatible = "qcom,sm6115-mdss", .data = (const void *) (PREFETCH_SHALLOW | CPRE | CMTLB) }, { .compatible = "qcom,sm6125-mdss", diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 0bd21d206eb3e..744ff8b4d5733 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -53,6 +53,11 @@ #define MSI_IOVA_BASE 0x8000000 #define MSI_IOVA_LENGTH 0x100000 +/* Interconnect bandwidth vote values for the SMMU register access path */ +#define ARM_SMMU_ICC_AVG_BW 0 +#define ARM_SMMU_ICC_PEAK_BW_HIGH 1000 +#define ARM_SMMU_ICC_PEAK_BW_LOW 0 + static int force_stage; module_param(force_stage, int, S_IRUGO); MODULE_PARM_DESC(force_stage, @@ -86,6 +91,36 @@ static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu) } } +static int arm_smmu_icc_get(struct arm_smmu_device *smmu) +{ + smmu->icc_path = devm_of_icc_get(smmu->dev, NULL); + if (IS_ERR(smmu->icc_path)) { + int err = PTR_ERR(smmu->icc_path); + + if (err == -ENODEV) { + smmu->icc_path = NULL; + return 0; + } + return dev_err_probe(smmu->dev, err, + "failed to get interconnect path\n"); + } + return 0; +} + +static void arm_smmu_icc_enable(struct arm_smmu_device *smmu) +{ + if (smmu->icc_path) + WARN_ON(icc_set_bw(smmu->icc_path, ARM_SMMU_ICC_AVG_BW, + ARM_SMMU_ICC_PEAK_BW_HIGH)); +} + +static void arm_smmu_icc_disable(struct arm_smmu_device *smmu) +{ + if (smmu->icc_path) + WARN_ON(icc_set_bw(smmu->icc_path, ARM_SMMU_ICC_AVG_BW, + ARM_SMMU_ICC_PEAK_BW_LOW)); +} + static void arm_smmu_rpm_use_autosuspend(struct arm_smmu_device *smmu) { /* @@ -462,10 +497,20 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) int idx = smmu_domain->cfg.cbndx; int ret; + if (!pm_runtime_get_if_active(smmu->dev)) + return IRQ_NONE; + + if (smmu->impl && smmu->impl->context_fault) { + ret = smmu->impl->context_fault(irq, dev); + goto out_power_off; + } + arm_smmu_read_context_fault_info(smmu, idx, &cfi); - if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT)) - return IRQ_NONE; + if (!(cfi.fsr & ARM_SMMU_CB_FSR_FAULT)) { + ret = IRQ_NONE; + goto out_power_off; + } ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova, cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ); @@ -480,7 +525,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) ret == -EAGAIN ? 0 : ARM_SMMU_RESUME_TERMINATE); } - return IRQ_HANDLED; + ret = IRQ_HANDLED; + +out_power_off: + pm_runtime_put_autosuspend(smmu->dev); + + return ret; } static irqreturn_t arm_smmu_global_fault(int irq, void *dev) @@ -489,14 +539,25 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev) struct arm_smmu_device *smmu = dev; static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); + int ret; + + if (!pm_runtime_get_if_active(smmu->dev)) + return IRQ_NONE; + + if (smmu->impl && smmu->impl->global_fault) { + ret = smmu->impl->global_fault(irq, dev); + goto out_power_off; + } gfsr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSR); gfsynr0 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR0); gfsynr1 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR1); gfsynr2 = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sGFSYNR2); - if (!gfsr) - return IRQ_NONE; + if (!gfsr) { + ret = IRQ_NONE; + goto out_power_off; + } if (__ratelimit(&rs)) { if (IS_ENABLED(CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT) && @@ -513,7 +574,11 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev) } arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sGFSR, gfsr); - return IRQ_HANDLED; + ret = IRQ_HANDLED; + +out_power_off: + pm_runtime_put_autosuspend(smmu->dev); + return ret; } static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, @@ -683,7 +748,6 @@ static int arm_smmu_init_domain_context(struct arm_smmu_domain *smmu_domain, enum io_pgtable_fmt fmt; struct iommu_domain *domain = &smmu_domain->domain; struct arm_smmu_cfg *cfg = &smmu_domain->cfg; - irqreturn_t (*context_fault)(int irq, void *dev); mutex_lock(&smmu_domain->init_mutex); if (smmu_domain->smmu) @@ -850,19 +914,14 @@ static int arm_smmu_init_domain_context(struct arm_smmu_domain *smmu_domain, */ irq = smmu->irqs[cfg->irptndx]; - if (smmu->impl && smmu->impl->context_fault) - context_fault = smmu->impl->context_fault; - else - context_fault = arm_smmu_context_fault; - if (smmu->impl && smmu->impl->context_fault_needs_threaded_irq) ret = devm_request_threaded_irq(smmu->dev, irq, NULL, - context_fault, + arm_smmu_context_fault, IRQF_ONESHOT | IRQF_SHARED, "arm-smmu-context-fault", smmu_domain); else - ret = devm_request_irq(smmu->dev, irq, context_fault, IRQF_SHARED, + ret = devm_request_irq(smmu->dev, irq, arm_smmu_context_fault, IRQF_SHARED, "arm-smmu-context-fault", smmu_domain); if (ret < 0) { @@ -2125,7 +2184,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int num_irqs, i, err; u32 global_irqs, pmu_irqs; - irqreturn_t (*global_fault)(int irq, void *dev); smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); if (!smmu) { @@ -2189,6 +2247,17 @@ static int arm_smmu_device_probe(struct platform_device *pdev) if (err) return err; + /* + * Acquire and vote the interconnect path before accessing any SMMU + * registers (including ARM_SMMU_GR0_ID0 in arm_smmu_device_cfg_probe). + */ + err = arm_smmu_icc_get(smmu); + if (err) { + clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); + return err; + } + arm_smmu_icc_enable(smmu); + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2205,18 +2274,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->num_context_irqs = smmu->num_context_banks; } - if (smmu->impl && smmu->impl->global_fault) - global_fault = smmu->impl->global_fault; - else - global_fault = arm_smmu_global_fault; - for (i = 0; i < global_irqs; i++) { int irq = platform_get_irq(pdev, i); if (irq < 0) return irq; - err = devm_request_irq(dev, irq, global_fault, IRQF_SHARED, + err = devm_request_irq(dev, irq, arm_smmu_global_fault, IRQF_SHARED, "arm-smmu global fault", smmu); if (err) return dev_err_probe(dev, err, @@ -2273,8 +2337,10 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) if (pm_runtime_enabled(smmu->dev)) pm_runtime_force_suspend(smmu->dev); - else + else { clk_bulk_disable(smmu->num_clks, smmu->clks); + arm_smmu_icc_disable(smmu); + } clk_bulk_unprepare(smmu->num_clks, smmu->clks); } @@ -2294,9 +2360,13 @@ static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) struct arm_smmu_device *smmu = dev_get_drvdata(dev); int ret; + arm_smmu_icc_enable(smmu); + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); - if (ret) + if (ret) { + arm_smmu_icc_disable(smmu); return ret; + } arm_smmu_device_reset(smmu); @@ -2308,6 +2378,7 @@ static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) struct arm_smmu_device *smmu = dev_get_drvdata(dev); clk_bulk_disable(smmu->num_clks, smmu->clks); + arm_smmu_icc_disable(smmu); return 0; } diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h index 26d2e33cd328b..c00606a416b2f 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -335,6 +336,7 @@ struct arm_smmu_device { int num_clks; unsigned int *irqs; struct clk_bulk_data *clks; + struct icc_path *icc_path; spinlock_t global_sync_lock; diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 42f2278a702d0..d8a9af2ad8132 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -528,6 +528,7 @@ config GOLDFISH_PIC config QCOM_PDC tristate "Qualcomm PDC" depends on ARCH_QCOM + depends on QCOM_AOSS_QMP select IRQ_DOMAIN_HIERARCHY help Power Domain Controller driver to manage and configure wakeup diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index 2014dbb0bc43a..578206b8a7e39 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -3,7 +3,6 @@ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. */ -#include #include #include #include @@ -20,32 +19,31 @@ #include #include #include +#include +#include #define PDC_MAX_GPIO_IRQS 256 -#define PDC_DRV_SIZE 0x10000 +#define PDC_DRV_OFFSET 0x10000 /* Valid only on HW version < 3.2 */ #define IRQ_ENABLE_BANK 0x10 #define IRQ_ENABLE_BANK_MAX (IRQ_ENABLE_BANK + BITS_TO_BYTES(PDC_MAX_GPIO_IRQS)) -#define IRQ_ENABLE_BANK_INDEX_MASK GENMASK(31, 5) -#define IRQ_ENABLE_BANK_BIT_MASK GENMASK(4, 0) +#define IRQ_i_CFG_IRQ_MASK_3_0 3 #define IRQ_i_CFG 0x110 /* Valid only on HW version >= 3.2 */ +#define IRQ_i_CFG_IRQ_MASK_3_2 4 #define IRQ_i_CFG_IRQ_ENABLE 3 -#define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0) +#define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0) -#define PDC_VERSION_REG 0x1000 -#define PDC_VERSION_MAJOR GENMASK(23, 16) -#define PDC_VERSION_MINOR GENMASK(15, 8) -#define PDC_VERSION_STEP GENMASK(7, 0) -#define PDC_VERSION(maj, min, step) (FIELD_PREP(PDC_VERSION_MAJOR, (maj)) | \ - FIELD_PREP(PDC_VERSION_MINOR, (min)) | \ - FIELD_PREP(PDC_VERSION_STEP, (step))) +#define PDC_VERSION_REG 0x1000 /* Notable PDC versions */ -#define PDC_VERSION_3_2 PDC_VERSION(3, 2, 0) +#define PDC_VERSION_3_0 0x30000 +#define PDC_VERSION_3_2 0x30200 + +#define PDC_PASS_THROUGH_MODE 0 struct pdc_pin_region { u32 pin_base; @@ -106,37 +104,55 @@ static void pdc_x1e_irq_enable_write(u32 bank, u32 enable) pdc_base_reg_write(base, IRQ_ENABLE_BANK, bank, enable); } -static void pdc_enable_intr_bank(int pin_out, bool on) +/* + * The new mask bit controls whether the interrupt is to be forwarded to the + * parent GIC in secondary controller mode. Writing the mask is do not care + * when the PDC is set to pass through mode. + * + * As linux only makes so far make use of pass through mode set all IRQs + * masked during probe. + */ +static void __pdc_mask_intr(int pin_out, bool mask) { - unsigned long enable; - u32 index, mask; + unsigned long irq_cfg; + int mask_bit; - index = FIELD_GET(IRQ_ENABLE_BANK_INDEX_MASK, pin_out); - mask = FIELD_GET(IRQ_ENABLE_BANK_BIT_MASK, pin_out); - - enable = pdc_reg_read(IRQ_ENABLE_BANK, index); - __assign_bit(mask, &enable, on); + /* Mask bit available from v3.0 */ + if (pdc_version < PDC_VERSION_3_0) + return; - if (pdc_x1e_quirk) - pdc_x1e_irq_enable_write(index, enable); + if (pdc_version < PDC_VERSION_3_2) + mask_bit = IRQ_i_CFG_IRQ_MASK_3_0; else - pdc_reg_write(IRQ_ENABLE_BANK, index, enable); -} + mask_bit = IRQ_i_CFG_IRQ_MASK_3_2; -static void pdc_enable_intr_cfg(int pin_out, bool on) -{ - unsigned long enable = pdc_reg_read(IRQ_i_CFG, pin_out); - - __assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on); - pdc_reg_write(IRQ_i_CFG, pin_out, enable); + irq_cfg = pdc_reg_read(IRQ_i_CFG, pin_out); + __assign_bit(mask_bit, &irq_cfg, mask); + pdc_reg_write(IRQ_i_CFG, pin_out, irq_cfg); } static void __pdc_enable_intr(int pin_out, bool on) { - if (pdc_version < PDC_VERSION_3_2) - pdc_enable_intr_bank(pin_out, on); - else - pdc_enable_intr_cfg(pin_out, on); + unsigned long enable; + + if (pdc_version < PDC_VERSION_3_2) { + u32 index, mask; + + index = pin_out / 32; + mask = pin_out % 32; + + enable = pdc_reg_read(IRQ_ENABLE_BANK, index); + __assign_bit(mask, &enable, on); + + if (pdc_x1e_quirk) + pdc_x1e_irq_enable_write(index, enable); + else + pdc_reg_write(IRQ_ENABLE_BANK, index, enable); + } else { + enable = pdc_reg_read(IRQ_i_CFG, pin_out); + __assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on); + pdc_reg_write(IRQ_i_CFG, pin_out, enable); + } } static void pdc_enable_intr(struct irq_data *d, bool on) @@ -330,7 +346,6 @@ static const struct irq_domain_ops qcom_pdc_ops = { static int pdc_setup_pin_mapping(struct device_node *np) { int ret, n, i; - n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32)); if (n <= 0 || n % 3) return -EINVAL; @@ -359,30 +374,43 @@ static int pdc_setup_pin_mapping(struct device_node *np) if (ret) return ret; - for (i = 0; i < pdc_region[n].cnt; i++) + for (i = 0; i < pdc_region[n].cnt; i++) { __pdc_enable_intr(i + pdc_region[n].pin_base, 0); + __pdc_mask_intr(i + pdc_region[n].pin_base, true); + } } return 0; } +#define QCOM_PDC_SIZE 0x10000 static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *parent) { + static const char buf[64] = "{class: cx_mol, res: cx, val: mol}"; + unsigned int domain_flag = IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP; struct irq_domain *parent_domain, *pdc_domain; struct device_node *node = pdev->dev.of_node; resource_size_t res_size; struct resource res; + struct qmp *pdc_qmp; int ret; /* compat with old sm8150 DT which had very small region for PDC */ if (of_address_to_resource(node, 0, &res)) return -EINVAL; - res_size = max_t(resource_size_t, resource_size(&res), PDC_DRV_SIZE); + res_size = max_t(resource_size_t, resource_size(&res), QCOM_PDC_SIZE); if (res_size > resource_size(&res)) pr_warn("%pOF: invalid reg size, please fix DT\n", node); + pdc_base = ioremap(res.start, res_size); + if (!pdc_base) { + pr_err("%pOF: unable to map PDC registers\n", node); + ret = -ENXIO; + goto fail; + } + /* * PDC has multiple DRV regions, each one provides the same set of * registers for a particular client in the system. Due to a hardware @@ -392,22 +420,78 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare * region with the expected offset to preserve support for old DTs. */ if (of_device_is_compatible(node, "qcom,x1e80100-pdc")) { - pdc_prev_base = ioremap(res.start - PDC_DRV_SIZE, IRQ_ENABLE_BANK_MAX); + pdc_prev_base = ioremap(res.start - PDC_DRV_OFFSET, IRQ_ENABLE_BANK_MAX); if (!pdc_prev_base) { pr_err("%pOF: unable to map previous PDC DRV region\n", node); return -ENXIO; } pdc_x1e_quirk = true; - } - pdc_base = ioremap(res.start, res_size); - if (!pdc_base) { - pr_err("%pOF: unable to map PDC registers\n", node); - ret = -ENXIO; - goto fail; + /* + * There are two modes PDC irqchip can work in + * - pass through mode + * - secondary controller mode + * + * All PDC irqchip supports pass through mode in which both + * Direct SPIs and GPIO IRQs (as SPIs) are sent to GIC + * without latching at PDC. + * + * Newer PDCs (v3.0 onwards) also support additional + * secondary controller mode where PDC latches GPIO IRQs + * and sends to GIC as level type IRQ. Direct SPIs still + * works same as pass through mode without latching at PDC + * even in secondary controller mode. + * + * All the SoCs so far default uses pass through mode with + * the exception of x1e. + * + * x1e modes: + * + * x1e PDC may be set to secondary controller mode for + * builds on CRD boards whereas it may be set to pass + * through mode for IoT-EVK boards. + * + * There is no way to read which current mode it is set to + * and make PDC work in respective mode as the read access + * is not opened up for non secure world. There is though + * write access opened up via SCM write API to set the mode. + * + * Configure PDC mode to pass through mode for all x1e based + * boards. + * + * For successful write: + * - Nothing more to be done + * + * For unsuccessful write: + * - Inform TLMM to monitor GPIO IRQs (same as MPM) + * - Prevent SoC low power mode (CxPC) as PDC is not + * monitoring GPIO IRQs which may be needed to wake + * the SoC from low power mode. + */ + ret = of_address_to_resource(node, 2, &res); + if (ret) { + domain_flag = IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP; + goto skip_scm_write; + } + + ret = qcom_scm_io_writel(res.start, PDC_PASS_THROUGH_MODE); + if (ret) { + pdc_qmp = qmp_get(&pdev->dev); + if (IS_ERR(pdc_qmp)) { + ret = PTR_ERR(pdc_qmp); + goto fail; + } else { + ret = qmp_send(pdc_qmp, buf, sizeof(buf)); + qmp_put(pdc_qmp); + if (ret) + goto fail; + } + domain_flag = IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP; + } } +skip_scm_write: pdc_version = pdc_reg_read(PDC_VERSION_REG, 0); parent_domain = irq_find_host(parent); @@ -424,7 +508,7 @@ static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *pare } pdc_domain = irq_domain_create_hierarchy(parent_domain, - IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP, + domain_flag, PDC_MAX_GPIO_IRQS, of_fwnode_handle(node), &qcom_pdc_ops, NULL); diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c index d3a8f6b4a03b3..8e544dbe3c5ff 100644 --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c @@ -168,6 +168,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = { { .compatible = "qcom,ipq8074-apcs-apps-global", .data = &ipq6018_apcs_data }, { .compatible = "qcom,sc7180-apss-shared", .data = &apps_shared_apcs_data }, { .compatible = "qcom,sc8180x-apss-shared", .data = &apps_shared_apcs_data }, + { .compatible = "qcom,shikra-apcs-hmss-global", .data = &apps_shared_apcs_data }, { .compatible = "qcom,sm8150-apss-shared", .data = &apps_shared_apcs_data }, {} }; diff --git a/drivers/media/platform/qcom/camss/Kconfig b/drivers/media/platform/qcom/camss/Kconfig index 4eda48cb1adf0..1edc5e5a1829e 100644 --- a/drivers/media/platform/qcom/camss/Kconfig +++ b/drivers/media/platform/qcom/camss/Kconfig @@ -7,3 +7,4 @@ config VIDEO_QCOM_CAMSS select VIDEO_V4L2_SUBDEV_API select VIDEOBUF2_DMA_SG select V4L2_FWNODE + select PHY_QCOM_MIPI_CSI2 diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 27898b3cc7d3c..c19d3183882a9 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -8,8 +8,10 @@ qcom-camss-objs += \ camss-csid-4-7.o \ camss-csid-340.o \ camss-csid-680.o \ + camss-csid-980.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ + camss-csid-gen4.o \ camss-csiphy.o \ camss-csiphy-2ph-1-0.o \ camss-csiphy-3ph-1-0.o \ @@ -27,6 +29,7 @@ qcom-camss-objs += \ camss-vfe-680.o \ camss-vfe-gen1.o \ camss-vfe-gen3.o \ + camss-vfe-gen4.o \ camss-vfe-vbif.o \ camss-video.o diff --git a/drivers/media/platform/qcom/camss/camss-csid-680.c b/drivers/media/platform/qcom/camss/camss-csid-680.c index 345a67c8fb947..bf7164085ddb4 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-680.c +++ b/drivers/media/platform/qcom/camss/camss-csid-680.c @@ -101,7 +101,6 @@ #define CSI2_RX_CFG0_DL2_INPUT_SEL 12 #define CSI2_RX_CFG0_DL3_INPUT_SEL 16 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 -#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSI2_RX_CFG0_PHY_TYPE_SEL 24 #define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) #define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) diff --git a/drivers/media/platform/qcom/camss/camss-csid-980.c b/drivers/media/platform/qcom/camss/camss-csid-980.c new file mode 100644 index 0000000000000..79eb063000b8d --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-980.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-980.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0xC +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10 +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x14 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x18 +#define CSID_AUP_CMD 0x1C +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x20 +#define RUP_SET BIT(0) +#define MUP BIT(4) + +#define CSID_LITE_RUP_AUP_CMD 0x18 +#define CSID_LITE_RUP_RDI(rdi) (BIT(4) << (rdi)) +#define CSID_LITE_AUP_RDI(rdi) (BIT(20) << (rdi)) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS (csid_is_lite(csid) ? 0x7C : 0x84) +#define CSID_TOP_IRQ_MASK (csid_is_lite(csid) ? 0x80 : 0x88) +#define CSID_TOP_IRQ_CLEAR (csid_is_lite(csid) ? 0x84 : 0x8C) +#define CSID_TOP_IRQ_SET (csid_is_lite(csid) ? 0x88 : 0x90) +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(csid_is_lite(csid) ? 13 : 3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS (csid_is_lite(csid) ? 0x8C : 0xA4) +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ? 1 : 16) +#define CSID_BUF_DONE_IRQ_MASK (csid_is_lite(csid) ? 0x90 : 0xA8) +#define CSID_BUF_DONE_IRQ_CLEAR (csid_is_lite(csid) ? 0x94 : 0xAC) +#define CSID_BUF_DONE_IRQ_SET (csid_is_lite(csid) ? 0x98 : 0xB0) + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS (csid_is_lite(csid) ? 0x9C : 0xB4) +#define CSID_CSI2_RX_IRQ_MASK (csid_is_lite(csid) ? 0xA0 : 0xB8) +#define CSID_CSI2_RX_IRQ_CLEAR (csid_is_lite(csid) ? 0xA4 : 0xBC) +#define CSID_CSI2_RX_IRQ_SET (csid_is_lite(csid) ? 0xA8 : 0xC0) + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 (csid_is_lite(csid) ? 0x200 : 0x400) +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 (csid_is_lite(csid) ? 0x204 : 0x404) +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_980 (csid_is_lite(csid) ? 4 : 5) + +#define CSID_RDI_CFG0(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x500 + 0x100 * _rdi : \ + 0xE00 + 0x200 * _rdi; \ + }) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_DT_ID 27 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x504 + 0x100 * _rdi : \ + 0xE04 + 0x200 * _rdi; \ + }) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x510 + 0x100 * _rdi : \ + 0xE10 + 0x200 * _rdi; \ + }) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0xE14 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) \ + (csid_is_lite(csid) ? 0xEC : 0x114 + 0x10 * (rdi)) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) \ + (csid_is_lite(csid) ? 0xF4 : 0x11C + 0x10 * (rdi)) +#define INFO_RUP_DONE BIT(23) + +static void __csid_full_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_AUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_rup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_RUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + if (csid_is_lite(csid)) { + csid->reg_update &= ~CSID_LITE_RUP_RDI(port_id); + csid->reg_update &= ~CSID_LITE_AUP_RDI(port_id); + } else { + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); + } +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + u32 rdi_ctrl_offset = CSID_RDI_CTRL(rdi); + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + rdi_ctrl_offset); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + u8 dt_id = vc & 0x03; + u32 rdi_cfg0_offset = CSID_RDI_CFG0(port); + u32 rdi_cfg1_offset = CSID_RDI_CFG1(port); + u32 rdi_ctrl_offset = CSID_RDI_CTRL(port); + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + val |= dt_id << RDI_CFG0_DT_ID; + writel(val, csid->base + rdi_cfg0_offset); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + rdi_cfg1_offset); + + /* Configure pixel store using dedicated register in 980 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + rdi_ctrl_offset); + + val = readl(csid->base + rdi_cfg0_offset); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + rdi_cfg0_offset); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) { + __csid_aup_update(csid, i); + __csid_rup_update(csid, i); + } + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_980 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; + diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 0fdbf75fb27db..da9458cd178bd 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -105,7 +105,6 @@ #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ (0x34C + 0x100 * (rdi)) :\ (0x54C + 0x100 * (rdi))) -#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 static void __csid_configure_rx(struct csid_device *csid, struct csid_phy_config *phy, int vc) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen4.c b/drivers/media/platform/qcom/camss/camss-csid-gen4.c new file mode 100644 index 0000000000000..41035352c4bb0 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-gen4.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-gen4.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include + +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0x108 +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10C +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x110 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x114 +#define CSID_AUP_CMD 0x118 +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x11C +#define RUP_SET BIT(0) +#define MUP BIT(4) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS 0x180 +#define CSID_TOP_IRQ_MASK 0x184 +#define CSID_TOP_IRQ_CLEAR 0x188 +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS 0x1A0 +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET 16 +#define CSID_BUF_DONE_IRQ_MASK 0x1A4 +#define CSID_BUF_DONE_IRQ_CLEAR 0x1A8 +#define CSID_BUF_DONE_IRQ_SET 0x1AC + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS 0x1B0 +#define CSID_CSI2_RX_IRQ_MASK 0x1B4 +#define CSID_CSI2_RX_IRQ_CLEAR 0x1B8 +#define CSID_CSI2_RX_IRQ_SET 0x1BC + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 0x880 +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 0x884 +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_GEN4 (csid_is_lite(csid) ? 4 : 5) + +/* RDI Configuration */ +#define CSID_RDI_CFG0(rdi) \ + ((csid_is_lite(csid) ? 0x3080 : 0x5480) + 0x200 * (rdi)) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ((csid_is_lite(csid) ? 0x3088 : 0x5488) + 0x200 * (rdi)) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ((csid_is_lite(csid) ? 0x3094 : 0x5494) + 0x200 * (rdi)) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0x5498 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0x224 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_MASK(rdi) (0x228 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0x22C + (0x10 * (rdi))) +#define INFO_RUP_DONE BIT(23) + +static void __csid_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_reg_update(struct csid_device *csid, int port_id) +{ + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + CSID_RDI_CTRL(rdi)); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + writel(val, csid->base + CSID_RDI_CFG0(port)); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + CSID_RDI_CFG1(port)); + + /* Configure pixel store using dedicated register in gen4 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + CSID_RDI_CTRL(port)); + + val = readl(csid->base + CSID_RDI_CFG0(port)); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + CSID_RDI_CFG0(port)); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) + __csid_aup_update(csid, i); + + __csid_reg_update(csid, i); + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -EIO; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_gen4 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 5296b10f6bac8..dd9c0868e9c73 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -27,6 +27,8 @@ /* CSID hardware can demultiplex up to 4 outputs */ #define MSM_CSID_MAX_SRC_STREAMS 4 +/* CSIPHY to hardware PHY selector mapping */ +#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSID_RESET_TIMEOUT_MS 500 enum csid_testgen_mode { @@ -154,7 +156,13 @@ struct csid_device { void __iomem *base; u32 irq; char irq_name[30]; - u32 reg_update; + union { + u32 reg_update; + struct { + u32 rup_update; + u32 aup_update; + }; + }; struct camss_clock *clock; int nclocks; struct regulator_bulk_data *supplies; @@ -216,8 +224,10 @@ extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; +extern const struct csid_hw_ops csid_ops_980; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; +extern const struct csid_hw_ops csid_ops_gen4; /* * csid_is_lite - Check if CSID is CSID lite. diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index dac8d2ecf7995..75c0aef3725e2 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -804,6 +804,123 @@ csiphy_lane_regs lane_regs_sm8650[] = { {0x0c10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* 3nm 2PH v 2.3.0/2.4.0 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_2_4_0[] = { + /* LN 0 */ + {0x0094, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0090, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0098, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x005C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 2 */ + {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0490, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0498, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x045C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 4 */ + {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x08A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0890, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0898, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x082C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0814, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0804, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0808, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x085C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0860, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 6 */ + {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0CA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C38, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x0C5C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0C60, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN CLK */ + {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0EA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0E30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E28, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E00, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E0C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E38, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ static const struct csiphy_lane_regs lane_regs_x1e80100[] = { @@ -1130,6 +1247,7 @@ static bool csiphy_is_gen2(u32 version) switch (version) { case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: @@ -1139,8 +1257,12 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = true; break; } @@ -1222,6 +1344,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); break; case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: regs->lane_regs = &lane_regs_qcm2290[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); @@ -1239,7 +1362,9 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sc8280xp[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); break; + case CAMSS_GLYMUR: case CAMSS_X1E80100: + case CAMSS_X1P42100: regs->lane_regs = &lane_regs_x1e80100[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_x1e80100); regs->offset = 0x1000; @@ -1259,6 +1384,14 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); break; + case CAMSS_8750: + case CAMSS_KAANAPALI: + /* CSPHY v2.4.0 is backward compatible with v2.3.0 settings */ + regs->lane_regs = &lane_regs_2_4_0[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); + regs->offset = 0x1000; + regs->common_status_offset = 0x138; + break; default: break; } diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index 539ac4888b608..57bc0eda43a18 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -7,12 +7,14 @@ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. * Copyright (C) 2016-2018 Linaro Ltd. */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -131,10 +133,10 @@ static u8 csiphy_get_bpp(const struct csiphy_format_info *formats, } /* - * csiphy_set_clock_rates - Calculate and set clock rates on CSIPHY module + * csiphy_set_clock_rates_legacy - Calculate and set clock rates on CSIPHY module * @csiphy: CSIPHY device */ -static int csiphy_set_clock_rates(struct csiphy_device *csiphy) +static int csiphy_set_clock_rates_legacy(struct csiphy_device *csiphy) { struct device *dev = csiphy->camss->dev; s64 link_freq; @@ -200,7 +202,7 @@ static int csiphy_set_clock_rates(struct csiphy_device *csiphy) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_set_power(struct v4l2_subdev *sd, int on) +static int csiphy_set_power_legacy(struct v4l2_subdev *sd, int on) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); struct device *dev = csiphy->camss->dev; @@ -219,7 +221,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) return ret; } - ret = csiphy_set_clock_rates(csiphy); + ret = csiphy_set_clock_rates_legacy(csiphy); if (ret < 0) { regulator_bulk_disable(csiphy->num_supplies, csiphy->supplies); @@ -254,7 +256,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) } /* - * csiphy_stream_on - Enable streaming on CSIPHY module + * csiphy_stream_on_legacy - Enable streaming on CSIPHY module * @csiphy: CSIPHY device * * Helper function to enable streaming on CSIPHY module. @@ -262,7 +264,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_stream_on(struct csiphy_device *csiphy) +static int csiphy_stream_on_legacy(struct csiphy_device *csiphy) { struct csiphy_config *cfg = &csiphy->cfg; s64 link_freq; @@ -306,11 +308,99 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) * * Helper function to disable streaming on CSIPHY module */ -static void csiphy_stream_off(struct csiphy_device *csiphy) +static void csiphy_stream_off_legacy(struct csiphy_device *csiphy) { csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg); } +/* + * csiphy_stream_on - Enable streaming on CSIPHY module + * @csiphy: CSIPHY device + * + * Helper function to enable streaming on CSIPHY module. + * Main configuration of CSIPHY module is also done here. + * + * Return 0 on success or a negative error code otherwise + */ +static int csiphy_stream_on(struct csiphy_device *csiphy) +{ + u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, + csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); + struct csiphy_lanes_cfg *lncfg = &csiphy->cfg.csi2->lane_cfg; + struct phy_configure_opts_mipi_dphy *dphy_cfg; + union phy_configure_opts dphy_opts = { 0 }; + struct device *dev = csiphy->camss->dev; + u8 num_lanes = lncfg->num_data; + s64 link_freq; + int i; + int ret; + + dphy_cfg = &dphy_opts.mipi_dphy; + + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + + if (link_freq < 0) { + dev_err(dev, + "Cannot get CSI2 transmitter's link frequency\n"); + return -EINVAL; + } + + phy_mipi_dphy_get_default_config_for_hsclk(link_freq, num_lanes, dphy_cfg); + + /* Set clock lane id and polarity */ + dphy_cfg->clock_lane_position = lncfg->clk.pos; + dphy_cfg->clock_lane_polarity = lncfg->clk.pol; + + /* Set data lane_mask and lane_polarities */ + for (i = 0; i < num_lanes; i++) { + dphy_cfg->lane_positions[i] = lncfg->data[i].pos; + dphy_cfg->lane_polarities[i] = lncfg->data[i].pol; + } + + phy_set_mode(csiphy->phy, PHY_MODE_MIPI_DPHY); + + ret = phy_configure(csiphy->phy, &dphy_opts); + if (ret) { + dev_err(dev, "failed to configure MIPI D-PHY\n"); + goto error; + } + + return phy_power_on(csiphy->phy); + +error: + return ret; +} + +/* + * csiphy_stream_off - Disable streaming on CSIPHY module + * @csiphy: CSIPHY device + * + * Helper function to disable streaming on CSIPHY module + */ +static void csiphy_stream_off(struct csiphy_device *csiphy) +{ + phy_power_off(csiphy->phy); +} + +/* + * csiphy_set_stream - Enable/disable streaming on CSIPHY module + * @sd: CSIPHY V4L2 subdevice + * @enable: Requested streaming state + * + * Return 0 on success or a negative error code otherwise + */ +static int csiphy_set_stream_legacy(struct v4l2_subdev *sd, int enable) +{ + struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); + int ret = 0; + + if (enable) + ret = csiphy_stream_on_legacy(csiphy); + else + csiphy_stream_off_legacy(csiphy); + + return ret; +} /* * csiphy_set_stream - Enable/disable streaming on CSIPHY module @@ -572,16 +662,16 @@ csiphy_match_clock_name(const char *clock_name, const char *format, ...) } /* - * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources + * msm_csiphy_subdev_init_legacy - Initialize CSIPHY device structure and resources * @csiphy: CSIPHY device * @res: CSIPHY module resources table * @id: CSIPHY module id * * Return 0 on success or a negative error code otherwise */ -int msm_csiphy_subdev_init(struct camss *camss, - struct csiphy_device *csiphy, - const struct camss_subdev_resources *res, u8 id) +int msm_csiphy_subdev_init_legacy(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id) { struct device *dev = camss->dev; struct platform_device *pdev = to_platform_device(dev); @@ -709,6 +799,60 @@ int msm_csiphy_subdev_init(struct camss *camss, return ret; } +/* + * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources + * @csiphy: CSIPHY device + * @res: CSIPHY module resources table + * @id: CSIPHY module id + * + * Return 0 on success or a negative error code otherwise + */ +int msm_csiphy_subdev_init(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id) +{ + struct device *dev = camss->dev; + struct of_phandle_args args; + int idx; + int ret; + + snprintf(csiphy->name, ARRAY_SIZE(csiphy->name), "csiphy%d", id); + + idx = of_property_match_string(dev->of_node, "phy-names", csiphy->name); + if (idx < 0) { + dev_err(dev, "%s not found\n", csiphy->name); + return idx; + } + + ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", idx, &args); + if (ret < 0) { + dev_err(dev, "unable to parse phys args %s\n", csiphy->name); + return ret; + } + + if (!of_device_is_available(args.np)) + goto put_np; + + csiphy->phy = devm_phy_get(dev, csiphy->name); + if (IS_ERR(csiphy->phy)) { + ret = PTR_ERR(csiphy->phy); + goto put_np; + } + + csiphy->camss = camss; + csiphy->id = id; + csiphy->res = &res->csiphy; + + ret = phy_init(csiphy->phy); + if (ret) + dev_err(dev, "phy %s init fail %d\n", csiphy->name, ret); + +put_np: + of_node_put(args.np); + + return ret; +} + /* * csiphy_link_setup - Setup CSIPHY connections * @entity: Pointer to media entity structure @@ -743,8 +887,12 @@ static int csiphy_link_setup(struct media_entity *entity, return 0; } -static const struct v4l2_subdev_core_ops csiphy_core_ops = { - .s_power = csiphy_set_power, +static const struct v4l2_subdev_core_ops csiphy_core_ops_legacy = { + .s_power = csiphy_set_power_legacy, +}; + +static const struct v4l2_subdev_video_ops csiphy_video_ops_legacy = { + .s_stream = csiphy_set_stream_legacy, }; static const struct v4l2_subdev_video_ops csiphy_video_ops = { @@ -758,8 +906,13 @@ static const struct v4l2_subdev_pad_ops csiphy_pad_ops = { .set_fmt = csiphy_set_format, }; +static const struct v4l2_subdev_ops csiphy_v4l2_ops_legacy = { + .core = &csiphy_core_ops_legacy, + .video = &csiphy_video_ops_legacy, + .pad = &csiphy_pad_ops, +}; + static const struct v4l2_subdev_ops csiphy_v4l2_ops = { - .core = &csiphy_core_ops, .video = &csiphy_video_ops, .pad = &csiphy_pad_ops, }; @@ -788,7 +941,11 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, struct device *dev = csiphy->camss->dev; int ret; - v4l2_subdev_init(sd, &csiphy_v4l2_ops); + if (IS_ERR(csiphy->phy)) + v4l2_subdev_init(sd, &csiphy_v4l2_ops_legacy); + else + v4l2_subdev_init(sd, &csiphy_v4l2_ops); + sd->internal_ops = &csiphy_v4l2_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", @@ -828,6 +985,8 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, */ void msm_csiphy_unregister_entity(struct csiphy_device *csiphy) { + if (!IS_ERR(csiphy->phy)) + phy_exit(csiphy->phy); v4l2_device_unregister_subdev(&csiphy->subdev); media_entity_cleanup(&csiphy->subdev.entity); } diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 9d9657b82f748..1879826034aac 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -97,6 +98,7 @@ struct csiphy_device_regs { struct csiphy_device { struct camss *camss; + struct phy *phy; u8 id; struct v4l2_subdev subdev; struct media_pad pads[MSM_CSIPHY_PADS_NUM]; @@ -104,6 +106,7 @@ struct csiphy_device { void __iomem *base_clk_mux; u32 irq; char irq_name[30]; + char name[16]; struct camss_clock *clock; bool *rate_set; int nclocks; @@ -118,6 +121,10 @@ struct csiphy_device { struct camss_subdev_resources; +int msm_csiphy_subdev_init_legacy(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id); + int msm_csiphy_subdev_init(struct camss *camss, struct csiphy_device *csiphy, const struct camss_subdev_resources *res, u8 id); diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c new file mode 100644 index 0000000000000..46d8e61b9bac0 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-vfe-gen4.c + * + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module gen4 + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include + +#include "camss.h" +#include "camss-vfe.h" + +#define IS_VFE_980(vfe) ((vfe)->camss->res->version == CAMSS_8750) + +#define BUS_REG_BASE_980 (vfe_is_lite(vfe) ? 0x200 : 0x800) +#define BUS_REG_BASE_1080 (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define BUS_REG_BASE \ + (IS_VFE_980(vfe) ? BUS_REG_BASE_980 : BUS_REG_BASE_1080) + +#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) +#define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) + +#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0x128) + +#define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) +#define WM_CFG_EN BIT(0) +#define WM_VIR_FRM_EN BIT(1) +#define WM_CFG_MODE BIT(16) +#define VFE_BUS_WM_IMAGE_ADDR(n) (BUS_REG_BASE + 0x504 + (n) * 0x100) +#define VFE_BUS_WM_FRAME_INCR(n) (BUS_REG_BASE + 0x508 + (n) * 0x100) +#define VFE_BUS_WM_IMAGE_CFG_0(n) (BUS_REG_BASE + 0x50C + (n) * 0x100) +#define WM_IMAGE_CFG_0_DEFAULT_WIDTH (0xFFFF) +#define VFE_BUS_WM_IMAGE_CFG_2(n) (BUS_REG_BASE + 0x514 + (n) * 0x100) +#define WM_IMAGE_CFG_2_DEFAULT_STRIDE (0xFFFF) +#define VFE_BUS_WM_PACKER_CFG(n) (BUS_REG_BASE + 0x518 + (n) * 0x100) + +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(n) (BUS_REG_BASE + 0x530 + (n) * 0x100) +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(n) (BUS_REG_BASE + 0x534 + (n) * 0x100) + +/* VFE lite has no such registers */ +#define VFE_BUS_WM_FRAMEDROP_PERIOD(n) (BUS_REG_BASE + 0x538 + (n) * 0x100) +#define VFE_BUS_WM_FRAMEDROP_PATTERN(n) (BUS_REG_BASE + 0x53C + (n) * 0x100) + +#define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x560 + (n) * 0x100) +#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x564 + (n) * 0x100) + +/* + * IFE write master client IDs + * + * VIDEO_FULL 0 + * VIDEO_DC4_Y 1 + * VIDEO_DC4_C 2 + * VIDEO_DC16_Y 3 + * VIDEO_DC16_C 4 + * DISPLAY_DS2_Y 5 + * DISPLAY_DS2_C 6 + * FD_Y 7 + * FD_C 8 + * RAW_OUT(1080)/IR_OUT(980) 9 + * STATS_AEC_BG 10 + * STATS_AEC_BHIST 11 + * STATS_TINTLESS_BG 12 + * STATS_AWB_BG 13 + * STATS_AWB_BFW 14 + * STATS_AF_BHIST 15 + * STATS_ALSC_BG 16 + * STATS_FLICKER_BAYERRS 17 + * STATS_TMC_BHIST 18 + * PDAF_0 19 + * PDAF_1 20 + * PDAF_2 21 + * PDAF_3 22 + * RDI0 23 + * RDI1 24 + * RDI2 25 + * RDI3 26 + * RDI4 27 + * + * IFE Lite write master client IDs + * + * RDI0 0 + * RDI1 1 + * RDI2 2 + * RDI3 3 + * GAMMA 4 + * STATES_BE 5 + */ +#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) + +static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) +{ + struct v4l2_pix_format_mplane *pix = + &line->video_out.active_fmt.fmt.pix_mp; + + wm = RDI_WM(wm); + + /* no clock gating at bus input */ + writel(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); + + writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); + + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF), + vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); + writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE, + vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); + writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); + + /* no dropped frames, one irq per frame */ + if (!vfe_is_lite(vfe)) { + writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); + } + + writel(0, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(wm)); + + writel(1, vfe->base + VFE_BUS_WM_MMU_PREFETCH_CFG(wm)); + writel(0xFFFFFFFF, vfe->base + VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(wm)); + + writel(WM_CFG_EN | WM_CFG_MODE, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_stop(struct vfe_device *vfe, u8 wm) +{ + wm = RDI_WM(wm); + writel(0, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, + struct vfe_line *line) +{ + wm = RDI_WM(wm); + writel(addr >> 8, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + + dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); +} + +static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, false); +} + +static inline void vfe_reg_update_clear(struct vfe_device *vfe, + enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, true); +} + +static const struct camss_video_ops vfe_video_ops_gen4 = { + .queue_buffer = vfe_queue_buffer_v2, + .flush_buffers = vfe_flush_buffers, +}; + +static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) +{ + vfe->video_ops = vfe_video_ops_gen4; +} + +static void vfe_global_reset(struct vfe_device *vfe) +{ + vfe_isr_reset_ack(vfe); +} + +static irqreturn_t vfe_isr(int irq, void *dev) +{ + /* nop */ + return IRQ_HANDLED; +} + +static int vfe_halt(struct vfe_device *vfe) +{ + /* rely on vfe_disable_output() to stop the VFE */ + return 0; +} + +const struct vfe_hw_ops vfe_ops_gen4 = { + .global_reset = vfe_global_reset, + .hw_version = vfe_hw_version, + .isr = vfe_isr, + .pm_domain_off = vfe_pm_domain_off, + .pm_domain_on = vfe_pm_domain_on, + .reg_update = vfe_reg_update, + .reg_update_clear = vfe_reg_update_clear, + .subdev_init = vfe_subdev_init, + .vfe_disable = vfe_disable, + .vfe_enable = vfe_enable_v2, + .vfe_halt = vfe_halt, + .vfe_wm_start = vfe_wm_start, + .vfe_wm_stop = vfe_wm_stop, + .vfe_buf_done = vfe_buf_done, + .vfe_wm_update = vfe_wm_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 319d191589884..c12814085b077 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -342,6 +342,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, break; case CAMSS_660: case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: @@ -352,8 +353,12 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -525,7 +530,8 @@ int vfe_enable_output_v2(struct vfe_line *line) spin_lock_irqsave(&vfe->output_lock, flags); - ops->reg_update_clear(vfe, line->id); + if (ops->reg_update_clear) + ops->reg_update_clear(vfe, line->id); if (output->state > VFE_OUTPUT_RESERVED) { dev_err(vfe->camss->dev, @@ -552,7 +558,9 @@ int vfe_enable_output_v2(struct vfe_line *line) output->gen2.active_num++; ops->vfe_wm_update(vfe, output->wm_idx[0], output->buf[i]->addr[0], line); - ops->reg_update(vfe, line->id); + + if (!vfe->res->reg_update_after_csid_config) + ops->reg_update(vfe, line->id); } spin_unlock_irqrestore(&vfe->output_lock, flags); @@ -2012,8 +2020,12 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = 16; break; default: diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index ae9dad353a378..c402ef170c81b 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -133,6 +133,7 @@ struct vfe_isr_ops { struct vfe_subdev_resources { bool is_lite; + bool reg_update_after_csid_config; u8 line_num; bool has_pd; char *pd_name; @@ -249,6 +250,7 @@ extern const struct vfe_hw_ops vfe_ops_340; extern const struct vfe_hw_ops vfe_ops_480; extern const struct vfe_hw_ops vfe_ops_680; extern const struct vfe_hw_ops vfe_ops_gen3; +extern const struct vfe_hw_ops vfe_ops_gen4; int vfe_get(struct vfe_device *vfe); void vfe_put(struct vfe_device *vfe); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 2123f6388e3d7..a00af0c718dcd 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -34,438 +35,353 @@ static const struct parent_dev_ops vfe_parent_dev_ops; -static const struct camss_subdev_resources csiphy_res_8x16[] = { +static const struct camss_subdev_resources csiphy_res_kaanapali[] = { /* CSIPHY0 */ { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" }, - .clock_rate = { { 0 }, - { 0 }, + .regulators = { + { .supply = "vdd-csiphy0-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, { 0 }, - { 100000000, 200000000 } }, - .reg = { "csiphy0", "csiphy0_clk_mux" }, + { 0 } }, + .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, - .hw_ops = &csiphy_ops_2ph_1_0, - .formats = &csiphy_formats_8x16 + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } }, - /* CSIPHY1 */ { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" }, - .clock_rate = { { 0 }, - { 0 }, + .regulators = { + { .supply = "vdd-csiphy1-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, { 0 }, - { 100000000, 200000000 } }, - .reg = { "csiphy1", "csiphy1_clk_mux" }, + { 0 } }, + .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { .id = 1, - .hw_ops = &csiphy_ops_2ph_1_0, - .formats = &csiphy_formats_8x16 + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } - } -}; - -static const struct camss_subdev_resources csid_res_8x16[] = { - /* CSID0 */ + }, + /* CSIPHY2 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 40000 } + { .supply = "vdd-csiphy2-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } }, - .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", - "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 100000000, 200000000 }, - { 0 }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, { 0 }, { 0 } }, - .reg = { "csid0" }, - .interrupt = { "csid0" }, - .csid = { - .hw_ops = &csid_ops_4_1, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_1 + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } }, - - /* CSID1 */ + /* CSIPHY3 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 40000 } + { .supply = "vdd-csiphy3-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } }, - .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", - "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 100000000, 200000000 }, - { 0 }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, { 0 }, { 0 } }, - .reg = { "csid1" }, - .interrupt = { "csid1" }, - .csid = { - .hw_ops = &csid_ops_4_1, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_1 + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } }, -}; - -static const struct camss_subdev_resources ispif_res_8x16 = { - /* ISPIF */ - .clock = { "top_ahb", "ahb", "ispif_ahb", - "csi0", "csi0_pix", "csi0_rdi", - "csi1", "csi1_pix", "csi1_rdi" }, - .clock_for_reset = { "vfe0", "csi_vfe0" }, - .reg = { "ispif", "csi_clk_mux" }, - .interrupt = { "ispif" }, -}; - -static const struct camss_subdev_resources vfe_res_8x16[] = { - /* VFE0 */ - { - .regulators = {}, - .clock = { "top_ahb", "vfe0", "csi_vfe0", - "vfe_ahb", "vfe_axi", "ahb" }, - .clock_rate = { { 0 }, - { 50000000, 80000000, 100000000, 160000000, - 177780000, 200000000, 266670000, 320000000, - 400000000, 465000000 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 } }, - .reg = { "vfe0" }, - .interrupt = { "vfe0" }, - .vfe = { - .line_num = 3, - .hw_ops = &vfe_ops_4_1, - .formats_rdi = &vfe_formats_rdi_8x16, - .formats_pix = &vfe_formats_pix_8x16 - } - } -}; - -static const struct camss_subdev_resources csiphy_res_8x39[] = { - /* CSIPHY0 */ + /* CSIPHY4 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 40000 } + { .supply = "vdd-csiphy4-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } }, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" }, - .clock_rate = { { 0 }, - { 40000000, 80000000 }, + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, { 0 }, - { 100000000, 200000000 } }, - .reg = { "csiphy0", "csiphy0_clk_mux" }, - .interrupt = { "csiphy0" }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, .csiphy = { - .id = 0, - .hw_ops = &csiphy_ops_2ph_1_0, - .formats = &csiphy_formats_8x16 + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } }, - - /* CSIPHY1 */ + /* CSIPHY5 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 40000 } + { .supply = "vdd-csiphy5-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } }, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" }, - .clock_rate = { { 0 }, - { 40000000, 80000000 }, + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, { 0 }, - { 100000000, 200000000 } }, - .reg = { "csiphy1", "csiphy1_clk_mux" }, - .interrupt = { "csiphy1" }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, .csiphy = { - .id = 1, - .hw_ops = &csiphy_ops_2ph_1_0, - .formats = &csiphy_formats_8x16 + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } - } + }, }; -static const struct camss_subdev_resources csid_res_8x39[] = { +static const struct camss_subdev_resources csid_res_kaanapali[] = { /* CSID0 */ { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", - "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, - .clock_rate = { { 0 }, - { 40000000, 80000000 }, - { 0 }, - { 0 }, - { 100000000, 200000000 }, - { 0 }, - { 0 }, - { 0 } }, + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { - .hw_ops = &csid_ops_4_1, + .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_1 + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 } }, - /* CSID1 */ { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", - "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, - .clock_rate = { { 0 }, - { 40000000, 80000000 }, - { 0 }, - { 0 }, - { 100000000, 200000000 }, - { 0 }, - { 0 }, - { 0 } }, + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { - .hw_ops = &csid_ops_4_1, + .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_1 + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 } }, - /* CSID2 */ { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", - "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, - .clock_rate = { { 0 }, - { 40000000, 80000000 }, - { 0 }, - { 0 }, - { 100000000, 200000000 }, - { 0 }, - { 0 }, - { 0 } }, + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, .csid = { - .hw_ops = &csid_ops_4_1, + .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_1 + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 } }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + } }; -static const struct camss_subdev_resources ispif_res_8x39 = { - /* ISPIF */ - .clock = { "top_ahb", "ispif_ahb", "ahb", - "csi0", "csi0_pix", "csi0_rdi", - "csi1", "csi1_pix", "csi1_rdi", - "csi2", "csi2_pix", "csi2_rdi" }, - .clock_for_reset = { "vfe0", "csi_vfe0" }, - .reg = { "ispif", "csi_clk_mux" }, - .interrupt = { "ispif" }, -}; - -static const struct camss_subdev_resources vfe_res_8x39[] = { - /* VFE0 */ +/* In Kaanapali, CAMNOC requires all CPAS_TFEX clocks + * to operate on any TFE Full. + */ +static const struct camss_subdev_resources vfe_res_kaanapali[] = { + /* VFE0 - TFE Full */ { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "vfe0", "csi_vfe0", - "vfe_ahb", "vfe_axi", "ahb" }, + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, .clock_rate = { { 0 }, - { 40000000, 80000000 }, - { 50000000, 80000000, 100000000, 160000000, - 177780000, 200000000, 266670000, 320000000, - 400000000, 465000000, 480000000, 600000000 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, { 0 }, { 0 }, { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { .line_num = 3, - .has_vbif = true, - .vbif_name = "vfe0_vbif", - .hw_ops = &vfe_ops_4_1, - .formats_rdi = &vfe_formats_rdi_8x16, - .formats_pix = &vfe_formats_pix_8x16 - } - } -}; - -static const struct camss_subdev_resources csid_res_8x53[] = { - /* CSID0 */ - { - .regulators = { - { .supply = "vdda", .init_load_uA = 9900 } - }, - .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", - "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 100000000, 200000000, 310000000, - 400000000, 465000000 }, - { 0 }, - { 0 }, - { 0 } }, - .reg = { "csid0" }, - .interrupt = { "csid0" }, - .csid = { - .hw_ops = &csid_ops_4_7, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_7 + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 } }, - - /* CSID1 */ + /* VFE1 - TFE Full */ { - .regulators = { - { .supply = "vdda", .init_load_uA = 9900 } - }, - .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", - "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, .clock_rate = { { 0 }, { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, { 0 }, { 0 }, - { 100000000, 200000000, 310000000, - 400000000, 465000000 }, { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, { 0 }, { 0 } }, - .reg = { "csid1" }, - .interrupt = { "csid1" }, - .csid = { - .hw_ops = &csid_ops_4_7, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_7 + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 } }, - - /* CSID2 */ + /* VFE2 - TFE Full */ { - .regulators = { - { .supply = "vdda", .init_load_uA = 9900 } - }, - .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", - "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, .clock_rate = { { 0 }, { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, { 0 }, { 0 }, - { 100000000, 200000000, 310000000, - 400000000, 465000000 }, { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, { 0 }, { 0 } }, - .reg = { "csid2" }, - .interrupt = { "csid2" }, - .csid = { - .hw_ops = &csid_ops_4_7, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_7 + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 } }, -}; - -static const struct camss_subdev_resources ispif_res_8x53 = { - /* ISPIF */ - .clock = { "top_ahb", "ahb", "ispif_ahb", - "csi0", "csi0_pix", "csi0_rdi", - "csi1", "csi1_pix", "csi1_rdi", - "csi2", "csi2_pix", "csi2_rdi" }, - .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" }, - .reg = { "ispif", "csi_clk_mux" }, - .interrupt = { "ispif" }, -}; - -static const struct camss_subdev_resources vfe_res_8x53[] = { - /* VFE0 */ + /* VFE3 - IFE Lite */ { - .regulators = {}, - .clock = { "top_ahb", "ahb", "ispif_ahb", - "vfe0", "csi_vfe0", "vfe0_ahb", "vfe0_axi" }, + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, .clock_rate = { { 0 }, { 0 }, + { 266666667, 400000000, 480000000 }, { 0 }, - { 50000000, 100000000, 133330000, - 160000000, 200000000, 266670000, - 310000000, 400000000, 465000000 }, - { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, { 0 }, { 0 } }, - .reg = { "vfe0" }, - .interrupt = { "vfe0" }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, .vfe = { - .line_num = 3, - .has_pd = true, - .pd_name = "vfe0", - .hw_ops = &vfe_ops_4_1, - .formats_rdi = &vfe_formats_rdi_8x16, - .formats_pix = &vfe_formats_pix_8x16 + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 } }, - - /* VFE1 */ + /* VFE4 - IFE Lite */ { - .regulators = {}, - .clock = { "top_ahb", "ahb", "ispif_ahb", - "vfe1", "csi_vfe1", "vfe1_ahb", "vfe1_axi" }, + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, .clock_rate = { { 0 }, { 0 }, + { 266666667, 400000000, 480000000 }, { 0 }, - { 50000000, 100000000, 133330000, - 160000000, 200000000, 266670000, - 310000000, 400000000, 465000000 }, - { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, { 0 }, { 0 } }, - .reg = { "vfe1" }, - .interrupt = { "vfe1" }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, .vfe = { - .line_num = 3, - .has_pd = true, - .pd_name = "vfe1", - .hw_ops = &vfe_ops_4_1, - .formats_rdi = &vfe_formats_rdi_8x16, - .formats_pix = &vfe_formats_pix_8x16 + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 } - } + }, }; -static const struct resources_icc icc_res_8x53[] = { - { - .name = "cam_ahb", - .icc_bw_tbl.avg = 38400, - .icc_bw_tbl.peak = 76800, - }, +static const struct resources_icc icc_res_kaanapali[] = { { - .name = "cam_vfe0_mem", - .icc_bw_tbl.avg = 939524, - .icc_bw_tbl.peak = 1342177, + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ { - .name = "cam_vfe1_mem", - .icc_bw_tbl.avg = 939524, - .icc_bw_tbl.peak = 1342177, + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, }, }; -static const struct camss_subdev_resources csiphy_res_8x96[] = { +static const struct camss_subdev_resources csiphy_res_8x16[] = { /* CSIPHY0 */ { .regulators = {}, @@ -473,13 +389,13 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = { .clock_rate = { { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 266666667 } }, + { 100000000, 200000000 } }, .reg = { "csiphy0", "csiphy0_clk_mux" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_8x96 + .hw_ops = &csiphy_ops_2ph_1_0, + .formats = &csiphy_formats_8x16 } }, @@ -490,39 +406,22 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = { .clock_rate = { { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 266666667 } }, + { 100000000, 200000000 } }, .reg = { "csiphy1", "csiphy1_clk_mux" }, .interrupt = { "csiphy1" }, .csiphy = { .id = 1, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_8x96 - } - }, - - /* CSIPHY2 */ - { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 100000000, 200000000, 266666667 } }, - .reg = { "csiphy2", "csiphy2_clk_mux" }, - .interrupt = { "csiphy2" }, - .csiphy = { - .id = 2, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_8x96 + .hw_ops = &csiphy_ops_2ph_1_0, + .formats = &csiphy_formats_8x16 } } }; -static const struct camss_subdev_resources csid_res_8x96[] = { +static const struct camss_subdev_resources csid_res_8x16[] = { /* CSID0 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 80160 } + { .supply = "vdda", .init_load_uA = 40000 } }, .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, @@ -530,23 +429,23 @@ static const struct camss_subdev_resources csid_res_8x96[] = { { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 266666667 }, + { 100000000, 200000000 }, { 0 }, { 0 }, { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { - .hw_ops = &csid_ops_4_7, + .hw_ops = &csid_ops_4_1, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_7 + .formats = &csid_formats_4_1 } }, /* CSID1 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 80160 } + { .supply = "vdda", .init_load_uA = 40000 } }, .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, @@ -554,91 +453,43 @@ static const struct camss_subdev_resources csid_res_8x96[] = { { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 266666667 }, + { 100000000, 200000000 }, { 0 }, { 0 }, { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { - .hw_ops = &csid_ops_4_7, + .hw_ops = &csid_ops_4_1, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_7 + .formats = &csid_formats_4_1 } }, +}; - /* CSID2 */ +static const struct camss_subdev_resources ispif_res_8x16 = { + /* ISPIF */ + .clock = { "top_ahb", "ahb", "ispif_ahb", + "csi0", "csi0_pix", "csi0_rdi", + "csi1", "csi1_pix", "csi1_rdi" }, + .clock_for_reset = { "vfe0", "csi_vfe0" }, + .reg = { "ispif", "csi_clk_mux" }, + .interrupt = { "ispif" }, +}; + +static const struct camss_subdev_resources vfe_res_8x16[] = { + /* VFE0 */ { - .regulators = { - { .supply = "vdda", .init_load_uA = 80160 } - }, - .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", - "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, + .regulators = {}, + .clock = { "top_ahb", "vfe0", "csi_vfe0", + "vfe_ahb", "vfe_axi", "ahb" }, .clock_rate = { { 0 }, + { 50000000, 80000000, 100000000, 160000000, + 177780000, 200000000, 266670000, 320000000, + 400000000, 465000000 }, { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 266666667 }, - { 0 }, - { 0 }, - { 0 } }, - .reg = { "csid2" }, - .interrupt = { "csid2" }, - .csid = { - .hw_ops = &csid_ops_4_7, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_7 - } - }, - - /* CSID3 */ - { - .regulators = { - { .supply = "vdda", .init_load_uA = 80160 } - }, - .clock = { "top_ahb", "ispif_ahb", "csi3_ahb", "ahb", - "csi3", "csi3_phy", "csi3_pix", "csi3_rdi" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 100000000, 200000000, 266666667 }, - { 0 }, - { 0 }, - { 0 } }, - .reg = { "csid3" }, - .interrupt = { "csid3" }, - .csid = { - .hw_ops = &csid_ops_4_7, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_4_7 - } - } -}; - -static const struct camss_subdev_resources ispif_res_8x96 = { - /* ISPIF */ - .clock = { "top_ahb", "ahb", "ispif_ahb", - "csi0", "csi0_pix", "csi0_rdi", - "csi1", "csi1_pix", "csi1_rdi", - "csi2", "csi2_pix", "csi2_rdi", - "csi3", "csi3_pix", "csi3_rdi" }, - .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" }, - .reg = { "ispif", "csi_clk_mux" }, - .interrupt = { "ispif" }, -}; - -static const struct camss_subdev_resources vfe_res_8x96[] = { - /* VFE0 */ - { - .regulators = {}, - .clock = { "top_ahb", "ahb", "vfe0", "csi_vfe0", "vfe_ahb", - "vfe0_ahb", "vfe_axi", "vfe0_stream"}, - .clock_rate = { { 0 }, - { 0 }, - { 75000000, 100000000, 300000000, - 320000000, 480000000, 600000000 }, - { 0 }, { 0 }, { 0 }, { 0 }, @@ -647,191 +498,330 @@ static const struct camss_subdev_resources vfe_res_8x96[] = { .interrupt = { "vfe0" }, .vfe = { .line_num = 3, - .has_pd = true, - .hw_ops = &vfe_ops_4_7, - .formats_rdi = &vfe_formats_rdi_8x96, - .formats_pix = &vfe_formats_pix_8x96 - } - }, - - /* VFE1 */ - { - .regulators = {}, - .clock = { "top_ahb", "ahb", "vfe1", "csi_vfe1", "vfe_ahb", - "vfe1_ahb", "vfe_axi", "vfe1_stream"}, - .clock_rate = { { 0 }, - { 0 }, - { 75000000, 100000000, 300000000, - 320000000, 480000000, 600000000 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 } }, - .reg = { "vfe1" }, - .interrupt = { "vfe1" }, - .vfe = { - .line_num = 3, - .has_pd = true, - .hw_ops = &vfe_ops_4_7, - .formats_rdi = &vfe_formats_rdi_8x96, - .formats_pix = &vfe_formats_pix_8x96 + .hw_ops = &vfe_ops_4_1, + .formats_rdi = &vfe_formats_rdi_8x16, + .formats_pix = &vfe_formats_pix_8x16 } } }; -static const struct camss_subdev_resources csiphy_res_2290[] = { +static const struct camss_subdev_resources csiphy_res_8x39[] = { /* CSIPHY0 */ { .regulators = { - { .supply = "vdd-csiphy-1p2", .init_load_uA = 26700 }, - { .supply = "vdd-csiphy-1p8", .init_load_uA = 2600 } + { .supply = "vdda", .init_load_uA = 40000 } }, - .clock = { "top_ahb", "ahb", "csiphy0", "csiphy0_timer" }, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" }, .clock_rate = { { 0 }, + { 40000000, 80000000 }, { 0 }, - { 240000000, 341330000, 384000000 }, - { 100000000, 200000000, 268800000 } }, - .reg = { "csiphy0" }, + { 100000000, 200000000 } }, + .reg = { "csiphy0", "csiphy0_clk_mux" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .hw_ops = &csiphy_ops_2ph_1_0, + .formats = &csiphy_formats_8x16 } }, /* CSIPHY1 */ { .regulators = { - { .supply = "vdd-csiphy-1p2", .init_load_uA = 26700 }, - { .supply = "vdd-csiphy-1p8", .init_load_uA = 2600 } + { .supply = "vdda", .init_load_uA = 40000 } }, - .clock = { "top_ahb", "ahb", "csiphy1", "csiphy1_timer" }, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" }, .clock_rate = { { 0 }, + { 40000000, 80000000 }, { 0 }, - { 240000000, 341330000, 384000000 }, - { 100000000, 200000000, 268800000 } }, - .reg = { "csiphy1" }, + { 100000000, 200000000 } }, + .reg = { "csiphy1", "csiphy1_clk_mux" }, .interrupt = { "csiphy1" }, .csiphy = { .id = 1, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .hw_ops = &csiphy_ops_2ph_1_0, + .formats = &csiphy_formats_8x16 } } }; -static const struct camss_subdev_resources csid_res_2290[] = { +static const struct camss_subdev_resources csid_res_8x39[] = { /* CSID0 */ { .regulators = {}, - .clock = { "top_ahb", "ahb", "csi0", "vfe0_cphy_rx", "vfe0" }, + .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", + "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, .clock_rate = { { 0 }, + { 40000000, 80000000 }, + { 0 }, + { 0 }, + { 100000000, 200000000 }, { 0 }, - { 192000000, 240000000, 384000000, 426400000 }, { 0 }, { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { - .hw_ops = &csid_ops_340, + .hw_ops = &csid_ops_4_1, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 + .formats = &csid_formats_4_1 } }, /* CSID1 */ { .regulators = {}, - .clock = { "top_ahb", "ahb", "csi1", "vfe1_cphy_rx", "vfe1" }, + .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", + "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, .clock_rate = { { 0 }, + { 40000000, 80000000 }, + { 0 }, + { 0 }, + { 100000000, 200000000 }, { 0 }, - { 192000000, 240000000, 384000000, 426400000 }, { 0 }, { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { - .hw_ops = &csid_ops_340, + .hw_ops = &csid_ops_4_1, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 + .formats = &csid_formats_4_1 } - } -}; + }, -static const struct camss_subdev_resources vfe_res_2290[] = { - /* VFE0 */ + /* CSID2 */ { .regulators = {}, - .clock = { "top_ahb", "ahb", "axi", "vfe0", "camnoc_rt_axi", "camnoc_nrt_axi" }, + .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", + "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, .clock_rate = { { 0 }, + { 40000000, 80000000 }, { 0 }, { 0 }, - { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, + { 100000000, 200000000 }, { 0 }, - { 0 }, }, - .reg = { "vfe0" }, - .interrupt = { "vfe0" }, - .vfe = { - .line_num = 4, - .hw_ops = &vfe_ops_340, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 + { 0 }, + { 0 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .hw_ops = &csid_ops_4_1, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_1 } }, +}; - /* VFE1 */ +static const struct camss_subdev_resources ispif_res_8x39 = { + /* ISPIF */ + .clock = { "top_ahb", "ispif_ahb", "ahb", + "csi0", "csi0_pix", "csi0_rdi", + "csi1", "csi1_pix", "csi1_rdi", + "csi2", "csi2_pix", "csi2_rdi" }, + .clock_for_reset = { "vfe0", "csi_vfe0" }, + .reg = { "ispif", "csi_clk_mux" }, + .interrupt = { "ispif" }, +}; + +static const struct camss_subdev_resources vfe_res_8x39[] = { + /* VFE0 */ { .regulators = {}, - .clock = { "top_ahb", "ahb", "axi", "vfe1", "camnoc_rt_axi", "camnoc_nrt_axi" }, + .clock = { "top_ahb", "ispif_ahb", "vfe0", "csi_vfe0", + "vfe_ahb", "vfe_axi", "ahb" }, .clock_rate = { { 0 }, + { 40000000, 80000000 }, + { 50000000, 80000000, 100000000, 160000000, + 177780000, 200000000, 266670000, 320000000, + 400000000, 465000000, 480000000, 600000000 }, { 0 }, { 0 }, - { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, { 0 }, - { 0 }, }, - .reg = { "vfe1" }, - .interrupt = { "vfe1" }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, .vfe = { - .line_num = 4, - .hw_ops = &vfe_ops_340, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 + .line_num = 3, + .has_vbif = true, + .vbif_name = "vfe0_vbif", + .hw_ops = &vfe_ops_4_1, + .formats_rdi = &vfe_formats_rdi_8x16, + .formats_pix = &vfe_formats_pix_8x16 } - }, -}; - -static const struct resources_icc icc_res_2290[] = { - { - .name = "ahb", - .icc_bw_tbl.avg = 150000, - .icc_bw_tbl.peak = 300000, - }, - { - .name = "hf_mnoc", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 3000000, - }, - { - .name = "sf_mnoc", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 3000000, - }, + } }; -static const struct camss_subdev_resources csiphy_res_660[] = { - /* CSIPHY0 */ +static const struct camss_subdev_resources csid_res_8x53[] = { + /* CSID0 */ { - .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer", - "csi0_phy", "csiphy_ahb2crif" }, + .regulators = { + { .supply = "vdda", .init_load_uA = 9900 } + }, + .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", + "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 269333333 }, - { 0 } }, - .reg = { "csiphy0", "csiphy0_clk_mux" }, + { 0 }, + { 100000000, 200000000, 310000000, + 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } + }, + + /* CSID1 */ + { + .regulators = { + { .supply = "vdda", .init_load_uA = 9900 } + }, + .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", + "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 100000000, 200000000, 310000000, + 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } + }, + + /* CSID2 */ + { + .regulators = { + { .supply = "vdda", .init_load_uA = 9900 } + }, + .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", + "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 100000000, 200000000, 310000000, + 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } + }, +}; + +static const struct camss_subdev_resources ispif_res_8x53 = { + /* ISPIF */ + .clock = { "top_ahb", "ahb", "ispif_ahb", + "csi0", "csi0_pix", "csi0_rdi", + "csi1", "csi1_pix", "csi1_rdi", + "csi2", "csi2_pix", "csi2_rdi" }, + .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" }, + .reg = { "ispif", "csi_clk_mux" }, + .interrupt = { "ispif" }, +}; + +static const struct camss_subdev_resources vfe_res_8x53[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "ispif_ahb", + "vfe0", "csi_vfe0", "vfe0_ahb", "vfe0_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 50000000, 100000000, 133330000, + 160000000, 200000000, 266670000, + 310000000, 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "vfe0", + .hw_ops = &vfe_ops_4_1, + .formats_rdi = &vfe_formats_rdi_8x16, + .formats_pix = &vfe_formats_pix_8x16 + } + }, + + /* VFE1 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "ispif_ahb", + "vfe1", "csi_vfe1", "vfe1_ahb", "vfe1_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 50000000, 100000000, 133330000, + 160000000, 200000000, 266670000, + 310000000, 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "vfe1", + .hw_ops = &vfe_ops_4_1, + .formats_rdi = &vfe_formats_rdi_8x16, + .formats_pix = &vfe_formats_pix_8x16 + } + } +}; + +static const struct resources_icc icc_res_8x53[] = { + { + .name = "cam_ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "cam_vfe0_mem", + .icc_bw_tbl.avg = 939524, + .icc_bw_tbl.peak = 1342177, + }, + { + .name = "cam_vfe1_mem", + .icc_bw_tbl.avg = 939524, + .icc_bw_tbl.peak = 1342177, + }, +}; + +static const struct camss_subdev_resources csiphy_res_8x96[] = { + /* CSIPHY0 */ + { + .regulators = {}, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 100000000, 200000000, 266666667 } }, + .reg = { "csiphy0", "csiphy0_clk_mux" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, @@ -843,13 +833,11 @@ static const struct camss_subdev_resources csiphy_res_660[] = { /* CSIPHY1 */ { .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer", - "csi1_phy", "csiphy_ahb2crif" }, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 269333333 }, - { 0 } }, + { 100000000, 200000000, 266666667 } }, .reg = { "csiphy1", "csiphy1_clk_mux" }, .interrupt = { "csiphy1" }, .csiphy = { @@ -862,13 +850,11 @@ static const struct camss_subdev_resources csiphy_res_660[] = { /* CSIPHY2 */ { .regulators = {}, - .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer", - "csi2_phy", "csiphy_ahb2crif" }, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 269333333 }, - { 0 } }, + { 100000000, 200000000, 266666667 } }, .reg = { "csiphy2", "csiphy2_clk_mux" }, .interrupt = { "csiphy2" }, .csiphy = { @@ -879,23 +865,19 @@ static const struct camss_subdev_resources csiphy_res_660[] = { } }; -static const struct camss_subdev_resources csid_res_660[] = { +static const struct camss_subdev_resources csid_res_8x96[] = { /* CSID0 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 0 }, - { .supply = "vdd_sec", .init_load_uA = 0 } + { .supply = "vdda", .init_load_uA = 80160 } }, .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", - "csi0", "csi0_phy", "csi0_pix", "csi0_rdi", - "cphy_csid0" }, + "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, .clock_rate = { { 0 }, { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 310000000, - 404000000, 465000000 }, - { 0 }, + { 100000000, 200000000, 266666667 }, { 0 }, { 0 }, { 0 } }, @@ -911,19 +893,15 @@ static const struct camss_subdev_resources csid_res_660[] = { /* CSID1 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 0 }, - { .supply = "vdd_sec", .init_load_uA = 0 } + { .supply = "vdda", .init_load_uA = 80160 } }, .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", - "csi1", "csi1_phy", "csi1_pix", "csi1_rdi", - "cphy_csid1" }, + "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, .clock_rate = { { 0 }, { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 310000000, - 404000000, 465000000 }, - { 0 }, + { 100000000, 200000000, 266666667 }, { 0 }, { 0 }, { 0 } }, @@ -939,19 +917,15 @@ static const struct camss_subdev_resources csid_res_660[] = { /* CSID2 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 0 }, - { .supply = "vdd_sec", .init_load_uA = 0 } + { .supply = "vdda", .init_load_uA = 80160 } }, .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", - "csi2", "csi2_phy", "csi2_pix", "csi2_rdi", - "cphy_csid2" }, + "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, .clock_rate = { { 0 }, { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 310000000, - 404000000, 465000000 }, - { 0 }, + { 100000000, 200000000, 266666667 }, { 0 }, { 0 }, { 0 } }, @@ -967,19 +941,15 @@ static const struct camss_subdev_resources csid_res_660[] = { /* CSID3 */ { .regulators = { - { .supply = "vdda", .init_load_uA = 0 }, - { .supply = "vdd_sec", .init_load_uA = 0 } + { .supply = "vdda", .init_load_uA = 80160 } }, .clock = { "top_ahb", "ispif_ahb", "csi3_ahb", "ahb", - "csi3", "csi3_phy", "csi3_pix", "csi3_rdi", - "cphy_csid3" }, + "csi3", "csi3_phy", "csi3_pix", "csi3_rdi" }, .clock_rate = { { 0 }, { 0 }, { 0 }, { 0 }, - { 100000000, 200000000, 310000000, - 404000000, 465000000 }, - { 0 }, + { 100000000, 200000000, 266666667 }, { 0 }, { 0 }, { 0 } }, @@ -993,7 +963,7 @@ static const struct camss_subdev_resources csid_res_660[] = { } }; -static const struct camss_subdev_resources ispif_res_660 = { +static const struct camss_subdev_resources ispif_res_8x96 = { /* ISPIF */ .clock = { "top_ahb", "ahb", "ispif_ahb", "csi0", "csi0_pix", "csi0_rdi", @@ -1005,19 +975,16 @@ static const struct camss_subdev_resources ispif_res_660 = { .interrupt = { "ispif" }, }; -static const struct camss_subdev_resources vfe_res_660[] = { +static const struct camss_subdev_resources vfe_res_8x96[] = { /* VFE0 */ { .regulators = {}, - .clock = { "throttle_axi", "top_ahb", "ahb", "vfe0", - "csi_vfe0", "vfe_ahb", "vfe0_ahb", "vfe_axi", - "vfe0_stream"}, + .clock = { "top_ahb", "ahb", "vfe0", "csi_vfe0", "vfe_ahb", + "vfe0_ahb", "vfe_axi", "vfe0_stream"}, .clock_rate = { { 0 }, { 0 }, - { 0 }, - { 120000000, 200000000, 256000000, - 300000000, 404000000, 480000000, - 540000000, 576000000 }, + { 75000000, 100000000, 300000000, + 320000000, 480000000, 600000000 }, { 0 }, { 0 }, { 0 }, @@ -1028,7 +995,7 @@ static const struct camss_subdev_resources vfe_res_660[] = { .vfe = { .line_num = 3, .has_pd = true, - .hw_ops = &vfe_ops_4_8, + .hw_ops = &vfe_ops_4_7, .formats_rdi = &vfe_formats_rdi_8x96, .formats_pix = &vfe_formats_pix_8x96 } @@ -1037,15 +1004,12 @@ static const struct camss_subdev_resources vfe_res_660[] = { /* VFE1 */ { .regulators = {}, - .clock = { "throttle_axi", "top_ahb", "ahb", "vfe1", - "csi_vfe1", "vfe_ahb", "vfe1_ahb", "vfe_axi", - "vfe1_stream"}, + .clock = { "top_ahb", "ahb", "vfe1", "csi_vfe1", "vfe_ahb", + "vfe1_ahb", "vfe_axi", "vfe1_stream"}, .clock_rate = { { 0 }, { 0 }, - { 0 }, - { 120000000, 200000000, 256000000, - 300000000, 404000000, 480000000, - 540000000, 576000000 }, + { 75000000, 100000000, 300000000, + 320000000, 480000000, 600000000 }, { 0 }, { 0 }, { 0 }, @@ -1056,26 +1020,25 @@ static const struct camss_subdev_resources vfe_res_660[] = { .vfe = { .line_num = 3, .has_pd = true, - .hw_ops = &vfe_ops_4_8, + .hw_ops = &vfe_ops_4_7, .formats_rdi = &vfe_formats_rdi_8x96, .formats_pix = &vfe_formats_pix_8x96 } } }; -static const struct camss_subdev_resources csiphy_res_670[] = { +static const struct camss_subdev_resources csiphy_res_2290[] = { /* CSIPHY0 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 42800 }, - { .supply = "vdda-pll", .init_load_uA = 13900 } + { .supply = "vdd-csiphy-1p2", .init_load_uA = 26700 }, + { .supply = "vdd-csiphy-1p8", .init_load_uA = 2600 } }, - .clock = { "soc_ahb", "cpas_ahb", - "csiphy0", "csiphy0_timer" }, + .clock = { "top_ahb", "ahb", "csiphy0", "csiphy0_timer" }, .clock_rate = { { 0 }, { 0 }, - { 0 }, - { 19200000, 240000000, 269333333 } }, + { 240000000, 341330000, 384000000 }, + { 100000000, 200000000, 268800000 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { @@ -1088,15 +1051,14 @@ static const struct camss_subdev_resources csiphy_res_670[] = { /* CSIPHY1 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 42800 }, - { .supply = "vdda-pll", .init_load_uA = 13900 } + { .supply = "vdd-csiphy-1p2", .init_load_uA = 26700 }, + { .supply = "vdd-csiphy-1p8", .init_load_uA = 2600 } }, - .clock = { "soc_ahb", "cpas_ahb", - "csiphy1", "csiphy1_timer" }, + .clock = { "top_ahb", "ahb", "csiphy1", "csiphy1_timer" }, .clock_rate = { { 0 }, { 0 }, - { 0 }, - { 19200000, 240000000, 269333333 } }, + { 240000000, 341330000, 384000000 }, + { 100000000, 200000000, 268800000 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { @@ -1104,45 +1066,23 @@ static const struct camss_subdev_resources csiphy_res_670[] = { .hw_ops = &csiphy_ops_3ph_1_0, .formats = &csiphy_formats_sdm845 } - }, - - /* CSIPHY2 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 42800 }, - { .supply = "vdda-pll", .init_load_uA = 13900 } - }, - .clock = { "soc_ahb", "cpas_ahb", - "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 19200000, 240000000, 269333333 } }, - .reg = { "csiphy2" }, - .interrupt = { "csiphy2" }, - .csiphy = { - .id = 2, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } } }; -static const struct camss_subdev_resources csid_res_670[] = { +static const struct camss_subdev_resources csid_res_2290[] = { /* CSID0 */ { .regulators = {}, - .clock = { "cpas_ahb", "soc_ahb", "vfe0", - "vfe0_cphy_rx", "csi0" }, + .clock = { "top_ahb", "ahb", "csi0", "vfe0_cphy_rx", "vfe0" }, .clock_rate = { { 0 }, { 0 }, - { 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 384000000 }, - { 19200000, 75000000, 384000000, 538666667 } }, + { 192000000, 240000000, 384000000, 426400000 }, + { 0 }, + { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { - .hw_ops = &csid_ops_gen2, + .hw_ops = &csid_ops_340, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 } @@ -1151,61 +1091,38 @@ static const struct camss_subdev_resources csid_res_670[] = { /* CSID1 */ { .regulators = {}, - .clock = { "cpas_ahb", "soc_ahb", "vfe1", - "vfe1_cphy_rx", "csi1" }, + .clock = { "top_ahb", "ahb", "csi1", "vfe1_cphy_rx", "vfe1" }, .clock_rate = { { 0 }, { 0 }, - { 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 384000000 }, - { 19200000, 75000000, 384000000, 538666667 } }, + { 192000000, 240000000, 384000000, 426400000 }, + { 0 }, + { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - - /* CSID2 */ - { - .regulators = {}, - .clock = { "cpas_ahb", "soc_ahb", "vfe_lite", - "vfe_lite_cphy_rx", "csi2" }, - .clock_rate = { { 0 }, - { 0 }, - { 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 384000000 }, - { 19200000, 75000000, 384000000, 538666667 } }, - .reg = { "csid2" }, - .interrupt = { "csid2" }, - .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen2, + .hw_ops = &csid_ops_340, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 } } }; -static const struct camss_subdev_resources vfe_res_670[] = { +static const struct camss_subdev_resources vfe_res_2290[] = { /* VFE0 */ { .regulators = {}, - .clock = { "camnoc_axi", "cpas_ahb", "soc_ahb", - "vfe0", "vfe0_axi" }, + .clock = { "top_ahb", "ahb", "axi", "vfe0", "camnoc_rt_axi", "camnoc_nrt_axi" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 0 } }, + { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, + { 0 }, + { 0 }, }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { .line_num = 4, - .has_pd = true, - .pd_name = "ife0", - .hw_ops = &vfe_ops_170, + .hw_ops = &vfe_ops_340, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -1214,321 +1131,298 @@ static const struct camss_subdev_resources vfe_res_670[] = { /* VFE1 */ { .regulators = {}, - .clock = { "camnoc_axi", "cpas_ahb", "soc_ahb", - "vfe1", "vfe1_axi" }, + .clock = { "top_ahb", "ahb", "axi", "vfe1", "camnoc_rt_axi", "camnoc_nrt_axi" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 0 } }, + { 19200000, 153600000, 192000000, 256000000, 384000000, 460800000 }, + { 0 }, + { 0 }, }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { .line_num = 4, - .has_pd = true, - .pd_name = "ife1", - .hw_ops = &vfe_ops_170, + .hw_ops = &vfe_ops_340, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, +}; - /* VFE-lite */ +static const struct resources_icc icc_res_2290[] = { { - .regulators = {}, - .clock = { "camnoc_axi", "cpas_ahb", "soc_ahb", - "vfe_lite" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 100000000, 320000000, 404000000, 480000000, 600000000 } }, - .reg = { "vfe_lite" }, - .interrupt = { "vfe_lite" }, - .vfe = { - .is_lite = true, - .line_num = 4, - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - } + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 3000000, + }, + { + .name = "sf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 3000000, + }, }; -static const struct camss_subdev_resources csiphy_res_845[] = { +static const struct camss_subdev_resources csiphy_res_660[] = { /* CSIPHY0 */ { .regulators = {}, - .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", - "cpas_ahb", "cphy_rx_src", "csiphy0", - "csiphy0_timer_src", "csiphy0_timer" }, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer", + "csi0_phy", "csiphy_ahb2crif" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 19200000, 240000000, 269333333 } }, - .reg = { "csiphy0" }, + { 100000000, 200000000, 269333333 }, + { 0 } }, + .reg = { "csiphy0", "csiphy0_clk_mux" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_8x96 } }, /* CSIPHY1 */ { .regulators = {}, - .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", - "cpas_ahb", "cphy_rx_src", "csiphy1", - "csiphy1_timer_src", "csiphy1_timer" }, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer", + "csi1_phy", "csiphy_ahb2crif" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 19200000, 240000000, 269333333 } }, - .reg = { "csiphy1" }, + { 100000000, 200000000, 269333333 }, + { 0 } }, + .reg = { "csiphy1", "csiphy1_clk_mux" }, .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_8x96 } }, /* CSIPHY2 */ { .regulators = {}, - .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", - "cpas_ahb", "cphy_rx_src", "csiphy2", - "csiphy2_timer_src", "csiphy2_timer" }, + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer", + "csi2_phy", "csiphy_ahb2crif" }, .clock_rate = { { 0 }, { 0 }, { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 19200000, 240000000, 269333333 } }, - .reg = { "csiphy2" }, + { 100000000, 200000000, 269333333 }, + { 0 } }, + .reg = { "csiphy2", "csiphy2_clk_mux" }, .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } - }, - - /* CSIPHY3 */ - { - .regulators = {}, - .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", - "cpas_ahb", "cphy_rx_src", "csiphy3", - "csiphy3_timer_src", "csiphy3_timer" }, - .clock_rate = { { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 0 }, - { 19200000, 240000000, 269333333 } }, - .reg = { "csiphy3" }, - .interrupt = { "csiphy3" }, - .csiphy = { - .id = 3, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_8x96 } } }; -static const struct camss_subdev_resources csid_res_845[] = { +static const struct camss_subdev_resources csid_res_660[] = { /* CSID0 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } + { .supply = "vdda", .init_load_uA = 0 }, + { .supply = "vdd_sec", .init_load_uA = 0 } }, - .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src", - "soc_ahb", "vfe0", "vfe0_src", - "vfe0_cphy_rx", "csi0", - "csi0_src" }, + .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", + "csi0", "csi0_phy", "csi0_pix", "csi0_rdi", + "cphy_csid0" }, .clock_rate = { { 0 }, - { 384000000 }, - { 80000000 }, { 0 }, - { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 320000000 }, { 0 }, - { 19200000, 75000000, 384000000, 538666667 }, - { 384000000 } }, + { 0 }, + { 100000000, 200000000, 310000000, + 404000000, 465000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { - .hw_ops = &csid_ops_gen2, + .hw_ops = &csid_ops_4_7, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 + .formats = &csid_formats_4_7 } }, /* CSID1 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } + { .supply = "vdda", .init_load_uA = 0 }, + { .supply = "vdd_sec", .init_load_uA = 0 } }, - .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src", - "soc_ahb", "vfe1", "vfe1_src", - "vfe1_cphy_rx", "csi1", - "csi1_src" }, + .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", + "csi1", "csi1_phy", "csi1_pix", "csi1_rdi", + "cphy_csid1" }, .clock_rate = { { 0 }, - { 384000000 }, - { 80000000 }, { 0 }, - { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 320000000 }, { 0 }, - { 19200000, 75000000, 384000000, 538666667 }, - { 384000000 } }, + { 0 }, + { 100000000, 200000000, 310000000, + 404000000, 465000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { - .hw_ops = &csid_ops_gen2, + .hw_ops = &csid_ops_4_7, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 + .formats = &csid_formats_4_7 } }, /* CSID2 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } + { .supply = "vdda", .init_load_uA = 0 }, + { .supply = "vdd_sec", .init_load_uA = 0 } }, - .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src", - "soc_ahb", "vfe_lite", "vfe_lite_src", - "vfe_lite_cphy_rx", "csi2", - "csi2_src" }, + .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", + "csi2", "csi2_phy", "csi2_pix", "csi2_rdi", + "cphy_csid2" }, .clock_rate = { { 0 }, - { 384000000 }, - { 80000000 }, { 0 }, - { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 320000000 }, { 0 }, - { 19200000, 75000000, 384000000, 538666667 }, - { 384000000 } }, + { 0 }, + { 100000000, 200000000, 310000000, + 404000000, 465000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen2, + .hw_ops = &csid_ops_4_7, .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 + .formats = &csid_formats_4_7 + } + }, + + /* CSID3 */ + { + .regulators = { + { .supply = "vdda", .init_load_uA = 0 }, + { .supply = "vdd_sec", .init_load_uA = 0 } + }, + .clock = { "top_ahb", "ispif_ahb", "csi3_ahb", "ahb", + "csi3", "csi3_phy", "csi3_pix", "csi3_rdi", + "cphy_csid3" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 100000000, 200000000, 310000000, + 404000000, 465000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid3" }, + .interrupt = { "csid3" }, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 } } }; -static const struct camss_subdev_resources vfe_res_845[] = { +static const struct camss_subdev_resources ispif_res_660 = { + /* ISPIF */ + .clock = { "top_ahb", "ahb", "ispif_ahb", + "csi0", "csi0_pix", "csi0_rdi", + "csi1", "csi1_pix", "csi1_rdi", + "csi2", "csi2_pix", "csi2_rdi", + "csi3", "csi3_pix", "csi3_rdi" }, + .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" }, + .reg = { "ispif", "csi_clk_mux" }, + .interrupt = { "ispif" }, +}; + +static const struct camss_subdev_resources vfe_res_660[] = { /* VFE0 */ { .regulators = {}, - .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src", - "soc_ahb", "vfe0", "vfe0_axi", - "vfe0_src", "csi0", - "csi0_src"}, + .clock = { "throttle_axi", "top_ahb", "ahb", "vfe0", + "csi_vfe0", "vfe_ahb", "vfe0_ahb", "vfe_axi", + "vfe0_stream"}, .clock_rate = { { 0 }, { 0 }, - { 80000000 }, { 0 }, - { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 120000000, 200000000, 256000000, + 300000000, 404000000, 480000000, + 540000000, 576000000 }, { 0 }, - { 320000000 }, - { 19200000, 75000000, 384000000, 538666667 }, - { 384000000 } }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { - .line_num = 4, - .pd_name = "ife0", + .line_num = 3, .has_pd = true, - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 + .hw_ops = &vfe_ops_4_8, + .formats_rdi = &vfe_formats_rdi_8x96, + .formats_pix = &vfe_formats_pix_8x96 } }, /* VFE1 */ { .regulators = {}, - .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src", - "soc_ahb", "vfe1", "vfe1_axi", - "vfe1_src", "csi1", - "csi1_src"}, + .clock = { "throttle_axi", "top_ahb", "ahb", "vfe1", + "csi_vfe1", "vfe_ahb", "vfe1_ahb", "vfe_axi", + "vfe1_stream"}, .clock_rate = { { 0 }, { 0 }, - { 80000000 }, { 0 }, - { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 120000000, 200000000, 256000000, + 300000000, 404000000, 480000000, + 540000000, 576000000 }, { 0 }, - { 320000000 }, - { 19200000, 75000000, 384000000, 538666667 }, - { 384000000 } }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { - .line_num = 4, - .pd_name = "ife1", + .line_num = 3, .has_pd = true, - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - - /* VFE-lite */ - { - .regulators = {}, - .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src", - "soc_ahb", "vfe_lite", - "vfe_lite_src", "csi2", - "csi2_src"}, - .clock_rate = { { 0 }, - { 0 }, - { 80000000 }, - { 0 }, - { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, - { 320000000 }, - { 19200000, 75000000, 384000000, 538666667 }, - { 384000000 } }, - .reg = { "vfe_lite" }, - .interrupt = { "vfe_lite" }, - .vfe = { - .is_lite = true, - .line_num = 4, - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 + .hw_ops = &vfe_ops_4_8, + .formats_rdi = &vfe_formats_rdi_8x96, + .formats_pix = &vfe_formats_pix_8x96 } } }; -static const struct camss_subdev_resources csiphy_res_sm6150[] = { +static const struct camss_subdev_resources csiphy_res_670[] = { /* CSIPHY0 */ { .regulators = { - { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 }, - { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 } + { .supply = "vdda-phy", .init_load_uA = 42800 }, + { .supply = "vdda-pll", .init_load_uA = 13900 } }, - .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 269333333, 384000000 }, - { 269333333 } }, + .clock = { "soc_ahb", "cpas_ahb", + "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 19200000, 240000000, 269333333 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { @@ -1537,15 +1431,19 @@ static const struct camss_subdev_resources csiphy_res_sm6150[] = { .formats = &csiphy_formats_sdm845 } }, + /* CSIPHY1 */ { .regulators = { - { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 }, - { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 } + { .supply = "vdda-phy", .init_load_uA = 42800 }, + { .supply = "vdda-pll", .init_load_uA = 13900 } }, - .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 269333333, 384000000 }, - { 269333333 } }, + .clock = { "soc_ahb", "cpas_ahb", + "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 19200000, 240000000, 269333333 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { @@ -1554,15 +1452,19 @@ static const struct camss_subdev_resources csiphy_res_sm6150[] = { .formats = &csiphy_formats_sdm845 } }, + /* CSIPHY2 */ { .regulators = { - { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 }, - { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 } + { .supply = "vdda-phy", .init_load_uA = 42800 }, + { .supply = "vdda-pll", .init_load_uA = 13900 } }, - .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 269333333, 384000000 }, - { 269333333 } }, + .clock = { "soc_ahb", "cpas_ahb", + "csiphy2", "csiphy2_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 19200000, 240000000, 269333333 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, .csiphy = { @@ -1570,74 +1472,84 @@ static const struct camss_subdev_resources csiphy_res_sm6150[] = { .hw_ops = &csiphy_ops_3ph_1_0, .formats = &csiphy_formats_sdm845 } - }, + } }; -static const struct camss_subdev_resources csid_res_sm6150[] = { +static const struct camss_subdev_resources csid_res_670[] = { /* CSID0 */ { .regulators = {}, - .clock = { "vfe0_cphy_rx", "vfe0_csid" }, - .clock_rate = { { 269333333, 384000000 }, - { 320000000, 540000000 } }, + .clock = { "cpas_ahb", "soc_ahb", "vfe0", + "vfe0_cphy_rx", "csi0" }, + .clock_rate = { { 0 }, + { 0 }, + { 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 384000000 }, + { 19200000, 75000000, 384000000, 538666667 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { - .is_lite = false, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 } }, + /* CSID1 */ { .regulators = {}, - .clock = { "vfe1_cphy_rx", "vfe1_csid" }, - .clock_rate = { { 269333333, 384000000 }, - { 320000000, 540000000 } }, + .clock = { "cpas_ahb", "soc_ahb", "vfe1", + "vfe1_cphy_rx", "csi1" }, + .clock_rate = { { 0 }, + { 0 }, + { 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 384000000 }, + { 19200000, 75000000, 384000000, 538666667 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { - .is_lite = false, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 } }, + /* CSID2 */ { .regulators = {}, - .clock = { "vfe_lite_cphy_rx", "vfe_lite_csid" }, - .clock_rate = { { 269333333, 384000000 }, - { 320000000, 540000000 } }, - .reg = { "csid_lite" }, - .interrupt = { "csid_lite" }, + .clock = { "cpas_ahb", "soc_ahb", "vfe_lite", + "vfe_lite_cphy_rx", "csi2" }, + .clock_rate = { { 0 }, + { 0 }, + { 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 384000000 }, + { 19200000, 75000000, 384000000, 538666667 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, .csid = { .is_lite = true, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 } - }, + } }; -static const struct camss_subdev_resources vfe_res_sm6150[] = { +static const struct camss_subdev_resources vfe_res_670[] = { /* VFE0 */ { .regulators = {}, - .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "soc_ahb", - "vfe0", "vfe0_axi"}, - .clock_rate = { { 0 }, + .clock = { "camnoc_axi", "cpas_ahb", "soc_ahb", + "vfe0", "vfe0_axi" }, + .clock_rate = { { 0 }, { 0 }, - { 80000000 }, - { 37500000, 40000000 }, - { 360000000, 432000000, 540000000, 600000000 }, - { 265000000, 426000000 } }, + { 0 }, + { 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { - .line_num = 3, - .is_lite = false, + .line_num = 4, .has_pd = true, .pd_name = "ife0", .hw_ops = &vfe_ops_170, @@ -1645,22 +1557,21 @@ static const struct camss_subdev_resources vfe_res_sm6150[] = { .formats_pix = &vfe_formats_pix_845 } }, + /* VFE1 */ { .regulators = {}, - .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "soc_ahb", - "vfe1", "vfe1_axi"}, + .clock = { "camnoc_axi", "cpas_ahb", "soc_ahb", + "vfe1", "vfe1_axi" }, .clock_rate = { { 0 }, { 0 }, - { 80000000 }, - { 37500000, 40000000 }, - { 360000000, 432000000, 540000000, 600000000 }, - { 265000000, 426000000 } }, + { 0 }, + { 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 0 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { - .line_num = 3, - .is_lite = false, + .line_num = 4, .has_pd = true, .pd_name = "ife1", .hw_ops = &vfe_ops_170, @@ -1668,51 +1579,43 @@ static const struct camss_subdev_resources vfe_res_sm6150[] = { .formats_pix = &vfe_formats_pix_845 } }, - /* VFE2 */ + + /* VFE-lite */ { .regulators = {}, - .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "soc_ahb", + .clock = { "camnoc_axi", "cpas_ahb", "soc_ahb", "vfe_lite" }, .clock_rate = { { 0 }, { 0 }, - { 80000000 }, - { 37500000, 40000000 }, - { 360000000, 432000000, 540000000, 600000000 } }, + { 0 }, + { 100000000, 320000000, 404000000, 480000000, 600000000 } }, .reg = { "vfe_lite" }, .interrupt = { "vfe_lite" }, .vfe = { - .line_num = 4, .is_lite = true, + .line_num = 4, .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } - }, -}; - -static const struct resources_icc icc_res_sm6150[] = { - { - .name = "ahb", - .icc_bw_tbl.avg = 38400, - .icc_bw_tbl.peak = 76800, - }, - { - .name = "hf_0", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, - }, + } }; -static const struct camss_subdev_resources csiphy_res_sm6350[] = { +static const struct camss_subdev_resources csiphy_res_845[] = { /* CSIPHY0 */ { - .regulators = { - { .supply = "vdd-csiphy0-0p9", .init_load_uA = 80000 }, - { .supply = "vdd-csiphy0-1p25", .init_load_uA = 80000 }, - }, - .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, - { 300000000 } }, + .regulators = {}, + .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", + "cpas_ahb", "cphy_rx_src", "csiphy0", + "csiphy0_timer_src", "csiphy0_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 19200000, 240000000, 269333333 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { @@ -1721,15 +1624,21 @@ static const struct camss_subdev_resources csiphy_res_sm6350[] = { .formats = &csiphy_formats_sdm845 } }, + /* CSIPHY1 */ { - .regulators = { - { .supply = "vdd-csiphy1-0p9", .init_load_uA = 80000 }, - { .supply = "vdd-csiphy1-1p25", .init_load_uA = 80000 }, - }, - .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, - { 300000000 } }, + .regulators = {}, + .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", + "cpas_ahb", "cphy_rx_src", "csiphy1", + "csiphy1_timer_src", "csiphy1_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 19200000, 240000000, 269333333 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { @@ -1738,15 +1647,21 @@ static const struct camss_subdev_resources csiphy_res_sm6350[] = { .formats = &csiphy_formats_sdm845 } }, + /* CSIPHY2 */ { - .regulators = { - { .supply = "vdd-csiphy2-0p9", .init_load_uA = 80000 }, - { .supply = "vdd-csiphy2-1p25", .init_load_uA = 80000 }, - }, - .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, - { 300000000 } }, + .regulators = {}, + .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", + "cpas_ahb", "cphy_rx_src", "csiphy2", + "csiphy2_timer_src", "csiphy2_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 19200000, 240000000, 269333333 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, .csiphy = { @@ -1755,15 +1670,21 @@ static const struct camss_subdev_resources csiphy_res_sm6350[] = { .formats = &csiphy_formats_sdm845 } }, + /* CSIPHY3 */ { - .regulators = { - { .supply = "vdd-csiphy3-0p9", .init_load_uA = 80000 }, - { .supply = "vdd-csiphy3-1p25", .init_load_uA = 80000 }, - }, - .clock = { "csiphy3", "csiphy3_timer" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, - { 300000000 } }, + .regulators = {}, + .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src", + "cpas_ahb", "cphy_rx_src", "csiphy3", + "csiphy3_timer_src", "csiphy3_timer" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 19200000, 240000000, 269333333 } }, .reg = { "csiphy3" }, .interrupt = { "csiphy3" }, .csiphy = { @@ -1774,14 +1695,26 @@ static const struct camss_subdev_resources csiphy_res_sm6350[] = { } }; -static const struct camss_subdev_resources csid_res_sm6350[] = { +static const struct camss_subdev_resources csid_res_845[] = { /* CSID0 */ { - .regulators = {}, - .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src", + "soc_ahb", "vfe0", "vfe0_src", + "vfe0_cphy_rx", "csi0", + "csi0_src" }, + .clock_rate = { { 0 }, + { 384000000 }, + { 80000000 }, { 0 }, - { 320000000, 404000000, 480000000, 600000000 } }, + { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 320000000 }, + { 0 }, + { 19200000, 75000000, 384000000, 538666667 }, + { 384000000 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { @@ -1790,13 +1723,26 @@ static const struct camss_subdev_resources csid_res_sm6350[] = { .formats = &csid_formats_gen2 } }, + /* CSID1 */ { - .regulators = {}, - .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src", + "soc_ahb", "vfe1", "vfe1_src", + "vfe1_cphy_rx", "csi1", + "csi1_src" }, + .clock_rate = { { 0 }, + { 384000000 }, + { 80000000 }, { 0 }, - { 320000000, 404000000, 480000000, 600000000 } }, + { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 320000000 }, + { 0 }, + { 19200000, 75000000, 384000000, 538666667 }, + { 384000000 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { @@ -1805,30 +1751,28 @@ static const struct camss_subdev_resources csid_res_sm6350[] = { .formats = &csid_formats_gen2 } }, + /* CSID2 */ { - .regulators = {}, - .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src", + "soc_ahb", "vfe_lite", "vfe_lite_src", + "vfe_lite_cphy_rx", "csi2", + "csi2_src" }, + .clock_rate = { { 0 }, + { 384000000 }, + { 80000000 }, { 0 }, - { 320000000, 404000000, 480000000, 600000000 } }, + { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 320000000 }, + { 0 }, + { 19200000, 75000000, 384000000, 538666667 }, + { 384000000 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, - .csid = { - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - /* CSID3 (lite) */ - { - .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite" }, - .clock_rate = { { 300000000, 384000000, 400000000 }, - { 0 }, - { 400000000, 480000000 } }, - .reg = { "csid_lite" }, - .interrupt = { "csid_lite" }, .csid = { .is_lite = true, .hw_ops = &csid_ops_gen2, @@ -1838,83 +1782,78 @@ static const struct camss_subdev_resources csid_res_sm6350[] = { } }; -static const struct camss_subdev_resources vfe_res_sm6350[] = { +static const struct camss_subdev_resources vfe_res_845[] = { /* VFE0 */ { .regulators = {}, - .clock = { "cpas_ahb", "camnoc_axi", "vfe0", - "vfe0_axi", "cam_axi", "soc_ahb" }, - .clock_rate = { { 19200000 }, + .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src", + "soc_ahb", "vfe0", "vfe0_axi", + "vfe0_src", "csi0", + "csi0_src"}, + .clock_rate = { { 0 }, { 0 }, - { 320000000, 404000000, 480000000, 600000000 }, + { 80000000 }, { 0 }, + { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, { 0 }, - { 0 } }, + { 320000000 }, + { 19200000, 75000000, 384000000, 538666667 }, + { 384000000 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { - .line_num = 3, - .has_pd = true, + .line_num = 4, .pd_name = "ife0", + .has_pd = true, .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, + /* VFE1 */ { .regulators = {}, - .clock = { "cpas_ahb", "camnoc_axi", "vfe1", - "vfe1_axi", "cam_axi", "soc_ahb" }, - .clock_rate = { { 19200000 }, + .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src", + "soc_ahb", "vfe1", "vfe1_axi", + "vfe1_src", "csi1", + "csi1_src"}, + .clock_rate = { { 0 }, { 0 }, - { 320000000, 404000000, 480000000, 600000000 }, + { 80000000 }, { 0 }, + { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, { 0 }, - { 0 } }, + { 320000000 }, + { 19200000, 75000000, 384000000, 538666667 }, + { 384000000 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { - .line_num = 3, - .has_pd = true, + .line_num = 4, .pd_name = "ife1", + .has_pd = true, .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE2 */ - { - .regulators = {}, - .clock = { "cpas_ahb", "camnoc_axi", "vfe2", - "vfe2_axi", "cam_axi", "soc_ahb" }, - .clock_rate = { { 19200000 }, - { 0 }, - { 320000000, 404000000, 480000000, 600000000 }, - { 0 }, - { 0 }, - { 0 } }, - .reg = { "vfe2" }, - .interrupt = { "vfe2" }, - .vfe = { - .line_num = 3, - .has_pd = true, - .pd_name = "ife2", - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE3 (lite) */ + + /* VFE-lite */ { .regulators = {}, - .clock = { "cpas_ahb", "camnoc_axi", "vfe_lite", - "cam_axi", "soc_ahb" }, - .clock_rate = { { 19200000 }, + .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src", + "soc_ahb", "vfe_lite", + "vfe_lite_src", "csi2", + "csi2_src"}, + .clock_rate = { { 0 }, { 0 }, - { 400000000, 480000000 }, + { 80000000 }, { 0 }, - { 0 } }, + { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 }, + { 320000000 }, + { 19200000, 75000000, 384000000, 538666667 }, + { 384000000 } }, .reg = { "vfe_lite" }, .interrupt = { "vfe_lite" }, .vfe = { @@ -1924,42 +1863,19 @@ static const struct camss_subdev_resources vfe_res_sm6350[] = { .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } - }, -}; - -static const struct resources_icc icc_res_sm6350[] = { - { - .name = "ahb", - .icc_bw_tbl.avg = 0, - .icc_bw_tbl.peak = 300000, - }, - { - .name = "hf_mnoc", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, - }, - { - .name = "sf_mnoc", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, - }, - { - .name = "sf_icp_mnoc", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, - }, + } }; -static const struct camss_subdev_resources csiphy_res_8250[] = { +static const struct camss_subdev_resources csiphy_res_sm6150[] = { /* CSIPHY0 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 17500 }, - { .supply = "vdda-pll", .init_load_uA = 10000 } + { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 }, + { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 } }, .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 400000000 }, - { 300000000 } }, + .clock_rate = { { 269333333, 384000000 }, + { 269333333 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { @@ -1971,12 +1887,12 @@ static const struct camss_subdev_resources csiphy_res_8250[] = { /* CSIPHY1 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 17500 }, - { .supply = "vdda-pll", .init_load_uA = 10000 } + { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 }, + { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 } }, .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 400000000 }, - { 300000000 } }, + .clock_rate = { { 269333333, 384000000 }, + { 269333333 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { @@ -1988,12 +1904,12 @@ static const struct camss_subdev_resources csiphy_res_8250[] = { /* CSIPHY2 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 17500 }, - { .supply = "vdda-pll", .init_load_uA = 10000 } + { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 }, + { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 } }, .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 400000000 }, - { 300000000 } }, + .clock_rate = { { 269333333, 384000000 }, + { 269333333 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, .csiphy = { @@ -2002,72 +1918,19 @@ static const struct camss_subdev_resources csiphy_res_8250[] = { .formats = &csiphy_formats_sdm845 } }, - /* CSIPHY3 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 17500 }, - { .supply = "vdda-pll", .init_load_uA = 10000 } - }, - .clock = { "csiphy3", "csiphy3_timer" }, - .clock_rate = { { 400000000 }, - { 300000000 } }, - .reg = { "csiphy3" }, - .interrupt = { "csiphy3" }, - .csiphy = { - .id = 3, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } - }, - /* CSIPHY4 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 17500 }, - { .supply = "vdda-pll", .init_load_uA = 10000 } - }, - .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 400000000 }, - { 300000000 } }, - .reg = { "csiphy4" }, - .interrupt = { "csiphy4" }, - .csiphy = { - .id = 4, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } - }, - /* CSIPHY5 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 17500 }, - { .supply = "vdda-pll", .init_load_uA = 10000 } - }, - .clock = { "csiphy5", "csiphy5_timer" }, - .clock_rate = { { 400000000 }, - { 300000000 } }, - .reg = { "csiphy5" }, - .interrupt = { "csiphy5" }, - .csiphy = { - .id = 5, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } - } }; -static const struct camss_subdev_resources csid_res_8250[] = { +static const struct camss_subdev_resources csid_res_sm6150[] = { /* CSID0 */ { .regulators = {}, - .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_areg", "vfe0_ahb" }, - .clock_rate = { { 400000000 }, - { 400000000 }, - { 350000000, 475000000, 576000000, 720000000 }, - { 100000000, 200000000, 300000000, 400000000 }, - { 0 } }, + .clock = { "vfe0_cphy_rx", "vfe0_csid" }, + .clock_rate = { { 269333333, 384000000 }, + { 320000000, 540000000 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { + .is_lite = false, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 @@ -2076,15 +1939,13 @@ static const struct camss_subdev_resources csid_res_8250[] = { /* CSID1 */ { .regulators = {}, - .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_areg", "vfe1_ahb" }, - .clock_rate = { { 400000000 }, - { 400000000 }, - { 350000000, 475000000, 576000000, 720000000 }, - { 100000000, 200000000, 300000000, 400000000 }, - { 0 } }, + .clock = { "vfe1_cphy_rx", "vfe1_csid" }, + .clock_rate = { { 269333333, 384000000 }, + { 320000000, 540000000 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { + .is_lite = false, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 @@ -2093,13 +1954,11 @@ static const struct camss_subdev_resources csid_res_8250[] = { /* CSID2 */ { .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" }, - .clock_rate = { { 400000000 }, - { 400000000 }, - { 400000000, 480000000 }, - { 0 } }, - .reg = { "csid2" }, - .interrupt = { "csid2" }, + .clock = { "vfe_lite_cphy_rx", "vfe_lite_csid" }, + .clock_rate = { { 269333333, 384000000 }, + { 320000000, 540000000 } }, + .reg = { "csid_lite" }, + .interrupt = { "csid_lite" }, .csid = { .is_lite = true, .hw_ops = &csid_ops_gen2, @@ -2107,48 +1966,28 @@ static const struct camss_subdev_resources csid_res_8250[] = { .formats = &csid_formats_gen2 } }, - /* CSID3 */ - { - .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" }, - .clock_rate = { { 400000000 }, - { 400000000 }, - { 400000000, 480000000 }, - { 0 } }, - .reg = { "csid3" }, - .interrupt = { "csid3" }, - .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - } }; -static const struct camss_subdev_resources vfe_res_8250[] = { +static const struct camss_subdev_resources vfe_res_sm6150[] = { /* VFE0 */ { .regulators = {}, - .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", - "camnoc_axi", "vfe0_ahb", "vfe0_areg", "vfe0", - "vfe0_axi", "cam_hf_axi" }, - .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, - { 19200000, 80000000 }, - { 19200000 }, - { 0 }, - { 0 }, - { 100000000, 200000000, 300000000, 400000000 }, - { 350000000, 475000000, 576000000, 720000000 }, + .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "soc_ahb", + "vfe0", "vfe0_axi"}, + .clock_rate = { { 0 }, { 0 }, - { 0 } }, + { 80000000 }, + { 37500000, 40000000 }, + { 360000000, 432000000, 540000000, 600000000 }, + { 265000000, 426000000 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { .line_num = 3, + .is_lite = false, .has_pd = true, .pd_name = "ife0", - .hw_ops = &vfe_ops_480, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2156,210 +1995,143 @@ static const struct camss_subdev_resources vfe_res_8250[] = { /* VFE1 */ { .regulators = {}, - .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", - "camnoc_axi", "vfe1_ahb", "vfe1_areg", "vfe1", - "vfe1_axi", "cam_hf_axi" }, - .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, - { 19200000, 80000000 }, - { 19200000 }, - { 0 }, - { 0 }, - { 100000000, 200000000, 300000000, 400000000 }, - { 350000000, 475000000, 576000000, 720000000 }, + .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "soc_ahb", + "vfe1", "vfe1_axi"}, + .clock_rate = { { 0 }, { 0 }, - { 0 } }, + { 80000000 }, + { 37500000, 40000000 }, + { 360000000, 432000000, 540000000, 600000000 }, + { 265000000, 426000000 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { .line_num = 3, + .is_lite = false, .has_pd = true, .pd_name = "ife1", - .hw_ops = &vfe_ops_480, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE2 (lite) */ + /* VFE2 */ { .regulators = {}, - .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", - "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi", - "vfe_lite", "cam_hf_axi" }, - .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, - { 19200000, 80000000 }, - { 19200000 }, - { 0 }, - { 0 }, + .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "soc_ahb", + "vfe_lite" }, + .clock_rate = { { 0 }, { 0 }, - { 400000000, 480000000 }, - { 0 } }, - .reg = { "vfe_lite0" }, - .interrupt = { "vfe_lite0" }, - .vfe = { - .is_lite = true, - .line_num = 4, - .hw_ops = &vfe_ops_480, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE3 (lite) */ - { - .regulators = {}, - .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", - "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi", - "vfe_lite", "cam_hf_axi" }, - .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, - { 19200000, 80000000 }, - { 19200000 }, - { 0 }, - { 0 }, - { 0 }, - { 400000000, 480000000 }, - { 0 } }, - .reg = { "vfe_lite1" }, - .interrupt = { "vfe_lite1" }, + { 80000000 }, + { 37500000, 40000000 }, + { 360000000, 432000000, 540000000, 600000000 } }, + .reg = { "vfe_lite" }, + .interrupt = { "vfe_lite" }, .vfe = { - .is_lite = true, .line_num = 4, - .hw_ops = &vfe_ops_480, + .is_lite = true, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, }; -static const struct resources_icc icc_res_sm8250[] = { +static const struct resources_icc icc_res_sm6150[] = { { - .name = "cam_ahb", + .name = "ahb", .icc_bw_tbl.avg = 38400, .icc_bw_tbl.peak = 76800, }, { - .name = "cam_hf_0_mnoc", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, - }, - { - .name = "cam_sf_0_mnoc", - .icc_bw_tbl.avg = 0, - .icc_bw_tbl.peak = 2097152, - }, - { - .name = "cam_sf_icp_mnoc", + .name = "hf_0", .icc_bw_tbl.avg = 2097152, .icc_bw_tbl.peak = 2097152, }, }; -static const struct camss_subdev_resources csiphy_res_7280[] = { +static const struct camss_subdev_resources csiphy_res_sm6350[] = { /* CSIPHY0 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 16100 }, - { .supply = "vdda-pll", .init_load_uA = 9000 } + { .supply = "vdd-csiphy0-0p9", .init_load_uA = 80000 }, + { .supply = "vdd-csiphy0-1p25", .init_load_uA = 80000 }, }, - .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 300000000, 400000000 }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 300000000 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, + .formats = &csiphy_formats_sdm845 } }, /* CSIPHY1 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 16100 }, - { .supply = "vdda-pll", .init_load_uA = 9000 } + { .supply = "vdd-csiphy1-0p9", .init_load_uA = 80000 }, + { .supply = "vdd-csiphy1-1p25", .init_load_uA = 80000 }, }, - .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 300000000, 400000000 }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 300000000 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, + .formats = &csiphy_formats_sdm845 } }, /* CSIPHY2 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 16100 }, - { .supply = "vdda-pll", .init_load_uA = 9000 } + { .supply = "vdd-csiphy2-0p9", .init_load_uA = 80000 }, + { .supply = "vdd-csiphy2-1p25", .init_load_uA = 80000 }, }, - .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 300000000, 400000000 }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 300000000 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, + .formats = &csiphy_formats_sdm845 } }, /* CSIPHY3 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 16100 }, - { .supply = "vdda-pll", .init_load_uA = 9000 } + { .supply = "vdd-csiphy3-0p9", .init_load_uA = 80000 }, + { .supply = "vdd-csiphy3-1p25", .init_load_uA = 80000 }, }, - .clock = { "csiphy3", "csiphy3_timer" }, - .clock_rate = { { 300000000, 400000000 }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 300000000 } }, .reg = { "csiphy3" }, .interrupt = { "csiphy3" }, .csiphy = { .id = 3, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - } - }, - /* CSIPHY4 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 16100 }, - { .supply = "vdda-pll", .init_load_uA = 9000 } - }, - - .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 300000000, 400000000 }, - { 300000000 } }, - .reg = { "csiphy4" }, - .interrupt = { "csiphy4" }, - .csiphy = { - .id = 4, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, + .formats = &csiphy_formats_sdm845 } - }, + } }; -static const struct camss_subdev_resources csid_res_7280[] = { +static const struct camss_subdev_resources csid_res_sm6350[] = { /* CSID0 */ { .regulators = {}, - .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0" }, - .clock_rate = { { 300000000, 400000000 }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 0 }, - { 380000000, 510000000, 637000000, 760000000 } - }, - + { 320000000, 404000000, 480000000, 600000000 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { - .is_lite = false, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 @@ -2368,17 +2140,13 @@ static const struct camss_subdev_resources csid_res_7280[] = { /* CSID1 */ { .regulators = {}, - .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1" }, - .clock_rate = { { 300000000, 400000000 }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 0 }, - { 380000000, 510000000, 637000000, 760000000 } - }, - + { 320000000, 404000000, 480000000, 600000000 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { - .is_lite = false, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 @@ -2387,82 +2155,52 @@ static const struct camss_subdev_resources csid_res_7280[] = { /* CSID2 */ { .regulators = {}, - .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2" }, - .clock_rate = { { 300000000, 400000000 }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 0 }, - { 380000000, 510000000, 637000000, 760000000 } - }, - + { 320000000, 404000000, 480000000, 600000000 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, .csid = { - .is_lite = false, - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - /* CSID3 */ - { - .regulators = {}, - - .clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" }, - .clock_rate = { { 300000000, 400000000 }, - { 0 }, - { 320000000, 400000000, 480000000, 600000000 } - }, - - .reg = { "csid_lite0" }, - .interrupt = { "csid_lite0" }, - .csid = { - .is_lite = true, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 } }, - /* CSID4 */ + /* CSID3 (lite) */ { .regulators = {}, - - .clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" }, - .clock_rate = { { 300000000, 400000000 }, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite" }, + .clock_rate = { { 300000000, 384000000, 400000000 }, { 0 }, - { 320000000, 400000000, 480000000, 600000000 } - }, - - .reg = { "csid_lite1" }, - .interrupt = { "csid_lite1" }, + { 400000000, 480000000 } }, + .reg = { "csid_lite" }, + .interrupt = { "csid_lite" }, .csid = { .is_lite = true, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 } - }, + } }; -static const struct camss_subdev_resources vfe_res_7280[] = { +static const struct camss_subdev_resources vfe_res_sm6350[] = { /* VFE0 */ { .regulators = {}, - - .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe0", - "vfe0_axi", "gcc_axi_hf", "gcc_axi_sf" }, - .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, - { 80000000 }, + .clock = { "cpas_ahb", "camnoc_axi", "vfe0", + "vfe0_axi", "cam_axi", "soc_ahb" }, + .clock_rate = { { 19200000 }, { 0 }, - { 380000000, 510000000, 637000000, 760000000 }, + { 320000000, 404000000, 480000000, 600000000 }, { 0 }, { 0 }, { 0 } }, - .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { .line_num = 3, - .is_lite = false, .has_pd = true, .pd_name = "ife0", .hw_ops = &vfe_ops_170, @@ -2473,22 +2211,18 @@ static const struct camss_subdev_resources vfe_res_7280[] = { /* VFE1 */ { .regulators = {}, - - .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe1", - "vfe1_axi", "gcc_axi_hf", "gcc_axi_sf" }, - .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, - { 80000000 }, + .clock = { "cpas_ahb", "camnoc_axi", "vfe1", + "vfe1_axi", "cam_axi", "soc_ahb" }, + .clock_rate = { { 19200000 }, { 0 }, - { 380000000, 510000000, 637000000, 760000000 }, + { 320000000, 404000000, 480000000, 600000000 }, { 0 }, { 0 }, { 0 } }, - .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { .line_num = 3, - .is_lite = false, .has_pd = true, .pd_name = "ife1", .hw_ops = &vfe_ops_170, @@ -2499,68 +2233,40 @@ static const struct camss_subdev_resources vfe_res_7280[] = { /* VFE2 */ { .regulators = {}, - - .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe2", - "vfe2_axi", "gcc_axi_hf", "gcc_axi_sf" }, - .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, - { 80000000 }, + .clock = { "cpas_ahb", "camnoc_axi", "vfe2", + "vfe2_axi", "cam_axi", "soc_ahb" }, + .clock_rate = { { 19200000 }, { 0 }, - { 380000000, 510000000, 637000000, 760000000 }, + { 320000000, 404000000, 480000000, 600000000 }, { 0 }, { 0 }, { 0 } }, - .reg = { "vfe2" }, .interrupt = { "vfe2" }, .vfe = { .line_num = 3, - .is_lite = false, - .hw_ops = &vfe_ops_170, .has_pd = true, .pd_name = "ife2", + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, /* VFE3 (lite) */ { - .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", - "vfe_lite0", "gcc_axi_hf", "gcc_axi_sf" }, - .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, - { 80000000 }, - { 0 }, - { 320000000, 400000000, 480000000, 600000000 }, - { 0 }, - { 0 } }, - .regulators = {}, - .reg = { "vfe_lite0" }, - .interrupt = { "vfe_lite0" }, - .vfe = { - .line_num = 4, - .is_lite = true, - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE4 (lite) */ - { - .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", - "vfe_lite1", "gcc_axi_hf", "gcc_axi_sf" }, - .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, - { 80000000 }, + .clock = { "cpas_ahb", "camnoc_axi", "vfe_lite", + "cam_axi", "soc_ahb" }, + .clock_rate = { { 19200000 }, { 0 }, - { 320000000, 400000000, 480000000, 600000000 }, + { 400000000, 480000000 }, { 0 }, { 0 } }, - - .regulators = {}, - .reg = { "vfe_lite1" }, - .interrupt = { "vfe_lite1" }, + .reg = { "vfe_lite" }, + .interrupt = { "vfe_lite" }, .vfe = { - .line_num = 4, .is_lite = true, + .line_num = 4, .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 @@ -2568,23 +2274,36 @@ static const struct camss_subdev_resources vfe_res_7280[] = { }, }; -static const struct resources_icc icc_res_sc7280[] = { +static const struct resources_icc icc_res_sm6350[] = { { .name = "ahb", - .icc_bw_tbl.avg = 38400, - .icc_bw_tbl.peak = 76800, + .icc_bw_tbl.avg = 0, + .icc_bw_tbl.peak = 300000, }, { - .name = "hf_0", + .name = "hf_mnoc", .icc_bw_tbl.avg = 2097152, .icc_bw_tbl.peak = 2097152, }, -}; - -static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { + { + .name = "sf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, + { + .name = "sf_icp_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + +static const struct camss_subdev_resources csiphy_res_8250[] = { /* CSIPHY0 */ { - .regulators = {}, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 17500 }, + { .supply = "vdda-pll", .init_load_uA = 10000 } + }, .clock = { "csiphy0", "csiphy0_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, @@ -2598,7 +2317,10 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { }, /* CSIPHY1 */ { - .regulators = {}, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 17500 }, + { .supply = "vdda-pll", .init_load_uA = 10000 } + }, .clock = { "csiphy1", "csiphy1_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, @@ -2612,7 +2334,10 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { }, /* CSIPHY2 */ { - .regulators = {}, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 17500 }, + { .supply = "vdda-pll", .init_load_uA = 10000 } + }, .clock = { "csiphy2", "csiphy2_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, @@ -2626,7 +2351,10 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { }, /* CSIPHY3 */ { - .regulators = {}, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 17500 }, + { .supply = "vdda-pll", .init_load_uA = 10000 } + }, .clock = { "csiphy3", "csiphy3_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, @@ -2638,19 +2366,51 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { .formats = &csiphy_formats_sdm845 } }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 17500 }, + { .supply = "vdda-pll", .init_load_uA = 10000 } + }, + .clock = { "csiphy4", "csiphy4_timer" }, + .clock_rate = { { 400000000 }, + { 300000000 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 17500 }, + { .supply = "vdda-pll", .init_load_uA = 10000 } + }, + .clock = { "csiphy5", "csiphy5_timer" }, + .clock_rate = { { 400000000 }, + { 300000000 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + } }; -static const struct camss_subdev_resources csid_res_sc8280xp[] = { +static const struct camss_subdev_resources csid_res_8250[] = { /* CSID0 */ { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_axi" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, + .regulators = {}, + .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_areg", "vfe0_ahb" }, + .clock_rate = { { 400000000 }, + { 400000000 }, + { 350000000, 475000000, 576000000, 720000000 }, + { 100000000, 200000000, 300000000, 400000000 }, { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, @@ -2662,14 +2422,12 @@ static const struct camss_subdev_resources csid_res_sc8280xp[] = { }, /* CSID1 */ { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_axi" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, + .regulators = {}, + .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_areg", "vfe1_ahb" }, + .clock_rate = { { 400000000 }, + { 400000000 }, + { 350000000, 475000000, 576000000, 720000000 }, + { 100000000, 200000000, 300000000, 400000000 }, { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, @@ -2681,18 +2439,16 @@ static const struct camss_subdev_resources csid_res_sc8280xp[] = { }, /* CSID2 */ { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2", "vfe2_axi" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" }, + .clock_rate = { { 400000000 }, + { 400000000 }, + { 400000000, 480000000 }, { 0 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, .csid = { + .is_lite = true, .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, .formats = &csid_formats_gen2 @@ -2700,92 +2456,14 @@ static const struct camss_subdev_resources csid_res_sc8280xp[] = { }, /* CSID3 */ { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe3_csid", "vfe3_cphy_rx", "vfe3", "vfe3_axi" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" }, + .clock_rate = { { 400000000 }, + { 400000000 }, + { 400000000, 480000000 }, { 0 } }, .reg = { "csid3" }, .interrupt = { "csid3" }, - .csid = { - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - /* CSID_LITE0 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, }, - .reg = { "csid0_lite" }, - .interrupt = { "csid0_lite" }, - .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - /* CSID_LITE1 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, }, - .reg = { "csid1_lite" }, - .interrupt = { "csid1_lite" }, - .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - /* CSID_LITE2 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe_lite2_csid", "vfe_lite2_cphy_rx", "vfe_lite2" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, }, - .reg = { "csid2_lite" }, - .interrupt = { "csid2_lite" }, - .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen2, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - /* CSID_LITE3 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 0 }, - { .supply = "vdda-pll", .init_load_uA = 0 } - }, - .clock = { "vfe_lite3_csid", "vfe_lite3_cphy_rx", "vfe_lite3" }, - .clock_rate = { { 400000000, 480000000, 600000000 }, - { 0 }, - { 0 }, }, - .reg = { "csid3_lite" }, - .interrupt = { "csid3_lite" }, .csid = { .is_lite = true, .hw_ops = &csid_ops_gen2, @@ -2795,23 +2473,29 @@ static const struct camss_subdev_resources csid_res_sc8280xp[] = { } }; -static const struct camss_subdev_resources vfe_res_sc8280xp[] = { +static const struct camss_subdev_resources vfe_res_8250[] = { /* VFE0 */ { .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe0", "vfe0_axi" }, - .clock_rate = { { 0 }, + .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", + "camnoc_axi", "vfe0_ahb", "vfe0_areg", "vfe0", + "vfe0_axi", "cam_hf_axi" }, + .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, + { 19200000, 80000000 }, + { 19200000 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 400000000, 558000000, 637000000, 760000000 }, - { 0 }, }, + { 0 }, + { 100000000, 200000000, 300000000, 400000000 }, + { 350000000, 475000000, 576000000, 720000000 }, + { 0 }, + { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { - .line_num = 4, + .line_num = 3, + .has_pd = true, .pd_name = "ife0", - .hw_ops = &vfe_ops_170, + .hw_ops = &vfe_ops_480, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -2819,155 +2503,93 @@ static const struct camss_subdev_resources vfe_res_sc8280xp[] = { /* VFE1 */ { .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe1", "vfe1_axi" }, - .clock_rate = { { 0 }, + .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", + "camnoc_axi", "vfe1_ahb", "vfe1_areg", "vfe1", + "vfe1_axi", "cam_hf_axi" }, + .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, + { 19200000, 80000000 }, + { 19200000 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 400000000, 558000000, 637000000, 760000000 }, - { 0 }, }, + { 0 }, + { 100000000, 200000000, 300000000, 400000000 }, + { 350000000, 475000000, 576000000, 720000000 }, + { 0 }, + { 0 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { - .line_num = 4, + .line_num = 3, + .has_pd = true, .pd_name = "ife1", - .hw_ops = &vfe_ops_170, + .hw_ops = &vfe_ops_480, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE2 */ + /* VFE2 (lite) */ { .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe2", "vfe2_axi" }, - .clock_rate = { { 0 }, + .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", + "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi", + "vfe_lite", "cam_hf_axi" }, + .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, + { 19200000, 80000000 }, + { 19200000 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 400000000, 558000000, 637000000, 760000000 }, - { 0 }, }, - .reg = { "vfe2" }, - .interrupt = { "vfe2" }, - .vfe = { - .line_num = 4, - .pd_name = "ife2", - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE3 */ - { - .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe3", "vfe3_axi" }, - .clock_rate = { { 0 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 400000000, 558000000, 637000000, 760000000 }, - { 0 }, }, - .reg = { "vfe3" }, - .interrupt = { "vfe3" }, - .vfe = { - .line_num = 4, - .pd_name = "ife3", - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE_LITE_0 */ - { - .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite0" }, - .clock_rate = { { 0 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 320000000, 400000000, 480000000, 600000000 }, }, + { 400000000, 480000000 }, + { 0 } }, .reg = { "vfe_lite0" }, .interrupt = { "vfe_lite0" }, .vfe = { .is_lite = true, .line_num = 4, - .hw_ops = &vfe_ops_170, + .hw_ops = &vfe_ops_480, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE_LITE_1 */ + /* VFE3 (lite) */ { .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite1" }, - .clock_rate = { { 0 }, + .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb", + "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi", + "vfe_lite", "cam_hf_axi" }, + .clock_rate = { { 19200000, 300000000, 400000000, 480000000 }, + { 19200000, 80000000 }, + { 19200000 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 320000000, 400000000, 480000000, 600000000 }, }, - .reg = { "vfe_lite1" }, - .interrupt = { "vfe_lite1" }, - .vfe = { - .is_lite = true, - .line_num = 4, - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE_LITE_2 */ - { - .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite2" }, - .clock_rate = { { 0 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 320000000, 400000000, 480000000, 600000000, }, }, - .reg = { "vfe_lite2" }, - .interrupt = { "vfe_lite2" }, - .vfe = { - .is_lite = true, - .line_num = 4, - .hw_ops = &vfe_ops_170, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE_LITE_3 */ - { - .regulators = {}, - .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite3" }, - .clock_rate = { { 0 }, { 0 }, - { 19200000, 80000000}, - { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, - { 320000000, 400000000, 480000000, 600000000 }, }, - .reg = { "vfe_lite3" }, - .interrupt = { "vfe_lite3" }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, .vfe = { .is_lite = true, .line_num = 4, - .hw_ops = &vfe_ops_170, + .hw_ops = &vfe_ops_480, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, }; -static const struct resources_icc icc_res_sc8280xp[] = { +static const struct resources_icc icc_res_sm8250[] = { { .name = "cam_ahb", - .icc_bw_tbl.avg = 150000, - .icc_bw_tbl.peak = 300000, + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, }, { - .name = "cam_hf_mnoc", + .name = "cam_hf_0_mnoc", .icc_bw_tbl.avg = 2097152, .icc_bw_tbl.peak = 2097152, }, { - .name = "cam_sf_mnoc", - .icc_bw_tbl.avg = 2097152, + .name = "cam_sf_0_mnoc", + .icc_bw_tbl.avg = 0, .icc_bw_tbl.peak = 2097152, }, { @@ -2977,240 +2599,212 @@ static const struct resources_icc icc_res_sc8280xp[] = { }, }; -static const struct camss_subdev_resources csiphy_res_8550[] = { +static const struct camss_subdev_resources csiphy_res_7280[] = { /* CSIPHY0 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 32200 }, - { .supply = "vdda-pll", .init_load_uA = 18000 } + { .supply = "vdda-phy", .init_load_uA = 16100 }, + { .supply = "vdda-pll", .init_load_uA = 9000 } }, + .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_sdm845, } }, /* CSIPHY1 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 32200 }, - { .supply = "vdda-pll", .init_load_uA = 18000 } + { .supply = "vdda-phy", .init_load_uA = 16100 }, + { .supply = "vdda-pll", .init_load_uA = 9000 } }, + .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_sdm845, } }, /* CSIPHY2 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 32200 }, - { .supply = "vdda-pll", .init_load_uA = 18000 } + { .supply = "vdda-phy", .init_load_uA = 16100 }, + { .supply = "vdda-pll", .init_load_uA = 9000 } }, + .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_sdm845, } }, /* CSIPHY3 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 32200 }, - { .supply = "vdda-pll", .init_load_uA = 18000 } + { .supply = "vdda-phy", .init_load_uA = 16100 }, + { .supply = "vdda-pll", .init_load_uA = 9000 } }, + .clock = { "csiphy3", "csiphy3_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, .reg = { "csiphy3" }, .interrupt = { "csiphy3" }, .csiphy = { .id = 3, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_sdm845, } }, /* CSIPHY4 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 37900 }, - { .supply = "vdda-pll", .init_load_uA = 18600 } + { .supply = "vdda-phy", .init_load_uA = 16100 }, + { .supply = "vdda-pll", .init_load_uA = 9000 } }, + .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, .reg = { "csiphy4" }, .interrupt = { "csiphy4" }, .csiphy = { .id = 4, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } - }, - /* CSIPHY5 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 32200 }, - { .supply = "vdda-pll", .init_load_uA = 18000 } - }, - .clock = { "csiphy5", "csiphy5_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, - .reg = { "csiphy5" }, - .interrupt = { "csiphy5" }, - .csiphy = { - .id = 5, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } - }, - /* CSIPHY6 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 37900 }, - { .supply = "vdda-pll", .init_load_uA = 18600 } - }, - .clock = { "csiphy6", "csiphy6_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, - .reg = { "csiphy6" }, - .interrupt = { "csiphy6" }, - .csiphy = { - .id = 6, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 + .formats = &csiphy_formats_sdm845, } }, - /* CSIPHY7 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 32200 }, - { .supply = "vdda-pll", .init_load_uA = 18000 } - }, - .clock = { "csiphy7", "csiphy7_timer" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000 } }, - .reg = { "csiphy7" }, - .interrupt = { "csiphy7" }, - .csiphy = { - .id = 7, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845 - } - } -}; - -static const struct resources_wrapper csid_wrapper_res_sm8550 = { - .reg = "csid_wrapper", }; -static const struct camss_subdev_resources csid_res_8550[] = { +static const struct camss_subdev_resources csid_res_7280[] = { /* CSID0 */ { .regulators = {}, - .clock = { "csid", "csiphy_rx" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000, 480000000 } }, + + .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 } + }, + .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { .is_lite = false, + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, /* CSID1 */ { .regulators = {}, - .clock = { "csid", "csiphy_rx" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000, 480000000 } }, + + .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 } + }, + .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { .is_lite = false, + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, /* CSID2 */ { .regulators = {}, - .clock = { "csid", "csiphy_rx" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000, 480000000 } }, - .reg = { "csid2" }, - .interrupt = { "csid2" }, + + .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 } + }, + + .reg = { "csid2" }, + .interrupt = { "csid2" }, .csid = { .is_lite = false, + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, /* CSID3 */ { .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000, 480000000 } }, + + .clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 } + }, + .reg = { "csid_lite0" }, .interrupt = { "csid_lite0" }, .csid = { .is_lite = true, + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } }, /* CSID4 */ { .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { { 400000000, 480000000 }, - { 400000000, 480000000 } }, + + .clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 } + }, + .reg = { "csid_lite1" }, .interrupt = { "csid_lite1" }, .csid = { .is_lite = true, + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, .formats = &csid_formats_gen2 } - } + }, }; -static const struct camss_subdev_resources vfe_res_8550[] = { +static const struct camss_subdev_resources vfe_res_7280[] = { /* VFE0 */ { .regulators = {}, - .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb_clk", "vfe0_fast_ahb", - "vfe0", "cpas_vfe0", "camnoc_axi" }, - .clock_rate = { { 0 }, + + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe0", + "vfe0_axi", "gcc_axi_hf", "gcc_axi_sf" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, { 80000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 466000000, 594000000, 675000000, 785000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 } }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { @@ -3218,7 +2812,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife0", - .hw_ops = &vfe_ops_gen3, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -3226,15 +2820,17 @@ static const struct camss_subdev_resources vfe_res_8550[] = { /* VFE1 */ { .regulators = {}, - .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb_clk", "vfe1_fast_ahb", - "vfe1", "cpas_vfe1", "camnoc_axi" }, - .clock_rate = { { 0 }, + + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe1", + "vfe1_axi", "gcc_axi_hf", "gcc_axi_sf" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, { 80000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 466000000, 594000000, 675000000, 785000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 } }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { @@ -3242,7 +2838,7 @@ static const struct camss_subdev_resources vfe_res_8550[] = { .is_lite = false, .has_pd = true, .pd_name = "ife1", - .hw_ops = &vfe_ops_gen3, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } @@ -3250,492 +2846,1707 @@ static const struct camss_subdev_resources vfe_res_8550[] = { /* VFE2 */ { .regulators = {}, - .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb_clk", "vfe2_fast_ahb", - "vfe2", "cpas_vfe2", "camnoc_axi" }, - .clock_rate = { { 0 }, + + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe2", + "vfe2_axi", "gcc_axi_hf", "gcc_axi_sf" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, { 80000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 466000000, 594000000, 675000000, 785000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 } }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, .interrupt = { "vfe2" }, .vfe = { .line_num = 3, .is_lite = false, + .hw_ops = &vfe_ops_170, .has_pd = true, .pd_name = "ife2", - .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE3 lite */ + /* VFE3 (lite) */ { - .regulators = {}, - .clock = { "gcc_axi_hf", "cpas_ahb", "vfe_lite_ahb", - "vfe_lite", "cpas_ife_lite", "camnoc_axi" }, - .clock_rate = { { 0 }, + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", + "vfe_lite0", "gcc_axi_hf", "gcc_axi_sf" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, { 80000000 }, - { 300000000, 400000000 }, - { 400000000, 480000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 } }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 }, + { 0 }, + { 0 } }, + + .regulators = {}, .reg = { "vfe_lite0" }, .interrupt = { "vfe_lite0" }, .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_gen3, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE4 lite */ + /* VFE4 (lite) */ { - .regulators = {}, - .clock = { "gcc_axi_hf", "cpas_ahb", "vfe_lite_ahb", - "vfe_lite", "cpas_ife_lite", "camnoc_axi" }, - .clock_rate = { { 0 }, + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", + "vfe_lite1", "gcc_axi_hf", "gcc_axi_sf" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, { 80000000 }, - { 300000000, 400000000 }, - { 400000000, 480000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 } }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 }, + { 0 }, + { 0 } }, + + .regulators = {}, .reg = { "vfe_lite1" }, .interrupt = { "vfe_lite1" }, .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_gen3, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, }; -static const struct resources_icc icc_res_sm8550[] = { +static const struct resources_icc icc_res_sc7280[] = { { .name = "ahb", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, }, { - .name = "hf_0_mnoc", + .name = "hf_0", .icc_bw_tbl.avg = 2097152, .icc_bw_tbl.peak = 2097152, }, }; -static const struct camss_subdev_resources csiphy_res_sm8650[] = { +static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { /* CSIPHY0 */ { - .regulators = { - { .supply = "vdd-csiphy01-0p9", .init_load_uA = 88000 }, - { .supply = "vdd-csiphy01-1p2", .init_load_uA = 17800 }, - }, + .regulators = {}, .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 400000000 }, - { 400000000 } }, + .clock_rate = { { 400000000 }, + { 300000000 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - }, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY1 */ { - .regulators = { - { .supply = "vdd-csiphy01-0p9", .init_load_uA = 88000 }, - { .supply = "vdd-csiphy01-1p2", .init_load_uA = 17800 }, - }, + .regulators = {}, .clock = { "csiphy1", "csiphy1_timer" }, .clock_rate = { { 400000000 }, - { 400000000 } }, + { 300000000 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - }, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY2 */ { - .regulators = { - { .supply = "vdd-csiphy24-0p9", .init_load_uA = 147000 }, - { .supply = "vdd-csiphy24-1p2", .init_load_uA = 24400 }, - }, + .regulators = {}, .clock = { "csiphy2", "csiphy2_timer" }, .clock_rate = { { 400000000 }, - { 400000000 } }, + { 300000000 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - }, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY3 */ { - .regulators = { - { .supply = "vdd-csiphy35-0p9", .init_load_uA = 88000 }, - { .supply = "vdd-csiphy35-1p2", .init_load_uA = 17800 }, - }, + .regulators = {}, .clock = { "csiphy3", "csiphy3_timer" }, .clock_rate = { { 400000000 }, - { 400000000 } }, + { 300000000 } }, .reg = { "csiphy3" }, .interrupt = { "csiphy3" }, .csiphy = { .id = 3, .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - }, - }, - /* CSIPHY4 */ - { - .regulators = { - { .supply = "vdd-csiphy24-0p9", .init_load_uA = 147000 }, - { .supply = "vdd-csiphy24-1p2", .init_load_uA = 24400 }, - }, - .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 400000000 }, - { 400000000 } }, - .reg = { "csiphy4" }, - .interrupt = { "csiphy4" }, - .csiphy = { - .id = 4, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - }, - }, - /* CSIPHY5 */ - { - .regulators = { - { .supply = "vdd-csiphy35-0p9", .init_load_uA = 88000 }, - { .supply = "vdd-csiphy35-1p2", .init_load_uA = 17800 }, - }, - .clock = { "csiphy5", "csiphy5_timer" }, - .clock_rate = { { 400000000 }, - { 400000000 } }, - .reg = { "csiphy5" }, - .interrupt = { "csiphy5" }, - .csiphy = { - .id = 5, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - }, + .formats = &csiphy_formats_sdm845 + } }, }; -static const struct camss_subdev_resources csid_res_sm8650[] = { +static const struct camss_subdev_resources csid_res_sc8280xp[] = { /* CSID0 */ { - .regulators = { }, - .clock = { "csid", "csiphy_rx" }, - .clock_rate = { { 400000000 }, - { 400000000, 480000000 } }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, - .formats = &csid_formats_gen2, - }, + .formats = &csid_formats_gen2 + } }, /* CSID1 */ { - .regulators = { }, - .clock = { "csid", "csiphy_rx" }, - .clock_rate = { { 400000000 }, - { 400000000, 480000000 } }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, .csid = { + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, - .formats = &csid_formats_gen2, - }, + .formats = &csid_formats_gen2 + } }, /* CSID2 */ { - .regulators = { }, - .clock = { "csid", "csiphy_rx" }, - .clock_rate = { { 400000000 }, - { 400000000, 480000000 } }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2", "vfe2_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, .csid = { + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, - .formats = &csid_formats_gen2, - }, + .formats = &csid_formats_gen2 + } }, - /* CSID3 lite */ + /* CSID3 */ { - .regulators = { }, - .clock = { "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { { 0 }, - { 400000000, 480000000 }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "vfe3_csid", "vfe3_cphy_rx", "vfe3", "vfe3_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, { 0 } }, - .reg = { "csid_lite0" }, - .interrupt = { "csid_lite0" }, + .reg = { "csid3" }, + .interrupt = { "csid3" }, .csid = { - .is_lite = true, + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, - .formats = &csid_formats_gen2, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } }, + .clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid0_lite" }, + .interrupt = { "csid0_lite" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } }, - /* CSID4 lite */ + /* CSID_LITE1 */ { - .regulators = { }, - .clock = { "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { { 0 }, - { 400000000, 480000000 }, - { 0 } }, - .reg = { "csid_lite1" }, - .interrupt = { "csid_lite1" }, + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid1_lite" }, + .interrupt = { "csid1_lite" }, .csid = { .is_lite = true, + .hw_ops = &csid_ops_gen2, .parent_dev_ops = &vfe_parent_dev_ops, - .hw_ops = &csid_ops_gen3, - .formats = &csid_formats_gen2, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE2 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } }, + .clock = { "vfe_lite2_csid", "vfe_lite2_cphy_rx", "vfe_lite2" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid2_lite" }, + .interrupt = { "csid2_lite" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } }, + /* CSID_LITE3 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 0 }, + { .supply = "vdda-pll", .init_load_uA = 0 } + }, + .clock = { "vfe_lite3_csid", "vfe_lite3_cphy_rx", "vfe_lite3" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid3_lite" }, + .interrupt = { "csid3_lite" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + } }; -static const struct camss_subdev_resources vfe_res_sm8650[] = { +static const struct camss_subdev_resources vfe_res_sc8280xp[] = { /* VFE0 */ { - .regulators = { }, - .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", - "camnoc_axi", "vfe0_fast_ahb", "vfe0", "cpas_vfe0", - "qdss_debug_xo", - }, - .clock_rate = { { 0 }, - { 80000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 0 }, - { 466000000, 594000000, 675000000, 785000000 }, - { 0 }, + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe0", "vfe0_axi" }, + .clock_rate = { { 0 }, { 0 }, - }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { - .line_num = 3, - .has_pd = true, + .line_num = 4, .pd_name = "ife0", - .hw_ops = &vfe_ops_gen3, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 - }, + } }, /* VFE1 */ { - .regulators = { }, - .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", - "camnoc_axi", "vfe1_fast_ahb", "vfe1", "cpas_vfe1", - "qdss_debug_xo", - }, - .clock_rate = { { 0 }, - { 80000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 0 }, - { 466000000, 594000000, 675000000, 785000000 }, - { 0 }, + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe1", "vfe1_axi" }, + .clock_rate = { { 0 }, { 0 }, - }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { - .line_num = 3, - .has_pd = true, + .line_num = 4, .pd_name = "ife1", - .hw_ops = &vfe_ops_gen3, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 - }, + } }, /* VFE2 */ { - .regulators = { }, - .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", - "camnoc_axi", "vfe2_fast_ahb", "vfe2", "cpas_vfe2", - "qdss_debug_xo", - }, + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe2", "vfe2_axi" }, .clock_rate = { { 0 }, - { 80000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 0 }, - { 466000000, 594000000, 675000000, 785000000 }, - { 0 }, { 0 }, - }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, .reg = { "vfe2" }, .interrupt = { "vfe2" }, .vfe = { - .line_num = 3, - .has_pd = true, + .line_num = 4, .pd_name = "ife2", - .hw_ops = &vfe_ops_gen3, + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 - }, + } }, - /* VFE3 lite */ + /* VFE3 */ { - .regulators = { }, - .clock = { "gcc_axi_hf", "cpas_ahb", "camnoc_axi", - "vfe_lite_ahb", "vfe_lite", "cpas_vfe_lite", - "qdss_debug_xo", - }, + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe3", "vfe3_axi" }, .clock_rate = { { 0 }, - { 80000000 }, - { 300000000, 400000000 }, - { 0 }, - { 400000000, 480000000 }, - { 0 }, { 0 }, - }, - .reg = { "vfe_lite0" }, - .interrupt = { "vfe_lite0" }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, + .reg = { "vfe3" }, + .interrupt = { "vfe3" }, .vfe = { .line_num = 4, - .is_lite = true, - .hw_ops = &vfe_ops_gen3, + .pd_name = "ife3", + .hw_ops = &vfe_ops_170, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 - }, + } }, - /* VFE4 lite */ + /* VFE_LITE_0 */ { - .regulators = { }, - .clock = { "gcc_axi_hf", "cpas_ahb", "camnoc_axi", - "vfe_lite_ahb", "vfe_lite", "cpas_vfe_lite", - "qdss_debug_xo", - }, - .clock_rate = { { 0 }, - { 80000000 }, - { 300000000, 400000000 }, + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite0" }, + .clock_rate = { { 0 }, { 0 }, - { 400000000, 480000000 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000 }, }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE_1 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite1" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000 }, }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE_2 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite2" }, + .clock_rate = { { 0 }, { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000, }, }, + .reg = { "vfe_lite2" }, + .interrupt = { "vfe_lite2" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE_3 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite3" }, + .clock_rate = { { 0 }, { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000 }, }, + .reg = { "vfe_lite3" }, + .interrupt = { "vfe_lite3" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_sc8280xp[] = { + { + .name = "cam_ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + { + .name = "cam_hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, + { + .name = "cam_sf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, + { + .name = "cam_sf_icp_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + +static const struct camss_subdev_resources csiphy_res_8550[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 32200 }, + { .supply = "vdda-pll", .init_load_uA = 18000 } + }, + .clock = { "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 32200 }, + { .supply = "vdda-pll", .init_load_uA = 18000 } + }, + .clock = { "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 32200 }, + { .supply = "vdda-pll", .init_load_uA = 18000 } + }, + .clock = { "csiphy2", "csiphy2_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 32200 }, + { .supply = "vdda-pll", .init_load_uA = 18000 } + }, + .clock = { "csiphy3", "csiphy3_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 37900 }, + { .supply = "vdda-pll", .init_load_uA = 18600 } + }, + .clock = { "csiphy4", "csiphy4_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 32200 }, + { .supply = "vdda-pll", .init_load_uA = 18000 } + }, + .clock = { "csiphy5", "csiphy5_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY6 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 37900 }, + { .supply = "vdda-pll", .init_load_uA = 18600 } + }, + .clock = { "csiphy6", "csiphy6_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy6" }, + .interrupt = { "csiphy6" }, + .csiphy = { + .id = 6, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY7 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 32200 }, + { .supply = "vdda-pll", .init_load_uA = 18000 } + }, + .clock = { "csiphy7", "csiphy7_timer" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 } }, + .reg = { "csiphy7" }, + .interrupt = { "csiphy7" }, + .csiphy = { + .id = 7, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + } +}; + +static const struct resources_wrapper csid_wrapper_res_sm8550 = { + .reg = "csid_wrapper", +}; + +static const struct camss_subdev_resources csid_res_8550[] = { + /* CSID0 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2 + } + }, + /* CSID3 */ + { + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2 + } + }, + /* CSID4 */ + { + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2 + } + } +}; + +static const struct camss_subdev_resources vfe_res_8550[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb_clk", "vfe0_fast_ahb", + "vfe0", "cpas_vfe0", "camnoc_axi" }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 466000000, 594000000, 675000000, 785000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb_clk", "vfe1_fast_ahb", + "vfe1", "cpas_vfe1", "camnoc_axi" }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 466000000, 594000000, 675000000, 785000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb_clk", "vfe2_fast_ahb", + "vfe2", "cpas_vfe2", "camnoc_axi" }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 466000000, 594000000, 675000000, 785000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 lite */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "vfe_lite_ahb", + "vfe_lite", "cpas_ife_lite", "camnoc_axi" }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 400000000, 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 lite */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "vfe_lite_ahb", + "vfe_lite", "cpas_ife_lite", "camnoc_axi" }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 400000000, 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_sm8550[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, + { + .name = "hf_0_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + +static const struct camss_subdev_resources csiphy_res_sm8650[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy01-0p9", .init_load_uA = 88000 }, + { .supply = "vdd-csiphy01-1p2", .init_load_uA = 17800 }, + }, + .clock = { "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 400000000 }, + { 400000000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + }, + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy01-0p9", .init_load_uA = 88000 }, + { .supply = "vdd-csiphy01-1p2", .init_load_uA = 17800 }, + }, + .clock = { "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 400000000 }, + { 400000000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + }, + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdd-csiphy24-0p9", .init_load_uA = 147000 }, + { .supply = "vdd-csiphy24-1p2", .init_load_uA = 24400 }, + }, + .clock = { "csiphy2", "csiphy2_timer" }, + .clock_rate = { { 400000000 }, + { 400000000 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + }, + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdd-csiphy35-0p9", .init_load_uA = 88000 }, + { .supply = "vdd-csiphy35-1p2", .init_load_uA = 17800 }, + }, + .clock = { "csiphy3", "csiphy3_timer" }, + .clock_rate = { { 400000000 }, + { 400000000 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + }, + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy24-0p9", .init_load_uA = 147000 }, + { .supply = "vdd-csiphy24-1p2", .init_load_uA = 24400 }, + }, + .clock = { "csiphy4", "csiphy4_timer" }, + .clock_rate = { { 400000000 }, + { 400000000 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + }, + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdd-csiphy35-0p9", .init_load_uA = 88000 }, + { .supply = "vdd-csiphy35-1p2", .init_load_uA = 17800 }, + }, + .clock = { "csiphy5", "csiphy5_timer" }, + .clock_rate = { { 400000000 }, + { 400000000 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + }, + }, +}; + +static const struct camss_subdev_resources csid_res_sm8650[] = { + /* CSID0 */ + { + .regulators = { }, + .clock = { "csid", "csiphy_rx" }, + .clock_rate = { { 400000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2, + }, + }, + /* CSID1 */ + { + .regulators = { }, + .clock = { "csid", "csiphy_rx" }, + .clock_rate = { { 400000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2, + }, + }, + /* CSID2 */ + { + .regulators = { }, + .clock = { "csid", "csiphy_rx" }, + .clock_rate = { { 400000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2, + }, + }, + /* CSID3 lite */ + { + .regulators = { }, + .clock = { "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2, + }, + }, + /* CSID4 lite */ + { + .regulators = { }, + .clock = { "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen3, + .formats = &csid_formats_gen2, + }, + }, +}; + +static const struct camss_subdev_resources vfe_res_sm8650[] = { + /* VFE0 */ + { + .regulators = { }, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "camnoc_axi", "vfe0_fast_ahb", "vfe0", "cpas_vfe0", + "qdss_debug_xo", + }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 466000000, 594000000, 675000000, 785000000 }, + { 0 }, + { 0 }, + }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* VFE1 */ + { + .regulators = { }, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "camnoc_axi", "vfe1_fast_ahb", "vfe1", "cpas_vfe1", + "qdss_debug_xo", + }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 466000000, 594000000, 675000000, 785000000 }, + { 0 }, + { 0 }, + }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* VFE2 */ + { + .regulators = { }, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "camnoc_axi", "vfe2_fast_ahb", "vfe2", "cpas_vfe2", + "qdss_debug_xo", + }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 466000000, 594000000, 675000000, 785000000 }, + { 0 }, + { 0 }, + }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* VFE3 lite */ + { + .regulators = { }, + .clock = { "gcc_axi_hf", "cpas_ahb", "camnoc_axi", + "vfe_lite_ahb", "vfe_lite", "cpas_vfe_lite", + "qdss_debug_xo", + }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 0 }, + { 400000000, 480000000 }, + { 0 }, + { 0 }, + }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* VFE4 lite */ + { + .regulators = { }, + .clock = { "gcc_axi_hf", "cpas_ahb", "camnoc_axi", + "vfe_lite_ahb", "vfe_lite", "cpas_vfe_lite", + "qdss_debug_xo", + }, + .clock_rate = { { 0 }, + { 80000000 }, + { 300000000, 400000000 }, + { 0 }, + { 400000000, 480000000 }, + { 0 }, + { 0 }, + }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, +}; + +static const struct resources_icc icc_res_sm8650[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + +static const struct camss_subdev_resources csiphy_res_8300[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 15900 }, + { .supply = "vdda-pll", .init_load_uA = 8900 } + }, + + .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 15900 }, + { .supply = "vdda-pll", .init_load_uA = 8900 } + }, + + .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 15900 }, + { .supply = "vdda-pll", .init_load_uA = 8900 } + }, + + .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer" }, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845, + } + }, +}; + +static const struct camss_subdev_resources csiphy_res_8775p[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 15900 }, + { .supply = "vdda-pll", .init_load_uA = 8900 } + }, + .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 15900 }, + { .supply = "vdda-pll", .init_load_uA = 8900 } + }, + .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 15900 }, + { .supply = "vdda-pll", .init_load_uA = 8900 } + }, + .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdda-phy", .init_load_uA = 15900 }, + { .supply = "vdda-pll", .init_load_uA = 8900 } + }, + .clock = { "csiphy_rx", "csiphy3", "csiphy3_timer"}, + .clock_rate = { + { 400000000 }, + { 0 }, + { 400000000 }, + }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + +static const struct camss_subdev_resources tpg_res_8775p[] = { + /* TPG0 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "tpg0" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG1 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "tpg1" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG2 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "tpg2" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, +}; + +static const struct camss_subdev_resources csid_res_8775p[] = { + /* CSID0 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx"}, + .clock_rate = { + { 400000000, 400000000}, + { 400000000, 400000000} + }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .regulators = {}, + .clock = { "csid", "csiphy_rx"}, + .clock_rate = { + { 400000000, 400000000}, + { 400000000, 400000000} + }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + + /* CSID2 (lite) */ + { + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { + { 400000000, 480000000 }, + { 400000000, 480000000 } + }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID3 (lite) */ + { + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { + { 400000000, 480000000 }, + { 400000000, 480000000 } + }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID4 (lite) */ + { + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { + { 400000000, 480000000 }, + { 400000000, 480000000 } + }, + .reg = { "csid_lite2" }, + .interrupt = { "csid_lite2" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID5 (lite) */ + { + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { + { 400000000, 480000000 }, + { 400000000, 480000000 } + }, + .reg = { "csid_lite3" }, + .interrupt = { "csid_lite3" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID6 (lite) */ + { + .regulators = {}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { + { 400000000, 480000000 }, + { 400000000, 480000000 } + }, + .reg = { "csid_lite4" }, + .interrupt = { "csid_lite4" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen3, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, +}; + +static const struct camss_subdev_resources vfe_res_8775p[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "cpas_vfe0", "vfe0", "vfe0_fast_ahb", + "cpas_ahb", "gcc_axi_hf", + "cpas_fast_ahb_clk", + "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 300000000, 400000000 }, + { 400000000 }, + }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = false, + .pd_name = NULL, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 */ + { + .regulators = {}, + .clock = { "cpas_vfe1", "vfe1", "vfe1_fast_ahb", + "cpas_ahb", "gcc_axi_hf", + "cpas_fast_ahb_clk", + "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 480000000 }, + { 300000000, 400000000 }, + { 300000000, 400000000 }, + { 0 }, + { 300000000, 400000000 }, + { 400000000 }, + }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = false, + .pd_name = NULL, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 (lite) */ + { + .regulators = {}, + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite", "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, + }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 (lite) */ + { + .regulators = {}, + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite", "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, + }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 (lite) */ + { + .regulators = {}, + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite", "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, + }, + .reg = { "vfe_lite2" }, + .interrupt = { "vfe_lite2" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE5 (lite) */ + { + .regulators = {}, + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite", "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, + }, + .reg = { "vfe_lite3" }, + .interrupt = { "vfe_lite3" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_gen3, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE6 (lite) */ + { + .regulators = {}, + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", + "vfe_lite_csid", "vfe_lite_cphy_rx", + "vfe_lite", "camnoc_axi"}, + .clock_rate = { + { 0 }, + { 0 }, + { 300000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 400000000, 400000000, 400000000, 400000000 }, + { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, }, - .reg = { "vfe_lite1" }, - .interrupt = { "vfe_lite1" }, + .reg = { "vfe_lite4" }, + .interrupt = { "vfe_lite4" }, .vfe = { .line_num = 4, .is_lite = true, .hw_ops = &vfe_ops_gen3, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 - }, + } }, }; -static const struct resources_icc icc_res_sm8650[] = { +static const struct resources_icc icc_res_qcs8300[] = { { .name = "ahb", .icc_bw_tbl.avg = 38400, .icc_bw_tbl.peak = 76800, }, { - .name = "hf_mnoc", + .name = "hf_0", .icc_bw_tbl.avg = 2097152, .icc_bw_tbl.peak = 2097152, }, }; -static const struct camss_subdev_resources csiphy_res_8300[] = { - /* CSIPHY0 */ - { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 15900 }, - { .supply = "vdda-pll", .init_load_uA = 8900 } - }, - - .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer" }, - .clock_rate = { - { 400000000 }, - { 0 }, - { 400000000 }, - }, - .reg = { "csiphy0" }, - .interrupt = { "csiphy0" }, - .csiphy = { - .id = 0, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - } - }, - /* CSIPHY1 */ +static const struct resources_icc icc_res_sa8775p[] = { { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 15900 }, - { .supply = "vdda-pll", .init_load_uA = 8900 } - }, - - .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer" }, - .clock_rate = { - { 400000000 }, - { 0 }, - { 400000000 }, - }, - .reg = { "csiphy1" }, - .interrupt = { "csiphy1" }, - .csiphy = { - .id = 1, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - } + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, }, - /* CSIPHY2 */ { - .regulators = { - { .supply = "vdda-phy", .init_load_uA = 15900 }, - { .supply = "vdda-pll", .init_load_uA = 8900 } - }, - - .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer" }, - .clock_rate = { - { 400000000 }, - { 0 }, - { 400000000 }, - }, - .reg = { "csiphy2" }, - .interrupt = { "csiphy2" }, - .csiphy = { - .id = 2, - .hw_ops = &csiphy_ops_3ph_1_0, - .formats = &csiphy_formats_sdm845, - } + .name = "hf_0", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, }, }; -static const struct camss_subdev_resources csiphy_res_8775p[] = { +static const struct camss_subdev_resources csiphy_res_8750[] = { /* CSIPHY0 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 15900 }, - { .supply = "vdda-pll", .init_load_uA = 8900 } - }, - .clock = { "csiphy_rx", "csiphy0", "csiphy0_timer"}, - .clock_rate = { - { 400000000 }, - { 0 }, - { 400000000 }, + { .supply = "vdd-csiphy0-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, .csiphy = { @@ -3747,15 +4558,15 @@ static const struct camss_subdev_resources csiphy_res_8775p[] = { /* CSIPHY1 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 15900 }, - { .supply = "vdda-pll", .init_load_uA = 8900 } - }, - .clock = { "csiphy_rx", "csiphy1", "csiphy1_timer"}, - .clock_rate = { - { 400000000 }, - { 0 }, - { 400000000 }, + { .supply = "vdd-csiphy1-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, .csiphy = { @@ -3767,15 +4578,15 @@ static const struct camss_subdev_resources csiphy_res_8775p[] = { /* CSIPHY2 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 15900 }, - { .supply = "vdda-pll", .init_load_uA = 8900 } - }, - .clock = { "csiphy_rx", "csiphy2", "csiphy2_timer"}, - .clock_rate = { - { 400000000 }, - { 0 }, - { 400000000 }, + { .supply = "vdd-csiphy2-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, .csiphy = { @@ -3787,15 +4598,15 @@ static const struct camss_subdev_resources csiphy_res_8775p[] = { /* CSIPHY3 */ { .regulators = { - { .supply = "vdda-phy", .init_load_uA = 15900 }, - { .supply = "vdda-pll", .init_load_uA = 8900 } - }, - .clock = { "csiphy_rx", "csiphy3", "csiphy3_timer"}, - .clock_rate = { - { 400000000 }, - { 0 }, - { 400000000 }, + { .supply = "vdd-csiphy3-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, .reg = { "csiphy3" }, .interrupt = { "csiphy3" }, .csiphy = { @@ -3804,401 +4615,271 @@ static const struct camss_subdev_resources csiphy_res_8775p[] = { .formats = &csiphy_formats_sdm845 } }, -}; - -static const struct camss_subdev_resources tpg_res_8775p[] = { - /* TPG0 */ - { - .regulators = {}, - .clock = { "cpas_ahb", "csiphy_rx" }, - .clock_rate = { - { 0 }, - { 400000000 }, - }, - .reg = { "tpg0" }, - .tpg = { - .lane_cnt = 4, - .formats = &tpg_formats_gen1, - .hw_ops = &tpg_ops_gen1 - } - }, - /* TPG1 */ + /* CSIPHY4 */ { - .regulators = {}, - .clock = { "cpas_ahb", "csiphy_rx" }, - .clock_rate = { - { 0 }, - { 400000000 }, + .regulators = { + { .supply = "vdd-csiphy4-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } }, - .reg = { "tpg1" }, - .tpg = { - .lane_cnt = 4, - .formats = &tpg_formats_gen1, - .hw_ops = &tpg_ops_gen1 + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } }, - /* TPG2 */ + /* CSIPHY5 */ { - .regulators = {}, - .clock = { "cpas_ahb", "csiphy_rx" }, - .clock_rate = { - { 0 }, - { 400000000 }, + .regulators = { + { .supply = "vdd-csiphy5-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } }, - .reg = { "tpg2" }, - .tpg = { - .lane_cnt = 4, - .formats = &tpg_formats_gen1, - .hw_ops = &tpg_ops_gen1 + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 } }, }; -static const struct camss_subdev_resources csid_res_8775p[] = { +static const struct camss_subdev_resources csid_res_8750[] = { /* CSID0 */ { - .regulators = {}, - .clock = { "csid", "csiphy_rx"}, - .clock_rate = { - { 400000000, 400000000}, - { 400000000, 400000000} - }, + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, .csid = { .is_lite = false, - .hw_ops = &csid_ops_gen3, .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, .formats = &csid_formats_gen2 } }, /* CSID1 */ { - .regulators = {}, - .clock = { "csid", "csiphy_rx"}, - .clock_rate = { - { 400000000, 400000000}, - { 400000000, 400000000} - }, - .reg = { "csid1" }, - .interrupt = { "csid1" }, - .csid = { - .is_lite = false, - .hw_ops = &csid_ops_gen3, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - - /* CSID2 (lite) */ - { - .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { - { 400000000, 480000000 }, - { 400000000, 480000000 } - }, - .reg = { "csid_lite0" }, - .interrupt = { "csid_lite0" }, - .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen3, - .parent_dev_ops = &vfe_parent_dev_ops, - .formats = &csid_formats_gen2 - } - }, - /* CSID3 (lite) */ - { - .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { - { 400000000, 480000000 }, - { 400000000, 480000000 } - }, - .reg = { "csid_lite1" }, - .interrupt = { "csid_lite1" }, + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen3, + .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, .formats = &csid_formats_gen2 } }, - /* CSID4 (lite) */ + /* CSID2 */ { - .regulators = {}, - .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { - { 400000000, 480000000 }, - { 400000000, 480000000 } - }, - .reg = { "csid_lite2" }, - .interrupt = { "csid_lite2" }, + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, .csid = { - .is_lite = true, - .hw_ops = &csid_ops_gen3, + .is_lite = false, .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, .formats = &csid_formats_gen2 } }, - /* CSID5 (lite) */ + /* CSID_LITE0 */ { - .regulators = {}, .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { - { 400000000, 480000000 }, - { 400000000, 480000000 } - }, - .reg = { "csid_lite3" }, - .interrupt = { "csid_lite3" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, .csid = { .is_lite = true, - .hw_ops = &csid_ops_gen3, .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, .formats = &csid_formats_gen2 } }, - /* CSID6 (lite) */ + /* CSID_LITE1 */ { - .regulators = {}, .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, - .clock_rate = { - { 400000000, 480000000 }, - { 400000000, 480000000 } - }, - .reg = { "csid_lite4" }, - .interrupt = { "csid_lite4" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, .csid = { .is_lite = true, - .hw_ops = &csid_ops_gen3, .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, .formats = &csid_formats_gen2 } - }, + } }; -static const struct camss_subdev_resources vfe_res_8775p[] = { - /* VFE0 */ +static const struct camss_subdev_resources vfe_res_8750[] = { + /* VFE0 - TFE Full */ { - .regulators = {}, - .clock = { "cpas_vfe0", "vfe0", "vfe0_fast_ahb", - "cpas_ahb", "gcc_axi_hf", - "cpas_fast_ahb_clk", - "camnoc_axi"}, - .clock_rate = { - { 0 }, - { 480000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 0 }, - { 300000000, 400000000 }, - { 400000000 }, - }, + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, .vfe = { .line_num = 3, .is_lite = false, - .has_pd = false, - .pd_name = NULL, - .hw_ops = &vfe_ops_gen3, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE1 */ + /* VFE1 - TFE Full */ { - .regulators = {}, - .clock = { "cpas_vfe1", "vfe1", "vfe1_fast_ahb", - "cpas_ahb", "gcc_axi_hf", - "cpas_fast_ahb_clk", - "camnoc_axi"}, - .clock_rate = { - { 0 }, - { 480000000 }, - { 300000000, 400000000 }, - { 300000000, 400000000 }, - { 0 }, - { 300000000, 400000000 }, - { 400000000 }, - }, + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, .vfe = { .line_num = 3, .is_lite = false, - .has_pd = false, - .pd_name = NULL, - .hw_ops = &vfe_ops_gen3, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE2 (lite) */ - { - .regulators = {}, - .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite", "camnoc_axi"}, - .clock_rate = { - { 0 }, - { 0 }, - { 300000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 480000000, 600000000, 600000000, 600000000 }, - { 400000000 }, - }, - .reg = { "vfe_lite0" }, - .interrupt = { "vfe_lite0" }, - .vfe = { - .line_num = 4, - .is_lite = true, - .hw_ops = &vfe_ops_gen3, - .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, - /* VFE3 (lite) */ - { - .regulators = {}, - .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite", "camnoc_axi"}, - .clock_rate = { - { 0 }, - { 0 }, - { 300000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 480000000, 600000000, 600000000, 600000000 }, - { 400000000 }, - }, - .reg = { "vfe_lite1" }, - .interrupt = { "vfe_lite1" }, - .vfe = { - .line_num = 4, - .is_lite = true, - .hw_ops = &vfe_ops_gen3, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE4 (lite) */ + /* VFE2 - TFE Full */ { - .regulators = {}, - .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite", "camnoc_axi"}, - .clock_rate = { - { 0 }, - { 0 }, - { 300000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 480000000, 600000000, 600000000, 600000000 }, - { 400000000 }, - }, - .reg = { "vfe_lite2" }, - .interrupt = { "vfe_lite2" }, + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, .vfe = { - .line_num = 4, - .is_lite = true, - .hw_ops = &vfe_ops_gen3, + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE5 (lite) */ + /* VFE_LITE0 */ { - .regulators = {}, - .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite", "camnoc_axi"}, - .clock_rate = { - { 0 }, - { 0 }, - { 300000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 480000000, 600000000, 600000000, 600000000 }, - { 400000000 }, - }, - .reg = { "vfe_lite3" }, - .interrupt = { "vfe_lite3" }, + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_gen3, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, .formats_rdi = &vfe_formats_rdi_845, .formats_pix = &vfe_formats_pix_845 } }, - /* VFE6 (lite) */ + /* VFE_LITE1 */ { - .regulators = {}, - .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite", "camnoc_axi"}, - .clock_rate = { - { 0 }, - { 0 }, - { 300000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 400000000, 400000000, 400000000, 400000000 }, - { 480000000, 600000000, 600000000, 600000000 }, - { 400000000 }, - }, - .reg = { "vfe_lite4" }, - .interrupt = { "vfe_lite4" }, + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, .vfe = { .line_num = 4, .is_lite = true, - .hw_ops = &vfe_ops_gen3, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, .formats_rdi = &vfe_formats_rdi_845, - .formats_pix = &vfe_formats_pix_845 - } - }, -}; - -static const struct resources_icc icc_res_qcs8300[] = { - { - .name = "ahb", - .icc_bw_tbl.avg = 38400, - .icc_bw_tbl.peak = 76800, - }, - { - .name = "hf_0", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, - }, + .formats_pix = &vfe_formats_pix_845 + } + } }; -static const struct resources_icc icc_res_sa8775p[] = { +static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", - .icc_bw_tbl.avg = 38400, - .icc_bw_tbl.peak = 76800, + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ { - .name = "hf_0", - .icc_bw_tbl.avg = 2097152, - .icc_bw_tbl.peak = 2097152, + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, }, }; static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy0" }, - .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, @@ -4207,15 +4888,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY1 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy1" }, - .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, @@ -4224,15 +4896,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY2 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy2" }, - .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, @@ -4241,15 +4904,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY4 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy4" }, - .interrupt = { "csiphy4" }, .csiphy = { .id = 4, .hw_ops = &csiphy_ops_3ph_1_0, @@ -4536,6 +5190,152 @@ static const struct resources_wrapper csid_wrapper_res_x1e80100 = { .reg = "csid_wrapper", }; +static const struct camss_subdev_resources csiphy_res_x1p42100[] = { + /* CSIPHY0 */ + { + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, + /* CSIPHY4 */ + { + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, +}; + +static const struct camss_subdev_resources vfe_res_x1p42100[] = { + /* IFE0 */ + { + .regulators = {}, + .clock = {"camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "cpas_fast_ahb", "cpas_vfe0", "vfe0_fast_ahb", + "vfe0" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 345600000, 432000000, 594000000, 675000000, + 727000000 }, }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 4, + .pd_name = "ife0", + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_0 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", + "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_1 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", + "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, +}; + +static const struct camss_subdev_resources csiphy_res_glymur[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy4", "csiphy4_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate @@ -4793,14 +5593,35 @@ static int camss_parse_endpoint_node(struct device *dev, static int camss_parse_ports(struct camss *camss) { struct device *dev = camss->dev; + const struct camss_resources *res = camss->res; struct fwnode_handle *fwnode = dev_fwnode(dev), *ep; int ret; fwnode_graph_for_each_endpoint(fwnode, ep) { struct camss_async_subdev *csd; + struct fwnode_handle *remote; + + if (!fwnode_device_is_available(ep)) + continue; + + if (res->legacy_phy) { + csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, + typeof(*csd)); + } else { + /* + * For non-legacy PHY, the CSIPHY is a separate device. + * Register the remote endpoint (CSIPHY's endpoint) as + * the async subdev, not the remote port parent. + */ + remote = fwnode_graph_get_remote_endpoint(ep); + if (!remote) + continue; + + csd = v4l2_async_nf_add_fwnode(&camss->notifier, remote, + struct camss_async_subdev); + fwnode_handle_put(remote); + } - csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, - typeof(*csd)); if (IS_ERR(csd)) { ret = PTR_ERR(csd); goto err_cleanup; @@ -4832,15 +5653,26 @@ static int camss_init_subdevices(struct camss *camss) unsigned int i; int ret; - for (i = 0; i < camss->res->csiphy_num; i++) { - ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], - &res->csiphy_res[i], - res->csiphy_res[i].csiphy.id); - if (ret < 0) { - dev_err(camss->dev, - "Failed to init csiphy%d sub-device: %d\n", - i, ret); - return ret; + if (!res->legacy_phy) { + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], + &res->csiphy_res[i], + res->csiphy_res[i].csiphy.id); + if (ret < 0) + return ret; + } + } else { + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_subdev_init_legacy(camss, &camss->csiphy[i], + &res->csiphy_res[i], + res->csiphy_res[i].csiphy.id); + if (ret < 0) { + dev_err(camss->dev, + "Failed to init csiphy%d sub-device: %d\n", + i, ret); + return ret; + } + camss->csiphy[i].phy = ERR_PTR(-ENODEV); } } @@ -4930,6 +5762,9 @@ static int camss_link_entities(struct camss *camss) for (i = 0; i < camss->res->csiphy_num; i++) { for (j = 0; j < camss->res->csid_num; j++) { + if (!camss->csiphy[i].phy) + continue; + ret = media_create_pad_link(&camss->csiphy[i].subdev.entity, MSM_CSIPHY_PAD_SRC, &camss->csid[j].subdev.entity, @@ -5056,6 +5891,9 @@ static int camss_register_entities(struct camss *camss) int ret; for (i = 0; i < camss->res->csiphy_num; i++) { + if (!camss->csiphy[i].phy) + continue; + ret = msm_csiphy_register_entity(&camss->csiphy[i], &camss->v4l2_dev); if (ret < 0) { @@ -5131,8 +5969,10 @@ static int camss_register_entities(struct camss *camss) i = camss->res->csiphy_num; err_reg_csiphy: - for (i--; i >= 0; i--) - msm_csiphy_unregister_entity(&camss->csiphy[i]); + for (i--; i >= 0; i--) { + if (camss->csiphy[i].phy) + msm_csiphy_unregister_entity(&camss->csiphy[i]); + } return ret; } @@ -5147,8 +5987,10 @@ static void camss_unregister_entities(struct camss *camss) { unsigned int i; - for (i = 0; i < camss->res->csiphy_num; i++) - msm_csiphy_unregister_entity(&camss->csiphy[i]); + for (i = 0; i < camss->res->csiphy_num; i++) { + if (camss->csiphy[i].phy) + msm_csiphy_unregister_entity(&camss->csiphy[i]); + } if (camss->tpg) { for (i = 0; i < camss->res->tpg_num; i++) @@ -5362,6 +6204,8 @@ static int camss_probe(struct platform_device *pdev) if (!camss) return -ENOMEM; + devm_of_platform_populate(dev); + camss->res = of_device_get_match_data(dev); atomic_set(&camss->ref_count, 0); @@ -5507,8 +6351,22 @@ static void camss_remove(struct platform_device *pdev) camss_genpd_cleanup(camss); } +static const struct camss_resources kaanapali_resources = { + .version = CAMSS_KAANAPALI, + .pd_name = "top", + .csiphy_res = csiphy_res_kaanapali, + .csid_res = csid_res_kaanapali, + .vfe_res = vfe_res_kaanapali, + .icc_res = icc_res_kaanapali, + .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), + .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), + .csid_num = ARRAY_SIZE(csid_res_kaanapali), + .vfe_num = ARRAY_SIZE(vfe_res_kaanapali), +}; + static const struct camss_resources msm8916_resources = { .version = CAMSS_8x16, + .legacy_phy = true, .csiphy_res = csiphy_res_8x16, .csid_res = csid_res_8x16, .ispif_res = &ispif_res_8x16, @@ -5520,6 +6378,7 @@ static const struct camss_resources msm8916_resources = { static const struct camss_resources msm8939_resources = { .version = CAMSS_8x39, + .legacy_phy = true, .csiphy_res = csiphy_res_8x39, .csid_res = csid_res_8x39, .ispif_res = &ispif_res_8x39, @@ -5531,6 +6390,7 @@ static const struct camss_resources msm8939_resources = { static const struct camss_resources msm8953_resources = { .version = CAMSS_8x53, + .legacy_phy = true, .icc_res = icc_res_8x53, .icc_path_num = ARRAY_SIZE(icc_res_8x53), .csiphy_res = csiphy_res_8x96, @@ -5544,6 +6404,7 @@ static const struct camss_resources msm8953_resources = { static const struct camss_resources msm8996_resources = { .version = CAMSS_8x96, + .legacy_phy = true, .csiphy_res = csiphy_res_8x96, .csid_res = csid_res_8x96, .ispif_res = &ispif_res_8x96, @@ -5555,6 +6416,20 @@ static const struct camss_resources msm8996_resources = { static const struct camss_resources qcm2290_resources = { .version = CAMSS_2290, + .legacy_phy = true, + .csiphy_res = csiphy_res_2290, + .csid_res = csid_res_2290, + .vfe_res = vfe_res_2290, + .icc_res = icc_res_2290, + .icc_path_num = ARRAY_SIZE(icc_res_2290), + .csiphy_num = ARRAY_SIZE(csiphy_res_2290), + .csid_num = ARRAY_SIZE(csid_res_2290), + .vfe_num = ARRAY_SIZE(vfe_res_2290), +}; + +static const struct camss_resources qcm2390_resources = { + .version = CAMSS_2390, + .legacy_phy = true, .csiphy_res = csiphy_res_2290, .csid_res = csid_res_2290, .vfe_res = vfe_res_2290, @@ -5568,6 +6443,7 @@ static const struct camss_resources qcm2290_resources = { static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8300, .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, @@ -5584,6 +6460,7 @@ static const struct camss_resources qcs8300_resources = { static const struct camss_resources sa8775p_resources = { .version = CAMSS_8775P, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8775p, .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, @@ -5599,6 +6476,7 @@ static const struct camss_resources sa8775p_resources = { static const struct camss_resources sdm660_resources = { .version = CAMSS_660, + .legacy_phy = true, .csiphy_res = csiphy_res_660, .csid_res = csid_res_660, .ispif_res = &ispif_res_660, @@ -5610,6 +6488,7 @@ static const struct camss_resources sdm660_resources = { static const struct camss_resources sdm670_resources = { .version = CAMSS_845, + .legacy_phy = true, .csiphy_res = csiphy_res_670, .csid_res = csid_res_670, .vfe_res = vfe_res_670, @@ -5621,6 +6500,7 @@ static const struct camss_resources sdm670_resources = { static const struct camss_resources sdm845_resources = { .version = CAMSS_845, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_845, .csid_res = csid_res_845, .vfe_res = vfe_res_845, @@ -5632,6 +6512,7 @@ static const struct camss_resources sdm845_resources = { static const struct camss_resources sm6150_resources = { .version = CAMSS_6150, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sm6150, .csid_res = csid_res_sm6150, .vfe_res = vfe_res_sm6150, @@ -5658,6 +6539,7 @@ static const struct camss_resources sm6350_resources = { static const struct camss_resources sm8250_resources = { .version = CAMSS_8250, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8250, .csid_res = csid_res_8250, .vfe_res = vfe_res_8250, @@ -5671,6 +6553,7 @@ static const struct camss_resources sm8250_resources = { static const struct camss_resources sc8280xp_resources = { .version = CAMSS_8280XP, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sc8280xp, .csid_res = csid_res_sc8280xp, .ispif_res = NULL, @@ -5685,6 +6568,7 @@ static const struct camss_resources sc8280xp_resources = { static const struct camss_resources sc7280_resources = { .version = CAMSS_7280, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_7280, .csid_res = csid_res_7280, .vfe_res = vfe_res_7280, @@ -5698,6 +6582,7 @@ static const struct camss_resources sc7280_resources = { static const struct camss_resources sm8550_resources = { .version = CAMSS_8550, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8550, .csid_res = csid_res_8550, .vfe_res = vfe_res_8550, @@ -5712,6 +6597,7 @@ static const struct camss_resources sm8550_resources = { static const struct camss_resources sm8650_resources = { .version = CAMSS_8650, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sm8650, .csid_res = csid_res_sm8650, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5723,6 +6609,19 @@ static const struct camss_resources sm8650_resources = { .vfe_num = ARRAY_SIZE(vfe_res_sm8650), }; +static const struct camss_resources sm8750_resources = { + .version = CAMSS_8750, + .pd_name = "top", + .csiphy_res = csiphy_res_8750, + .csid_res = csid_res_8750, + .vfe_res = vfe_res_8750, + .icc_res = icc_res_sm8750, + .csiphy_num = ARRAY_SIZE(csiphy_res_8750), + .csid_num = ARRAY_SIZE(csid_res_8750), + .vfe_num = ARRAY_SIZE(vfe_res_8750), + .icc_path_num = ARRAY_SIZE(icc_res_sm8750), +}; + static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", @@ -5739,7 +6638,42 @@ static const struct camss_resources x1e80100_resources = { .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), }; +static const struct camss_resources x1p42100_resources = { + .version = CAMSS_X1P42100, + .pd_name = "top", + .csiphy_res = csiphy_res_x1p42100, + .tpg_res = tpg_res_x1e80100, + .csid_res = csid_res_x1e80100, + .vfe_res = vfe_res_x1p42100, + .csid_wrapper_res = &csid_wrapper_res_x1e80100, + .icc_res = icc_res_x1e80100, + .icc_path_num = ARRAY_SIZE(icc_res_x1e80100), + .csiphy_num = ARRAY_SIZE(csiphy_res_x1p42100), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_x1e80100), + .vfe_num = ARRAY_SIZE(vfe_res_x1p42100), +}; + +static const struct camss_resources glymur_resources = { + .version = CAMSS_GLYMUR, + .pd_name = "top", + .legacy_phy = true, + .csiphy_res = csiphy_res_glymur, + .tpg_res = tpg_res_x1e80100, + .csid_res = csid_res_x1e80100, + .vfe_res = vfe_res_x1e80100, + .csid_wrapper_res = &csid_wrapper_res_x1e80100, + .icc_res = icc_res_x1e80100, + .icc_path_num = ARRAY_SIZE(icc_res_x1e80100), + .csiphy_num = ARRAY_SIZE(csiphy_res_glymur), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_x1e80100), + .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), +}; + static const struct of_device_id camss_dt_match[] = { + { .compatible = "qcom,glymur-camss", .data = &glymur_resources }, + { .compatible = "qcom,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, @@ -5752,12 +6686,15 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, { .compatible = "qcom,sdm670-camss", .data = &sdm670_resources }, { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources }, + { .compatible = "qcom,shikra-camss", .data = &qcm2390_resources }, { .compatible = "qcom,sm6150-camss", .data = &sm6150_resources }, { .compatible = "qcom,sm6350-camss", .data = &sm6350_resources }, { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, { .compatible = "qcom,sm8550-camss", .data = &sm8550_resources }, { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, + { .compatible = "qcom,sm8750-camss", .data = &sm8750_resources }, { .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources }, + { .compatible = "qcom,x1p42100-camss", .data = &x1p42100_resources }, { } }; diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 93d691c8ac63b..91438769419e5 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -82,6 +82,7 @@ enum pm_domain { enum camss_version { CAMSS_660, CAMSS_2290, + CAMSS_2390, CAMSS_6150, CAMSS_6350, CAMSS_7280, @@ -95,8 +96,12 @@ enum camss_version { CAMSS_845, CAMSS_8550, CAMSS_8650, + CAMSS_8750, CAMSS_8775P, + CAMSS_GLYMUR, + CAMSS_KAANAPALI, CAMSS_X1E80100, + CAMSS_X1P42100, }; enum icc_count { @@ -107,6 +112,7 @@ enum icc_count { struct camss_resources { enum camss_version version; const char *pd_name; + const bool legacy_phy; const struct camss_subdev_resources *csiphy_res; const struct camss_subdev_resources *tpg_res; const struct camss_subdev_resources *csid_res; diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 48e415cbc4390..4a70e124e75f6 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -12,8 +12,10 @@ qcom-iris-objs += iris_buffer.o \ iris_hfi_gen2_packet.o \ iris_hfi_gen2_response.o \ iris_hfi_queue.o \ + iris_platform_glymur.o \ iris_platform_vpu2.o \ iris_platform_vpu3x.o \ + iris_platform_vpu_ar50lt.o \ iris_power.o \ iris_probe.o \ iris_resources.o \ @@ -26,6 +28,7 @@ qcom-iris-objs += iris_buffer.o \ iris_vpu2.o \ iris_vpu3x.o \ iris_vpu4x.o \ + iris_vpu_ar50lt.o \ iris_vpu_buffer.o \ iris_vpu_common.o \ diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 246ad0abbac35..249c9f1d0d5da 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -529,7 +529,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, enum iris_buffer_type buffer_type, u32 index) { struct iris_buffers *buffers = &inst->buffers[buffer_type]; - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer_type); struct iris_buffer *buffer; if (!buffers->size) @@ -545,7 +545,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, buffer->buffer_size = buffers->size; buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING; - buffer->kvaddr = dma_alloc_attrs(core->dev, buffer->buffer_size, + buffer->kvaddr = dma_alloc_attrs(dev, buffer->buffer_size, &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs); if (!buffer->kvaddr) { kfree(buffer); @@ -682,10 +682,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer) { - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer->type); list_del(&buffer->list); - dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr, + dma_free_attrs(dev, buffer->buffer_size, buffer->kvaddr, buffer->device_addr, buffer->dma_attrs); kfree(buffer); diff --git a/drivers/media/platform/qcom/iris/iris_common.c b/drivers/media/platform/qcom/iris/iris_common.c index 25836561bcf3e..dade0273717a2 100644 --- a/drivers/media/platform/qcom/iris/iris_common.c +++ b/drivers/media/platform/qcom/iris/iris_common.c @@ -46,6 +46,16 @@ void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) inst->metadata_idx++; } +int iris_set_core_id(struct iris_inst *inst) +{ + const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; + + if (!inst->core->iris_platform_data->dual_core) + return 0; + + return hfi_ops->session_set_core_id(inst, inst->core_id); +} + int iris_process_streamon_input(struct iris_inst *inst) { const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; diff --git a/drivers/media/platform/qcom/iris/iris_common.h b/drivers/media/platform/qcom/iris/iris_common.h index b2a27b781c9ac..34e32c60f7687 100644 --- a/drivers/media/platform/qcom/iris/iris_common.h +++ b/drivers/media/platform/qcom/iris/iris_common.h @@ -11,6 +11,7 @@ struct iris_buffer; int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf); void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_set_core_id(struct iris_inst *inst); int iris_process_streamon_input(struct iris_inst *inst); int iris_process_streamon_output(struct iris_inst *inst); int iris_session_streamoff(struct iris_inst *inst, u32 plane); diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index 52bf56e517f91..b65ede5bd693a 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -18,6 +18,7 @@ void iris_core_deinit(struct iris_core *core) if (core->state != IRIS_CORE_DEINIT) { iris_fw_unload(core); iris_vpu_power_off(core); + iris_fw_deinit(core); iris_hfi_queues_deinit(core); core->state = IRIS_CORE_DEINIT; } @@ -45,6 +46,7 @@ static int iris_wait_for_system_response(struct iris_core *core) int iris_core_init(struct iris_core *core) { + const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops; int ret; mutex_lock(&core->lock); @@ -66,10 +68,14 @@ int iris_core_init(struct iris_core *core) if (ret) goto error_queue_deinit; - ret = iris_fw_load(core); + ret = iris_fw_init(core); if (ret) goto error_power_off; + ret = iris_fw_load(core); + if (ret) + goto error_firmware_deinit; + ret = iris_vpu_boot_firmware(core); if (ret) goto error_unload_fw; @@ -78,6 +84,9 @@ int iris_core_init(struct iris_core *core) if (ret) goto error_unload_fw; + if (vpu_ops->disable_arp) + vpu_ops->disable_arp(core); + core->iris_firmware_data->init_hfi_ops(core); ret = iris_hfi_core_init(core); @@ -90,6 +99,8 @@ int iris_core_init(struct iris_core *core) error_unload_fw: iris_fw_unload(core); +error_firmware_deinit: + iris_fw_deinit(core); error_power_off: iris_vpu_power_off(core); error_queue_deinit: diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 24da60448cf24..1bc001df0cec4 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -32,10 +32,18 @@ enum domain_type { struct qcom_ubwc_cfg_data; +enum iris_vcodec_core_id { + IRIS_VCODEC0 = 1, + IRIS_VCODEC1, +}; + /** * struct iris_core - holds core parameters valid for all instances * * @dev: reference to device structure + * @dev_np: reference to non-pixel context bank device structure + * @dev_p: reference to pixel context bank device structure + * @dev_bs: reference to bitstream context bank device structure * @reg_base: IO memory base address * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure @@ -81,11 +89,19 @@ struct qcom_ubwc_cfg_data; struct iris_core { struct device *dev; + struct device *dev_np; + struct device *dev_p; + struct device *dev_bs; void __iomem *reg_base; int irq; struct v4l2_device v4l2_dev; struct video_device *vdev_dec; struct video_device *vdev_enc; + struct video_firmware { + struct device *dev; + struct qcom_scm_pas_context *ctx; + struct iommu_domain *iommu_domain; + } fw; const struct v4l2_file_operations *iris_v4l2_file_ops; const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_dec; const struct v4l2_ioctl_ops *iris_v4l2_ioctl_ops_enc; diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 10e33b8a73f60..33a34573391a4 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -534,6 +534,9 @@ int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) u32 work_route = inst->fw_caps[PIPE].value; u32 hfi_id = inst->fw_caps[cap_id].hfi_id; + if (!hfi_id) + return 0; + return hfi_ops->session_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE, iris_get_port_info(inst, cap_id), diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index 1a476146d7580..64c5ad4b4fc21 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -3,10 +3,15 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include +#include +#include #include +#include #include +#include #include #include "iris_core.h" @@ -16,20 +21,95 @@ #define MAX_FIRMWARE_NAME_SIZE 128 -static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) +/* Detect Gen2 firmware by scanning the blob for: + * QC_IMAGE_VERSION_STRING= + * and then checking: + * - version starts with "vfw", OR + * - version matches "video-firmware.N.M" with N >= 2 + */ + +static bool iris_detect_gen2_from_fwdata(const u8 *data, size_t size) +{ + const char *marker = "QC_IMAGE_VERSION_STRING="; + const size_t mlen = strlen(marker); + int major = 0, minor = 0; + char version_buf[64]; + size_t max; + + max = (size > mlen) ? size - mlen : 0; + for (size_t i = 0; i < max; i++) { + if (!memcmp(data + i, marker, mlen)) { + const char *found = (const char *)(data + i + mlen); + + strscpy(version_buf, found, sizeof(version_buf)); + if (!strncmp(version_buf, "vfw", 3)) + return true; + if (sscanf(version_buf, "video-firmware.%d.%d", &major, &minor) == 2 && + major >= 2) + return true; + break; + } + } + + return false; +} + +static const struct firmware *iris_detect_firmware(struct iris_core *core, + const char **fw_name) +{ + const struct firmware *firmware; + bool has_both_gens; + int ret; + + *fw_name = NULL; + if (core->iris_platform_data->firmware_desc_gen2) + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen2; + else if (core->iris_platform_data->firmware_desc_gen1) + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen1; + else + return ERR_PTR(-EINVAL); + + has_both_gens = core->iris_platform_data->firmware_desc_gen2 && + core->iris_platform_data->firmware_desc_gen1; + + ret = of_property_read_string_index(dev_of_node(core->dev), "firmware-name", 0, fw_name); + if (ret) { + *fw_name = core->iris_firmware_desc->fwname; + ret = request_firmware(&firmware, *fw_name, core->dev); + if (ret && has_both_gens) { + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen1; + *fw_name = core->iris_firmware_desc->fwname; + ret = request_firmware(&firmware, *fw_name, core->dev); + } + + return ret ? ERR_PTR(ret) : firmware; + } + + ret = request_firmware(&firmware, *fw_name, core->dev); + if (ret) + return ERR_PTR(ret); + + if (has_both_gens && + !iris_detect_gen2_from_fwdata((const u8 *)firmware->data, firmware->size)) { + dev_info(core->dev, "Gen1 FW detected in %s\n", *fw_name); + core->iris_firmware_desc = core->iris_platform_data->firmware_desc_gen1; + } + + return firmware; +} + +static int iris_load_fw_to_memory(struct iris_core *core) { const struct firmware *firmware = NULL; + struct qcom_scm_pas_context *ctx; struct device *dev = core->dev; struct resource res; phys_addr_t mem_phys; + const char *fw_name; size_t res_size; ssize_t fw_size; - void *mem_virt; int ret; - if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) - return -EINVAL; - ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); if (ret) return ret; @@ -37,9 +117,19 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) mem_phys = res.start; res_size = resource_size(&res); - ret = request_firmware(&firmware, fw_name, dev); - if (ret) - return ret; + dev = core->fw.dev ? : core->dev; + + ctx = devm_qcom_scm_pas_context_alloc(dev, IRIS_PAS_ID, mem_phys, res_size); + if (!ctx) + return -ENOMEM; + + ctx->use_tzmem = core->fw.dev; + + firmware = iris_detect_firmware(core, &fw_name); + if (IS_ERR(firmware)) + return PTR_ERR(firmware); + + core->iris_firmware_data = core->iris_firmware_desc->firmware_data; fw_size = qcom_mdt_get_size(firmware); if (fw_size < 0 || res_size < (size_t)fw_size) { @@ -47,16 +137,28 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) goto err_release_fw; } - mem_virt = memremap(mem_phys, res_size, MEMREMAP_WC); - if (!mem_virt) { - ret = -ENOMEM; + ret = qcom_mdt_pas_load(ctx, firmware, fw_name, NULL); + qcom_scm_pas_metadata_release(ctx); + if (ret) goto err_release_fw; + + if (core->fw.iommu_domain) { + ret = iommu_map(core->fw.iommu_domain, 0, mem_phys, res_size, + IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) + goto err_release_fw; } - ret = qcom_mdt_load(dev, firmware, fw_name, - IRIS_PAS_ID, mem_virt, mem_phys, res_size, NULL); + ret = qcom_scm_pas_prepare_and_auth_reset(ctx); + if (ret) + goto err_iommu_unmap; + + core->fw.ctx = ctx; + + return ret; - memunmap(mem_virt); +err_iommu_unmap: + iommu_unmap(core->fw.iommu_domain, 0, res_size); err_release_fw: release_firmware(firmware); @@ -66,23 +168,11 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) int iris_fw_load(struct iris_core *core) { const struct tz_cp_config *cp_config; - const char *fwpath = NULL; int i, ret; - ret = of_property_read_string_index(core->dev->of_node, "firmware-name", 0, - &fwpath); - if (ret) - fwpath = core->iris_firmware_desc->fwname; - - ret = iris_load_fw_to_memory(core, fwpath); + ret = iris_load_fw_to_memory(core); if (ret) { - dev_err(core->dev, "firmware download failed\n"); - return -ENOMEM; - } - - ret = qcom_scm_pas_auth_and_reset(IRIS_PAS_ID); - if (ret) { - dev_err(core->dev, "auth and reset failed: %d\n", ret); + dev_err(core->dev, "firmware download failed %d\n", ret); return ret; } @@ -99,15 +189,96 @@ int iris_fw_load(struct iris_core *core) } } - return ret; + return 0; } int iris_fw_unload(struct iris_core *core) { - return qcom_scm_pas_shutdown(IRIS_PAS_ID); + struct qcom_scm_pas_context *ctx = core->fw.ctx; + int ret; + + if (!ctx) + return -EINVAL; + + ret = qcom_scm_pas_shutdown(ctx->pas_id); + if (core->fw.iommu_domain) + iommu_unmap(core->fw.iommu_domain, 0, ctx->mem_size); + + core->fw.ctx = NULL; + return ret; } int iris_set_hw_state(struct iris_core *core, bool resume) { return qcom_scm_set_remote_state(resume, 0); } + +int iris_fw_init(struct iris_core *core) +{ + struct platform_device_info info; + struct iommu_domain *iommu_dom; + struct platform_device *pdev; + struct device_node *np; + int ret; + + np = of_get_child_by_name(core->dev->of_node, "video-firmware"); + if (!np) + return 0; + + memset(&info, 0, sizeof(info)); + info.fwnode = &np->fwnode; + info.parent = core->dev; + info.name = np->name; + info.dma_mask = DMA_BIT_MASK(32); + + pdev = platform_device_register_full(&info); + if (IS_ERR(pdev)) { + of_node_put(np); + return PTR_ERR(pdev); + } + + pdev->dev.of_node = np; + + ret = of_dma_configure(&pdev->dev, np, true); + if (ret) + goto err_unregister; + + core->fw.dev = &pdev->dev; + + iommu_dom = iommu_get_domain_for_dev(core->fw.dev); + if (!iommu_dom) { + ret = -EINVAL; + goto err_unset_fw_dev; + } + + ret = iommu_attach_device(iommu_dom, core->fw.dev); + if (ret) + goto err_unset_fw_dev; + + core->fw.iommu_domain = iommu_dom; + + of_node_put(np); + + return 0; + +err_unset_fw_dev: + core->fw.dev = NULL; +err_unregister: + platform_device_unregister(pdev); + of_node_put(np); + return ret; +} + +void iris_fw_deinit(struct iris_core *core) +{ + if (!core->fw.dev) + return; + + if (core->fw.iommu_domain) { + iommu_detach_device(core->fw.iommu_domain, core->fw.dev); + core->fw.iommu_domain = NULL; + } + + platform_device_unregister(to_platform_device(core->fw.dev)); + core->fw.dev = NULL; +} diff --git a/drivers/media/platform/qcom/iris/iris_firmware.h b/drivers/media/platform/qcom/iris/iris_firmware.h index e833ecd348871..adde461099667 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.h +++ b/drivers/media/platform/qcom/iris/iris_firmware.h @@ -11,5 +11,7 @@ struct iris_core; int iris_fw_load(struct iris_core *core); int iris_fw_unload(struct iris_core *core); int iris_set_hw_state(struct iris_core *core, bool resume); +int iris_fw_init(struct iris_core *core); +void iris_fw_deinit(struct iris_core *core); #endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c index 8769ec61f1176..8f04f3793d9af 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c @@ -144,6 +144,7 @@ int iris_hfi_pm_suspend(struct iris_core *core) int iris_hfi_pm_resume(struct iris_core *core) { + const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops; const struct iris_hfi_sys_ops *ops = core->hfi_sys_ops; int ret; @@ -163,6 +164,9 @@ int iris_hfi_pm_resume(struct iris_core *core) if (ret) goto err_suspend_hw; + if (vpu_ops->disable_arp) + vpu_ops->disable_arp(core); + ret = ops->sys_interframe_powercollapse(core); if (ret) goto err_suspend_hw; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index a27447eb25199..5841e5f9c1228 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -121,6 +121,7 @@ struct iris_hfi_session_ops { int (*session_set_property)(struct iris_inst *inst, u32 packet_type, u32 flag, u32 plane, u32 payload_type, void *payload, u32 payload_size); + int (*session_get_property)(struct iris_inst *inst, u32 packet_type); int (*session_open)(struct iris_inst *inst); int (*session_start)(struct iris_inst *inst, u32 plane); int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buffer); @@ -131,6 +132,7 @@ struct iris_hfi_session_ops { int (*session_drain)(struct iris_inst *inst, u32 plane); int (*session_resume_drain)(struct iris_inst *inst, u32 plane); int (*session_close)(struct iris_inst *inst); + int (*session_set_core_id)(struct iris_inst *inst, u32 core_id); }; struct hfi_subscription_params { diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c index ca1545d28b531..a8819470f7033 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c @@ -13,7 +13,7 @@ #define BITRATE_MAX 160000000 #define BITRATE_STEP 100 -static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = { +static const struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = { { .cap_id = PIPE, /* .max, .min and .value are set via platform data */ @@ -443,3 +443,230 @@ const struct iris_firmware_data iris_hfi_gen1_data = { .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl, .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl), }; + +static const struct platform_inst_fw_cap iris_inst_fw_cap_gen1_ar50lt_dec[] = { + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, + .set = iris_set_stage, + }, +}; + +static const struct platform_inst_fw_cap inst_fw_cap_gen1_ar50lt_enc[] = { + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, + .set = iris_set_stage, + }, + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile_level_gen1, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen1, + }, + { + .cap_id = BITRATE, + .min = BITRATE_MIN, + .max = BITRATE_MAX_AR50LT, + .step_or_mask = BITRATE_STEP, + .value = BITRATE_DEFAULT_AR50LT, + .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate_gen1, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen1, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = (1 << 16) - 1, + .step_or_mask = 1, + .value = 30, + .set = iris_set_u32 + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen1, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP_HEVC, + .step_or_mask = 1, + .value = MAX_QP_HEVC, + .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_qp_range, + }, +}; + +static const u32 iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl[] = { + BUF_BIN, + BUF_SCRATCH_1, +}; + +const struct iris_firmware_data iris_hfi_gen1_ar50lt_data = { + .init_hfi_ops = &iris_hfi_gen1_sys_ops_init, + + .inst_fw_caps_dec = iris_inst_fw_cap_gen1_ar50lt_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(iris_inst_fw_cap_gen1_ar50lt_dec), + .inst_fw_caps_enc = inst_fw_cap_gen1_ar50lt_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_gen1_ar50lt_enc), + + .dec_input_config_params_default = + sm8250_vdec_input_config_param_default, + .dec_input_config_params_default_size = + ARRAY_SIZE(sm8250_vdec_input_config_param_default), + .enc_input_config_params = sm8250_venc_input_config_param, + .enc_input_config_params_size = + ARRAY_SIZE(sm8250_venc_input_config_param), + + .dec_ip_int_buf_tbl = iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8250_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_op_int_buf_tbl), + + .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl, + .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl), +}; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 7674b47ad6c49..99e82e5510abe 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -1117,10 +1117,31 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p return 0; } +static int iris_hfi_gen1_session_get_property(struct iris_inst *inst, u32 packet_type) +{ + struct hfi_session_get_property_pkt pkt; + int ret; + + pkt.shdr.hdr.size = sizeof(pkt); + pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_GET_PROPERTY; + pkt.shdr.session_id = inst->session_id; + pkt.num_properties = 1; + pkt.data = packet_type; + + reinit_completion(&inst->completion); + + ret = iris_hfi_queue_cmd_write(inst->core, &pkt, pkt.shdr.hdr.size); + if (ret) + return ret; + + return iris_wait_for_session_response(inst, false); +} + static const struct iris_hfi_session_ops iris_hfi_gen1_session_ops = { .session_open = iris_hfi_gen1_session_open, .session_set_config_params = iris_hfi_gen1_session_set_config_params, .session_set_property = iris_hfi_gen1_session_set_property, + .session_get_property = iris_hfi_gen1_session_get_property, .session_start = iris_hfi_gen1_session_start, .session_queue_buf = iris_hfi_gen1_session_queue_buffer, .session_release_buf = iris_hfi_gen1_session_unset_buffers, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h index 0e4dee1923846..bb495a1d2623e 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -35,6 +35,7 @@ #define HFI_CMD_SESSION_EMPTY_BUFFER 0x211004 #define HFI_CMD_SESSION_FILL_BUFFER 0x211005 #define HFI_CMD_SESSION_FLUSH 0x211008 +#define HFI_CMD_SESSION_GET_PROPERTY 0x211009 #define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b #define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c #define HFI_CMD_SESSION_CONTINUE 0x21100d @@ -113,6 +114,7 @@ #define HFI_MSG_SESSION_FLUSH 0x221006 #define HFI_MSG_SESSION_EMPTY_BUFFER 0x221007 #define HFI_MSG_SESSION_FILL_BUFFER 0x221008 +#define HFI_MSG_SESSION_PROPERTY_INFO 0x221009 #define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a #define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c @@ -205,6 +207,12 @@ struct hfi_session_set_property_pkt { u32 data[]; }; +struct hfi_session_get_property_pkt { + struct hfi_session_hdr_pkt shdr; + u32 num_properties; + u32 data; +}; + struct hfi_sys_pc_prep_pkt { struct hfi_pkt_hdr hdr; }; @@ -574,6 +582,13 @@ struct hfi_msg_session_fbd_uncompressed_plane0_pkt { u32 data[]; }; +struct hfi_msg_session_property_info_pkt { + struct hfi_session_hdr_pkt shdr; + u32 num_properties; + u32 property; + u8 data[]; +}; + struct hfi_msg_session_release_buffers_done_pkt { struct hfi_msg_session_hdr_pkt shdr; u32 num_buffers; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c index bfd7495bf44f0..ee996eb1f41fa 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -533,6 +533,78 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet) dev_err(core->dev, "error in ftb done\n"); } +static enum iris_buffer_type iris_hfi_gen1_buf_type(struct iris_inst *inst, u32 type) +{ + switch (type) { + case HFI_BUFFER_INPUT: + return BUF_INPUT; + case HFI_BUFFER_OUTPUT: + if (iris_split_mode_enabled(inst)) + return BUF_DPB; + return BUF_OUTPUT; + case HFI_BUFFER_OUTPUT2: + if (iris_split_mode_enabled(inst)) + return BUF_OUTPUT; + return BUF_DPB; + case HFI_BUFFER_INTERNAL_PERSIST_1: + return BUF_PERSIST; + case HFI_BUFFER_INTERNAL_SCRATCH: + return BUF_BIN; + case HFI_BUFFER_INTERNAL_SCRATCH_1: + return BUF_SCRATCH_1; + case HFI_BUFFER_INTERNAL_SCRATCH_2: + return BUF_SCRATCH_2; + case HFI_BUFFER_INTERNAL_PERSIST: + return BUF_ARP; + default: + return -EINVAL; + } +} + +static void iris_hfi_gen1_session_buffer_requirements(struct iris_inst *inst, + void *data, size_t size) +{ + struct hfi_buffer_requirements *req; + + if (!size || size % sizeof(*req)) + return; + + for (req = data; size; size -= sizeof(*req), req++) { + enum iris_buffer_type type = iris_hfi_gen1_buf_type(inst, req->type); + + if (type == -EINVAL) + continue; + + inst->buffers[type].min_count = req->hold_count; + inst->buffers[type].size = req->size; + + if (type == BUF_OUTPUT) + inst->fw_min_count = req->count_actual; + } +} + +static void iris_hfi_gen1_session_property_info(struct iris_inst *inst, void *packet) +{ + struct hfi_msg_session_property_info_pkt *pkt = packet; + + if (!pkt->num_properties) { + dev_err(inst->core->dev, "error, no properties\n"); + goto out; + } + + switch (pkt->property) { + case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: + iris_hfi_gen1_session_buffer_requirements(inst, pkt->data, + pkt->shdr.hdr.size - sizeof(*pkt)); + break; + default: + dev_warn(inst->core->dev, "unknown property id: %x\n", pkt->property); + } + +out: + complete(&inst->completion); +} + struct iris_hfi_gen1_response_pkt_info { u32 pkt; u32 pkt_sz; @@ -591,6 +663,10 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = { .pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), }, + { + .pkt = HFI_MSG_SESSION_PROPERTY_INFO, + .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt), + }, }; static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response) @@ -652,6 +728,8 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response iris_hfi_gen1_session_etb_done(inst, hdr); } else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) { iris_hfi_gen1_session_ftb_done(inst, hdr); + } else if (hdr->pkt_type == HFI_MSG_SESSION_PROPERTY_INFO) { + iris_hfi_gen1_session_property_info(inst, hdr); } else { struct hfi_msg_session_hdr_pkt *shdr; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c index acc0ed8adda1a..f89245269e8c1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c @@ -1118,3 +1118,616 @@ const struct iris_firmware_data iris_hfi_gen2_data = { .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), }; + +static const struct platform_inst_fw_cap inst_fw_cap_gen2_ar50lt_dec[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = PROFILE_VP9, + .min = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .max = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0), + .value = V4L2_MPEG_VIDEO_VP9_PROFILE_0, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = LEVEL_VP9, + .min = V4L2_MPEG_VIDEO_VP9_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = TIER, + .min = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH), + .value = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, + .hfi_id = HFI_PROP_TIER, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_u32_enum, + }, + { + .cap_id = INPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .set = iris_set_stage, + }, + { + .cap_id = POC, + .min = 0, + .max = 2, + .step_or_mask = 1, + .value = 1, + .hfi_id = HFI_PROP_PIC_ORDER_CNT_TYPE, + }, + { + .cap_id = CODED_FRAMES, + .min = CODED_FRAMES_PROGRESSIVE, + .max = CODED_FRAMES_PROGRESSIVE, + .step_or_mask = 0, + .value = CODED_FRAMES_PROGRESSIVE, + .hfi_id = HFI_PROP_CODED_FRAMES, + }, + { + .cap_id = BIT_DEPTH, + .min = BIT_DEPTH_8, + .max = BIT_DEPTH_8, + .step_or_mask = 1, + .value = BIT_DEPTH_8, + .hfi_id = HFI_PROP_LUMA_CHROMA_BIT_DEPTH, + }, + { + .cap_id = RAP_FRAME, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + .hfi_id = HFI_PROP_DEC_START_FROM_RAP_FRAME, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, +}; + +static const struct platform_inst_fw_cap inst_fw_cap_gen2_ar50lt_enc[] = { + { + .cap_id = PROFILE_H264, + .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, + .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH), + .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = PROFILE_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .hfi_id = HFI_PROP_PROFILE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_profile, + }, + { + .cap_id = LEVEL_H264, + .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, + .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2), + .value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = LEVEL_HEVC, + .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, + .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | + BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1), + .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1, + .hfi_id = HFI_PROP_LEVEL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_level, + }, + { + .cap_id = STAGE, + .min = STAGE_1, + .max = STAGE_2, + .step_or_mask = 1, + .value = STAGE_2, + .hfi_id = HFI_PROP_STAGE, + .set = iris_set_stage, + }, + { + .cap_id = HEADER_MODE, + .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) | + BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME), + .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + .hfi_id = HFI_PROP_SEQ_HEADER_MODE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_header_mode_gen2, + }, + { + .cap_id = PREPEND_SPSPPS_TO_IDR, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 0, + }, + { + .cap_id = BITRATE, + .min = 1, + .max = BITRATE_MAX_AR50LT, + .step_or_mask = 1, + .value = BITRATE_DEFAULT_AR50LT, + .hfi_id = HFI_PROP_TOTAL_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_bitrate_gen2, + }, + { + .cap_id = BITRATE_PEAK, + .min = 1, + .max = BITRATE_MAX_AR50LT, + .step_or_mask = 1, + .value = BITRATE_DEFAULT_AR50LT, + .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_peak_bitrate, + }, + { + .cap_id = BITRATE_MODE, + .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | + BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR), + .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .hfi_id = HFI_PROP_RATE_CONTROL, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_bitrate_mode_gen2, + }, + { + .cap_id = FRAME_SKIP_MODE, + .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) | + BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT), + .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = FRAME_RC_ENABLE, + .min = 0, + .max = 1, + .step_or_mask = 1, + .value = 1, + }, + { + .cap_id = GOP_SIZE, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 2 * DEFAULT_FPS - 1, + .hfi_id = HFI_PROP_MAX_GOP_FRAMES, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_u32, + }, + { + .cap_id = ENTROPY_MODE, + .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC, + .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) | + BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC), + .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, + .hfi_id = HFI_PROP_CABAC_SESSION, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + .set = iris_set_entropy_mode_gen2, + }, + { + .cap_id = MIN_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MIN_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + .hfi_id = HFI_PROP_MIN_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_min_qp, + }, + { + .cap_id = MAX_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = MAX_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + .hfi_id = HFI_PROP_MAX_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_max_qp, + }, + { + .cap_id = I_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = I_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = P_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = P_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = B_FRAME_MIN_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = B_FRAME_MIN_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MIN_QP_8BIT_AR50LT, + }, + { + .cap_id = I_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = P_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = B_FRAME_MAX_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = MAX_QP, + }, + { + .cap_id = I_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = I_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = P_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_H264, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = B_FRAME_QP_HEVC, + .min = MIN_QP_8BIT_AR50LT, + .max = MAX_QP, + .step_or_mask = 1, + .value = DEFAULT_QP, + .hfi_id = HFI_PROP_QP_PACKED, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_frame_qp, + }, + { + .cap_id = INPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_INPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = OUTPUT_BUF_HOST_MAX_COUNT, + .min = DEFAULT_MAX_HOST_BUF_COUNT, + .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT, + .step_or_mask = 1, + .value = DEFAULT_MAX_HOST_BUF_COUNT, + .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT, + .flags = CAP_FLAG_OUTPUT_PORT, + .set = iris_set_u32, + }, + { + .cap_id = IR_TYPE, + .min = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, + .max = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, + .step_or_mask = BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM), + .value = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, + }, + { + .cap_id = IR_PERIOD, + .min = 0, + .max = INT_MAX, + .step_or_mask = 1, + .value = 0, + .flags = CAP_FLAG_OUTPUT_PORT | + CAP_FLAG_DYNAMIC_ALLOWED, + .set = iris_set_ir_period_gen2, + }, +}; + +static const u32 iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl[] = { + BUF_BIN, + BUF_COMV, + BUF_NON_COMV, + BUF_LINE, +}; + +const struct iris_firmware_data iris_hfi_gen2_ar50lt_data = { + .init_hfi_ops = iris_hfi_gen2_sys_ops_init, + + .core_arch = VIDEO_ARCH_LX, + + .inst_fw_caps_dec = inst_fw_cap_gen2_ar50lt_dec, + .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_gen2_ar50lt_dec), + .inst_fw_caps_enc = inst_fw_cap_gen2_ar50lt_enc, + .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_gen2_ar50lt_enc), + .dec_input_config_params_default = + sm8550_vdec_input_config_params_default, + .dec_input_config_params_default_size = + ARRAY_SIZE(sm8550_vdec_input_config_params_default), + .dec_input_config_params_hevc = + sm8550_vdec_input_config_param_hevc, + .dec_input_config_params_hevc_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_hevc), + .dec_input_config_params_vp9 = + sm8550_vdec_input_config_param_vp9, + .dec_input_config_params_vp9_size = + ARRAY_SIZE(sm8550_vdec_input_config_param_vp9), + .dec_output_config_params = + sm8550_vdec_output_config_params, + .dec_output_config_params_size = + ARRAY_SIZE(sm8550_vdec_output_config_params), + .enc_input_config_params = + sm8550_venc_input_config_params, + .enc_input_config_params_size = + ARRAY_SIZE(sm8550_venc_input_config_params), + .enc_output_config_params = + sm8550_venc_output_config_params, + .enc_output_config_params_size = + ARRAY_SIZE(sm8550_venc_output_config_params), + .dec_input_prop = sm8550_vdec_subscribe_input_properties, + .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties), + .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc, + .dec_output_prop_avc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc), + .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc, + .dec_output_prop_hevc_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc), + .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9, + .dec_output_prop_vp9_size = + ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9), + .dec_ip_int_buf_tbl = iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl, + .dec_ip_int_buf_tbl_size = ARRAY_SIZE(iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl), + .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl, + .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl), + .enc_ip_int_buf_tbl = sm8550_enc_ip_int_buf_tbl, + .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_ip_int_buf_tbl), + .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl, + .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl), +}; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c index ca2954f8bd3ad..e73743a391e0f 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -1360,6 +1360,24 @@ static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i inst_hfi_gen2->packet->size); } +static int iris_hfi_gen2_set_core_id(struct iris_inst *inst, u32 core_id) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 payload = core_id; + + iris_hfi_gen2_packet_session_command(inst, + HFI_PROP_CORE_ID, + HFI_HOST_FLAGS_NONE, + HFI_PORT_NONE, + inst->session_id, + HFI_PAYLOAD_U32, + &payload, + sizeof(u32)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + static const struct iris_hfi_session_ops iris_hfi_gen2_session_ops = { .session_open = iris_hfi_gen2_session_open, .session_set_config_params = iris_hfi_gen2_session_set_config_params, @@ -1373,6 +1391,7 @@ static const struct iris_hfi_session_ops iris_hfi_gen2_session_ops = { .session_drain = iris_hfi_gen2_session_drain, .session_resume_drain = iris_hfi_gen2_session_resume_drain, .session_close = iris_hfi_gen2_session_close, + .session_set_core_id = iris_hfi_gen2_set_core_id, }; static struct iris_inst *iris_hfi_gen2_get_instance(void) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h index 776b21cd11b2c..2e374c2005ef4 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -56,6 +56,7 @@ #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 +#define HFI_PROP_CORE_ID 0x030001a9 enum hfi_rate_control { HFI_RC_VBR_CFR = 0x00000000, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c index 0d05dd2afc07d..6e04175eb904b 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c @@ -140,6 +140,9 @@ void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_heade &payload, sizeof(u32)); + if (!ubwc->ubwc_enc_version) + return; + payload = qcom_ubwc_macrotile_mode(ubwc) ? 8 : 4; iris_hfi_gen2_create_packet(hdr, HFI_PROP_UBWC_MAX_CHANNELS, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c index bf6db23b53e21..f465ff00a9ba3 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -245,25 +245,26 @@ static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q) int iris_hfi_queues_init(struct iris_core *core) { + struct device *dev = core->dev_np ? core->dev_np : core->dev; struct iris_hfi_queue_table_header *q_tbl_hdr; u32 queue_size; /* Iris hardware requires 4K queue alignment */ queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K); - core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size, + core->iface_q_table_vaddr = dma_alloc_attrs(dev, queue_size, &core->iface_q_table_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->iface_q_table_vaddr) { - dev_err(core->dev, "queues alloc and map failed\n"); + dev_err(dev, "queues alloc and map failed\n"); return -ENOMEM; } - core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE, + core->sfr_vaddr = dma_alloc_attrs(dev, SFR_SIZE, &core->sfr_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->sfr_vaddr) { - dev_err(core->dev, "sfr alloc and map failed\n"); - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + dev_err(dev, "sfr alloc and map failed\n"); + dma_free_attrs(dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); return -ENOMEM; } @@ -291,6 +292,7 @@ int iris_hfi_queues_init(struct iris_core *core) void iris_hfi_queues_deinit(struct iris_core *core) { + struct device *dev = core->dev_np ? core->dev_np : core->dev; u32 queue_size; if (!core->iface_q_table_vaddr) @@ -300,7 +302,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) iris_hfi_queue_deinit(&core->message_queue); iris_hfi_queue_deinit(&core->command_queue); - dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr, + dma_free_attrs(dev, SFR_SIZE, core->sfr_vaddr, core->sfr_daddr, DMA_ATTR_WRITE_COMBINE); core->sfr_vaddr = NULL; @@ -309,7 +311,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + dma_free_attrs(dev, queue_size, core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); core->iface_q_table_vaddr = NULL; diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index a770331d16757..585aa7c51fb0c 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -36,6 +36,7 @@ enum iris_fmt_type_cap { * * @list: used for attach an instance to the core * @core: pointer to core structure + * @core_id: specifies the hardware core on which the session runs * @session_id: id of current video session * @hfi_session_ops: iris HFI session ops * @ctx_q_lock: lock to serialize queues related ioctls @@ -83,6 +84,7 @@ enum iris_fmt_type_cap { struct iris_inst { struct list_head list; struct iris_core *core; + u32 core_id; u32 session_id; const struct iris_hfi_session_ops *hfi_session_ops; struct mutex ctx_q_lock;/* lock to serialize queues related ioctls */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index c9256f2323dc4..58651f0725b8a 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -38,6 +38,13 @@ struct iris_inst; #define MAX_HEVC_LAYER_HP_SLIDING_WINDOW 3 #define MAX_HEVC_VBR_LAYER_HP_SLIDING_WINDOW 5 #define MAX_HIER_CODING_LAYER_GEN1 6 +#define BITRATE_MAX_AR50LT 100000000 +#define BITRATE_DEFAULT_AR50LT 20000000 +#define MIN_QP_8BIT_AR50LT 0 + +#define VIDEO_REGION_SECURE_FW_REGION_ID 0 +#define VIDEO_REGION_VM0_SECURE_NP_ID 1 +#define VIDEO_REGION_VM0_NONSECURE_NP_ID 5 enum stage_type { STAGE_1 = 1, @@ -51,8 +58,12 @@ enum pipe_type { }; extern const struct iris_firmware_data iris_hfi_gen1_data; +extern const struct iris_firmware_data iris_hfi_gen1_ar50lt_data; extern const struct iris_firmware_data iris_hfi_gen2_data; +extern const struct iris_firmware_data iris_hfi_gen2_ar50lt_data; +extern const struct iris_platform_data glymur_data; +extern const struct iris_platform_data qcm2290_data; extern const struct iris_platform_data qcs8300_data; extern const struct iris_platform_data sc7280_data; extern const struct iris_platform_data sm8250_data; @@ -62,18 +73,22 @@ extern const struct iris_platform_data sm8750_data; extern const struct iris_platform_data x1p42100_data; enum platform_clk_type { - IRIS_AXI_CLK, /* AXI0 in case of platforms with multiple AXI clocks */ + IRIS_AXI_VCODEC_CLK, IRIS_CTRL_CLK, IRIS_AHB_CLK, - IRIS_HW_CLK, - IRIS_HW_AHB_CLK, - IRIS_AXI1_CLK, + IRIS_VCODEC_CLK, + IRIS_VCODEC_AHB_CLK, + IRIS_AXI_CTRL_CLK, IRIS_CTRL_FREERUN_CLK, - IRIS_HW_FREERUN_CLK, + IRIS_VCODEC_FREERUN_CLK, IRIS_BSE_HW_CLK, IRIS_VPP0_HW_CLK, IRIS_VPP1_HW_CLK, IRIS_APV_HW_CLK, + IRIS_THROTTLE_CLK, + IRIS_AXI_VCODEC1_CLK, + IRIS_VCODEC1_CLK, + IRIS_VCODEC1_FREERUN_CLK, }; struct platform_clk_data { @@ -230,10 +245,11 @@ struct icc_vote_data { enum platform_pm_domain_type { IRIS_CTRL_POWER_DOMAIN, - IRIS_HW_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, IRIS_VPP0_HW_POWER_DOMAIN, IRIS_VPP1_HW_POWER_DOMAIN, IRIS_APV_HW_POWER_DOMAIN, + IRIS_VCODEC1_POWER_DOMAIN, }; struct iris_firmware_data { @@ -288,20 +304,24 @@ struct iris_firmware_desc { const char *fwname; }; +struct platform_pd_data { + enum platform_pm_domain_type *pd_types; + const char **pd_names; + u32 pd_count; +}; + struct iris_platform_data { - /* - * XXX: replace with gen1 / gen2 pointers once we have platforms - * supporting both firmware kinds. - */ - const struct iris_firmware_desc *firmware_desc; + const struct iris_firmware_desc *firmware_desc_gen1, *firmware_desc_gen2; const struct vpu_ops *vpu_ops; + + int (*init_cb_devs)(struct iris_core *core); + void (*deinit_cb_devs)(struct iris_core *core); const struct icc_info *icc_tbl; unsigned int icc_tbl_size; const struct bw_info *bw_tbl_dec; unsigned int bw_tbl_dec_size; - const char * const *pmdomain_tbl; - unsigned int pmdomain_tbl_size; + const struct platform_pd_data *pmdomain_tbl; const char * const *opp_pd_tbl; unsigned int opp_pd_tbl_size; const struct platform_clk_data *clk_tbl; @@ -319,11 +339,15 @@ struct iris_platform_data { u32 tz_cp_config_data_size; u32 num_vpp_pipe; bool no_aon; + bool no_rpmh; + u32 wd_intr_mask; + u32 icc_ib_multiplier; u32 max_session_count; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; /* max number of macroblocks per second supported */ u32 max_core_mbps; + bool dual_core; }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_glymur.c b/drivers/media/platform/qcom/iris/iris_platform_glymur.c new file mode 100644 index 0000000000000..194431665e077 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_glymur.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_platform_common.h" +#include "iris_platform_glymur.h" + +const struct platform_clk_data iris_glymur_clk_table[] = { + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_AXI_CTRL_CLK, "iface1" }, + {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, + {IRIS_VCODEC_FREERUN_CLK, "vcodec0_core_freerun" }, + {IRIS_AXI_VCODEC1_CLK, "iface2" }, + {IRIS_VCODEC1_CLK, "vcodec1_core" }, + {IRIS_VCODEC1_FREERUN_CLK, "vcodec1_core_freerun" }, +}; + +const char * const iris_glymur_clk_reset_table[] = { + "bus0", + "bus1", + "core", + "vcodec0_core", + "bus2", + "vcodec1_core", +}; + +const char * const iris_glymur_opp_clk_table[] = { + "vcodec0_core", + "vcodec1_core", + "core", + NULL, +}; + +const struct platform_pd_data iris_glymur_pmdomain_table = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + IRIS_VCODEC1_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + "vcodec1", + }, + .pd_count = 3, +}; + +const struct tz_cp_config iris_glymur_tz_cp_config[] = { + { + .cp_start = VIDEO_REGION_SECURE_FW_REGION_ID, + .cp_size = 0, + .cp_nonpixel_start = 0, + .cp_nonpixel_size = 0x1000000, + }, + { + .cp_start = VIDEO_REGION_VM0_SECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x1000000, + .cp_nonpixel_size = 0x24800000, + }, + { + .cp_start = VIDEO_REGION_VM0_NONSECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x25800000, + .cp_nonpixel_size = 0xda600000, + }, +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_glymur.h b/drivers/media/platform/qcom/iris/iris_platform_glymur.h new file mode 100644 index 0000000000000..875a3c65c58f1 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_glymur.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_PLATFORM_GLYMUR_H__ +#define __IRIS_PLATFORM_GLYMUR_H__ + +extern const struct platform_clk_data iris_glymur_clk_table[9]; +extern const char * const iris_glymur_clk_reset_table[6]; +extern const char * const iris_glymur_opp_clk_table[4]; +extern const struct platform_pd_data iris_glymur_pmdomain_table; +extern const struct tz_cp_config iris_glymur_tz_cp_config[3]; + +#endif /* __IRIS_PLATFORM_GLYMUR_H__ */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h index 0ec8f334df670..6b783e524b819 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h @@ -16,11 +16,11 @@ static const struct bw_info sc7280_bw_table_dec[] = { static const char * const sc7280_opp_pd_table[] = { "cx" }; static const struct platform_clk_data sc7280_clk_table[] = { - {IRIS_CTRL_CLK, "core" }, - {IRIS_AXI_CLK, "iface" }, - {IRIS_AHB_CLK, "bus" }, - {IRIS_HW_CLK, "vcodec_core" }, - {IRIS_HW_AHB_CLK, "vcodec_bus" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_AHB_CLK, "bus" }, + {IRIS_VCODEC_CLK, "vcodec_core" }, + {IRIS_VCODEC_AHB_CLK, "vcodec_bus" }, }; static const char * const sc7280_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.h b/drivers/media/platform/qcom/iris/iris_platform_sm8250.h index 50306043eb8ec..964e1cd920860 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.h @@ -16,9 +16,9 @@ static const struct bw_info sm8250_bw_table_dec[] = { static const char * const sm8250_opp_pd_table[] = { "mx", "mmcx" }; static const struct platform_clk_data sm8250_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, }; static const char * const sm8250_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.h b/drivers/media/platform/qcom/iris/iris_platform_sm8550.h index 3c9dae995bb24..03a63904579e1 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.h @@ -9,9 +9,9 @@ static const char * const sm8550_clk_reset_table[] = { "bus" }; static const struct platform_clk_data sm8550_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, }; static struct platform_inst_caps platform_inst_cap_sm8550 = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h index 719056656a5ba..f843f13251c5c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h @@ -11,12 +11,12 @@ static const char * const sm8750_clk_reset_table[] = { }; static const struct platform_clk_data sm8750_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_AXI1_CLK, "iface1" }, - {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, - {IRIS_HW_FREERUN_CLK, "vcodec0_core_freerun" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_AXI_CTRL_CLK, "iface1" }, + {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, + {IRIS_VCODEC_FREERUN_CLK, "vcodec0_core_freerun" }, }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c index 6e06a32822bbb..3bfafa705291c 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c @@ -16,12 +16,20 @@ #include "iris_platform_sc7280.h" #include "iris_platform_sm8250.h" +#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) + static const struct iris_firmware_desc iris_vpu20_p1_gen1_desc = { .firmware_data = &iris_hfi_gen1_data, .get_vpu_buffer_size = iris_vpu_buf_size, .fwname = "qcom/vpu/vpu20_p1.mbn", }; +static const struct iris_firmware_desc iris_vpu20_p1_gen2_s6_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu33_buf_size, + .fwname = "qcom/vpu/vpu20_p1_gen2_s6.mbn", +}; + static const struct iris_firmware_desc iris_vpu20_p4_gen1_desc = { .firmware_data = &iris_hfi_gen1_data, .get_vpu_buffer_size = iris_vpu_buf_size, @@ -53,7 +61,17 @@ static const struct icc_info iris_icc_info_vpu2[] = { static const char * const iris_clk_reset_table_vpu2[] = { "bus", "core" }; -static const char * const iris_pmdomain_table_vpu2[] = { "venus", "vcodec0" }; +static const struct platform_pd_data iris_pmdomain_table_vpu2 = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + }, + .pd_count = 2, +}; static const struct tz_cp_config tz_cp_config_vpu2[] = { { @@ -65,14 +83,14 @@ static const struct tz_cp_config tz_cp_config_vpu2[] = { }; const struct iris_platform_data sc7280_data = { - .firmware_desc = &iris_vpu20_p1_gen1_desc, + .firmware_desc_gen1 = &iris_vpu20_p1_gen1_desc, + .firmware_desc_gen2 = &iris_vpu20_p1_gen2_s6_desc, .vpu_ops = &iris_vpu2_ops, .icc_tbl = iris_icc_info_vpu2, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), .bw_tbl_dec = sc7280_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sc7280_bw_table_dec), - .pmdomain_tbl = iris_pmdomain_table_vpu2, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu2), + .pmdomain_tbl = &iris_pmdomain_table_vpu2, .opp_pd_tbl = sc7280_opp_pd_table, .opp_pd_tbl_size = ARRAY_SIZE(sc7280_opp_pd_table), .clk_tbl = sc7280_clk_table, @@ -87,6 +105,8 @@ const struct iris_platform_data sc7280_data = { .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2), .num_vpp_pipe = 1, .no_aon = true, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = 4096 * 2176 / 256 * 2 + 1920 * 1088 / 256, /* max spec for SC7280 is 4096x2176@60fps */ @@ -94,7 +114,7 @@ const struct iris_platform_data sc7280_data = { }; const struct iris_platform_data sm8250_data = { - .firmware_desc = &iris_vpu20_p4_gen1_desc, + .firmware_desc_gen1 = &iris_vpu20_p4_gen1_desc, .vpu_ops = &iris_vpu2_ops, .icc_tbl = iris_icc_info_vpu2, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), @@ -102,8 +122,7 @@ const struct iris_platform_data sm8250_data = { .clk_rst_tbl_size = ARRAY_SIZE(iris_clk_reset_table_vpu2), .bw_tbl_dec = sm8250_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sm8250_bw_table_dec), - .pmdomain_tbl = iris_pmdomain_table_vpu2, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu2), + .pmdomain_tbl = &iris_pmdomain_table_vpu2, .opp_pd_tbl = sm8250_opp_pd_table, .opp_pd_tbl_size = ARRAY_SIZE(sm8250_opp_pd_table), .clk_tbl = sm8250_clk_table, @@ -117,6 +136,8 @@ const struct iris_platform_data sm8250_data = { .tz_cp_config_data = tz_cp_config_vpu2, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K, .max_core_mbps = ((7680 * 4320) / 256) * 60, diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 2c63adbc55791..ffa5aa018c1bb 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -12,12 +12,15 @@ #include "iris_vpu_buffer.h" #include "iris_vpu_common.h" +#include "iris_platform_glymur.h" #include "iris_platform_qcs8300.h" #include "iris_platform_sm8550.h" #include "iris_platform_sm8650.h" #include "iris_platform_sm8750.h" #include "iris_platform_x1p42100.h" +#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) + static const struct iris_firmware_desc iris_vpu30_p4_s6_gen2_desc = { .firmware_data = &iris_hfi_gen2_data, .get_vpu_buffer_size = iris_vpu_buf_size, @@ -48,6 +51,12 @@ static const struct iris_firmware_desc iris_vpu35_p4_gen2_desc = { .fwname = "qcom/vpu/vpu35_p4.mbn", }; +const struct iris_firmware_desc iris_vpu36_p4_s7_gen2_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu_buf_size, + .fwname = "qcom/vpu/vpu36_p4_s7.mbn", +}; + static const u32 iris_fmts_vpu3x_dec[] = { [IRIS_FMT_H264] = V4L2_PIX_FMT_H264, [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC, @@ -67,7 +76,17 @@ static const struct bw_info iris_bw_table_dec_vpu3x[] = { { ((1920 * 1080) / 256) * 30, 294000 }, }; -static const char * const iris_pmdomain_table_vpu3x[] = { "venus", "vcodec0" }; +static const struct platform_pd_data iris_pmdomain_table_vpu3x = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + }, + .pd_count = 2, +}; static const char * const iris_opp_pd_table_vpu3x[] = { "mxc", "mmcx" }; @@ -85,12 +104,53 @@ static const struct tz_cp_config tz_cp_config_vpu3[] = { }, }; +static int sm8550_init_cb_devs(struct iris_core *core) +{ + const u32 f_id_np = 0; /* IRIS_NON_PIXEL_VCODEC */ + const u32 f_id_p = 1; /* IRIS_PIXEL */ + struct device *dev; + + dev = iris_create_cb_dev(core, "iris_non_pixel", &f_id_np); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + core->dev_np = dev; + core->dev_bs = core->dev_np; + + dev = iris_create_cb_dev(core, "iris_pixel", &f_id_p); + if (IS_ERR(dev)) + goto err_unreg_dev_np; + + core->dev_p = dev; + + return 0; + +err_unreg_dev_np: + platform_device_unregister(to_platform_device(core->dev_np)); + core->dev_np = NULL; + core->dev_bs = NULL; + + return PTR_ERR(dev); +} + +static void sm8550_deinit_cb_devs(struct iris_core *core) +{ + if (core->dev_np) + platform_device_unregister(to_platform_device(core->dev_np)); + if (core->dev_p) + platform_device_unregister(to_platform_device(core->dev_p)); + + core->dev_np = NULL; + core->dev_bs = NULL; + core->dev_p = NULL; +} + /* * Shares most of SM8550 data except: * - inst_caps to platform_inst_cap_qcs8300 */ const struct iris_platform_data qcs8300_data = { - .firmware_desc = &iris_vpu30_p4_s6_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p4_s6_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -98,8 +158,7 @@ const struct iris_platform_data qcs8300_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8550_clk_table, @@ -113,22 +172,25 @@ const struct iris_platform_data qcs8300_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 2, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = ((4096 * 2176) / 256) * 4, .max_core_mbps = (((3840 * 2176) / 256) * 120), }; const struct iris_platform_data sm8550_data = { - .firmware_desc = &iris_vpu30_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p4_gen2_desc, .vpu_ops = &iris_vpu3_ops, + .init_cb_devs = sm8550_init_cb_devs, + .deinit_cb_devs = sm8550_deinit_cb_devs, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), .clk_rst_tbl = sm8550_clk_reset_table, .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8550_clk_table, @@ -142,6 +204,8 @@ const struct iris_platform_data sm8550_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, @@ -154,7 +218,7 @@ const struct iris_platform_data sm8550_data = { * - controller_rst_tbl to sm8650_controller_reset_table */ const struct iris_platform_data sm8650_data = { - .firmware_desc = &iris_vpu33_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu33_p4_gen2_desc, .vpu_ops = &iris_vpu33_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -164,8 +228,7 @@ const struct iris_platform_data sm8650_data = { .controller_rst_tbl_size = ARRAY_SIZE(sm8650_controller_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8550_clk_table, @@ -179,13 +242,15 @@ const struct iris_platform_data sm8650_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, }; const struct iris_platform_data sm8750_data = { - .firmware_desc = &iris_vpu35_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu35_p4_gen2_desc, .vpu_ops = &iris_vpu35_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -193,8 +258,7 @@ const struct iris_platform_data sm8750_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8750_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = sm8750_clk_table, @@ -208,6 +272,8 @@ const struct iris_platform_data sm8750_data = { .tz_cp_config_data = tz_cp_config_vpu3, .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), .num_vpp_pipe = 4, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 1, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, @@ -220,7 +286,7 @@ const struct iris_platform_data sm8750_data = { * - different num_vpp_pipe */ const struct iris_platform_data x1p42100_data = { - .firmware_desc = &iris_vpu30_p1_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p1_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -228,8 +294,7 @@ const struct iris_platform_data x1p42100_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .pmdomain_tbl = &iris_pmdomain_table_vpu3x, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), .clk_tbl = x1p42100_clk_table, @@ -247,3 +312,32 @@ const struct iris_platform_data x1p42100_data = { .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((7680 * 4320) / 256) * 60, }; + +const struct iris_platform_data glymur_data = { + .firmware_desc_gen2 = &iris_vpu36_p4_s7_gen2_desc, + .vpu_ops = &iris_vpu36_ops, + .icc_tbl = iris_icc_info_vpu3x, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), + .clk_rst_tbl = iris_glymur_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(iris_glymur_clk_reset_table), + .bw_tbl_dec = iris_bw_table_dec_vpu3x, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), + .pmdomain_tbl = &iris_glymur_pmdomain_table, + .opp_pd_tbl = iris_opp_pd_table_vpu3x, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), + .clk_tbl = iris_glymur_clk_table, + .clk_tbl_size = ARRAY_SIZE(iris_glymur_clk_table), + .opp_clk_tbl = iris_glymur_opp_clk_table, + /* Upper bound of DMA address range */ + .dma_mask = 0xffe00000 - 1, + .inst_iris_fmts = iris_fmts_vpu3x_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec), + .inst_caps = &platform_inst_cap_sm8550, + .tz_cp_config_data = iris_glymur_tz_cp_config, + .tz_cp_config_data_size = ARRAY_SIZE(iris_glymur_tz_cp_config), + .num_vpp_pipe = 4, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_8K * 2, + .max_core_mbps = ((8192 * 4320) / 256) * 60, + .dual_core = true, +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c new file mode 100644 index 0000000000000..8e97f7191eac7 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_ctrls.h" +#include "iris_hfi_gen2.h" +#include "iris_hfi_gen2_defines.h" +#include "iris_platform_common.h" +#include "iris_vpu_buffer.h" +#include "iris_vpu_common.h" + +#define WRAPPER_INTR_STATUS_A2HWD_BMSK 0x10 + +const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_desc = { + .firmware_data = &iris_hfi_gen1_ar50lt_data, + .get_vpu_buffer_size = iris_vpu_ar50lt_gen1_buf_size, + .fwname = "qcom/venus-6.0/venus.mbn", +}; + +const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen2_s6_desc = { + .firmware_data = &iris_hfi_gen2_ar50lt_data, + .get_vpu_buffer_size = iris_vpu_ar50lt_gen2_buf_size, + .fwname = "qcom/vpu/ar50lt_p1_gen2_s6.mbn", +}; + +static const u32 iris_fmts_ar50lt_dec[] = { + [IRIS_FMT_H264] = V4L2_PIX_FMT_H264, + [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC, + [IRIS_FMT_VP9] = V4L2_PIX_FMT_VP9, +}; + +static const struct bw_info iris_bw_table_dec_ar50lt[] = { + { ((1920 * 1080) / 256) * 60, 1564000, }, + { ((1920 * 1080) / 256) * 30, 791000, }, + { ((1280 * 720) / 256) * 60, 688000, }, + { ((1280 * 720) / 256) * 30, 347000, }, +}; + +static const struct icc_info iris_icc_info_ar50lt[] = { + { "cpu-cfg", 1000, 1000 }, + { "video-mem", 1000, 6500000 }, +}; + +static const struct platform_pd_data iris_pmdomain_table_ar50lt = { + .pd_types = (enum platform_pm_domain_type []) { + IRIS_CTRL_POWER_DOMAIN, + IRIS_VCODEC_POWER_DOMAIN, + }, + .pd_names = (const char *[]) { + "venus", + "vcodec0", + }, + .pd_count = 2, +}; + +static const char * const iris_opp_pd_table_ar50lt[] = { "cx" }; + +static const struct platform_clk_data iris_clk_table_ar50lt[] = { + {IRIS_CTRL_CLK, "core" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_AHB_CLK, "bus" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_VCODEC_AHB_CLK, "vcodec0_bus" }, + {IRIS_THROTTLE_CLK, "throttle" }, +}; + +static const char * const iris_opp_clk_table_ar50lt[] = { + "vcodec0_core", + NULL, +}; + +static const struct tz_cp_config tz_cp_config_ar50lt[] = { + { + .cp_start = 0, + .cp_size = 0x25800000, + .cp_nonpixel_start = 0x01000000, + .cp_nonpixel_size = 0x24800000, + }, +}; + +static struct platform_inst_caps platform_inst_cap_ar50lt = { + .min_frame_width = 128, + .max_frame_width = 1920, + .min_frame_height = 128, + .max_frame_height = 1920, + .max_mbpf = (1920 * 1088) / 256, + .mb_cycles_vpp = 440, + .mb_cycles_fw = 733003, + .mb_cycles_fw_vpp = 225975, + .max_frame_rate = 120, + .max_operating_rate = 120, +}; + +const struct iris_platform_data qcm2290_data = { + .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_desc, + .firmware_desc_gen2 = &iris_vpu_ar50lt_p1_gen2_s6_desc, + .vpu_ops = &iris_vpu_ar50lt_ops, + .icc_tbl = iris_icc_info_ar50lt, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_ar50lt), + .bw_tbl_dec = iris_bw_table_dec_ar50lt, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_ar50lt), + .pmdomain_tbl = &iris_pmdomain_table_ar50lt, + .opp_pd_tbl = iris_opp_pd_table_ar50lt, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_ar50lt), + .clk_tbl = iris_clk_table_ar50lt, + .clk_tbl_size = ARRAY_SIZE(iris_clk_table_ar50lt), + .opp_clk_tbl = iris_opp_clk_table_ar50lt, + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, + .inst_iris_fmts = iris_fmts_ar50lt_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_ar50lt_dec), + .inst_caps = &platform_inst_cap_ar50lt, + .tz_cp_config_data = tz_cp_config_ar50lt, + .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_ar50lt), + .num_vpp_pipe = 1, + .no_rpmh = true, + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK, + .icc_ib_multiplier = 2, + .max_session_count = 8, + .max_core_mbpf = ((1920 * 1088) / 256) * 4, + /* Concurrency: 1080p@30 decode + 1080p@30 encode */ + /* Concurrency: 3 * 1080p@30 decode */ + .max_core_mbps = (((1920 * 1088) / 256) * 90), +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h b/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h index d89acfbc1233d..2c0b0644cd5aa 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h +++ b/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h @@ -7,10 +7,10 @@ #define __IRIS_PLATFORM_X1P42100_H__ static const struct platform_clk_data x1p42100_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_BSE_HW_CLK, "vcodec0_bse" }, + {IRIS_AXI_VCODEC_CLK, "iface" }, + {IRIS_CTRL_CLK, "core" }, + {IRIS_VCODEC_CLK, "vcodec0_core" }, + {IRIS_BSE_HW_CLK, "vcodec0_bse" }, }; static const char *const x1p42100_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_power.c b/drivers/media/platform/qcom/iris/iris_power.c index 91aa21d4070eb..0e116c63f529d 100644 --- a/drivers/media/platform/qcom/iris/iris_power.c +++ b/drivers/media/platform/qcom/iris/iris_power.c @@ -77,9 +77,9 @@ static int iris_vote_interconnects(struct iris_inst *inst) static int iris_set_clocks(struct iris_inst *inst) { + u64 vcodec0_freq = 0, vcodec1_freq = 0; struct iris_core *core = inst->core; struct iris_inst *instance; - u64 freq = 0; int ret; mutex_lock(&core->lock); @@ -87,11 +87,14 @@ static int iris_set_clocks(struct iris_inst *inst) if (!instance->max_input_data_size) continue; - freq += instance->power.min_freq; + if (instance->core_id == IRIS_VCODEC0) + vcodec0_freq += instance->power.min_freq; + else if (instance->core_id == IRIS_VCODEC1) + vcodec1_freq += instance->power.min_freq; } - core->power.clk_freq = freq; - ret = iris_opp_set_rate(core->dev, freq); + core->power.clk_freq = vcodec0_freq > vcodec1_freq ? vcodec0_freq : vcodec1_freq; + ret = iris_opp_set_rate(core->dev, core->power.clk_freq); mutex_unlock(&core->lock); return ret; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index c2dcb50a27824..278f6df716e82 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -44,8 +44,8 @@ static int iris_init_power_domains(struct iris_core *core) int ret; struct dev_pm_domain_attach_data iris_pd_data = { - .pd_names = core->iris_platform_data->pmdomain_tbl, - .num_pd_names = core->iris_platform_data->pmdomain_tbl_size, + .pd_names = core->iris_platform_data->pmdomain_tbl->pd_names, + .num_pd_names = core->iris_platform_data->pmdomain_tbl->pd_count, .pd_flags = PD_FLAG_NO_DEV_LINK, }; @@ -131,6 +131,20 @@ static int iris_init_resets(struct iris_core *core) core->iris_platform_data->controller_rst_tbl_size); } +static int iris_init_cb_devs(struct iris_core *core) +{ + if (core->iris_platform_data->init_cb_devs) + return core->iris_platform_data->init_cb_devs(core); + + return 0; +} + +static void iris_deinit_cb_devs(struct iris_core *core) +{ + if (core->iris_platform_data->deinit_cb_devs) + core->iris_platform_data->deinit_cb_devs(core); +} + static int iris_init_resources(struct iris_core *core) { int ret; @@ -201,6 +215,7 @@ static void iris_remove(struct platform_device *pdev) return; iris_core_deinit(core); + iris_deinit_cb_devs(core); video_unregister_device(core->vdev_dec); video_unregister_device(core->vdev_enc); @@ -251,8 +266,6 @@ static int iris_probe(struct platform_device *pdev) return core->irq; core->iris_platform_data = of_device_get_match_data(core->dev); - core->iris_firmware_desc = core->iris_platform_data->firmware_desc; - core->iris_firmware_data = core->iris_firmware_desc->firmware_data; core->ubwc_cfg = qcom_ubwc_config_get_data(); if (IS_ERR(core->ubwc_cfg)) @@ -271,11 +284,13 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - iris_session_init_caps(core); + ret = iris_init_cb_devs(core); + if (ret) + return ret; ret = v4l2_device_register(dev, &core->v4l2_dev); if (ret) - return ret; + goto err_deinit_cb; ret = iris_register_video_device(core, DECODER); if (ret) @@ -289,9 +304,11 @@ static int iris_probe(struct platform_device *pdev) dma_mask = core->iris_platform_data->dma_mask; - ret = dma_set_mask_and_coherent(dev, dma_mask); - if (ret) - goto err_vdev_unreg_enc; + if (device_iommu_mapped(core->dev)) { + ret = dma_set_mask_and_coherent(core->dev, dma_mask); + if (ret) + goto err_vdev_unreg_enc; + } dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); @@ -310,6 +327,8 @@ static int iris_probe(struct platform_device *pdev) video_unregister_device(core->vdev_dec); err_v4l2_unreg: v4l2_device_unregister(&core->v4l2_dev); +err_deinit_cb: + iris_deinit_cb_devs(core); return ret; } @@ -360,6 +379,14 @@ static const struct dev_pm_ops iris_pm_ops = { }; static const struct of_device_id iris_dt_match[] = { + { + .compatible = "qcom,glymur-iris", + .data = &glymur_data, + }, + { + .compatible = "qcom,qcm2290-venus", + .data = &qcm2290_data, + }, { .compatible = "qcom,qcs8300-iris", .data = &qcs8300_data, diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index 773f6548370a2..df9b7badf0c62 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -6,18 +6,21 @@ #include #include #include +#include #include #include #include #include #include "iris_core.h" +#include "iris_instance.h" #include "iris_resources.h" #define BW_THRESHOLD 50000 int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw) { + u32 icc_ib_multiplier = core->iris_platform_data->icc_ib_multiplier; unsigned long bw_kbps = 0, bw_prev = 0; const struct icc_info *icc_tbl; int ret = 0, i; @@ -36,6 +39,7 @@ int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw) return ret; core->icc_tbl[i].avg_bw = bw_kbps; + core->icc_tbl[i].peak_bw = bw_kbps * icc_ib_multiplier; core->power.icc_bw = bw_kbps; break; @@ -70,10 +74,43 @@ int iris_opp_set_rate(struct device *dev, unsigned long freq) return dev_pm_opp_set_opp(dev, opp); } -int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev) +static int iris_get_pd_index_by_type(struct iris_core *core, enum platform_pm_domain_type pd_type) { + const struct platform_pd_data *pd_tbl; + u32 pd_count, i; + + pd_tbl = core->iris_platform_data->pmdomain_tbl; + pd_count = core->iris_platform_data->pmdomain_tbl->pd_count; + + for (i = 0; i < pd_count; i++) { + if (pd_tbl->pd_types[i] == pd_type) + return i; + } + + return -EINVAL; +} + +int iris_genpd_set_hwmode(struct iris_core *core, enum platform_pm_domain_type pd_type, bool hwmode) +{ + int pd_index = iris_get_pd_index_by_type(core, pd_type); + + if (pd_index < 0) + return pd_index; + + return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[pd_index], hwmode); +} + +int iris_enable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type) +{ + int pd_index = iris_get_pd_index_by_type(core, pd_type); + struct device *pd_dev; int ret; + if (pd_index < 0) + return pd_index; + + pd_dev = core->pmdomain_tbl->pd_devs[pd_index]; + ret = iris_opp_set_rate(core->dev, ULONG_MAX); if (ret) return ret; @@ -85,10 +122,17 @@ int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev) return ret; } -int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev) +int iris_disable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type) { + int pd_index = iris_get_pd_index_by_type(core, pd_type); + struct device *pd_dev; int ret; + if (pd_index < 0) + return pd_index; + + pd_dev = core->pmdomain_tbl->pd_devs[pd_index]; + ret = iris_opp_set_rate(core->dev, 0); if (ret) return ret; @@ -141,3 +185,77 @@ int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type return 0; } + +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, 0); + if (!pdev) + return ERR_PTR(-ENOMEM); + + pdev->dev.parent = core->dev; + + ret = platform_device_add(pdev); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = of_dma_configure_id(&pdev->dev, core->dev->of_node, true, f_id); + if (ret) + goto error_unregister; + + ret = dma_set_mask_and_coherent(&pdev->dev, core->iris_platform_data->dma_mask); + if (ret) + goto error_unregister; + + return &pdev->dev; + +error_unregister: + platform_device_unregister(to_platform_device(&pdev->dev)); + + return ERR_PTR(ret); +} + +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + struct iris_core *core = inst->core; + struct device *dev = NULL; + + switch (buffer_type) { + case BUF_INPUT: + if (inst->domain == DECODER) + dev = core->dev_bs; + else + dev = core->dev_p; + break; + case BUF_OUTPUT: + if (inst->domain == DECODER) + dev = core->dev_p; + else + dev = core->dev_bs; + break; + case BUF_BIN: + dev = core->dev_bs; + break; + case BUF_DPB: + case BUF_PARTIAL: + case BUF_SCRATCH_2: + case BUF_VPSS: + dev = core->dev_p; + break; + case BUF_ARP: + case BUF_COMV: + case BUF_LINE: + case BUF_NON_COMV: + case BUF_PERSIST: + dev = core->dev_np; + break; + default: + dev_err(core->dev, "invalid buffer type: %d\n", buffer_type); + } + + return dev ? dev : core->dev; +} diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h index 6bfbd2dc6db09..982ca764cb20b 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.h +++ b/drivers/media/platform/qcom/iris/iris_resources.h @@ -9,11 +9,15 @@ struct iris_core; int iris_opp_set_rate(struct device *dev, unsigned long freq); -int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev); -int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev); +int iris_enable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type); +int iris_disable_power_domains(struct iris_core *core, enum platform_pm_domain_type pd_type); int iris_unset_icc_bw(struct iris_core *core); int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw); int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type); int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type); +int iris_genpd_set_hwmode(struct iris_core *core, enum platform_pm_domain_type pd_type, + bool hwmode); +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id); +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c index ba5c8dc1280c2..7ebe4052ec41d 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.c +++ b/drivers/media/platform/qcom/iris/iris_utils.c @@ -101,40 +101,95 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id) return NULL; } +static u32 iris_get_mbps(struct iris_inst *inst) +{ + u32 fps = max(inst->frame_rate, inst->operating_rate); + + return iris_get_mbpf(inst) * fps; +} + +static void iris_get_core_load(struct iris_core *core, u32 *core_load, u32 *core_session, bool mbpf) +{ + bool dual_core = core->iris_platform_data->dual_core; + struct iris_inst *inst; + u32 load; + + core_load[0] = 0; + core_load[1] = 0; + core_session[0] = 0; + core_session[1] = 0; + + list_for_each_entry(inst, &core->instances, list) { + if (mbpf) + load = iris_get_mbpf(inst); + else + load = iris_get_mbps(inst); + + if (inst->core_id == IRIS_VCODEC0) { + core_load[0] += load; + core_session[0]++; + } else if (dual_core && inst->core_id == IRIS_VCODEC1) { + core_load[1] += load; + core_session[1]++; + } + } +} + +static int iris_select_core_id(struct iris_inst *inst, u32 *core_load, u32 *core_session, + u32 max_load, u32 new_load) +{ + u32 max_session = inst->core->iris_platform_data->max_session_count; + bool dual_core = inst->core->iris_platform_data->dual_core; + u32 core_index; + + core_index = (core_load[0] > core_load[1] && dual_core) ? 1 : 0; + + if (core_session[core_index] >= max_session) + core_index = core_index == 0 && dual_core ? 1 : 0; + + if (core_session[core_index] >= max_session) + return -ENOMEM; + + if (core_load[core_index] + new_load <= max_load) + inst->core_id = core_index == 0 ? IRIS_VCODEC0 : IRIS_VCODEC1; + else + return -ENOMEM; + + return 0; +} + int iris_check_core_mbpf(struct iris_inst *inst) { + u32 max_core_mbpf = inst->core->iris_platform_data->max_core_mbpf; + u32 core_mbpf[2], core_session[2], new_mbpf; struct iris_core *core = inst->core; - struct iris_inst *instance; - u32 total_mbpf = 0; + int ret; mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) - total_mbpf += iris_get_mbpf(instance); + inst->core_id = 0; + iris_get_core_load(inst->core, core_mbpf, core_session, true); + new_mbpf = iris_get_mbpf(inst); + ret = iris_select_core_id(inst, core_mbpf, core_session, max_core_mbpf, new_mbpf); mutex_unlock(&core->lock); - if (total_mbpf > core->iris_platform_data->max_core_mbpf) - return -ENOMEM; - - return 0; + return ret; } int iris_check_core_mbps(struct iris_inst *inst) { + u32 max_core_mbps = inst->core->iris_platform_data->max_core_mbps; + u32 core_mbps[2] = {0, 0}, core_session[2], new_mbps; struct iris_core *core = inst->core; - struct iris_inst *instance; - u32 total_mbps = 0, fps = 0; + int ret; mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) { - fps = max(instance->frame_rate, instance->operating_rate); - total_mbps += iris_get_mbpf(instance) * fps; - } + inst->core_id = 0; + iris_get_core_load(inst->core, core_mbps, core_session, false); + new_mbps = iris_get_mbps(inst); + ret = iris_select_core_id(inst, core_mbps, core_session, max_core_mbps, new_mbps); mutex_unlock(&core->lock); - if (total_mbps > core->iris_platform_data->max_core_mbps) - return -ENOMEM; - - return 0; + return ret; } bool is_rotation_90_or_270(struct iris_inst *inst) diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index a2ea2d67f60d0..dbb89396e6514 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -176,6 +176,10 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) if (ret) goto error; + ret = iris_set_core_id(inst); + if (ret) + goto error; + if (V4L2_TYPE_IS_OUTPUT(q->type)) { if (inst->domain == DECODER) ret = iris_vdec_streamon_input(inst); diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index 9e228b70420e4..7da43f312ba98 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -3,6 +3,7 @@ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include @@ -71,6 +72,7 @@ static const u32 iris_vdec_formats_cap[] = { static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size, i; const u32 *fmt; @@ -82,6 +84,9 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_vdec_formats_cap; size = ARRAY_SIZE(iris_vdec_formats_cap); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; default: return false; @@ -110,6 +115,7 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size; const u32 *fmt; @@ -121,6 +127,9 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_vdec_formats_cap; size = ARRAY_SIZE(iris_vdec_formats_cap); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; default: return 0; diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c index a945992f63aa8..2cafbe9f8abb5 100644 --- a/drivers/media/platform/qcom/iris/iris_venc.c +++ b/drivers/media/platform/qcom/iris/iris_venc.c @@ -3,6 +3,7 @@ * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include #include @@ -91,6 +92,7 @@ static const u32 iris_venc_formats_out[] = { static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size, i; const u32 *fmt; @@ -98,6 +100,9 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: fmt = iris_venc_formats_out; size = ARRAY_SIZE(iris_venc_formats_out); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_venc_formats_cap; @@ -117,6 +122,7 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type) static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) { + const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg; unsigned int size; const u32 *fmt; @@ -124,6 +130,9 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: fmt = iris_venc_formats_out; size = ARRAY_SIZE(iris_venc_formats_out); + /* Last format is UBWC; drop it if UBWC is unsupported */ + if (!ubwc->ubwc_enc_version) + size--; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: fmt = iris_venc_formats_cap; diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 14d63dc76c9ba..ae27d12a06b14 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -9,6 +9,7 @@ #include #include +#include "iris_ctrls.h" #include "iris_vidc.h" #include "iris_instance.h" #include "iris_vdec.h" @@ -41,16 +42,20 @@ static void iris_v4l2_fh_deinit(struct iris_inst *inst, struct file *filp) static void iris_add_session(struct iris_inst *inst) { + u32 max_session_count = inst->core->iris_platform_data->max_session_count; struct iris_core *core = inst->core; struct iris_inst *iter; u32 count = 0; + if (inst->core->iris_platform_data->dual_core) + max_session_count *= 2; + mutex_lock(&core->lock); list_for_each_entry(iter, &core->instances, list) count++; - if (count < core->iris_platform_data->max_session_count) + if (count < max_session_count) list_add_tail(&inst->list, &core->instances); mutex_unlock(&core->lock); @@ -107,7 +112,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ src_vq->drv_priv = inst; src_vq->buf_struct_size = sizeof(struct iris_buffer); src_vq->min_reqbufs_allocation = MIN_BUFFERS; - src_vq->dev = inst->core->dev; + src_vq->dev = iris_get_cb_dev(inst, BUF_INPUT); src_vq->lock = &inst->ctx_q_lock; ret = vb2_queue_init(src_vq); if (ret) @@ -121,7 +126,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ dst_vq->drv_priv = inst; dst_vq->buf_struct_size = sizeof(struct iris_buffer); dst_vq->min_reqbufs_allocation = MIN_BUFFERS; - dst_vq->dev = inst->core->dev; + dst_vq->dev = iris_get_cb_dev(inst, BUF_OUTPUT); dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); @@ -196,6 +201,8 @@ int iris_open(struct file *filp) goto fail_m2m_release; } + iris_session_init_caps(core); + if (inst->domain == DECODER) ret = iris_vdec_inst_init(inst); else if (inst->domain == ENCODER) diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c index b8714dcbad10a..dd2eeae0d9eb8 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_vpu2.c @@ -45,4 +45,6 @@ const struct vpu_ops iris_vpu2_ops = { .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu2_calc_freq, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 3dad47be78b58..40fa9ebada78a 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -27,6 +27,16 @@ static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) return pwr_status ? false : true; } +static bool iris_vpu36_hw1_power_collapsed(struct iris_core *core) +{ + u32 value, pwr_status; + + value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); + pwr_status = value & BIT(4); + + return !pwr_status; +} + static void iris_vpu3_power_off_hardware(struct iris_core *core) { u32 reg_val = 0, value, i; @@ -208,8 +218,8 @@ static int iris_vpu33_power_off_controller(struct iris_core *core) iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); return 0; } @@ -218,30 +228,30 @@ static int iris_vpu35_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_FREERUN_CLK); if (ret) goto err_disable_axi_clk; - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); if (ret) goto err_disable_hw_free_clk; return 0; err_disable_hw_free_clk: - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); err_disable_axi_clk: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); return ret; } @@ -250,8 +260,126 @@ static void iris_vpu35_power_off_hw(struct iris_core *core) { iris_vpu33_power_off_hardware(core); - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); +} + +static int iris_vpu36_power_on_hw1(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, IRIS_VCODEC1_POWER_DOMAIN); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC1_CLK); + if (ret) + goto err_disable_hw1_power; + + ret = iris_prepare_enable_clock(core, IRIS_VCODEC1_FREERUN_CLK); + if (ret) + goto err_disable_axi1_clk; + + ret = iris_prepare_enable_clock(core, IRIS_VCODEC1_CLK); + if (ret) + goto err_disable_hw1_free_clk; + + return 0; + +err_disable_hw1_free_clk: + iris_disable_unprepare_clock(core, IRIS_VCODEC1_FREERUN_CLK); +err_disable_axi1_clk: + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC1_CLK); +err_disable_hw1_power: + iris_disable_power_domains(core, IRIS_VCODEC1_POWER_DOMAIN); + + return ret; +} + +static int iris_vpu36_power_on_hw(struct iris_core *core) +{ + int ret; + + ret = iris_vpu35_power_on_hw(core); + if (ret) + return ret; + + ret = iris_vpu36_power_on_hw1(core); + if (ret) + goto err_power_off_hw; + + return 0; + +err_power_off_hw: + iris_vpu35_power_off_hw(core); + + return ret; +} + +static void iris_vpu36_power_off_hw1(struct iris_core *core) +{ + u32 value, i; + int ret; + + if (iris_vpu36_hw1_power_collapsed(core)) + goto disable_power; + + value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + if (value) + writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + + for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) { + ret = readl_poll_timeout(core->reg_base + VCODEC1_SS_IDLE_STATUSN + 4 * i, + value, value & DMA_NOC_IDLE, 2000, 20000); + if (ret) + goto disable_power; + } + + writel(REQ_VCODEC1_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, + value, value & NOC_LPI_VCODEC1_STATUS_DONE, 2000, 20000); + if (ret) + goto disable_power; + + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + writel(VCODEC1_BRIDGE_SW_RESET | VCODEC1_BRIDGE_HW_RESET_DISABLE, core->reg_base + + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(VCODEC1_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + +disable_power: + iris_genpd_set_hwmode(core, IRIS_VCODEC1_POWER_DOMAIN, false); + iris_disable_unprepare_clock(core, IRIS_VCODEC1_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC1_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC1_CLK); + iris_disable_power_domains(core, IRIS_VCODEC1_POWER_DOMAIN); +} + +static void iris_vpu36_power_off_hw(struct iris_core *core) +{ + iris_vpu35_power_off_hw(core); + iris_vpu36_power_off_hw1(core); +} + +static int iris_vpu36_set_hwmode(struct iris_core *core) +{ + int ret; + + ret = iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, true); + if (ret) + return ret; + + ret = iris_genpd_set_hwmode(core, IRIS_VCODEC1_POWER_DOMAIN, true); + if (ret) + goto error_disable_hwmode; + + return 0; + +error_disable_hwmode: + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, false); + + return ret; } const struct vpu_ops iris_vpu3_ops = { @@ -261,6 +389,8 @@ const struct vpu_ops iris_vpu3_ops = { .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; const struct vpu_ops iris_vpu33_ops = { @@ -270,6 +400,8 @@ const struct vpu_ops iris_vpu33_ops = { .power_on_controller = iris_vpu_power_on_controller, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; const struct vpu_ops iris_vpu35_ops = { @@ -280,4 +412,17 @@ const struct vpu_ops iris_vpu35_ops = { .program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, +}; + +const struct vpu_ops iris_vpu36_ops = { + .power_off_hw = iris_vpu36_power_off_hw, + .power_on_hw = iris_vpu36_power_on_hw, + .power_off_controller = iris_vpu35_vpu4x_power_off_controller, + .power_on_controller = iris_vpu35_vpu4x_power_on_controller, + .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, + .set_hwmode = iris_vpu36_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index 02e100a4045fc..946c165ac9342 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -27,27 +27,24 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 { int ret; - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, hw_mode); if (ret) return ret; if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_VPP0_HW_POWER_DOMAIN, hw_mode); if (ret) goto restore_hw_domain_mode; } if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_VPP1_HW_POWER_DOMAIN, hw_mode); if (ret) goto restore_vpp0_domain_mode; } if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_APV_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core, IRIS_APV_HW_POWER_DOMAIN, hw_mode); if (ret) goto restore_vpp1_domain_mode; } @@ -56,14 +53,12 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 restore_vpp1_domain_mode: if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP1_HW_POWER_DOMAIN], - !hw_mode); + iris_genpd_set_hwmode(core, IRIS_VPP1_HW_POWER_DOMAIN, !hw_mode); restore_vpp0_domain_mode: if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP0_HW_POWER_DOMAIN], - !hw_mode); + iris_genpd_set_hwmode(core, IRIS_VPP0_HW_POWER_DOMAIN, !hw_mode); restore_hw_domain_mode: - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], !hw_mode); + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, !hw_mode); return ret; } @@ -72,8 +67,7 @@ static int iris_vpu4x_power_on_apv(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, - core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_APV_HW_POWER_DOMAIN); if (ret) return ret; @@ -84,7 +78,7 @@ static int iris_vpu4x_power_on_apv(struct iris_core *core) return 0; disable_apv_hw_power_domain: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_APV_HW_POWER_DOMAIN); return ret; } @@ -139,7 +133,7 @@ static void iris_vpu4x_power_off_apv(struct iris_core *core) disable_clocks_and_power: iris_disable_unprepare_clock(core, IRIS_APV_HW_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_APV_HW_POWER_DOMAIN); } static void iris_vpu4x_ahb_sync_reset_apv(struct iris_core *core) @@ -162,15 +156,15 @@ static int iris_vpu4x_enable_hardware_clocks(struct iris_core *core, u32 efuse_v { int ret; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_FREERUN_CLK); if (ret) goto disable_axi_clock; - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); if (ret) goto disable_hw_free_run_clock; @@ -198,11 +192,11 @@ static int iris_vpu4x_enable_hardware_clocks(struct iris_core *core, u32 efuse_v disable_bse_hw_clock: iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); disable_hw_free_run_clock: - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); return ret; } @@ -216,9 +210,9 @@ static void iris_vpu4x_disable_hardware_clocks(struct iris_core *core, u32 efuse iris_disable_unprepare_clock(core, IRIS_VPP0_HW_CLK); iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_FREERUN_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); } static int iris_vpu4x_power_on_hardware(struct iris_core *core) @@ -226,20 +220,18 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core) u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); if (ret) return ret; if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VPP0_HW_POWER_DOMAIN); if (ret) goto disable_hw_power_domain; } if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VPP1_HW_POWER_DOMAIN); if (ret) goto disable_vpp0_power_domain; } @@ -260,14 +252,12 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core) iris_vpu4x_disable_hardware_clocks(core, efuse_value); disable_vpp1_power_domain: if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP1_HW_POWER_DOMAIN); disable_vpp0_power_domain: if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP0_HW_POWER_DOMAIN); disable_hw_power_domain: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); return ret; } @@ -338,14 +328,12 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core) iris_vpu4x_disable_hardware_clocks(core, efuse_value); if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP1_HW_POWER_DOMAIN); if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VPP0_HW_POWER_DOMAIN); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); } static int iris_vpu4x_set_hwmode(struct iris_core *core) @@ -368,4 +356,6 @@ const struct vpu_ops iris_vpu4x_ops = { .program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu4x_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, }; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c new file mode 100644 index 0000000000000..11369c847711c --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include + +#include "iris_instance.h" +#include "iris_vpu_common.h" + +#include "iris_vpu_register_defines.h" + +#define WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50LT BIT(3) + +#define WRAPPER_VCODEC0_CLOCK_CONFIG_AR50LT 0xb0080 + +#define CPU_CS_VCICMD 0xa0020 +#define CPU_CS_VCICMD_ARP_OFF 0x1 + +static void iris_vpu_ar50lt_set_preset_registers(struct iris_core *core) +{ + writel(0x0, core->reg_base + WRAPPER_VCODEC0_CLOCK_CONFIG_AR50LT); +} + +static void iris_vpu_ar50lt_interrupt_init(struct iris_core *core) +{ + writel(WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50LT, core->reg_base + WRAPPER_INTR_MASK); +} + +static void iris_vpu_ar50lt_disable_arp(struct iris_core *core) +{ + writel(CPU_CS_VCICMD_ARP_OFF, core->reg_base + CPU_CS_VCICMD); +} + +static int iris_vpu_ar50lt_power_off_controller(struct iris_core *core) +{ + iris_disable_unprepare_clock(core, IRIS_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); + + return 0; +} + +static void iris_vpu_ar50lt_power_off_hw(struct iris_core *core) +{ + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, false); + iris_disable_unprepare_clock(core, IRIS_THROTTLE_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); +} + +static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); + if (ret && ret != -ENOENT) + goto err_disable_ctrl_clock; + + ret = iris_prepare_enable_clock(core, IRIS_AHB_CLK); + if (ret) + goto err_disable_axi_clock; + + return 0; + +err_disable_axi_clock: + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); +err_disable_ctrl_clock: + iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); +err_disable_power: + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); + + return ret; +} + +static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core) +{ + int ret; + + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); + if (ret) + return ret; + + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); + if (ret) + goto err_disable_power; + + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_AHB_CLK); + if (ret) + goto err_disable_hw_clock; + + ret = iris_prepare_enable_clock(core, IRIS_THROTTLE_CLK); + if (ret) + goto err_disable_hw_ahb_clock; + + return 0; + +err_disable_hw_ahb_clock: + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); +err_disable_hw_clock: + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); +err_disable_power: + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); + + return ret; +} + +static u64 iris_vpu_ar50lt_calc_freq(struct iris_inst *inst, size_t data_size) +{ + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; + struct v4l2_format *inp_f = inst->fmt_src; + u32 mbs_per_second, mbpf, height, width; + unsigned long vpp_freq, vsp_freq; + u32 fps = DEFAULT_FPS; + + width = max(inp_f->fmt.pix_mp.width, inst->crop.width); + height = max(inp_f->fmt.pix_mp.height, inst->crop.height); + + mbpf = NUM_MBS_PER_FRAME(height, width); + mbs_per_second = mbpf * fps; + + vpp_freq = mbs_per_second * caps->mb_cycles_vpp; + + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; + vsp_freq = mbs_per_second * caps->mb_cycles_vsp; + + /* 10 / 7 is overhead factor */ + vsp_freq += ((fps * data_size * 8) * 10) / 7; + + return max(vpp_freq, vsp_freq); +} + +const struct vpu_ops iris_vpu_ar50lt_ops = { + .power_off_hw = iris_vpu_ar50lt_power_off_hw, + .power_on_hw = iris_vpu_ar50lt_power_on_hw, + .power_off_controller = iris_vpu_ar50lt_power_off_controller, + .power_on_controller = iris_vpu_ar50lt_power_on_controller, + .calc_freq = iris_vpu_ar50lt_calc_freq, + .set_hwmode = iris_vpu_set_hwmode, + .set_preset_registers = iris_vpu_ar50lt_set_preset_registers, + .interrupt_init = iris_vpu_ar50lt_interrupt_init, + .disable_arp = iris_vpu_ar50lt_disable_arp, +}; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index fb6f1016415e2..ca03d65705136 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -50,6 +50,32 @@ static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_p return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); } +static u32 size_h264d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_yuv, size_bin_hdr, size_bin_res; + + size_yuv = ((frame_width * frame_height * 3) >> 1); + if (size_yuv <= 1920 * 1088 * 3 / 2) { + size_bin_hdr = size_yuv * H264_CABAC_HDR_RATIO_SM_TOT; + size_bin_res = size_yuv * H264_CABAC_RES_RATIO_SM_TOT; + } else { + size_bin_hdr = (size_yuv * 3) / 5; + size_bin_res = (size_yuv * 3) / 2; + } + size_bin_hdr = ALIGN(size_bin_hdr, DMA_ALIGNMENT); + size_bin_res = ALIGN(size_bin_res, DMA_ALIGNMENT); + + return size_bin_hdr + size_bin_res; +} + +static u32 hfi_buffer_bin_h264d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 n_aligned_h = ALIGN(frame_height, 16); + u32 n_aligned_w = ALIGN(frame_width, 16); + + return size_h264d_hw_bin_buffer_ar50lt(n_aligned_w, n_aligned_h, num_vpp_pipes); +} + static u32 size_av1d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { u32 size_yuv, size_bin_hdr, size_bin_res; @@ -103,6 +129,21 @@ static u32 hfi_buffer_bin_vp9d(u32 frame_width, u32 frame_height, u32 num_vpp_pi return _size * num_vpp_pipes; } +static u32 hfi_buffer_bin_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_yuv, size; + + size_yuv = ALIGN(frame_width, 16) * ALIGN(frame_height, 16) * 3 / 2; + size_yuv = ALIGN(size_yuv, DMA_ALIGNMENT); + + size = ALIGN(((((MAX(size_yuv, VPX_DECODER_FRAME_BIN_BUFFER_SIZE)) * 6) / 5) / + num_vpp_pipes), DMA_ALIGNMENT) + + ALIGN((((MAX(size_yuv, VPX_DECODER_FRAME_BIN_BUFFER_SIZE)) * 4) / num_vpp_pipes), + DMA_ALIGNMENT); + + return size * num_vpp_pipes; +} + static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { u32 n_aligned_w = ALIGN(frame_width, 16); @@ -111,6 +152,32 @@ static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_p return size_h265d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes); } +static u32 size_h265d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_yuv, size_bin_hdr, size_bin_res; + + size_yuv = ((frame_width * frame_height * 3) >> 1); + if (size_yuv <= ((BIN_BUFFER_THRESHOLD * 3) >> 1)) { + size_bin_hdr = size_yuv * H265_CABAC_HDR_RATIO_SM_TOT; + size_bin_res = size_yuv * H265_CABAC_RES_RATIO_SM_TOT; + } else { + size_bin_hdr = (size_yuv * 41) / 50; + size_bin_res = (size_yuv * 59) / 50; + } + size_bin_hdr = ALIGN(size_bin_hdr, DMA_ALIGNMENT); + size_bin_res = ALIGN(size_bin_res, DMA_ALIGNMENT); + + return size_bin_hdr + size_bin_res; +} + +static u32 hfi_buffer_bin_h265d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 n_aligned_w = ALIGN(frame_width, 16); + u32 n_aligned_h = ALIGN(frame_height, 16); + + return size_h265d_hw_bin_buffer_ar50lt(n_aligned_w, n_aligned_h, num_vpp_pipes); +} + static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bufcount) { u32 frame_height_in_mbs = DIV_ROUND_UP(frame_height, 16); @@ -174,6 +241,14 @@ static u32 size_h264d_bse_cmd_buf(u32 frame_height) SIZE_H264D_BSE_CMD_PER_BUF; } +static u32 size_h264d_bse_cmd_buf_ar50lt(u32 frame_height) +{ + u32 height = ALIGN(frame_height, 32); + + return min_t(u32, (DIV_ROUND_UP(height, 16) * 12), H264D_MAX_SLICE) * + SIZE_H264D_BSE_CMD_PER_BUF; +} + static u32 size_h265d_bse_cmd_buf(u32 frame_width, u32 frame_height) { u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * @@ -185,6 +260,18 @@ static u32 size_h265d_bse_cmd_buf(u32 frame_width, u32 frame_height) return _size; } +static u32 size_h265d_bse_cmd_buf_ar50lt(u32 frame_width, u32 frame_height) +{ + u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) * + NUM_HW_PIC_BUF, DMA_ALIGNMENT); + + _size = min_t(u32, _size, H265D_MAX_SLICE_AR50LT + 1); + _size = 2 * _size * SIZE_H265D_BSE_CMD_PER_BUF; + + return _size; +} + static u32 hfi_buffer_persist_h265d(u32 rpu_enabled) { return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 + @@ -195,6 +282,13 @@ static u32 hfi_buffer_persist_h265d(u32 rpu_enabled) DMA_ALIGNMENT); } +static u32 hfi_buffer_persist_h265d_ar50lt(void) +{ + return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 + + H265_NUM_TILE * sizeof(u32) + NUM_HW_PIC_BUF * SIZE_SEI_USERDATA), + DMA_ALIGNMENT); +} + static inline u32 hfi_iris3_vp9d_comv_size(void) { @@ -212,6 +306,13 @@ static u32 hfi_buffer_persist_vp9d(void) HDR10_HIST_EXTRADATA_SIZE; } +static u32 hfi_buffer_persist_vp9d_ar50lt(void) +{ + return ALIGN(VP9_NUM_PROBABILITY_TABLE_BUF * VP9_PROB_TABLE_SIZE, DMA_ALIGNMENT) + + ALIGN(hfi_iris3_vp9d_comv_size(), DMA_ALIGNMENT) + + ALIGN(MAX_SUPERFRAME_HEADER_LEN, DMA_ALIGNMENT); +} + static u32 size_h264d_vpp_cmd_buf(u32 frame_height) { u32 size, height = ALIGN(frame_height, 32); @@ -222,6 +323,16 @@ static u32 size_h264d_vpp_cmd_buf(u32 frame_height) return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size; } +static u32 size_h264d_vpp_cmd_buf_ar50lt(u32 frame_height) +{ + u32 size, height = ALIGN(frame_height, 32); + + size = min_t(u32, (DIV_ROUND_UP(height, 16) * 12), H264D_MAX_SLICE) * + SIZE_H264D_VPP_CMD_PER_BUF; + + return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size; +} + static u32 hfi_buffer_persist_h264d(void) { return ALIGN(SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264 + @@ -230,6 +341,11 @@ static u32 hfi_buffer_persist_h264d(void) DMA_ALIGNMENT); } +static u32 hfi_buffer_persist_h264d_ar50lt(void) +{ + return ALIGN((SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264), DMA_ALIGNMENT); +} + static u32 hfi_buffer_persist_av1d(u32 max_width, u32 max_height, u32 total_ref_count) { u32 comv_size, size; @@ -255,6 +371,17 @@ static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u32 num_ return ALIGN(size, DMA_ALIGNMENT); } +static u32 hfi_buffer_non_comv_h264d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 size_bse = size_h264d_bse_cmd_buf_ar50lt(frame_height); + u32 size_vpp = size_h264d_vpp_cmd_buf_ar50lt(frame_height); + u32 size = ALIGN(size_bse, DMA_ALIGNMENT) + + ALIGN(size_vpp, DMA_ALIGNMENT) + + ALIGN(SIZE_HW_PIC(SIZE_H264D_HW_PIC_T), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + static u32 size_h265d_vpp_cmd_buf(u32 frame_width, u32 frame_height) { u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * @@ -269,6 +396,20 @@ static u32 size_h265d_vpp_cmd_buf(u32 frame_width, u32 frame_height) return _size; } +static u32 size_h265d_vpp_cmd_buf_ar50lt(u32 frame_width, u32 frame_height) +{ + u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) * + NUM_HW_PIC_BUF, DMA_ALIGNMENT); + _size = min_t(u32, _size, H265D_MAX_SLICE_AR50LT + 1); + _size = ALIGN(_size, 4); + _size = 2 * _size * SIZE_H265D_VPP_CMD_PER_BUF_AR50LT; + if (_size > VPP_CMD_MAX_SIZE) + _size = VPP_CMD_MAX_SIZE; + + return _size; +} + static u32 hfi_buffer_non_comv_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) { u32 _size_bse = size_h265d_bse_cmd_buf(frame_width, frame_height); @@ -285,6 +426,20 @@ static u32 hfi_buffer_non_comv_h265d(u32 frame_width, u32 frame_height, u32 num_ return ALIGN(_size, DMA_ALIGNMENT); } +static u32 hfi_buffer_non_comv_h265d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + u32 _size_bse = size_h265d_bse_cmd_buf_ar50lt(frame_width, frame_height); + u32 _size_vpp = size_h265d_vpp_cmd_buf_ar50lt(frame_width, frame_height); + u32 _size = ALIGN(_size_bse, DMA_ALIGNMENT) + + ALIGN(_size_vpp, DMA_ALIGNMENT) + + ALIGN(2 * sizeof(u16) * + (ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) * + (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS), DMA_ALIGNMENT) + + ALIGN(SIZE_HW_PIC(SIZE_H265D_HW_PIC_T), DMA_ALIGNMENT); + + return ALIGN(_size, DMA_ALIGNMENT); +} + static u32 size_vpss_lb(u32 frame_width, u32 frame_height) { u32 opb_lb_wr_llb_y_buffer_size, opb_lb_wr_llb_uv_buffer_size; @@ -317,6 +472,13 @@ u32 size_h265d_lb_fe_top_data(u32 frame_width, u32 frame_height) (ALIGN(frame_width, 64) + 8) * 2; } +static inline +u32 size_h265d_lb_fe_top_data_ar50lt(u32 frame_width, u32 frame_height) +{ + return ALIGN(MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * + (ALIGN(frame_width, 64) + 8), DMA_ALIGNMENT) * 2; +} + static inline u32 size_h265d_lb_fe_top_ctrl(u32 frame_width, u32 frame_height) { @@ -348,6 +510,17 @@ u32 size_h265d_lb_se_left_ctrl(u32 frame_width, u32 frame_height) MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)); } +static inline +u32 size_h265d_lb_se_left_ctrl_ar50lt(u32 frame_width, u32 frame_height) +{ + return max_t(u32, ((frame_height + 16 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT, + max_t(u32, ((frame_height + 32 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT, + ((frame_height + 64 - 1) / 8) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT)); +} + static inline u32 size_h265d_lb_pe_top_data(u32 frame_width, u32 frame_height) { @@ -355,6 +528,13 @@ u32 size_h265d_lb_pe_top_data(u32 frame_width, u32 frame_height) (ALIGN(frame_width, LCU_MIN_SIZE_PELS) / LCU_MIN_SIZE_PELS); } +static inline +u32 size_h265d_lb_pe_top_data_ar50lt(u32 frame_width, u32 frame_height) +{ + return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE_AR50LT * + (ALIGN(frame_width, LCU_MIN_SIZE_PELS) / LCU_MIN_SIZE_PELS); +} + static inline u32 size_h265d_lb_vsp_top(u32 frame_width, u32 frame_height) { @@ -404,6 +584,29 @@ u32 hfi_buffer_line_h265d(u32 frame_width, u32 frame_height, bool is_opb, u32 nu return ALIGN((_size + vpss_lb_size), DMA_ALIGNMENT); } +static inline +u32 hfi_buffer_line_h265d_ar50lt(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes) +{ + u32 size; + + size = ALIGN(size_h265d_lb_fe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_fe_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_fe_left_ctrl(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_se_left_ctrl_ar50lt(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_pe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_h265d_lb_vsp_left(frame_width, frame_height), + DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h265d_lb_recon_dma_metadata_wr(frame_width, frame_height), + DMA_ALIGNMENT) * 4 + + ALIGN(size_h265d_qp(frame_width, frame_height), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + static inline u32 size_vpxd_lb_fe_left_ctrl(u32 frame_width, u32 frame_height) { @@ -438,6 +641,17 @@ u32 size_vpxd_lb_se_left_ctrl(u32 frame_width, u32 frame_height) MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE)); } +static inline +u32 size_vpxd_lb_se_left_ctrl_ar50lt(u32 frame_width, u32 frame_height) +{ + return max_t(u32, ((frame_height + 15) >> 4) * + MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT, + max_t(u32, ((frame_height + 31) >> 5) * + MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT, + ((frame_height + 63) >> 6) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT)); +} + static inline u32 size_vpxd_lb_recon_dma_metadata_wr(u32 frame_width, u32 frame_height) { @@ -492,6 +706,19 @@ u32 hfi_iris3_vp9d_lb_size(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) ALIGN(size_vp9d_qp(frame_width, frame_height), DMA_ALIGNMENT); } +static inline +u32 hfi_ar50lt_vp9d_lb_size(u32 frame_width, u32 frame_height, u32 num_vpp_pipes) +{ + return ALIGN(size_vpxd_lb_fe_left_ctrl(frame_width, frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_vpxd_lb_se_left_ctrl_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_vp9d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vpxd_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vp9d_lb_pe_top_data(frame_width, frame_height), DMA_ALIGNMENT) + + ALIGN(size_vp9d_lb_fe_top_data(frame_width, frame_height), DMA_ALIGNMENT); +} + static inline u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min, bool is_opb, u32 num_vpp_pipes) @@ -507,6 +734,13 @@ u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_mi return _lb_size + vpss_lb_size + 4096; } +static inline +u32 hfi_buffer_line_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min, + bool is_opb, u32 num_vpp_pipes) +{ + return hfi_ar50lt_vp9d_lb_size(frame_width, frame_height, num_vpp_pipes); +} + static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes) { @@ -529,6 +763,25 @@ static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height, return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT); } +static u32 hfi_buffer_line_h264d_ar50lt(u32 frame_width, u32 frame_height, + bool is_opb, u32 num_vpp_pipes) +{ + u32 size; + + size = ALIGN(size_h264d_lb_fe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_fe_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes + + ALIGN(size_h264d_lb_se_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_se_left_ctrl_ar50lt(frame_height), DMA_ALIGNMENT) * + num_vpp_pipes + + ALIGN(size_h264d_lb_pe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_vsp_top(frame_width), DMA_ALIGNMENT) + + ALIGN(size_h264d_lb_recon_dma_metadata_wr(frame_height), DMA_ALIGNMENT) * 2 + + ALIGN(size_h264d_qp(frame_width, frame_height), DMA_ALIGNMENT); + + return ALIGN(size, DMA_ALIGNMENT); +} + static u32 size_av1d_lb_opb_wr1_nv12_ubwc(u32 frame_width, u32 frame_height) { u32 size, y_width, y_width_a = 128; @@ -724,6 +977,23 @@ static u32 iris_vpu_dec_bin_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_bin_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_bin_h264d_ar50lt(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_bin_h265d_ar50lt(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_bin_vp9d_ar50lt(width, height, num_vpp_pipes); + + return 0; +} + static u32 iris_vpu_dec_comv_size(struct iris_inst *inst) { u32 num_comv = VIDEO_MAX_FRAME; @@ -785,6 +1055,18 @@ static u32 iris_vpu_dec_persist_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_persist_size(struct iris_inst *inst) +{ + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_persist_h264d_ar50lt(); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_persist_h265d_ar50lt(); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_persist_vp9d_ar50lt(); + + return 0; +} + static u32 iris_vpu_dec_dpb_size(struct iris_inst *inst) { if (iris_split_mode_enabled(inst)) @@ -808,6 +1090,21 @@ static u32 iris_vpu_dec_non_comv_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_non_comv_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_non_comv_h264d_ar50lt(width, height, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_non_comv_h265d_ar50lt(width, height, num_vpp_pipes); + + return 0; +} + static u32 iris_vpu_dec_line_size(struct iris_inst *inst) { u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; @@ -833,6 +1130,29 @@ static u32 iris_vpu_dec_line_size(struct iris_inst *inst) return 0; } +static u32 iris_vpu_ar50lt_dec_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + bool is_opb = false; + u32 out_min_count = inst->buffers[BUF_OUTPUT].min_count; + + if (iris_split_mode_enabled(inst)) + is_opb = true; + + if (inst->codec == V4L2_PIX_FMT_H264) + return hfi_buffer_line_h264d_ar50lt(width, height, is_opb, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_HEVC) + return hfi_buffer_line_h265d_ar50lt(width, height, is_opb, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_VP9) + return hfi_buffer_line_vp9d_ar50lt(width, height, out_min_count, is_opb, + num_vpp_pipes); + + return 0; +} + static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) { return iris_vpu_dec_comv_size(inst) + @@ -840,6 +1160,13 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst) iris_vpu_dec_line_size(inst); } +static u32 iris_vpu_ar50lt_dec_scratch1_size(struct iris_inst *inst) +{ + return iris_vpu_dec_comv_size(inst) + + iris_vpu_ar50lt_dec_non_comv_size(inst) + + iris_vpu_ar50lt_dec_line_size(inst); +} + static inline u32 iris_vpu_enc_get_bitstream_width(struct iris_inst *inst) { if (is_rotation_90_or_270(inst)) @@ -1470,6 +1797,15 @@ u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit) return size; } +static inline +u32 hfi_buffer_dpb_enc_ar50lt(u32 frame_width, u32 frame_height, bool is_ten_bit) +{ + if (!is_ten_bit) + return size_enc_ref_buffer(frame_width, frame_height); + else + return size_enc_ten_bit_ref_buffer(frame_width, frame_height); +} + static u32 iris_vpu_enc_arp_size(struct iris_inst *inst) { return HFI_BUFFER_ARP_ENC; @@ -1494,6 +1830,16 @@ u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable, return 0; } +static inline +u32 hfi_buffer_vpss_enc_ar50lt(u32 dswidth, u32 dsheight, bool ds_enable, + u32 blur, bool is_ten_bit) +{ + if (ds_enable || blur) + return hfi_buffer_dpb_enc_ar50lt(dswidth, dsheight, is_ten_bit); + + return 0; +} + static inline u32 hfi_buffer_scratch1_enc(u32 frame_width, u32 frame_height, u32 lcu_size, u32 num_ref, bool ten_bit, u32 num_vpp_pipes, @@ -1752,6 +2098,16 @@ static u32 iris_vpu_enc_vpss_size(struct iris_inst *inst) return hfi_buffer_vpss_enc(width, height, ds_enable, 0, 0); } +static u32 iris_vpu_ar50lt_enc_vpss_size(struct iris_inst *inst) +{ + u32 ds_enable = is_scaling_enabled(inst); + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + + return hfi_buffer_vpss_enc_ar50lt(width, height, ds_enable, 0, 0); +} + static inline u32 size_dpb_opb(u32 height, u32 lcu_size) { u32 max_tile_height = ((height + lcu_size - 1) / lcu_size) * lcu_size + 8; @@ -2194,6 +2550,64 @@ u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_typ return size; } +u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; + int ret; + + /* return 0 on error to let the driver cope */ + ret = hfi_ops->session_get_property(inst, HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS); + if (ret) + return 0; + + return inst->buffers[buffer_type].size; +} + +u32 iris_vpu_ar50lt_gen2_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL; + u32 size = 0, buf_type_handle_size = 0, i; + + static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_ar50lt_dec_bin_size }, + {BUF_COMV, iris_vpu_dec_comv_size }, + {BUF_NON_COMV, iris_vpu_ar50lt_dec_non_comv_size }, + {BUF_LINE, iris_vpu_ar50lt_dec_line_size }, + {BUF_PERSIST, iris_vpu_ar50lt_dec_persist_size }, + {BUF_DPB, iris_vpu_dec_dpb_size }, + {BUF_SCRATCH_1, iris_vpu_ar50lt_dec_scratch1_size }, + {BUF_PARTIAL, iris_vpu_dec_partial_size }, + }; + + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_ar50lt_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) { + buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr = dec_internal_buf_type_handle; + } else if (inst->domain == ENCODER) { + buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle); + buf_type_handle_arr = enc_internal_buf_type_handle; + } + + for (i = 0; i < buf_type_handle_size; i++) { + if (buf_type_handle_arr[i].type == buffer_type) { + size = buf_type_handle_arr[i].handle(inst); + break; + } + } + + return size; +} + static u32 internal_buffer_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) { diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 8c0d6b7b5de85..2085e316a6bd8 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -61,17 +61,26 @@ struct iris_inst; #define MAX_FE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE 64 #define MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE (128 / 8) #define MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE (128 / 8) +#define MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT (8 / 8) +#define MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT (16 / 8) +#define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT (32 / 8) #define VP9_UDC_HEADER_BUF_SIZE (3 * 128) #define SIZE_SEI_USERDATA 4096 #define SIZE_DOLBY_RPU_METADATA (41 * 1024) #define H264_CABAC_HDR_RATIO_HD_TOT 1 #define H264_CABAC_RES_RATIO_HD_TOT 3 +#define H264_CABAC_HDR_RATIO_SM_TOT 1 +#define H264_CABAC_RES_RATIO_SM_TOT 2 #define H265D_MAX_SLICE 3600 +#define H265D_MAX_SLICE_AR50LT 600 #define SIZE_H265D_HW_PIC_T SIZE_H264D_HW_PIC_T #define H265_CABAC_HDR_RATIO_HD_TOT 2 #define H265_CABAC_RES_RATIO_HD_TOT 2 +#define H265_CABAC_HDR_RATIO_SM_TOT 1 +#define H265_CABAC_RES_RATIO_SM_TOT 6 #define SIZE_H265D_VPP_CMD_PER_BUF (256) +#define SIZE_H265D_VPP_CMD_PER_BUF_AR50LT (192) #define SIZE_THREE_DIMENSION_USERDATA 768 #define SIZE_H265D_ARP 9728 @@ -81,6 +90,7 @@ struct iris_inst; #define VPX_DECODER_FRAME_BIN_DENOMINATOR 2 #define VPX_DECODER_FRAME_BIN_RES_BUDGET_RATIO (3 / 2) +#define VPX_DECODER_FRAME_BIN_BUFFER_SIZE (1024 * 1024) #define SIZE_H264D_HW_PIC_T (BIT(11)) @@ -99,6 +109,7 @@ struct iris_inst; #define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64 #define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 16 #define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384 +#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE_AR50LT 176 #define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640 #define AV1_CABAC_HDR_RATIO_HD_TOT 2 @@ -155,11 +166,21 @@ static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; } +static inline u32 size_h264d_lb_fe_top_data_ar50lt(u32 frame_width) +{ + return 16 * ALIGN(frame_width, 16) * 2; +} + static inline u32 size_h264d_lb_fe_top_ctrl(u32 frame_width) { return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); } +static inline u32 size_h264d_lb_fe_top_ctrl_ar50lt(u32 frame_width) +{ + return 16 * DIV_ROUND_UP(frame_width, 16); +} + static inline u32 size_h264d_lb_fe_left_ctrl(u32 frame_height) { return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); @@ -170,16 +191,31 @@ static inline u32 size_h264d_lb_se_top_ctrl(u32 frame_width) return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); } +static inline u32 size_h264d_lb_se_top_ctrl_ar50lt(u32 frame_width) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT * DIV_ROUND_UP(frame_width, 16); +} + static inline u32 size_h264d_lb_se_left_ctrl(u32 frame_height) { return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16); } +static inline u32 size_h264d_lb_se_left_ctrl_ar50lt(u32 frame_height) +{ + return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT * DIV_ROUND_UP(frame_height, 16); +} + static inline u32 size_h264d_lb_pe_top_data(u32 frame_width) { return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16); } +static inline u32 size_h264d_lb_pe_top_data_ar50lt(u32 frame_width) +{ + return 64 * DIV_ROUND_UP(frame_width, 16); +} + static inline u32 size_h264d_lb_vsp_top(u32 frame_width) { return (DIV_ROUND_UP(frame_width, 16) << 7); @@ -288,6 +324,8 @@ static inline u32 size_av1d_qp(u32 frame_width, u32 frame_height) u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu_ar50lt_gen2_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index ab41da1f47c82..ac9881e2cdc29 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -31,7 +31,7 @@ #define UC_REGION_ADDR (CPU_CS_BASE_OFFS + 0x64) #define UC_REGION_SIZE (CPU_CS_BASE_OFFS + 0x68) -static void iris_vpu_interrupt_init(struct iris_core *core) +void iris_vpu_interrupt_init(struct iris_core *core) { u32 mask_val; @@ -78,7 +78,6 @@ int iris_vpu_boot_firmware(struct iris_core *core) iris_vpu_setup_ucregion_memory_map(core); writel(ctrl_init, core->reg_base + CTRL_INIT); - writel(0x1, core->reg_base + CPU_CS_SCIACMDARG3); while (!ctrl_status && count < max_tries) { ctrl_status = readl(core->reg_base + CTRL_STATUS); @@ -97,7 +96,8 @@ int iris_vpu_boot_firmware(struct iris_core *core) } writel(HOST2XTENSA_INTR_ENABLE, core->reg_base + CPU_CS_H2XSOFTINTEN); - writel(0x0, core->reg_base + CPU_CS_X2RPMH); + if (!core->iris_platform_data->no_rpmh) + writel(0x0, core->reg_base + CPU_CS_X2RPMH); return 0; } @@ -109,11 +109,11 @@ void iris_vpu_raise_interrupt(struct iris_core *core) void iris_vpu_clear_interrupt(struct iris_core *core) { + u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask; u32 intr_status, mask; intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS); - mask = (WRAPPER_INTR_STATUS_A2H_BMSK | - WRAPPER_INTR_STATUS_A2HWD_BMSK | + mask = (WRAPPER_INTR_STATUS_A2H_BMSK | wd_intr_mask | CTRL_INIT_IDLE_MSG_BMSK); if (intr_status & mask) @@ -124,7 +124,9 @@ void iris_vpu_clear_interrupt(struct iris_core *core) int iris_vpu_watchdog(struct iris_core *core, u32 intr_status) { - if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) { + u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask; + + if (intr_status & wd_intr_mask) { dev_err(core->dev, "received watchdog interrupt\n"); return -ETIME; } @@ -214,19 +216,19 @@ int iris_vpu_power_off_controller(struct iris_core *core) disable_power: iris_disable_unprepare_clock(core, IRIS_AHB_CLK); iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return 0; } void iris_vpu_power_off_hw(struct iris_core *core) { - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, false); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); } void iris_vpu_power_off(struct iris_core *core) @@ -245,7 +247,7 @@ int iris_vpu_power_on_controller(struct iris_core *core) u32 rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); if (ret) return ret; @@ -253,7 +255,7 @@ int iris_vpu_power_on_controller(struct iris_core *core) if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_VCODEC_CLK); if (ret) goto err_disable_power; @@ -270,9 +272,9 @@ int iris_vpu_power_on_controller(struct iris_core *core) err_disable_ctrl_clock: iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); err_disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return ret; } @@ -281,15 +283,15 @@ int iris_vpu_power_on_hw(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_CLK); if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_HW_AHB_CLK); + ret = iris_prepare_enable_clock(core, IRIS_VCODEC_AHB_CLK); if (ret && ret != -ENOENT) goto err_disable_hw_clock; @@ -300,18 +302,18 @@ int iris_vpu_power_on_hw(struct iris_core *core) return 0; err_disable_hw_ahb_clock: - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_AHB_CLK); err_disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); + iris_disable_unprepare_clock(core, IRIS_VCODEC_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_VCODEC_POWER_DOMAIN); return ret; } int iris_vpu_set_hwmode(struct iris_core *core) { - return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true); + return iris_genpd_set_hwmode(core, IRIS_VCODEC_POWER_DOMAIN, true); } int iris_vpu_switch_to_hwmode(struct iris_core *core) @@ -374,9 +376,9 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core) disable_power: iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_CTRL_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); reset_control_bulk_reset(clk_rst_tbl_size, core->resets); @@ -387,11 +389,11 @@ int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) { int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + ret = iris_enable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); if (ret) return ret; - ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); + ret = iris_prepare_enable_clock(core, IRIS_AXI_CTRL_CLK); if (ret) goto err_disable_power; @@ -408,9 +410,9 @@ int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) err_disable_ctrl_free_clk: iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); err_disable_axi1_clk: - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); + iris_disable_unprepare_clock(core, IRIS_AXI_CTRL_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domains(core, IRIS_CTRL_POWER_DOMAIN); return ret; } @@ -483,9 +485,9 @@ int iris_vpu_power_on(struct iris_core *core) iris_opp_set_rate(core->dev, freq); - iris_vpu_set_preset_registers(core); + core->iris_platform_data->vpu_ops->set_preset_registers(core); - iris_vpu_interrupt_init(core); + core->iris_platform_data->vpu_ops->interrupt_init(core); core->intr_status = 0; enable_irq(core->irq); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 09799a375c142..8d954426a9482 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -12,7 +12,9 @@ extern const struct vpu_ops iris_vpu2_ops; extern const struct vpu_ops iris_vpu3_ops; extern const struct vpu_ops iris_vpu33_ops; extern const struct vpu_ops iris_vpu35_ops; +extern const struct vpu_ops iris_vpu36_ops; extern const struct vpu_ops iris_vpu4x_ops; +extern const struct vpu_ops iris_vpu_ar50lt_ops; struct vpu_ops { void (*power_off_hw)(struct iris_core *core); @@ -22,6 +24,9 @@ struct vpu_ops { void (*program_bootup_registers)(struct iris_core *core); u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); int (*set_hwmode)(struct iris_core *core); + void (*set_preset_registers)(struct iris_core *core); + void (*interrupt_init)(struct iris_core *core); + void (*disable_arp)(struct iris_core *core); }; int iris_vpu_boot_firmware(struct iris_core *core); @@ -43,5 +48,6 @@ void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core); u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size); void iris_vpu_set_preset_registers(struct iris_core *core); +void iris_vpu_interrupt_init(struct iris_core *core); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h index 72168b9ffa738..dc29e950f01cc 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h @@ -7,6 +7,7 @@ #define __IRIS_VPU_REGISTER_DEFINES_H__ #define VCODEC_BASE_OFFS 0x00000000 +#define VCODEC1_BASE_OFFS 0x00040000 #define AON_MVP_NOC_RESET 0x0001F000 #define CPU_BASE_OFFS 0x000A0000 #define WRAPPER_BASE_OFFS 0x000B0000 @@ -14,6 +15,8 @@ #define AON_BASE_OFFS 0x000E0000 #define VCODEC_SS_IDLE_STATUSN (VCODEC_BASE_OFFS + 0x70) +#define VCODEC1_SS_IDLE_STATUSN (VCODEC1_BASE_OFFS + 0x70) +#define DMA_NOC_IDLE BIT(22) #define AON_WRAPPER_MVP_NOC_RESET_REQ (AON_MVP_NOC_RESET + 0x000) #define VIDEO_NOC_RESET_REQ (BIT(0) | BIT(1)) @@ -35,13 +38,14 @@ #define CPU_CS_AHB_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS + 0x160) #define CORE_BRIDGE_SW_RESET BIT(0) #define CORE_BRIDGE_HW_RESET_DISABLE BIT(1) +#define VCODEC1_BRIDGE_SW_RESET BIT(2) +#define VCODEC1_BRIDGE_HW_RESET_DISABLE BIT(3) #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) #define MSK_SIGNAL_FROM_TENSILICA BIT(0) #define MSK_CORE_POWER_ON BIT(1) #define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) -#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3) #define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2) #define WRAPPER_INTR_MASK (WRAPPER_BASE_OFFS + 0x10) @@ -52,11 +56,13 @@ #define WRAPPER_DEBUG_BRIDGE_LPI_STATUS (WRAPPER_BASE_OFFS + 0x58) #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) #define REQ_POWER_DOWN_PREP BIT(0) +#define REQ_VCODEC1_POWER_DOWN_PREP BIT(1) #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) #define NOC_LPI_STATUS_DONE BIT(0) /* Indicates the NOC handshake is complete */ #define NOC_LPI_STATUS_DENY BIT(1) /* Indicates the NOC handshake is denied */ #define NOC_LPI_STATUS_ACTIVE BIT(2) /* Indicates the NOC is active */ +#define NOC_LPI_VCODEC1_STATUS_DONE BIT(8) #define WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0 (WRAPPER_BASE_OFFS + 0x78) #define WRAPPER_CORE_POWER_STATUS (WRAPPER_BASE_OFFS + 0x80) diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 243e342b0ae75..3c88594eb1d00 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -1118,7 +1118,6 @@ static const struct venus_resources sc7280_res = { .dec_nodename = "video-decoder", .enc_nodename = "video-encoder", }; -#endif static const struct bw_tbl qcm2290_bw_table_dec[] = { { 352800, 597000, 0, 746000, 0 }, /* 1080p@30 + 720p@30 */ @@ -1169,13 +1168,16 @@ static const struct venus_resources qcm2290_res = { .enc_nodename = "video-encoder", .min_fw = &min_fw, }; +#endif static const struct of_device_id venus_dt_match[] = { { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, }, { .compatible = "qcom,msm8939-venus", .data = &msm8939_res, }, { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, }, { .compatible = "qcom,msm8998-venus", .data = &msm8998_res, }, +#if (!IS_ENABLED(CONFIG_VIDEO_QCOM_IRIS)) { .compatible = "qcom,qcm2290-venus", .data = &qcm2290_res, }, +#endif { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, { .compatible = "qcom,sdm660-venus", .data = &sdm660_res, }, { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, }, diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 46705a6667762..a52cd14539183 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -223,6 +223,8 @@ struct venus_core { size_t mapped_mem_size; phys_addr_t mem_phys; size_t mem_size; + struct qcom_scm_pas_context *ctx; + bool iommu_domain_owned; } fw; struct mutex lock; struct list_head instances; diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 1de7436713ed9..dbfb322a99978 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "core.h" #include "firmware.h" @@ -78,87 +79,125 @@ int venus_set_hw_state(struct venus_core *core, bool resume) return 0; } -static int venus_load_fw(struct venus_core *core, const char *fwname, - phys_addr_t *mem_phys, size_t *mem_size) +static int venus_load_fw_prepare(struct venus_core *core, const char *fwname, + phys_addr_t *mem_phys, size_t *res_size, + const struct firmware **mdt) { - const struct firmware *mdt; struct resource res; - struct device *dev; ssize_t fw_size; - void *mem_va; int ret; - *mem_phys = 0; - *mem_size = 0; - - dev = core->dev; - ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); + ret = of_reserved_mem_region_to_resource(core->dev->of_node, 0, &res); if (ret) { - dev_err(dev, "failed to lookup reserved memory-region\n"); + dev_err(core->dev, "failed to lookup reserved memory-region\n"); return -EINVAL; } - ret = request_firmware(&mdt, fwname, dev); - if (ret < 0) + *mem_phys = res.start; + *res_size = resource_size(&res); + + ret = request_firmware(mdt, fwname, core->dev); + if (ret < 0) { + dev_err(core->dev, "%s: request_firmware: %d\n", __func__, ret); return ret; + } - fw_size = qcom_mdt_get_size(mdt); + fw_size = qcom_mdt_get_size(*mdt); if (fw_size < 0) { ret = fw_size; - goto err_release_fw; + goto err_release; } - *mem_phys = res.start; - *mem_size = resource_size(&res); - - if (*mem_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) { + if (*res_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) { ret = -EINVAL; - goto err_release_fw; - } - - mem_va = memremap(*mem_phys, *mem_size, MEMREMAP_WC); - if (!mem_va) { - dev_err(dev, "unable to map memory region %pa size %#zx\n", mem_phys, *mem_size); - ret = -ENOMEM; - goto err_release_fw; + goto err_release; } - if (core->use_tz) - ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, - mem_va, *mem_phys, *mem_size, NULL); - else - ret = qcom_mdt_load_no_init(dev, mdt, fwname, mem_va, - *mem_phys, *mem_size, NULL); + return 0; - memunmap(mem_va); -err_release_fw: - release_firmware(mdt); +err_release: + release_firmware(*mdt); return ret; } -static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys, - size_t mem_size) +static int venus_load_fw(struct venus_core *core, + const struct firmware *mdt, const char *fwname, + phys_addr_t mem_phys, size_t res_size) { - struct iommu_domain *iommu; + struct qcom_scm_pas_context *ctx; struct device *dev; int ret; - dev = core->fw.dev; - if (!dev) - return -EPROBE_DEFER; + dev = core->fw.dev ? core->fw.dev : core->dev; + ctx = devm_qcom_scm_pas_context_alloc(dev, VENUS_PAS_ID, mem_phys, res_size); + if (!ctx) { + dev_err(core->dev, "%s: ctx is null\n", __func__); + return -ENOMEM; + } - iommu = core->fw.iommu_domain; - core->fw.mapped_mem_size = mem_size; + ctx->use_tzmem = !!core->fw.dev; - ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size, - IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + ret = qcom_mdt_pas_load(ctx, mdt, fwname, NULL); + qcom_scm_pas_metadata_release(ctx); if (ret) { - dev_err(dev, "could not map video firmware region\n"); + dev_err(core->dev, "%s: qcom_mdt_pas_load: %d\n", __func__, ret); return ret; } - venus_reset_cpu(core); + if (core->fw.iommu_domain) { + ret = iommu_map(core->fw.iommu_domain, 0, mem_phys, res_size, + IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) { + dev_err(core->dev, "%s: iommu_map: %d\n", __func__, ret); + return ret; + } + } + + core->fw.mapped_mem_size = res_size; + + ret = qcom_scm_pas_prepare_and_auth_reset(ctx); + if (ret) { + dev_err(core->dev, "%s: qcom_scm_pas_prepare_and_auth_reset: %d\n", __func__, ret); + if (core->fw.iommu_domain) + iommu_unmap(core->fw.iommu_domain, 0, res_size); + core->fw.mapped_mem_size = 0; + return ret; + } + core->fw.ctx = ctx; + return 0; +} + +static int venus_load_fw_no_tz(struct venus_core *core, + const struct firmware *mdt, const char *fwname, + phys_addr_t mem_phys, size_t res_size) +{ + void *mem_va; + int ret; + + mem_va = memremap(mem_phys, res_size, MEMREMAP_WC); + if (!mem_va) { + dev_err(core->dev, + "unable to map memory region %pa size %#zx\n", &mem_phys, res_size); + return -ENOMEM; + } + + ret = qcom_mdt_load_no_init(core->fw.dev, mdt, fwname, mem_va, mem_phys, res_size, NULL); + memunmap(mem_va); + if (ret) { + dev_err(core->dev, "%s: qcom_mdt_load_no_init: %d\n", __func__, ret); + return ret; + } + + ret = iommu_map(core->fw.iommu_domain, VENUS_FW_START_ADDR, mem_phys, + res_size, IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) { + dev_err(core->dev, "could not map video firmware region\n"); + return ret; + } + + core->fw.mapped_mem_size = res_size; + venus_reset_cpu(core); return 0; } @@ -212,36 +251,35 @@ int venus_boot(struct venus_core *core) { struct device *dev = core->dev; const struct venus_resources *res = core->res; + const struct firmware *mdt; const char *fwpath = NULL; phys_addr_t mem_phys; - size_t mem_size; + size_t res_size; int ret; if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || - (core->use_tz && !qcom_scm_is_available())) - return -EPROBE_DEFER; + (!core->use_tz && !core->fw.dev)) + return driver_deferred_probe_check_state(core->dev); - ret = of_property_read_string_index(dev->of_node, "firmware-name", 0, - &fwpath); + ret = of_property_read_string_index(dev->of_node, "firmware-name", 0, &fwpath); if (ret) fwpath = core->res->fwname; - ret = venus_load_fw(core, fwpath, &mem_phys, &mem_size); - if (ret) { - dev_err(dev, "fail to load video firmware\n"); - return -EINVAL; - } - - core->fw.mem_size = mem_size; - core->fw.mem_phys = mem_phys; + ret = venus_load_fw_prepare(core, fwpath, &mem_phys, &res_size, &mdt); + if (ret) + return ret; if (core->use_tz) - ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID); + ret = venus_load_fw(core, mdt, fwpath, mem_phys, res_size); else - ret = venus_boot_no_tz(core, mem_phys, mem_size); + ret = venus_load_fw_no_tz(core, mdt, fwpath, mem_phys, res_size); - if (ret) + release_firmware(mdt); + + if (ret) { + dev_err(dev, "fail to load video firmware\n"); return ret; + } if (core->use_tz && res->cp_size) { /* @@ -259,24 +297,29 @@ int venus_boot(struct venus_core *core) res->cp_nonpixel_start, res->cp_nonpixel_size); if (ret) { - qcom_scm_pas_shutdown(VENUS_PAS_ID); - dev_err(dev, "set virtual address ranges fail (%d)\n", - ret); + venus_shutdown(core); + dev_err(dev, "set virtual address ranges fail (%d)\n", ret); return ret; } } - return 0; + return ret; } int venus_shutdown(struct venus_core *core) { int ret; - if (core->use_tz) + if (core->use_tz) { ret = qcom_scm_pas_shutdown(VENUS_PAS_ID); - else + if (core->fw.iommu_domain && core->fw.mapped_mem_size) { + iommu_unmap(core->fw.iommu_domain, 0, core->fw.mapped_mem_size); + core->fw.mapped_mem_size = 0; + } + core->fw.ctx = NULL; + } else { ret = venus_shutdown_no_tz(core); + } return ret; } @@ -301,6 +344,94 @@ int venus_firmware_check(struct venus_core *core) return -EINVAL; } +static struct device *venus_firmware_alloc_platform_dev(struct venus_core *core, + const char *name, const u32 *f_id) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, 0); + if (!pdev) { + dev_err(core->dev, "%s: platform_device_alloc err\n", __func__); + return ERR_PTR(-ENOMEM); + } + + pdev->dev.parent = core->dev; + + ret = platform_device_add(pdev); + if (ret) { + dev_err(core->dev, "%s: platform_device_add err(%d)\n", __func__, ret); + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = of_dma_configure_id(&pdev->dev, core->dev->of_node, true, f_id); + if (ret) { + dev_err(core->dev, "%s: of_dma_configure_id err(%d)\n", __func__, ret); + platform_device_unregister(to_platform_device(&pdev->dev)); + return ERR_PTR(ret); + } + + return &pdev->dev; +} + +static int venus_firmware_setup_iommu_dev(struct venus_core *core) +{ + const u32 f_id = VENUS_FIRMWARE; + struct device *dev; + int ret = 0; + + dev = venus_firmware_alloc_platform_dev(core, "video_firmware", &f_id); + if (IS_ERR(dev)) { + dev_err(core->dev, "%s: err\n", __func__); + return PTR_ERR(dev); + } + + if (!device_iommu_mapped(dev)) { + device_unregister(dev); + return -ENODEV; + } + + ret = dma_set_mask_and_coherent(dev, core->res->dma_mask); + if (ret) { + device_unregister(dev); + return ret; + } + + core->fw.dev = dev; + core->fw.iommu_domain = iommu_get_domain_for_dev(core->fw.dev); + core->fw.iommu_domain_owned = false; + + return 0; +} + +static int venus_firmware_init_auto_detect(struct venus_core *core) +{ + int ret; + + core->use_tz = false; + if (qcom_scm_is_available()) { + if (qcom_scm_pas_supported(VENUS_PAS_ID)) + core->use_tz = true; + } else { + ret = driver_deferred_probe_check_state(core->dev); + if (ret == -EPROBE_DEFER) + return ret; + } + + /* + * 1. use_tz is false: No authentication is performed. + * 2. use_tz is true: TZ perform authentication. + * a. device_iommu_mapped true: Linux config smmu + * b. device_iommu_mapped false: TZ config smmu + */ + ret = venus_firmware_setup_iommu_dev(core); + if (ret == -ENODEV && core->use_tz) + ret = 0; + + return ret; +} + int venus_firmware_init(struct venus_core *core) { struct platform_device_info info; @@ -311,8 +442,8 @@ int venus_firmware_init(struct venus_core *core) np = of_get_child_by_name(core->dev->of_node, "video-firmware"); if (!np) { - core->use_tz = true; - return 0; + ret = venus_firmware_init_auto_detect(core); + return ret; } memset(&info, 0, sizeof(info)); @@ -351,6 +482,7 @@ int venus_firmware_init(struct venus_core *core) } core->fw.iommu_domain = iommu_dom; + core->fw.iommu_domain_owned = true; of_node_put(np); @@ -359,6 +491,7 @@ int venus_firmware_init(struct venus_core *core) err_iommu_free: iommu_domain_free(iommu_dom); err_unregister: + core->fw.dev = NULL; platform_device_unregister(pdev); of_node_put(np); return ret; @@ -371,14 +504,17 @@ void venus_firmware_deinit(struct venus_core *core) if (!core->fw.dev) return; - iommu = core->fw.iommu_domain; - - iommu_detach_device(iommu, core->fw.dev); + if (!core->use_tz && core->fw.iommu_domain_owned) { + iommu = core->fw.iommu_domain; - if (core->fw.iommu_domain) { - iommu_domain_free(iommu); - core->fw.iommu_domain = NULL; + if (iommu) { + iommu_detach_device(iommu, core->fw.dev); + iommu_domain_free(iommu); + } } - platform_device_unregister(to_platform_device(core->fw.dev)); + core->fw.dev = NULL; + core->fw.ctx = NULL; + core->fw.iommu_domain = NULL; + core->fw.iommu_domain_owned = false; } diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 390256ed91f41..4791ac9e4e1db 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -310,6 +310,20 @@ config QCOM_FASTRPC applications DSP processor. Say M if you want to enable this module. +config QCOM_DCC + tristate "Qualcomm Data Capture and Compare (DCC) engine driver" + depends on ARCH_QCOM || COMPILE_TEST + help + This option enables the driver for the Data Capture and Compare engine. DCC + driver provides interfaces to configure DCC block and read back the captured + data from the DCC's internal SRAM. The module name for this is qcom-dcc. + +config QCOM_DCC_DEV + tristate "Qualcomm Data Capture and Compare (DCC) engine device instance" + depends on QCOM_DCC + help + This is the device instance of the QCOM DCC driver. + config SGI_GRU tristate "SGI GRU driver" depends on X86_UV && SMP diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index fed47c7672b95..b3e5e5c01dd18 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -74,3 +74,5 @@ obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o obj-y += keba/ obj-y += amd-sbi/ obj-$(CONFIG_MISC_RP1) += rp1/ +obj-$(CONFIG_QCOM_DCC) += qcom-dcc.o +obj-$(CONFIG_QCOM_DCC_DEV) += qcom-dcc-dev.o diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index f3a49384586d1..27a07bfef3c6f 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #define ADSP_DOMAIN_ID (0) #define MDSP_DOMAIN_ID (1) @@ -37,7 +40,13 @@ #define FASTRPC_CTX_MAX (256) #define FASTRPC_INIT_HANDLE 1 #define FASTRPC_DSP_UTILITIES_HANDLE 2 -#define FASTRPC_CTXID_MASK (0xFF0) +/* + * Maximum handle value for static handles. + * Static handles are pre-defined, fixed numeric values statically assigned + * in the IDL file or FastRPC framework. + */ +#define FASTRPC_MAX_STATIC_HANDLE (20) +#define FASTRPC_CTXID_MASK GENMASK(15, 8) #define INIT_FILELEN_MAX (2 * 1024 * 1024) #define INIT_FILE_NAMELEN_MAX (128) #define FASTRPC_DEVICE_NAME "fastrpc" @@ -105,6 +114,12 @@ #define miscdev_to_fdevice(d) container_of(d, struct fastrpc_device, miscdev) +/* Poll response number from remote processor for call completion */ +#define FASTRPC_POLL_RESPONSE (0xdecaf) + +/* Polling mode timeout limit */ +#define FASTRPC_POLL_MAX_TIMEOUT_US (10000) + struct fastrpc_phy_page { dma_addr_t addr; /* dma address */ u64 size; /* size of contiguous region */ @@ -187,6 +202,7 @@ struct fastrpc_buf_overlap { u64 mstart; u64 mend; u64 offset; + bool do_cmo; }; struct fastrpc_buf { @@ -233,9 +249,16 @@ struct fastrpc_invoke_ctx { int pid; int client_id; u32 sc; + u64 *fdlist; u32 *crc; + /* Poll memory that DSP updates */ + u32 *poll_addr; u64 ctxid; u64 msg_sz; + /* work done status flag */ + bool is_work_done; + /* process updates poll memory instead of glink response */ + bool is_polled; struct kref refcount; struct list_head node; /* list of ctxs */ struct completion work; @@ -255,12 +278,16 @@ struct fastrpc_session_ctx { int sid; bool used; bool valid; + bool allocated; + struct mutex mutex; + bool coherent; }; struct fastrpc_soc_data { u32 sid_pos; u32 dma_addr_bits_cdsp; u32 dma_addr_bits_default; + bool poll_mode_supported; }; struct fastrpc_channel_ctx { @@ -276,6 +303,8 @@ struct fastrpc_channel_ctx { struct kref refcount; /* Flag if dsp attributes are cached */ bool valid_attributes; + /* Flag if audio PD init mem was allocated */ + bool audio_init_mem; u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; struct fastrpc_device *secure_fdevice; struct fastrpc_device *fdevice; @@ -283,6 +312,7 @@ struct fastrpc_channel_ctx { struct list_head invoke_interrupted_mmaps; bool secure; bool unsigned_support; + bool poll_mode_supported; u64 dma_mask; const struct fastrpc_soc_data *soc_data; }; @@ -306,6 +336,8 @@ struct fastrpc_user { int client_id; int pd; bool is_secure_dev; + /* Flags poll mode state */ + bool poll_mode; /* Lock for lists */ spinlock_t lock; /* lock for allocations */ @@ -332,12 +364,29 @@ static inline u64 fastrpc_sid_offset(struct fastrpc_channel_ctx *cctx, return (u64)sctx->sid << cctx->soc_data->sid_pos; } +/* + * Align buffer size to kernel page granularity for dma-buf cache maintenance. + */ +static inline uint64_t buf_page_size(uint64_t size) +{ + int cache_align = dma_get_cache_alignment(); + uint64_t sz = ALIGN(size, cache_align); + + return max_t(uint64_t, sz, (uint64_t)cache_align); +} + + static void fastrpc_free_map(struct kref *ref) { struct fastrpc_map *map; + struct fastrpc_user *fl; map = container_of(ref, struct fastrpc_map, refcount); + fl = map->fl; + if (!fl) + return; + if (map->table) { if (map->attr & FASTRPC_ATTR_SECUREMAP) { struct qcom_scm_vmperm perm; @@ -356,10 +405,16 @@ static void fastrpc_free_map(struct kref *ref) return; } } + mutex_lock(&fl->sctx->mutex); + if (!fl->sctx->dev) { + mutex_unlock(&fl->sctx->mutex); + return; + } dma_buf_unmap_attachment_unlocked(map->attach, map->table, DMA_BIDIRECTIONAL); dma_buf_detach(map->buf, map->attach); dma_buf_put(map->buf); + mutex_unlock(&fl->sctx->mutex); } if (map->fl) { @@ -422,9 +477,21 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, static void fastrpc_buf_free(struct fastrpc_buf *buf) { - dma_free_coherent(buf->dev, buf->size, buf->virt, - fastrpc_ipa_to_dma_addr(buf->fl->cctx, buf->dma_addr)); - kfree(buf); + if (!buf) + return; + + struct fastrpc_user *fl = buf->fl; + + if (!fl) + return; + mutex_lock(&fl->sctx->mutex); + if (fl->sctx->dev) { + dma_free_coherent(buf->dev, buf->size, buf->virt, + fastrpc_ipa_to_dma_addr(buf->fl->cctx, + buf->dma_addr)); + kfree(buf); + } + mutex_unlock(&fl->sctx->mutex); } static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, @@ -447,8 +514,11 @@ static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, buf->dev = dev; buf->raddr = 0; - buf->virt = dma_alloc_coherent(dev, buf->size, &buf->dma_addr, - GFP_KERNEL); + mutex_lock(&fl->sctx->mutex); + if (fl->sctx->dev) + buf->virt = dma_alloc_coherent(dev, buf->size, &buf->dma_addr, + GFP_KERNEL); + mutex_unlock(&fl->sctx->mutex); if (!buf->virt) { mutex_destroy(&buf->lock); kfree(buf); @@ -491,6 +561,10 @@ static void fastrpc_channel_ctx_free(struct kref *ref) struct fastrpc_channel_ctx *cctx; cctx = container_of(ref, struct fastrpc_channel_ctx, refcount); + for (int i = 0; i < FASTRPC_MAX_SESSIONS; i++) { + if (cctx->session[i].allocated) + mutex_destroy(&cctx->session[i].mutex); + } kfree(cctx); } @@ -514,8 +588,7 @@ static void fastrpc_user_free(struct kref *ref) struct fastrpc_map *map, *m; struct fastrpc_buf *buf, *b; - if (fl->init_mem) - fastrpc_buf_free(fl->init_mem); + fastrpc_buf_free(fl->init_mem); list_for_each_entry_safe(ctx, n, &fl->pending, node) { list_del(&ctx->node); @@ -560,11 +633,10 @@ static void fastrpc_context_free(struct kref *ref) for (i = 0; i < ctx->nbufs; i++) fastrpc_map_put(ctx->maps[i]); - if (ctx->buf) - fastrpc_buf_free(ctx->buf); + fastrpc_buf_free(ctx->buf); spin_lock_irqsave(&cctx->lock, flags); - idr_remove(&cctx->ctx_idr, ctx->ctxid >> 4); + idr_remove(&cctx->ctx_idr, FIELD_GET(FASTRPC_CTXID_MASK, ctx->ctxid)); spin_unlock_irqrestore(&cctx->lock, flags); kfree(ctx->maps); @@ -610,7 +682,9 @@ static int olaps_cmp(const void *a, const void *b) static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) { u64 max_end = 0; + int max_raix = -1; int i; + int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); for (i = 0; i < ctx->nbufs; ++i) { ctx->olaps[i].start = ctx->args[i].ptr; @@ -630,6 +704,9 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) if (ctx->olaps[i].end > max_end) { max_end = ctx->olaps[i].end; } else { + if ((max_raix < inbufs && ctx->olaps[i].raix + 1 > inbufs) || + (ctx->olaps[i].raix < inbufs && max_raix + 1 > inbufs)) + ctx->olaps[i].do_cmo = true; ctx->olaps[i].mend = 0; ctx->olaps[i].mstart = 0; } @@ -639,6 +716,7 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) ctx->olaps[i].mstart = ctx->olaps[i].start; ctx->olaps[i].offset = 0; max_end = ctx->olaps[i].end; + max_raix = ctx->olaps[i].raix; } } } @@ -702,7 +780,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( spin_unlock_irqrestore(&cctx->lock, flags); goto err_idr; } - ctx->ctxid = ret << 4; + ctx->ctxid = FIELD_PREP(FASTRPC_CTXID_MASK, ret); spin_unlock_irqrestore(&cctx->lock, flags); kref_init(&ctx->refcount); @@ -855,19 +933,28 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd, goto get_err; } + mutex_lock(&fl->sctx->mutex); + if (!fl->sctx->dev) { + err = -ENODEV; + mutex_unlock(&fl->sctx->mutex); + goto attach_err; + } + map->attach = dma_buf_attach(map->buf, sess->dev); if (IS_ERR(map->attach)) { dev_err(sess->dev, "Failed to attach dmabuf\n"); err = PTR_ERR(map->attach); + mutex_unlock(&fl->sctx->mutex); goto attach_err; } - table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL); if (IS_ERR(table)) { err = PTR_ERR(table); + mutex_unlock(&fl->sctx->mutex); goto map_err; } map->table = table; + mutex_unlock(&fl->sctx->mutex); if (attr & FASTRPC_ATTR_SECUREMAP) map->dma_addr = sg_phys(map->table->sgl); @@ -967,7 +1054,8 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) sizeof(struct fastrpc_invoke_buf) + sizeof(struct fastrpc_phy_page)) * ctx->nscalars + sizeof(u64) * FASTRPC_MAX_FDLIST + - sizeof(u32) * FASTRPC_MAX_CRCLIST; + sizeof(u32) * FASTRPC_MAX_CRCLIST + + sizeof(u32); return size; } @@ -1019,6 +1107,70 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx) return 0; } +static int fastrpc_flush_args(struct fastrpc_invoke_ctx *ctx, + union fastrpc_remote_arg *rpra) +{ + int oix, inbufs, outbufs; + struct device *dev = ctx->fl->sctx->dev; + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); + for (oix = 0; oix < inbufs+outbufs; ++oix) { + int i = ctx->olaps[oix].raix; + struct fastrpc_map *map = ctx->maps[i]; + + if (i+1 > inbufs) + continue; + if (!map) + continue; + if (rpra[i].buf.len && ctx->olaps[oix].mstart) { + if (map->buf) { + if ((buf_page_size(ctx->olaps[oix].mend - + ctx->olaps[oix].mstart)) == map->size ) { + dma_buf_begin_cpu_access(map->buf, DMA_TO_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE); + } + } + } + } + return 0; +} + +static int fastrpc_inv_args(struct fastrpc_invoke_ctx *ctx) +{ + int i, inbufs, outbufs; + uint32_t sc = ctx->sc; + union fastrpc_remote_arg *rpra = ctx->rpra; + struct device *dev = ctx->fl->sctx->dev; + + inbufs = REMOTE_SCALARS_INBUFS(sc); + outbufs = REMOTE_SCALARS_OUTBUFS(sc); + for (i = 0; i < inbufs+outbufs; ++i) { + int over = ctx->olaps[i].raix; + struct fastrpc_map *map = ctx->maps[over]; + + if (over + 1 <= inbufs) + continue; + if (!rpra[over].buf.len) + continue; + if (!map) + continue; + if (((uintptr_t)rpra & PAGE_MASK) == + ((uintptr_t)rpra[over].buf.pv & PAGE_MASK)) + continue; + if (ctx->olaps[i].mstart) { + if (map->buf) { + if (((buf_page_size(ctx->olaps[i].mend - + ctx->olaps[i].mstart)) == map->size)) { + dma_buf_begin_cpu_access(map->buf, DMA_FROM_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE); + } + } + } + } + return 0; +} + static struct fastrpc_invoke_buf *fastrpc_invoke_buf_start(union fastrpc_remote_arg *pra, int len) { return (struct fastrpc_invoke_buf *)(&pra[len]); @@ -1062,6 +1214,10 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) rpra = ctx->buf->virt; list = fastrpc_invoke_buf_start(rpra, ctx->nscalars); pages = fastrpc_phy_page_start(list, ctx->nscalars); + ctx->fdlist = (u64 *)(pages + ctx->nscalars); + ctx->poll_addr = (u32 *)((uintptr_t)ctx->fdlist + sizeof(u64) * FASTRPC_MAX_FDLIST + + sizeof(u32) * FASTRPC_MAX_CRCLIST); + args = (uintptr_t)ctx->buf->virt + metalen; rlen = pkt_size - metalen; ctx->rpra = rpra; @@ -1139,6 +1295,12 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) } } + if (!ctx->fl->sctx->coherent) { + err = fastrpc_flush_args(ctx, rpra); + if (err) + goto bail; + } + for (i = ctx->nbufs; i < ctx->nscalars; ++i) { list[i].num = ctx->args[i].length ? 1 : 0; list[i].pgidx = i; @@ -1164,18 +1326,11 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx, union fastrpc_remote_arg *rpra = ctx->rpra; struct fastrpc_user *fl = ctx->fl; struct fastrpc_map *mmap = NULL; - struct fastrpc_invoke_buf *list; - struct fastrpc_phy_page *pages; - u64 *fdlist; - int i, inbufs, outbufs, handles; + u64 *fdlist = ctx->fdlist; + int i, inbufs; int ret = 0; inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); - outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); - handles = REMOTE_SCALARS_INHANDLES(ctx->sc) + REMOTE_SCALARS_OUTHANDLES(ctx->sc); - list = fastrpc_invoke_buf_start(rpra, ctx->nscalars); - pages = fastrpc_phy_page_start(list, ctx->nscalars); - fdlist = (uint64_t *)(pages + inbufs + outbufs + handles); for (i = inbufs; i < ctx->nbufs; ++i) { if (!ctx->maps[i]) { @@ -1238,6 +1393,71 @@ static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx, } +static u32 fastrpc_read_poll_addr(struct fastrpc_invoke_ctx *ctx) +{ + dma_rmb(); + return READ_ONCE(*ctx->poll_addr); +} + +static int poll_for_remote_response(struct fastrpc_invoke_ctx *ctx) +{ + u32 val; + int ret; + + /* + * Poll until DSP writes FASTRPC_POLL_RESPONSE into *ctx->poll_addr + * or until another path marks the work done. + */ + ret = read_poll_timeout_atomic(fastrpc_read_poll_addr, val, + (val == FASTRPC_POLL_RESPONSE) || ctx->is_work_done, 1, + FASTRPC_POLL_MAX_TIMEOUT_US, false, ctx); + + if (!ret && val == FASTRPC_POLL_RESPONSE) { + /* + * DSP writes FASTRPC_POLL_RESPONSE to signal successful + * completion via the poll path. + */ + ctx->is_work_done = true; + ctx->retval = 0; + } + + if (ret == -ETIMEDOUT) + ret = -EIO; + + return ret; +} + +static inline int fastrpc_wait_for_response(struct fastrpc_invoke_ctx *ctx, + u32 kernel) +{ + int err = 0; + + if (kernel) { + if (!wait_for_completion_timeout(&ctx->work, 10 * HZ)) + err = -ETIMEDOUT; + } else { + err = wait_for_completion_interruptible(&ctx->work); + } + + return err; +} + +static int fastrpc_wait_for_completion(struct fastrpc_invoke_ctx *ctx, + u32 kernel) +{ + int err; + + if (ctx->is_polled) { + err = poll_for_remote_response(ctx); + if (!err) + return 0; + /* If polling timed out or failed, move to normal response mode */ + ctx->is_polled = false; + } + + return fastrpc_wait_for_response(ctx, kernel); +} + static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, u32 handle, u32 sc, struct fastrpc_invoke_args *args) @@ -1266,6 +1486,11 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, if (err) goto bail; + if (!fl->sctx->coherent) { + err = fastrpc_inv_args(ctx); + if (err) + goto bail; + } /* make sure that all CPU memory writes are seen by DSP */ dma_wmb(); /* Send invoke buffer to remote dsp */ @@ -1273,18 +1498,24 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, if (err) goto bail; - if (kernel) { - if (!wait_for_completion_timeout(&ctx->work, 10 * HZ)) - err = -ETIMEDOUT; - } else { - err = wait_for_completion_interruptible(&ctx->work); - } + /* + * Set message context as polled if the call is for a user PD + * dynamic module and user has enabled poll mode. + */ + if (handle > FASTRPC_MAX_STATIC_HANDLE && fl->pd == USER_PD && fl->poll_mode) + ctx->is_polled = true; + err = fastrpc_wait_for_completion(ctx, kernel); if (err) goto bail; /* make sure that all memory writes by DSP are seen by CPU */ dma_rmb(); + if (!fl->sctx->coherent) { + err = fastrpc_inv_args(ctx); + if (err) + goto bail; + } /* populate all the output buffers with results */ err = fastrpc_put_args(ctx, kernel); if (err) @@ -1341,15 +1572,24 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, struct fastrpc_init_create_static init; struct fastrpc_invoke_args *args; struct fastrpc_phy_page pages[1]; + struct fastrpc_channel_ctx *cctx = fl->cctx; char *name; int err; - bool scm_done = false; struct { int client_id; u32 namelen; u32 pageslen; } inbuf; u32 sc; + unsigned long flags; + + if (!cctx->remote_heap || !cctx->remote_heap->dma_addr || + !cctx->remote_heap->size) { + err = -ENOMEM; + dev_dbg(fl->sctx->dev, + "remote heap memory region is not added\n"); + return err; + } args = kzalloc_objs(*args, FASTRPC_CREATE_STATIC_PROCESS_NARGS); if (!args) @@ -1370,35 +1610,10 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, err = PTR_ERR(name); goto err; } - - if (!fl->cctx->remote_heap) { - err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen, - &fl->cctx->remote_heap); - if (err) - goto err_name; - - /* Map if we have any heap VMIDs associated with this ADSP Static Process. */ - if (fl->cctx->vmcount) { - u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); - - err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr, - (u64)fl->cctx->remote_heap->size, - &src_perms, - fl->cctx->vmperms, fl->cctx->vmcount); - if (err) { - dev_err(fl->sctx->dev, - "Failed to assign memory with dma_addr %pad size 0x%llx err %d\n", - &fl->cctx->remote_heap->dma_addr, - fl->cctx->remote_heap->size, err); - goto err_map; - } - scm_done = true; - } - } - inbuf.client_id = fl->client_id; inbuf.namelen = init.namelen; inbuf.pageslen = 0; + fl->pd = USER_PD; args[0].ptr = (u64)(uintptr_t)&inbuf; @@ -1409,8 +1624,17 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, args[1].length = inbuf.namelen; args[1].fd = -1; - pages[0].addr = fl->cctx->remote_heap->dma_addr; - pages[0].size = fl->cctx->remote_heap->size; + spin_lock_irqsave(&cctx->lock, flags); + if (!cctx->audio_init_mem) { + pages[0].addr = cctx->remote_heap->dma_addr; + pages[0].size = cctx->remote_heap->size; + cctx->audio_init_mem = true; + inbuf.pageslen = 1; + } else { + pages[0].addr = 0; + pages[0].size = 0; + } + spin_unlock_irqrestore(&cctx->lock, flags); args[2].ptr = (u64)(uintptr_t) pages; args[2].length = sizeof(*pages); @@ -1428,27 +1652,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, return 0; err_invoke: - if (fl->cctx->vmcount && scm_done) { - u64 src_perms = 0; - struct qcom_scm_vmperm dst_perms; - u32 i; - - for (i = 0; i < fl->cctx->vmcount; i++) - src_perms |= BIT(fl->cctx->vmperms[i].vmid); - - dst_perms.vmid = QCOM_SCM_VMID_HLOS; - dst_perms.perm = QCOM_SCM_PERM_RWX; - err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr, - (u64)fl->cctx->remote_heap->size, - &src_perms, &dst_perms, 1); - if (err) - dev_err(fl->sctx->dev, "Failed to assign memory dma_addr %pad size 0x%llx err %d\n", - &fl->cctx->remote_heap->dma_addr, fl->cctx->remote_heap->size, err); - } -err_map: - fastrpc_buf_free(fl->cctx->remote_heap); - fl->cctx->remote_heap = NULL; -err_name: + cctx->audio_init_mem = false; kfree(name); err: kfree(args); @@ -1828,7 +2032,7 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap, kfree(dsp_attributes); return -EOPNOTSUPP; } else if (err) { - dev_err(&cctx->rpdev->dev, "Error: dsp information is incorrect err: %d\n", err); + dev_dbg(&cctx->rpdev->dev, "Error: dsp information is incorrect err: %d\n", err); kfree(dsp_attributes); return err; } @@ -1843,6 +2047,35 @@ static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap, return 0; } +static int fastrpc_set_option(struct fastrpc_user *fl, char __user *argp) +{ + struct fastrpc_ioctl_set_option opt = {0}; + int i; + + if (copy_from_user(&opt, argp, sizeof(opt))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(opt.reserved); i++) { + if (opt.reserved[i] != 0) + return -EINVAL; + } + + if (opt.request_id != FASTRPC_POLL_MODE) + return -EINVAL; + + if (!fl->cctx->poll_mode_supported) + return -EOPNOTSUPP; + + if (opt.value == FASTRPC_POLL_MODE_ENABLE) + fl->poll_mode = true; + else if (opt.value == FASTRPC_POLL_MODE_DISABLE) + fl->poll_mode = false; + else + return -EINVAL; + + return 0; +} + static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp) { struct fastrpc_ioctl_capability cap = {0}; @@ -1889,9 +2122,6 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf * &args[0]); if (!err) { dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); - spin_lock(&fl->lock); - list_del(&buf->node); - spin_unlock(&fl->lock); fastrpc_buf_free(buf); } else { dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr); @@ -1905,6 +2135,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) struct fastrpc_buf *buf = NULL, *iter, *b; struct fastrpc_req_munmap req; struct device *dev = fl->sctx->dev; + int err; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; @@ -1912,6 +2143,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) spin_lock(&fl->lock); list_for_each_entry_safe(iter, b, &fl->mmaps, node) { if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) { + list_del(&iter->node); buf = iter; break; } @@ -1924,7 +2156,14 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) return -EINVAL; } - return fastrpc_req_munmap_impl(fl, buf); + err = fastrpc_req_munmap_impl(fl, buf); + if (err) { + spin_lock(&fl->lock); + list_add_tail(&buf->node, &fl->mmaps); + spin_unlock(&fl->lock); + } + + return err; } static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) @@ -2198,6 +2437,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, case FASTRPC_IOCTL_MEM_UNMAP: err = fastrpc_req_mem_unmap(fl, argp); break; + case FASTRPC_IOCTL_SET_OPTION: + err = fastrpc_set_option(fl, argp); + break; case FASTRPC_IOCTL_GET_DSP_INFO: err = fastrpc_get_dsp_info(fl, argp); break; @@ -2243,6 +2485,9 @@ static int fastrpc_cb_probe(struct platform_device *pdev) sess->used = false; sess->valid = true; sess->dev = dev; + mutex_init(&sess->mutex); + sess->allocated = true; + sess->coherent = of_property_read_bool(dev->of_node, "dma-coherent"); dev_set_drvdata(dev, sess); if (cctx->domain_id == CDSP_DOMAIN_ID) @@ -2259,6 +2504,8 @@ static int fastrpc_cb_probe(struct platform_device *pdev) break; dup_sess = &cctx->session[cctx->sesscount++]; memcpy(dup_sess, sess, sizeof(*dup_sess)); + mutex_init(&dup_sess->mutex); + dup_sess->allocated = true; } } spin_unlock_irqrestore(&cctx->lock, flags); @@ -2281,6 +2528,11 @@ static void fastrpc_cb_remove(struct platform_device *pdev) spin_lock_irqsave(&cctx->lock, flags); for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) { if (cctx->session[i].sid == sess->sid) { + spin_unlock_irqrestore(&cctx->lock, flags); + mutex_lock(&cctx->session[i].mutex); + cctx->session[i].dev = NULL; + mutex_unlock(&cctx->session[i].mutex); + spin_lock_irqsave(&cctx->lock, flags); cctx->session[i].valid = false; cctx->sesscount--; } @@ -2353,6 +2605,7 @@ static const struct fastrpc_soc_data kaanapali_soc_data = { .sid_pos = 56, .dma_addr_bits_cdsp = 34, .dma_addr_bits_default = 32, + .poll_mode_supported = true, }; static const struct fastrpc_soc_data default_soc_data = { @@ -2361,6 +2614,29 @@ static const struct fastrpc_soc_data default_soc_data = { .dma_addr_bits_default = 32, }; +/* + * Exception list for older platforms that use default_soc_data but whose + * DSP firmware supports FastRPC polling mode. + * + * NOTE: This list is intentionally closed. + * Do NOT add new platforms here. New SoCs must advertise polling mode + * support via their soc_data. + */ + +static const struct of_device_id fastrpc_poll_supported_machines[] __maybe_unused = { + { .compatible = "qcom,milos" }, + { .compatible = "qcom,qcs8300" }, + { .compatible = "qcom,sa8775p" }, + { .compatible = "qcom,sar2130p" }, + { .compatible = "qcom,sm8450" }, + { .compatible = "qcom,sm8550" }, + { .compatible = "qcom,sm8650" }, + { .compatible = "qcom,sm8750" }, + { .compatible = "qcom,x1e80100" }, + { .compatible = "qcom,x1p42100" }, + {}, +}; + static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) { struct device *rdev = &rpdev->dev; @@ -2387,7 +2663,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } if (of_reserved_mem_device_init_by_idx(rdev, rdev->of_node, 0)) - dev_info(rdev, "no reserved DMA memory for FASTRPC\n"); + dev_dbg(rdev, "no reserved DMA memory for FASTRPC\n"); vmcount = of_property_read_variable_u32_array(rdev->of_node, "qcom,vmids", &vmids[0], 0, FASTRPC_MAX_VMIDS); @@ -2408,12 +2684,23 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } } - if (domain_id == SDSP_DOMAIN_ID) { + if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) { struct resource res; u64 src_perms; err = of_reserved_mem_region_to_resource(rdev->of_node, 0, &res); if (!err) { + if (domain_id == ADSP_DOMAIN_ID) { + data->remote_heap = + kzalloc_obj(*data->remote_heap, GFP_KERNEL); + if (!data->remote_heap) { + err = -ENOMEM; + goto err_free_data; + } + + data->remote_heap->dma_addr = res.start; + data->remote_heap->size = resource_size(&res); + } src_perms = BIT(QCOM_SCM_VMID_HLOS); err = qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms, @@ -2421,12 +2708,13 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (err) goto err_free_data; } - } secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain")); data->secure = secure_dsp; data->soc_data = soc_data; + data->poll_mode_supported = soc_data->poll_mode_supported || + of_machine_get_match(fastrpc_poll_supported_machines); switch (domain_id) { case ADSP_DOMAIN_ID: @@ -2480,6 +2768,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) misc_deregister(&data->secure_fdevice->miscdev); err_free_data: + kfree(data->remote_heap); kfree(data); return err; } @@ -2502,6 +2791,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_buf *buf, *b; struct fastrpc_user *user; unsigned long flags; + int err; /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); @@ -2519,8 +2809,27 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node) list_del(&buf->node); - if (cctx->remote_heap) - fastrpc_buf_free(cctx->remote_heap); + if (cctx->remote_heap && cctx->vmcount) { + u64 src_perms = 0; + struct qcom_scm_vmperm dst_perms; + + for (u32 i = 0; i < cctx->vmcount; i++) + src_perms |= BIT(cctx->vmperms[i].vmid); + + dst_perms.vmid = QCOM_SCM_VMID_HLOS; + dst_perms.perm = QCOM_SCM_PERM_RWX; + + err = qcom_scm_assign_mem(cctx->remote_heap->dma_addr, + cctx->remote_heap->size, &src_perms, + &dst_perms, 1); + if (err) + dev_err(&rpdev->dev, + "Failed to assign memory back to HLOS: dma_addr %pad size %#llx err %d\n", + &cctx->remote_heap->dma_addr, cctx->remote_heap->size, err); + } + + kfree(cctx->remote_heap); + cctx->remote_heap = NULL; of_platform_depopulate(&rpdev->dev); @@ -2542,7 +2851,7 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, if (!cctx) return -ENODEV; - ctxid = ((rsp->ctx & FASTRPC_CTXID_MASK) >> 4); + ctxid = FIELD_GET(FASTRPC_CTXID_MASK, rsp->ctx); spin_lock_irqsave(&cctx->lock, flags); ctx = idr_find(&cctx->ctx_idr, ctxid); @@ -2554,6 +2863,7 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, } ctx->retval = rsp->retval; + ctx->is_work_done = true; complete(&ctx->work); /* diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c new file mode 100644 index 0000000000000..73994f39de30e --- /dev/null +++ b/drivers/misc/qcom-dcc-dev.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include "qcom-dcc.h" +#include "qcom-dcc-talos-config.h" +#include "qcom-dcc-lemans-config.h" +#include "qcom-dcc-kodiak-config.h" +#include "qcom-dcc-pakala-config.h" +#include "qcom-dcc-shikra-config.h" + +#define DEV_NAME "qcom-dcc" + +static struct platform_device *dcc_pdev; + +static const struct dcc_pdata kaanapali_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x8000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + +static const struct dcc_pdata hamoa_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x18000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + +static const struct dcc_pdata glymur_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x8000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + +static int __init dcc_dev_init(void) +{ + int ret; + u32 soc_id; + + dcc_pdev = platform_device_alloc(DEV_NAME, -1); + if (!dcc_pdev) + return -ENOMEM; + + ret = qcom_smem_get_soc_id(&soc_id); + if (ret) + goto fail; + + switch (soc_id) { + case 475: + case 497: + case 498: + case 515: + ret = platform_device_add_data(dcc_pdev, &kodiak_pdata, sizeof(kodiak_pdata)); + if (ret) + goto fail; + + break; + /* lemans IDs */ + case 534: + case 667: + case 676: + /* monaco IDs */ + case 606: + case 674: + case 675: + ret = platform_device_add_data(dcc_pdev, &lemans_pdata, sizeof(lemans_pdata)); + if (ret) + goto fail; + + break; + case 377: + case 380: + case 384: + case 401: + case 406: + case 680: + ret = platform_device_add_data(dcc_pdev, &talos_pdata, sizeof(talos_pdata)); + if (ret) + goto fail; + + break; + case 618: + case 639: + case 705: + case 706: + ret = platform_device_add_data(dcc_pdev, &pakala_pdata, sizeof(pakala_pdata)); + if (ret) + goto fail; + + break; + case 660: + case 661: + case 704: + case 722: + case 723: + case 730: + case 743: + ret = platform_device_add_data(dcc_pdev, &kaanapali_pdata, sizeof(kaanapali_pdata)); + if (ret) + goto fail; + + break; + case 555: + case 615: + case 616: + case 709: + case 710: + ret = platform_device_add_data(dcc_pdev, &hamoa_pdata, sizeof(hamoa_pdata)); + if (ret) + goto fail; + + break; + case 662: + case 698: + case 699: + case 718: + case 719: + ret = platform_device_add_data(dcc_pdev, &glymur_pdata, sizeof(glymur_pdata)); + if (ret) + goto fail; + + break; + case 756: + case 758: + case 759: + ret = platform_device_add_data(dcc_pdev, &shikra_pdata, sizeof(shikra_pdata)); + if (ret) + goto fail; + break; + default: + pr_err("DCC: Invalid SoC ID\n"); + ret = -EINVAL; + goto fail; + } + + ret = platform_device_add(dcc_pdev); + if (ret) + goto fail; + + pr_info("DCC platform device has registered\n"); + + return 0; + +fail: + pr_err("Failed to register DCC platform device\n"); + platform_device_put(dcc_pdev); + + return ret; +} + +static void __exit dcc_dev_exit(void) +{ + platform_device_unregister(dcc_pdev); +} + +late_initcall(dcc_dev_init); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver, device stub"); diff --git a/drivers/misc/qcom-dcc-kodiak-config.h b/drivers/misc/qcom-dcc-kodiak-config.h new file mode 100644 index 0000000000000..7184252734917 --- /dev/null +++ b/drivers/misc/qcom-dcc-kodiak-config.h @@ -0,0 +1,1188 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_KODIAK_CONFIG_H +#define _QCOM_DCC_KODIAK_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry kodiak_dcc_entries_ll6[] = { + /* pcu */ + { "R 0x18000010" }, + { "R 0x18000024" }, + { "R 0x18000038 6" }, + { "R 0x18010010" }, + { "R 0x18010024" }, + { "R 0x18010038 6" }, + { "R 0x18020010" }, + { "R 0x18020024" }, + { "R 0x18020038 6" }, + { "R 0x18030010" }, + { "R 0x18030024" }, + { "R 0x18030038 6" }, + { "R 0x18040010" }, + { "R 0x18040024" }, + { "R 0x18040038 6" }, + { "R 0x18050010" }, + { "R 0x18050024" }, + { "R 0x18050038 6" }, + { "R 0x18060010" }, + { "R 0x18060024" }, + { "R 0x18060038 6" }, + { "R 0x18070010" }, + { "R 0x18070024" }, + { "R 0x18070038 6" }, + { "R 0x18080010" }, + { "R 0x18080024" }, + { "R 0x18080038 6" }, + { "R 0x1808006c 5" }, + { "R 0x18080084" }, + { "R 0x180800f4 18" }, + { "R 0x18080158 5" }, + { "R 0x18080170 2" }, + { "R 0x18080188 5" }, + { "R 0x180801ac 6" }, + { "R 0x180801c8" }, + { "R 0x180801f0" }, + /* epss */ + { "R 0x18598020" }, + { "R 0x1859001c 2" }, + { "R 0x1859002c" }, + { "R 0x18590064 6" }, + { "R 0x1859008c" }, + { "R 0x185900dc" }, + { "R 0x185900e8 3" }, + { "R 0x18590300" }, + { "R 0x1859030c" }, + { "R 0x18590320" }, + { "R 0x1859034c" }, + { "R 0x185903bc 2" }, + { "R 0x1859101c 2" }, + { "R 0x1859102c" }, + { "R 0x18591064 6" }, + { "R 0x1859108c" }, + { "R 0x185910dc" }, + { "R 0x185910e8 3" }, + { "R 0x18591300" }, + { "R 0x1859130c" }, + { "R 0x18591320" }, + { "R 0x1859134c" }, + { "R 0x185913bc 2" }, + { "R 0x1859201c 2" }, + { "R 0x1859202c" }, + { "R 0x18592064 6" }, + { "R 0x1859208c" }, + { "R 0x185920dc" }, + { "R 0x185920e8 3" }, + { "R 0x18592300" }, + { "R 0x1859230c" }, + { "R 0x18592320" }, + { "R 0x1859234c" }, + { "R 0x185923bc 2" }, + { "R 0x1859301c 2" }, + { "R 0x18593064 6" }, + { "R 0x1859308c" }, + { "R 0x185930dc" }, + { "R 0x185930e8 3" }, + { "R 0x18593300" }, + { "R 0x1859330c" }, + { "R 0x18593320" }, + { "R 0x1859302c" }, + { "R 0x1859334c" }, + { "R 0x185933bc 2" }, + { "R 0x18300000" }, + { "R 0x1830000c" }, + { "R 0x18300018" }, + { "R 0x17c21000 2" }, + { "R 0x18393a84 2" }, + { "R 0x183a3a84 2" }, + { "R 0x18280000 2" }, + { "R 0x18282000 2" }, + { "R 0x18284000 2" }, + { "R 0x18286000 2" }, + { "R 0x18300000" }, + { "R 0x18200400 3" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200d0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + /* pimem */ + { "R 0x610100 11" }, + /* core */ + { "R 0x18000058 4" }, + { "R 0x1800006c" }, + { "R 0x180000f0 2" }, + { "R 0x18010058 4" }, + { "R 0x1801006c" }, + { "R 0x180100f0 2" }, + { "R 0x18020058 4" }, + { "R 0x1802006c" }, + { "R 0x180200f0 2" }, + { "R 0x18030058 4" }, + { "R 0x1803006c" }, + { "R 0x180300f0 2" }, + { "R 0x18040058 4" }, + { "R 0x1804006c" }, + { "R 0x180400f0 2" }, + { "R 0x18050058 4" }, + { "R 0x1805006c" }, + { "R 0x180500f0 2" }, + { "R 0x18060058 4" }, + { "R 0x1806006c" }, + { "R 0x180600f0 2" }, + { "R 0x18070058 4" }, + { "R 0x1807006c" }, + { "R 0x180700f0 2" }, + { "R 0x18101908" }, + { "R 0x18101c18" }, + { "R 0x18390810" }, + { "R 0x18390c50" }, + { "R 0x18390814" }, + { "R 0x18390c54" }, + { "R 0x18390818" }, + { "R 0x18390c58" }, + { "R 0x18393a84 2" }, + { "R 0x18100908" }, + { "R 0x18100c18" }, + { "R 0x183a0810" }, + { "R 0x183a0c50" }, + { "R 0x183a0814" }, + { "R 0x183a0c54" }, + { "R 0x183a0818" }, + { "R 0x183a0c58" }, + { "R 0x183a3a84 2" }, + { "R 0x18393500" }, + { "R 0x18393580" }, + { "R 0x183a3500" }, + { "R 0x183a3580" }, + { "R 0x18282000 4" }, + { "R 0x18282028" }, + { "R 0x18282038" }, + { "R 0x18282080 5" }, + { "R 0x18286000 4" }, + { "R 0x18286028" }, + { "R 0x18286038" }, + { "R 0x18286080 5" }, + { "R 0xc201244" }, + { "R 0xc202244" }, + { "R 0x18300000" }, + { "R 0x1829208c" }, + { "R 0x18292098" }, + { "R 0x18292098" }, + { "R 0x1829608c" }, + { "R 0x18296098" }, + { "R 0x18296098" }, + { "R 0x784184" }, + /* gemnoc */ + { "R 0x9103008" }, + { "R 0x9103408" }, + { "R 0x9143008" }, + { "R 0x9143408" }, + { "R 0x91b0008" }, + { "R 0x91b1008" }, + { "R 0x9101808 2" }, + { "R 0x9141808 2" }, + { "R 0x91a8008 2" }, + { "R 0x91a8808 2" }, + { "R 0x9100000" }, + { "R 0x9100008 2" }, + { "R 0x9140000" }, + { "R 0x9140008 2" }, + { "R 0x9180000" }, + { "R 0x9180008 2" }, + { "R 0x9180404 3" }, + { "R 0x9181010" }, + { "R 0x9181020 8" }, + { "R 0x91e1048" }, + { "R 0x9121010" }, + { "R 0x9122010" }, + { "R 0x9123010" }, + { "R 0x9125010" }, + { "R 0x9161010" }, + { "R 0x9162010" }, + { "R 0x9163010" }, + { "R 0x9165010" }, + { "R 0x91cf010" }, + { "R 0x91d0010" }, + { "R 0x91d1010" }, + { "R 0x91d2010" }, + { "R 0x91d3010" }, + { "R 0x91d4010" }, + { "R 0x91d5010" }, + { "R 0x91d6010" }, + { "R 0x91d7010" }, + { "R 0x9101408" }, + { "R 0x9141410" }, + { "R 0x9100810" }, + { "R 0x9140810" }, + { "R 0x9100820" }, + { "R 0x9140820" }, + { "R 0x9100828 2" }, + { "R 0x9140828 2" }, + /* tsens */ + { "R 0xc222004" }, + { "R 0xc263014" }, + { "R 0xc2630e0" }, + { "R 0xc2630ec" }, + { "R 0xc2630a0 16" }, + { "R 0xc2630e8" }, + { "R 0xc26313c" }, + { "R 0xc223004" }, + { "R 0xc265014" }, + { "R 0xc2650e0" }, + { "R 0xc2650ec" }, + { "R 0xc2650a0 16" }, + { "R 0xc2650e8" }, + { "R 0xc26513c" }, + /* spmi */ + { "R 0xc410000" }, + { "R 0xc40af04" }, + { "R 0xc40af10" }, + { "R 0xc40a000" }, + { "R 0xc40a018" }, + { "R 0xc40a028 2" }, + { "R 0xc40a100" }, + { "R 0xc2a22fc 3" }, + { "R 0xc440200 2" }, + { "R 0xc442200 4" }, + /* gpu */ + { "R 0x3d9100c 3" }, + { "R 0x3d9106c 3" }, + { "R 0x3d91004" }, + { "R 0x3d91054 5" }, + { "R 0x3d91070 2" }, + { "R 0x3d91080 3" }, + { "R 0x3d91078 2" }, + { "R 0x3d9108c 2" }, + { "R 0x3d91098 2" }, + { "R 0x3d910a4 2" }, + { "R 0x3d910f0 2" }, + { "R 0x3d91100" }, + { "R 0x3d91118" }, + { "R 0x3d91164 2" }, + { "R 0x3d91170" }, + { "R 0x3d91178" }, + { "R 0x3d91204" }, + { "R 0x3d9120c" }, + { "R 0x3d98024" }, + { "R 0x3d9802c 2" }, + { "R 0x3d92000 2" }, + { "R 0x3d93000 2" }, + { "R 0x3d95000 2" }, + { "R 0x3d96000 2" }, + { "R 0x3d97000 2" }, + { "R 0x119000" }, + { "R 0x11903c" }, + { "R 0x171004 3" }, + { "R 0x171014 2" }, + { "R 0x171154 3" }, + { "R 0x17a04c" }, + { "R 0x17b000" }, + { "R 0x17b03c" }, + { "R 0x17c000" }, + { "R 0x17c03c" }, + { "R 0x17d000" }, + { "R 0x17d03c" }, + { "R 0x17e000" }, + { "R 0x17e03c" }, + { "R 0x187000" }, + { "R 0x18703c" }, + { "R 0x3d91534" }, + { "R 0x3d002b4" }, + { "R 0x3d00410 2" }, + { "R 0x3d00818" }, + { "R 0x3d7e220 2" }, + /* sysnoc */ + { "R 0x1680000" }, + { "R 0x1680008" }, + { "R 0x1680010" }, + { "R 0x1680020 8" }, + { "R 0x1680248" }, + { "R 0x1680b00 6" }, + /* aggrenoc */ + { "R 0x16e4008" }, + { "R 0x1706208" }, + { "R 0x16e0000" }, + { "R 0x16e0010" }, + { "R 0x16e0008" }, + { "R 0x16e0020 8" }, + { "R 0x16e5048" }, + { "R 0x16e5248" }, + { "R 0x16e5448" }, + { "R 0x16e5100 5" }, + { "R 0x16e5300 2" }, + { "R 0x16e5500 2" }, + { "R 0x1700000" }, + { "R 0x1700008" }, + { "R 0x1700010" }, + { "R 0x1700020 8" }, + { "R 0x170b100 5" }, + { "R 0x170b048" }, + /* gcc */ + { "R 0x100000 15" }, + { "R 0x101000 15" }, + { "R 0x176000 15" }, + { "R 0x174000 15" }, + { "R 0x113000 15" }, + { "R 0x11a000 15" }, + { "R 0x11c000 15" }, + { "R 0x11c048 3" }, + { "R 0x11e000 15" }, + { "R 0x10401c" }, + { "R 0x105074" }, + { "R 0x183024" }, + { "R 0x109050" }, + { "R 0x123020" }, + { "R 0x117024" }, + { "R 0x117154" }, + { "R 0x117284" }, + { "R 0x1173b4" }, + { "R 0x1174e4" }, + { "R 0x117614" }, + { "R 0x117744" }, + { "R 0x117874" }, + { "R 0x118024" }, + { "R 0x118154" }, + { "R 0x118284" }, + { "R 0x1183b4" }, + { "R 0x1184e4" }, + { "R 0x118614" }, + { "R 0x118744" }, + { "R 0x118874" }, + { "R 0x129020" }, + { "R 0x11d020" }, + { "R 0x134024" }, + { "R 0x141024" }, + { "R 0x14415c" }, + { "R 0x14504c" }, + { "R 0x18903c" }, + { "R 0x151000" }, + { "R 0x151008" }, + { "R 0x151010" }, + { "R 0x152000" }, + { "R 0x152008" }, + { "R 0x152010" }, + { "R 0x153020" }, + { "R 0x153028" }, + { "R 0x153030" }, + { "R 0x155000" }, + { "R 0x155008" }, + { "R 0x155010" }, + { "R 0x15b000" }, + { "R 0x15b008" }, + { "R 0x15b010" }, + { "R 0x157000" }, + { "R 0x157008" }, + { "R 0x157010" }, + { "R 0x135020" }, + { "R 0x135028" }, + { "R 0x135030" }, + { "R 0x156000" }, + { "R 0x156008" }, + { "R 0x156010" }, + { "R 0x15a000" }, + { "R 0x15a008" }, + { "R 0x15a010" }, + { "R 0x190004" }, + { "R 0x109008" }, + { "R 0x190010" }, + { "R 0x190020" }, + { "R 0x190028" }, + { "R 0x109010" }, + { "R 0x109018" }, + { "R 0x109018" }, + { "R 0x109020" }, + { "R 0x18d080" }, + { "R 0x145014" }, + { "R 0x14501c" }, + { "R 0x183004 2" }, + { "R 0x183140" }, + { "R 0x171158 2" }, + { "R 0x109004 3" }, + { "R 0x109160" }, + { "R 0x109468" }, + { "R 0x10f004 3" }, + { "R 0x145000 3" }, + { "R 0x16b004 3" }, + { "R 0x18d004 3" }, + { "R 0x177004 3" }, + { "R 0x189004 3" }, + { "R 0x153000 9" }, + { "R 0x135000 9" }, + { "R 0x106100" }, + { "R 0x147004" }, + { "R 0x17b000 12" }, + { "R 0x17b03c 12" }, + { "R 0x17c000 12" }, + { "R 0x17c03c 12" }, + { "R 0x153124" }, + { "R 0x156124" }, + { "R 0x1453a4" }, + { "R 0x182884" }, + { "R 0x145384" }, + { "R 0xc2a0000 15" }, + { "R 0xc2a1000 15" }, + { "R 0x17101c 2" }, + { "R 0x14401c 2" }, + { "R 0x183010 2" }, + { "R 0x18a160 2" }, + { "R 0x18a004" }, + { "R 0x18a01c 3" }, + { "R 0x19d004 2" }, + { "R 0x196100" }, + { "R 0x10003c" }, + { "R 0x10103c" }, + { "R 0x10203c" }, + { "R 0x10303c" }, + { "R 0x11303c" }, + { "R 0x11a03c" }, + { "R 0x11c03c" }, + { "R 0x17403c" }, + { "R 0x17603c" }, + { "R 0x11e03c" }, + { "R 0xbbf0004 12" }, + { "R 0xbbf0800 12" }, + { "R 0xbbf0004 12" }, + { "R 0xbbf0800 12" }, +}; + +static const struct dcc_register_entry kodiak_dcc_entries_ll4[] = { + /* confignoc */ + { "R 0x1510008" }, + { "R 0x151d208" }, + { "R 0x1507008" }, + { "R 0x151d308" }, + { "R 0x1509008" }, + { "R 0x1514008" }, + { "R 0x1500000" }, + { "R 0x1500010" }, + { "R 0x1510010" }, + { "R 0x1500020 8" }, + { "R 0x1510020 8" }, + { "R 0x1511048" }, + { "R 0x1501048 2" }, + { "R 0x1501058" }, + { "R 0x1501248" }, + { "R 0x1511248" }, + { "R 0x1501248" }, + { "R 0x1511b00" }, + { "R 0x151e100" }, + { "R 0x150b100" }, + /* limits */ + { "R 0xec80004" }, + { "R 0xec80058" }, + { "R 0xec80060 8" }, + { "R 0xec800a0 40" }, + { "R 0x634008" }, + { "R 0x634f00 8" }, + { "R 0x635560" }, + { "R 0x635570" }, + { "R 0x635580" }, + { "R 0x635590" }, + { "R 0x6355a0 4" }, + { "R 0x635600" }, + { "R 0x635610" }, + { "R 0x636008" }, + { "R 0x636f00 8" }, + { "R 0x637560" }, + { "R 0x637570" }, + { "R 0x637580" }, + { "R 0x637590" }, + { "R 0x6375a0 4" }, + { "R 0x637600" }, + { "R 0x637610" }, + { "R 0x18370220 2" }, + { "R 0x183702a0 2" }, + { "R 0x183704a0 12" }, + { "R 0x18370520" }, + { "R 0x18370588" }, + { "R 0x18370d10 12" }, + { "R 0x18370f90 10" }, + { "R 0x18371010 10" }, + { "R 0x18371a10 8" }, + { "R 0x183784a0 12" }, + { "R 0x18378520" }, + { "R 0x18378588" }, + { "R 0x18378d10 8" }, + { "R 0x18378f90 6" }, + { "R 0x18379010 6" }, + { "R 0x18379a10 4" }, + { "R 0xa310220 3" }, + { "R 0xa3102a0 3" }, + { "R 0xa3104a0 6" }, + { "R 0xa310520" }, + { "R 0xa310588" }, + { "R 0xa310d10 8" }, + { "R 0xa310f90 6" }, + { "R 0xa311010 6" }, + { "R 0xa311a10 3" }, + /* gic */ + { "R 0x17a00104 29" }, + { "R 0x17a00204 29" }, + /* mmssnoc */ + { "R 0x1741008" }, + { "R 0x1740000" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020 8" }, + { "R 0x174b048" }, + { "R 0x174b100 8" }, + { "R 0x90e0000" }, + { "R 0x90e0008" }, + { "R 0x90e0010" }, + { "R 0x90e0020 8" }, + { "R 0x90e0248" }, + { "R 0x90e3100" }, + { "R 0x90e4100 7" }, + { "R 0x1750010" }, + { "R 0x1750190" }, + { "R 0x1751010" }, + { "R 0x1752010" }, + { "R 0x1754010" }, + { "R 0x1755010" }, + { "R 0x1756010" }, + { "R 0x1758010" }, + { "R 0x1758090" }, + { "R 0x1759010" }, + { "R 0x175a010" }, + { "R 0x175c010" }, + { "R 0x175d010" }, + { "R 0x175e010" }, + /* apps_rsc */ + { "R 0xb201020 2" }, + { "R 0xb200010 4" }, + { "R 0xb220010 4" }, + { "R 0xb200900 4" }, + { "R 0xb220900 4" }, + { "R 0xb201030" }, + { "R 0xb201204" }, + { "R 0xb201218" }, + { "R 0xb20122c" }, + { "R 0xb201240" }, + { "R 0xb201254" }, + { "R 0xb201208" }, + { "R 0xb20121c" }, + { "R 0xb201230" }, + { "R 0xb201244" }, + { "R 0xb201258" }, + { "R 0xb204510 2" }, + { "R 0xb204520" }, + { "R 0xb211024" }, + { "R 0xb221024" }, + { "R 0xb231024" }, + { "R 0x18220010" }, + { "R 0x18220030" }, + { "R 0x182200d0" }, + { "R 0x18220408" }, + { "R 0x18230408" }, + /* misc */ + { "R 0x17e00434" }, + { "R 0x17e0043c 2" }, + { "R 0x17c00038 2" }, + { "R 0x17c00438" }, + { "R 0x17e0041c 2" }, + { "R 0x17e00404" }, + { "R 0xc220000 2" }, + { "R 0xc230000 6" }, + { "R 0xc260008" }, + { "R 0x18598014" }, + { "R 0x4d8634" }, + { "R 0x4d8834" }, + { "R 0x418620" }, + { "R 0x418820" }, + /* ddr */ + { "R 0x9084208" }, + { "R 0x9084204" }, + { "R 0x9084108" }, + { "R 0x90841c0" }, + { "R 0x10c034 2" }, + { "R 0x144018" }, + { "R 0x9050078" }, + { "R 0x9050110 8" }, + { "R 0x9080058 2" }, + { "R 0x90800c8" }, + { "R 0x90800d4" }, + { "R 0x90800e0" }, + { "R 0x90800fc" }, + { "R 0x9084030" }, + { "R 0x9084038 2" }, + { "R 0x90840e4" }, + { "R 0x90840f4" }, + { "R 0x9084104 2" }, + { "R 0x9084198" }, + { "R 0x9084804" }, + { "R 0x908480c" }, + { "R 0x9084844" }, + { "R 0x9084850 2" }, + { "R 0x9084860 3" }, + { "R 0x9084888 2" }, + { "R 0x908409c 2" }, + { "R 0x908426c" }, + { "R 0x908439c" }, + { "R 0x9085124" }, + { "R 0x9085134 2" }, + { "R 0x9084840" }, + { "R 0x9084834" }, + { "R 0x9085124" }, + { "R 0x90ba280" }, + { "R 0x90ba288 7" }, + { "R 0x9258610 4" }, + { "R 0x92d8610 4" }, + { "R 0x9220344 8" }, + { "R 0x9220370 6" }, + { "R 0x9220480" }, + { "R 0x9222400" }, + { "R 0x922240c" }, + { "R 0x9223214 2" }, + { "R 0x9223220 3" }, + { "R 0x9223308" }, + { "R 0x9223318" }, + { "R 0x9232100" }, + { "R 0x9236040 6" }, + { "R 0x92360b0" }, + { "R 0x923a004 4" }, + { "R 0x923e030 2" }, + { "R 0x9241000" }, + { "R 0x9242028" }, + { "R 0x9242044 3" }, + { "R 0x9242070" }, + { "R 0x9248030" }, + { "R 0x9248048 8" }, + { "R 0x9238030" }, + { "R 0x9238060 2" }, + { "R 0x9238074" }, + { "R 0x9238088" }, + { "R 0x92380a0" }, + { "R 0x92380b0" }, + { "R 0x92a0344 8" }, + { "R 0x92a0370 6" }, + { "R 0x92a0480" }, + { "R 0x92a2400" }, + { "R 0x92a240c" }, + { "R 0x92a3214 2" }, + { "R 0x92a3220 3" }, + { "R 0x92a3308" }, + { "R 0x92a3318" }, + { "R 0x92b2100" }, + { "R 0x92b6040 6" }, + { "R 0x92b60b0" }, + { "R 0x92ba004 4" }, + { "R 0x92be030 2" }, + { "R 0x92c1000" }, + { "R 0x92c2028" }, + { "R 0x92c2044 3" }, + { "R 0x92c2070" }, + { "R 0x92c8030" }, + { "R 0x92c8048 8" }, + { "R 0x92b8030" }, + { "R 0x92b8060 2" }, + { "R 0x92b8074" }, + { "R 0x92b8088" }, + { "R 0x92b80a0" }, + { "R 0x92b80b0" }, + { "R 0x92c8064" }, + { "R 0x9270080" }, + { "R 0x9270310" }, + { "R 0x9270400" }, + { "R 0x9270410 6" }, + { "R 0x9270430" }, + { "R 0x9270440" }, + { "R 0x9270448" }, + { "R 0x92704a0" }, + { "R 0x92704b0" }, + { "R 0x92704b8 2" }, + { "R 0x92704d0 2" }, + { "R 0x9271400" }, + { "R 0x9271408" }, + { "R 0x927341c 2" }, + { "R 0x92753b0" }, + { "R 0x9275804" }, + { "R 0x9275c18 2" }, + { "R 0x9275c2c" }, + { "R 0x9275c38" }, + { "R 0x9276418 2" }, + { "R 0x9279100" }, + { "R 0x9279110" }, + { "R 0x9279120" }, + { "R 0x9279180 2" }, + { "R 0x92f0080" }, + { "R 0x92f0310" }, + { "R 0x92f0400" }, + { "R 0x92f0410 6" }, + { "R 0x92f0430" }, + { "R 0x92f0440" }, + { "R 0x92f0448" }, + { "R 0x92f04a0" }, + { "R 0x92f04b0" }, + { "R 0x92f04b8 2" }, + { "R 0x92f04d0 2" }, + { "R 0x92f1400" }, + { "R 0x92f1408" }, + { "R 0x92f341c 2" }, + { "R 0x92f53b0" }, + { "R 0x92f5804" }, + { "R 0x92f5c18 2" }, + { "R 0x92f5c2c" }, + { "R 0x92f5c38" }, + { "R 0x92f6418 2" }, + { "R 0x92f9100" }, + { "R 0x92f9110" }, + { "R 0x92f9120" }, + { "R 0x92f9180 2" }, + { "R 0x9260080" }, + { "R 0x9260400" }, + { "R 0x9260410 3" }, + { "R 0x9260420 2" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92604b0" }, + { "R 0x92604b8 2" }, + { "R 0x92604d0 2" }, + { "R 0x9261400" }, + { "R 0x9263410" }, + { "R 0x92653b0" }, + { "R 0x9265804" }, + { "R 0x9265b1c" }, + { "R 0x9265b2c" }, + { "R 0x9265b38" }, + { "R 0x9269100" }, + { "R 0x9269108" }, + { "R 0x9269110" }, + { "R 0x9269118" }, + { "R 0x9269120" }, + { "R 0x9269180 2" }, + { "R 0x92e0080" }, + { "R 0x92e0400" }, + { "R 0x92e0410 3" }, + { "R 0x92e0420 2" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x92e04b0" }, + { "R 0x92e04b8 2" }, + { "R 0x92e04d0 2" }, + { "R 0x92e1400" }, + { "R 0x92e3410" }, + { "R 0x92e53b0" }, + { "R 0x92e5804" }, + { "R 0x92e5b1c" }, + { "R 0x92e5b2c" }, + { "R 0x92e5b38" }, + { "R 0x92e9100" }, + { "R 0x92e9108" }, + { "R 0x92e9110" }, + { "R 0x92e9118" }, + { "R 0x92e9120" }, + { "R 0x92e9180 2" }, + { "R 0x96b0868" }, + { "R 0x96b0870" }, + { "R 0x96b1004" }, + { "R 0x96b100c" }, + { "R 0x96b1014" }, + { "R 0x96b1204" }, + { "R 0x96b120c" }, + { "R 0x96b1214" }, + { "R 0x96b1504" }, + { "R 0x96b150c" }, + { "R 0x96b1514" }, + { "R 0x96b1604" }, + { "R 0x96b8100" }, + { "R 0x96b813c" }, + { "R 0x96b8500" }, + { "R 0x96b853c" }, + { "R 0x96b8a04" }, + { "R 0x96b8a18" }, + { "R 0x96b8ea8" }, + { "R 0x96b9044" }, + { "R 0x96b904c" }, + { "R 0x96b9054" }, + { "R 0x96b905c" }, + { "R 0x96b910c 2" }, + { "R 0x96b9204" }, + { "R 0x96b920c" }, + { "R 0x96b9238" }, + { "R 0x96b9240" }, + { "R 0x96b926c" }, + { "R 0x96b9394" }, + { "R 0x96b939c" }, + { "R 0x96b9704" }, + { "R 0x96b970c" }, + { "R 0x96f0868" }, + { "R 0x96f0870" }, + { "R 0x96f1004" }, + { "R 0x96f100c" }, + { "R 0x96f1014" }, + { "R 0x96f1204" }, + { "R 0x96f120c" }, + { "R 0x96f1214" }, + { "R 0x96f1504" }, + { "R 0x96f150c" }, + { "R 0x96f1514" }, + { "R 0x96f1604" }, + { "R 0x96f8100" }, + { "R 0x96f813c" }, + { "R 0x96f8500" }, + { "R 0x96f853c" }, + { "R 0x96f8a04" }, + { "R 0x96f8a18" }, + { "R 0x96f8ea8" }, + { "R 0x96f9044" }, + { "R 0x96f904c" }, + { "R 0x96f9054" }, + { "R 0x96f905c" }, + { "R 0x96f910c 2" }, + { "R 0x96f9204" }, + { "R 0x96f920c" }, + { "R 0x96f9238" }, + { "R 0x96f9240" }, + { "R 0x96f926c" }, + { "R 0x96f9394" }, + { "R 0x96f939c" }, + { "R 0x96f9704" }, + { "R 0x96f970c" }, + { "R 0x9130100 3" }, + { "R 0x9170100 3" }, + { "R 0x91dd100 4" }, + { "R 0x91df100" }, + { "R 0x610110 5" }, + { "R 0x9230010" }, + { "R 0x9230020" }, + { "R 0x9230030" }, + { "R 0x9230040" }, + { "R 0x92b0010" }, + { "R 0x92b0020" }, + { "R 0x92b0030" }, + { "R 0x92b0040" }, + { "R 0x9232050" }, + { "R 0x923605c 2" }, + { "R 0x92360a0" }, + { "R 0x923a018 2" }, + { "R 0x92b2050" }, + { "R 0x92b605c 2" }, + { "R 0x92b60a0" }, + { "R 0x92ba018 2" }, + { "R 0x9222404 2" }, + { "R 0x9222410" }, + { "R 0x9238004" }, + { "R 0x9238014" }, + { "R 0x923805c" }, + { "R 0x923a014" }, + { "R 0x92a2404 2" }, + { "R 0x92a2410" }, + { "R 0x92b8004" }, + { "R 0x92b8014" }, + { "R 0x92b805c" }, + { "R 0x92ba014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x9067e00 124" }, + { "R 0x905000c" }, + { "R 0x9050948" }, + { "R 0x9050078" }, + { "R 0x9050008" }, +}; + +static const struct dcc_register_entry kodiak_dcc_entries_ll3[] = { + /* lpass_rsc */ + { "R 0xb254520" }, + { "R 0xb251020 2" }, + { "R 0xb251030" }, + { "R 0xb251200" }, + { "R 0xb251214" }, + { "R 0xb251228" }, + { "R 0xb25123c" }, + { "R 0xb251250" }, + { "R 0xb251204" }, + { "R 0xb251218" }, + { "R 0xb25122c" }, + { "R 0xb251240" }, + { "R 0xb251254" }, + { "R 0xb251208" }, + { "R 0xb25121c" }, + { "R 0xb251230" }, + { "R 0xb251244" }, + { "R 0xb251258" }, + { "R 0xb254510 2" }, + { "R 0xb250010 2" }, + { "R 0xb250900 2" }, + { "R 0x3500010 3" }, + { "R 0x3500030" }, + { "R 0x3500038" }, + { "R 0x3500040" }, + { "R 0x3500048" }, + { "R 0x35000d0" }, + { "R 0x3500210" }, + { "R 0x3500230" }, + { "R 0x3500250" }, + { "R 0x3500270" }, + { "R 0x3500290" }, + { "R 0x35002b0" }, + { "R 0x3500208" }, + { "R 0x3500228" }, + { "R 0x3500248" }, + { "R 0x3500268" }, + { "R 0x3500288" }, + { "R 0x35002a8" }, + { "R 0x350020c" }, + { "R 0x350022c" }, + { "R 0x350024c" }, + { "R 0x350026c" }, + { "R 0x350028c" }, + { "R 0x35002ac" }, + { "R 0x3500400 3" }, + { "R 0x3500d04" }, + { "R 0x30b0010 3" }, + { "R 0x30b0210" }, + { "R 0x30b0230" }, + { "R 0x30b0250" }, + { "R 0x30b0270" }, + { "R 0x30b0290" }, + { "R 0x30b02b0" }, + { "R 0x30b0208" }, + { "R 0x30b0228" }, + { "R 0x30b0248" }, + { "R 0x30b0268" }, + { "R 0x30b0288" }, + { "R 0x30b02a8" }, + { "R 0x30b020c" }, + { "R 0x30b022c" }, + { "R 0x30b024c" }, + { "R 0x30b026c" }, + { "R 0x30b028c" }, + { "R 0x30b02ac" }, + { "R 0x30b0400 3" }, + /* nsp_rsc */ + { "R 0xb2b4520" }, + { "R 0xb2b1020 2" }, + { "R 0xb2b1030" }, + { "R 0xb2b1200" }, + { "R 0xb2b1214" }, + { "R 0xb2b1228" }, + { "R 0xb2b123c" }, + { "R 0xb2b1250" }, + { "R 0xb2b1204" }, + { "R 0xb2b1218" }, + { "R 0xb2b122c" }, + { "R 0xb2b1240" }, + { "R 0xb2b1254" }, + { "R 0xb2b1208" }, + { "R 0xb2b121c" }, + { "R 0xb2b1230" }, + { "R 0xb2b1244" }, + { "R 0xb2b1258" }, + { "R 0xb2b4510 2" }, + { "R 0xb2b0010" }, + { "R 0xb2b0900" }, + { "R 0xa302028" }, + { "R 0xa0a4010 3" }, + { "R 0xa0a4030" }, + { "R 0xa0a4038" }, + { "R 0xa0a4040 2" }, + { "R 0xa0a40d0" }, + { "R 0xa0a4210" }, + { "R 0xa0a4230" }, + { "R 0xa0a4250" }, + { "R 0xa0a4270" }, + { "R 0xa0a4290" }, + { "R 0xa0a42b0" }, + { "R 0xa0a4208" }, + { "R 0xa0a4228" }, + { "R 0xa0a4248" }, + { "R 0xa0a4268" }, + { "R 0xa0a4288" }, + { "R 0xa0a42a8" }, + { "R 0xa0a420c" }, + { "R 0xa0a422c" }, + { "R 0xa0a424c" }, + { "R 0xa0a426c" }, + { "R 0xa0a428c" }, + { "R 0xa0a42ac" }, + { "R 0xa0a4400 2" }, + { "R 0xa0a4d04" }, + { "R 0xa3b0010 3" }, + { "R 0xa3b0210" }, + { "R 0xa3b0230" }, + { "R 0xa3b0250" }, + { "R 0xa3b0270" }, + { "R 0xa3b0290" }, + { "R 0xa3b02b0" }, + { "R 0xa3b0208" }, + { "R 0xa3b0228" }, + { "R 0xa3b0248" }, + { "R 0xa3b0268" }, + { "R 0xa3b0288" }, + { "R 0xa3b02a8" }, + { "R 0xa3b020c" }, + { "R 0xa3b022c" }, + { "R 0xa3b024c" }, + { "R 0xa3b026c" }, + { "R 0xa3b028c" }, + { "R 0xa3b02ac" }, + { "R 0xa3b0400 3" }, + /* sdi_debug */ + { "R 0x10413c" }, + { "R 0x105024" }, + { "R 0x108008" }, + { "R 0x108004" }, + { "R 0x10500c" }, + { "R 0x105658" }, + { "R 0x105640 2" }, + { "R 0x105010" }, + { "R 0x10500c" }, + { "R 0x105024" }, + /* lpass_cdsp_tunning */ + { "R 0x3500d00 3" }, + { "R 0x3500d10 4" }, + { "R 0x3500fb0 4" }, + { "R 0x3501250 4" }, + { "R 0x35014f0 4" }, + { "R 0x3501790 4" }, + { "R 0x3501a30 4" }, + { "R 0x3503d44 4" }, + { "R 0x35000d0 3" }, + { "R 0x3500100" }, + { "R 0x3500d3c" }, + { "R 0xa0a40d0 3" }, + { "R 0xa0a4100" }, + { "R 0xa0a4d3c" }, + { "R 0xa0a7d44 4" }, + { "R 0xa0a4d00 3" }, + /* wpss_rsc */ + { "R 0x8a02028" }, + { "R 0x8b00000 2" }, + { "R 0x8b00010 15" }, + { "R 0x8b000d0" }, + { "R 0x8b000d8" }, + { "R 0x8b00100 3" }, + { "R 0x8b00200 2" }, + { "R 0x8b00224" }, + { "R 0x8b00244" }, + { "R 0x8b00264" }, + { "R 0x8b00284" }, + { "R 0x8b002a4" }, + { "R 0x8b00208" }, + { "R 0x8b00228" }, + { "R 0x8b00248" }, + { "R 0x8b00268" }, + { "R 0x8b00288" }, + { "R 0x8b002a8" }, + { "R 0x8b0020c" }, + { "R 0x8b0022c" }, + { "R 0x8b0024c" }, + { "R 0x8b0026c" }, + { "R 0x8b0028c" }, + { "R 0x8b002ac" }, + { "R 0x8b00210" }, + { "R 0x8b00230" }, + { "R 0x8b00250" }, + { "R 0x8b00270" }, + { "R 0x8b00290" }, + { "R 0x8b002b0" }, + { "R 0x8b00400 3" }, + { "R 0x8b00460 2" }, + { "R 0x8b004a0 7" }, + { "R 0x8ab0000 2" }, + { "R 0x8ab0010 3" }, + { "R 0x8ab00d0" }, + { "R 0x8ab00d8" }, + { "R 0x8ab0100 3" }, + { "R 0x8ab0200 2" }, + { "R 0x8ab0224" }, + { "R 0x8ab0244" }, + { "R 0x8ab0264" }, + { "R 0x8ab0284" }, + { "R 0x8ab02a4" }, + { "R 0x8ab0208" }, + { "R 0x8ab0228" }, + { "R 0x8ab0248" }, + { "R 0x8ab0268" }, + { "R 0x8ab0288" }, + { "R 0x8ab02a8" }, + { "R 0x8ab020c" }, + { "R 0x8ab022c" }, + { "R 0x8ab024c" }, + { "R 0x8ab026c" }, + { "R 0x8ab028c" }, + { "R 0x8ab02ac" }, + { "R 0x8ab0210" }, + { "R 0x8ab0230" }, + { "R 0x8ab0250" }, + { "R 0x8ab0270" }, + { "R 0x8ab0290" }, + { "R 0x8ab02b0" }, + { "R 0x8ab0400 3" }, + { "R 0x8ab0460 2" }, + { "R 0x8ab04a0 7" }, + /* video_noc */ + { "R 0xaa10504 2" }, + { "R 0xaa10510" }, + { "R 0xaa10520 8" }, + { "R 0xaa10300" }, + { "R 0xaa10010" }, + { "R 0xaa10020" }, +}; + +static const struct dcc_link_config kodiak_link_configs[] = { + { + .link_list = 6, + .entries = kodiak_dcc_entries_ll6, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll6), + }, + { + .link_list = 4, + .entries = kodiak_dcc_entries_ll4, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll4), + }, + { + .link_list = 3, + .entries = kodiak_dcc_entries_ll3, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll3), + }, +}; + +static const struct dcc_config kodiak_config = { + .lists = kodiak_link_configs, + .num_lists = ARRAY_SIZE(kodiak_link_configs), +}; + +static const struct dcc_pdata kodiak_pdata = { + .base = 0x0117f000, + .size = 0x00001000, + .ram_base = 0x01112000, + .ram_size = 0x00006000, + .dcc_offset = 0x12000, + .map_ver = 0x2, + .config = &kodiak_config, +}; + +#endif /* _QCOM_DCC_KODIAK_CONFIG_H */ diff --git a/drivers/misc/qcom-dcc-lemans-config.h b/drivers/misc/qcom-dcc-lemans-config.h new file mode 100644 index 0000000000000..01327a67eac91 --- /dev/null +++ b/drivers/misc/qcom-dcc-lemans-config.h @@ -0,0 +1,1630 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_LEMANS_CONFIG_H +#define _QCOM_DCC_LEMANS_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry lemans_dcc_entries[] = { + /* lpm */ + { "R 0x18000040" }, + { "R 0x18000024" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x18090024" }, + { "R 0x18090040" }, + { "R 0x18090104" }, + { "R 0x180900f8" }, + { "R 0x180800f4" }, + { "R 0x18080104" }, + { "R 0x180800f8" }, + { "R 0x180900f4" }, + { "R 0x18210404 2" }, + { "R 0xb201024" }, + { "R 0xb201020" }, + { "R 0xb211020" }, + { "R 0xb221020" }, + { "R 0xb232020" }, + /* tsens */ + { "R 0xc222004" }, + { "R 0xc263014" }, + { "R 0xc2630e0" }, + { "R 0xc2630ec" }, + { "R 0xc2630a0 16" }, + { "R 0xc2630e8" }, + { "R 0xc26313c" }, + { "R 0xc223004" }, + { "R 0xc265014" }, + { "R 0xc2650e0" }, + { "R 0xc2650ec" }, + { "R 0xc2650a0 16" }, + { "R 0xc2650e8" }, + { "R 0xc26513c" }, + { "R 0xc224004" }, + { "R 0xc251014" }, + { "R 0xc2510e0" }, + { "R 0xc2510ec" }, + { "R 0xc2510a0 16" }, + { "R 0xc2510e8" }, + { "R 0xc25113c" }, + { "R 0xc225004" }, + { "R 0xc252014" }, + { "R 0xc2520e0" }, + { "R 0xc2520ec" }, + { "R 0xc2520a0 16" }, + { "R 0xc2520e8" }, + { "R 0xc25213c" }, + /* pll */ + { "R 0x182b0000 12" }, + { "R 0x182b003c" }, + { "R 0x182b4000 12" }, + { "R 0x182b403c" }, + { "R 0x18280044" }, + { "R 0x1828004c" }, + { "R 0x18280060" }, + { "R 0x18284044" }, + { "R 0x1828404c" }, + { "R 0x18284060" }, + { "R 0x182b2000 12" }, + { "R 0x182b203c" }, + { "R 0x182b6000 12" }, + { "R 0x182b603c" }, + { "R 0x18282044" }, + { "R 0x1828204c" }, + { "R 0x18282060" }, + { "R 0x18286044" }, + { "R 0x1828604c" }, + { "R 0x18286060" }, + /* limits */ + { "R 0xec80010" }, + { "R 0xec81000" }, + { "R 0xec81010 64" }, + { "R 0x18378220 2" }, + { "R 0x183782a0 2" }, + { "R 0x183784a0 12" }, + { "R 0x18378520" }, + { "R 0x18378588" }, + { "R 0x18378d90 12" }, + { "R 0x18379010 10" }, + { "R 0x18379090 10" }, + { "R 0x18379a90 8" }, + { "R 0x18370220 2" }, + { "R 0x183702a0 2" }, + { "R 0x183704a0 12" }, + { "R 0x18370520" }, + { "R 0x18370588" }, + { "R 0x18370d90 12" }, + { "R 0x18371010 10" }, + { "R 0x18371090 10" }, + { "R 0x18371a90 8" }, + { "R 0x26310220 3" }, + { "R 0x263102a0 3" }, + { "R 0x263104a0 6" }, + { "R 0x26310520" }, + { "R 0x26310588" }, + { "R 0x26310d90 8" }, + { "R 0x26311010 6" }, + { "R 0x26311090 6" }, + { "R 0x26311a90 3" }, + { "R 0x2a310220 3" }, + { "R 0x2a3102a0 3" }, + { "R 0x2a3104a0 6" }, + { "R 0x2a310520" }, + { "R 0x2a310588" }, + { "R 0x2a310d90 8" }, + { "R 0x2a311010 6" }, + { "R 0x2a311090 6" }, + { "R 0x2a311a90 3" }, + /* ddr */ + { "R 0x610110" }, + { "R 0x9050008" }, + { "R 0x905001c" }, + { "R 0x9050030" }, + { "R 0x9050050" }, + { "R 0x9050070" }, + { "R 0x9050948" }, + { "R 0x905104c" }, + { "R 0x9050078" }, + { "R 0x9050114" }, + { "R 0x90a0008 2" }, + { "R 0x90a0080" }, + { "R 0x90a1008 2" }, + { "R 0x90a80e4 2" }, + { "R 0x90a816c 2" }, + { "R 0x90a80f8" }, + { "R 0x90a8180 2" }, + { "R 0x90a81a0 2" }, + { "R 0x90a81c0 2" }, + { "R 0x90a81e4" }, + { "R 0x90a81f4" }, + { "R 0x90a8204" }, + { "R 0x90a8218" }, + { "R 0x90a8228" }, + { "R 0x90a8264 2" }, + { "R 0x90a8270" }, + { "R 0x90a80fc 4" }, + { "R 0x90a8148 2" }, + { "R 0x90a8158 2" }, + { "R 0x90a8190 2" }, + { "R 0x90a81b0 2" }, + { "R 0x90a81d0 2" }, + { "R 0x90a84f4" }, + { "R 0x90a8138" }, + { "R 0x90a8150" }, + { "R 0x90a8160" }, + { "R 0x90a8198" }, + { "R 0x90a81b8" }, + { "R 0x90a81d8" }, + { "R 0x90a8280" }, + { "R 0x90a819c" }, + { "R 0x90a81bc" }, + { "R 0x90a81dc" }, + { "R 0x90a821c" }, + { "R 0x90a822c" }, + { "R 0x90a84f8" }, + { "R 0x90a9204" }, + { "R 0x90a880c" }, + { "R 0x90a8834" }, + { "R 0x90a8840 2" }, + { "R 0x90a8850 2" }, + { "R 0x90a8860 3" }, + { "R 0x90a8878" }, + { "R 0x90a8884" }, + { "R 0x90a9260" }, + { "R 0x90a8900" }, + { "R 0x90a9134 2" }, + { "R 0x90a8880 3" }, + { "R 0x90e0000" }, + { "R 0x90e0008" }, + { "R 0x90e0010" }, + { "R 0x90e0020 8" }, + { "R 0x90e0248" }, + { "R 0x90e3100" }, + { "R 0x90e4100 7" }, + { "R 0x90e5008" }, + { "R 0x90e5010 3" }, + { "R 0x9080024" }, + { "R 0x908002c" }, + { "R 0x9080034" }, + { "R 0x908003c" }, + { "R 0x9080044" }, + { "R 0x908004c" }, + { "R 0x9080054 3" }, + { "R 0x90800b8 2" }, + { "R 0x90800c8" }, + { "R 0x90800d4" }, + { "R 0x90800e0" }, + { "R 0x90800ec" }, + { "R 0x90800f8" }, + { "R 0x9080104 2" }, + { "R 0x9080114" }, + { "R 0x9080144" }, + { "R 0x908014c" }, + { "R 0x9080168" }, + { "R 0x9080174" }, + { "R 0x90801ac" }, + { "R 0x90801b4" }, + { "R 0x90801bc" }, + { "R 0x90801c4" }, + { "R 0x90801cc" }, + { "R 0x90801d4" }, + { "R 0x90801dc" }, + { "R 0x90801e4" }, + { "R 0x90801ec" }, + { "R 0x90801f4 2" }, + { "R 0x90ba000" }, + { "R 0x90ba050" }, + { "R 0x90ba280" }, + { "R 0x90ba288" }, + { "R 0x9280610 4" }, + { "R 0x9280680 4" }, + { "R 0x9380610" }, + { "R 0x9280614" }, + { "R 0x9380618 2" }, + { "R 0x9380680 4" }, + { "R 0x9480610 4" }, + { "R 0x9480680 4" }, + { "R 0x9580610 4" }, + { "R 0x9580680 4" }, + { "R 0x9680610 4" }, + { "R 0x9680680 4" }, + { "R 0x9380610" }, + { "R 0x9280614" }, + { "R 0x9380618 2" }, + { "R 0x9380680 4" }, + { "R 0x9100008" }, + { "R 0x9100010" }, + { "R 0x9100408" }, + { "R 0x9100410" }, + { "R 0x9100808" }, + { "R 0x9100810" }, + { "R 0x9100c08" }, + { "R 0x9100c10" }, + { "R 0x9101008" }, + { "R 0x9101010" }, + { "R 0x9101408" }, + { "R 0x9101410" }, + { "R 0x9101808" }, + { "R 0x9101810" }, + { "R 0x9101c08" }, + { "R 0x9101c10" }, + { "R 0x9102008" }, + { "R 0x9102010" }, + { "R 0x9102408" }, + { "R 0x9102410" }, + { "R 0x9102808" }, + { "R 0x9102810" }, + { "R 0x9102c08" }, + { "R 0x9102c10" }, + { "R 0x9103000 3" }, + { "R 0x9103010 3" }, + { "R 0x9103080 3" }, + { "R 0x9103090 3" }, + { "R 0x9104008" }, + { "R 0x9105008" }, + { "R 0x9106008" }, + { "R 0x9107008" }, + { "R 0x9108008" }, + { "R 0x9108808" }, + { "R 0x9109008" }, + { "R 0x9109808" }, + { "R 0x9122008" }, + { "R 0x9122408" }, + { "R 0x9122808" }, + { "R 0x9122c08" }, + { "R 0x9123008" }, + { "R 0x9123408" }, + { "R 0x9123808" }, + { "R 0x9123c08" }, + { "R 0x9124008" }, + { "R 0x9124408" }, + { "R 0x9124808" }, + { "R 0x9124c08" }, + { "R 0x9138008" }, + { "R 0x9138088" }, + { "R 0x9138108" }, + { "R 0x9138188" }, + { "R 0x9138208" }, + { "R 0x9138288" }, + { "R 0x9138308" }, + { "R 0x9138388" }, + { "R 0x9138408" }, + { "R 0x9138488" }, + { "R 0x9138508" }, + { "R 0x9138588" }, + { "R 0x9138608" }, + { "R 0x9138688" }, + { "R 0x9140000 5" }, + { "R 0x9140018" }, + { "R 0x9140020 3" }, + { "R 0x9140030 3" }, + { "R 0x9140040 3" }, + { "R 0x9140400 5" }, + { "R 0x9140418" }, + { "R 0x9140420 3" }, + { "R 0x9140430 3" }, + { "R 0x9140440 3" }, + { "R 0x9140800 5" }, + { "R 0x9140818" }, + { "R 0x9140820 3" }, + { "R 0x9140830 3" }, + { "R 0x9140840 3" }, + { "R 0x9140c00 5" }, + { "R 0x9140c18" }, + { "R 0x9140c20 3" }, + { "R 0x9140c30 3" }, + { "R 0x9140c40 3" }, + { "R 0x9141000 5" }, + { "R 0x9141018" }, + { "R 0x9141020 3" }, + { "R 0x9141030 3" }, + { "R 0x9141040 3" }, + { "R 0x9141400 5" }, + { "R 0x9141418" }, + { "R 0x9141420 3" }, + { "R 0x9141430 3" }, + { "R 0x9141440 3" }, + { "R 0x9141800 3" }, + { "R 0x9141810 3" }, + { "R 0x9141880 3" }, + { "R 0x9141890 3" }, + { "R 0x9142008" }, + { "R 0x9143008" }, + { "R 0x9144008" }, + { "R 0x9145008" }, + { "R 0x9146008" }, + { "R 0x9147008" }, + { "R 0x9148008" }, + { "R 0x9149008" }, + { "R 0x914a008" }, + { "R 0x914b008" }, + { "R 0x914c008" }, + { "R 0x914d008" }, + { "R 0x914e008" }, + { "R 0x914e208" }, + { "R 0x914e408" }, + { "R 0x914e608" }, + { "R 0x914e808" }, + { "R 0x914ea08" }, + { "R 0x914f008" }, + { "R 0x914f808" }, + { "R 0x9150008" }, + { "R 0x9150808" }, + { "R 0x9151008" }, + { "R 0x9151808" }, + { "R 0x9152008" }, + { "R 0x9153008" }, + { "R 0x9154008" }, + { "R 0x9155008" }, + { "R 0x9156008" }, + { "R 0x9157008" }, + { "R 0x9163008" }, + { "R 0x9163010" }, + { "R 0x9165008" }, + { "R 0x9165010" }, + { "R 0x9167008" }, + { "R 0x9167010" }, + { "R 0x9169008" }, + { "R 0x9169010" }, + { "R 0x916b008" }, + { "R 0x916b010" }, + { "R 0x916d008" }, + { "R 0x916d010" }, + { "R 0x9170000 3" }, + { "R 0x9170010" }, + { "R 0x9170018" }, + { "R 0x9170020 6" }, + { "R 0x9170400 3" }, + { "R 0x9170410" }, + { "R 0x9170418" }, + { "R 0x9170420 6" }, + { "R 0x9170800 3" }, + { "R 0x9170810" }, + { "R 0x9170818" }, + { "R 0x9170820 6" }, + { "R 0x9170c00 3" }, + { "R 0x9170c10" }, + { "R 0x9170c18" }, + { "R 0x9170c20 6" }, + { "R 0x9171000 3" }, + { "R 0x9171010" }, + { "R 0x9171018" }, + { "R 0x9171020 6" }, + { "R 0x9171400 3" }, + { "R 0x9171410" }, + { "R 0x9171418" }, + { "R 0x9171420 6" }, + { "R 0x9178008" }, + { "R 0x9178088" }, + { "R 0x9178108" }, + { "R 0x9178188" }, + { "R 0x9178208" }, + { "R 0x9178288" }, + { "R 0x9178308" }, + { "R 0x9178388" }, + { "R 0x9178408" }, + { "R 0x9178488" }, + { "R 0x9178508" }, + { "R 0x9180000 5" }, + { "R 0x9180018" }, + { "R 0x9180020 3" }, + { "R 0x9180030 3" }, + { "R 0x9180040 3" }, + { "R 0x9180400 5" }, + { "R 0x9180418" }, + { "R 0x9180420 3" }, + { "R 0x9180430 3" }, + { "R 0x9180440 3" }, + { "R 0x9180800 3" }, + { "R 0x9180810 3" }, + { "R 0x9180880 3" }, + { "R 0x9180890 3" }, + { "R 0x9180900 3" }, + { "R 0x9180910 3" }, + { "R 0x9180a08" }, + { "R 0x9181008" }, + { "R 0x9181808" }, + { "R 0x9182208" }, + { "R 0x9182408" }, + { "R 0x9182608" }, + { "R 0x9182808" }, + { "R 0x9182a08" }, + { "R 0x9182c08" }, + { "R 0x9182e08" }, + { "R 0x9183008" }, + { "R 0x9183808" }, + { "R 0x9184008" }, + { "R 0x9185008" }, + { "R 0x9186008" }, + { "R 0x9187008" }, + { "R 0x9188008" }, + { "R 0x9189008" }, + { "R 0x918a008" }, + { "R 0x918b008" }, + { "R 0x9190000 3" }, + { "R 0x9190010" }, + { "R 0x9190018" }, + { "R 0x9190020 6" }, + { "R 0x9190400 3" }, + { "R 0x9190410" }, + { "R 0x9190418" }, + { "R 0x9190420 6" }, + { "R 0x9197008" }, + { "R 0x9197088" }, + { "R 0x9198008" }, + { "R 0x9198088" }, + { "R 0x9198108" }, + { "R 0x9198188" }, + { "R 0x9198208" }, + { "R 0x9198288" }, + { "R 0x9198308" }, + { "R 0x9198388" }, + { "R 0x9198408" }, + { "R 0x9198508" }, + { "R 0x9198588" }, + { "R 0x9198608" }, + { "R 0x9198688" }, + { "R 0x9198708" }, + { "R 0x9198788" }, + { "R 0x9198808" }, + { "R 0x9198888" }, + { "R 0x9198908" }, + { "R 0x9198988" }, + { "R 0x9198a08" }, + { "R 0x9198a88" }, + { "R 0x9198b08" }, + { "R 0x9198b88" }, + { "R 0x9198c08" }, + { "R 0x9198e40" }, + { "R 0x9198e48" }, + { "R 0x91a0008" }, + { "R 0x91a1008" }, + { "R 0x91a2008" }, + { "R 0x91a6040" }, + { "R 0x91a6048" }, + { "R 0x91a8100 4" }, + { "R 0x91ab100" }, + { "R 0x91ac040" }, + { "R 0x91ac048" }, + { "R 0x91ad008" }, + { "R 0x91ad010" }, + { "R 0x91ae008" }, + { "R 0x91ae010" }, + { "R 0x91af008" }, + { "R 0x91af010" }, + { "R 0x91b0008" }, + { "R 0x91b0010" }, + { "R 0x91b1008" }, + { "R 0x91b1010" }, + { "R 0x91b2008" }, + { "R 0x91b2010" }, + { "R 0x91b3008" }, + { "R 0x91b3010" }, + { "R 0x91b4008" }, + { "R 0x91b4010" }, + { "R 0x91b5008" }, + { "R 0x91b5010" }, + { "R 0x91b6008" }, + { "R 0x91b6010" }, + { "R 0x91b7008" }, + { "R 0x91b7010" }, + { "R 0x91b8008" }, + { "R 0x91b8010" }, + { "R 0x91b9008" }, + { "R 0x91b9010" }, + { "R 0x91ba008" }, + { "R 0x91ba010" }, + { "R 0x91c0008" }, + { "R 0x91c0208" }, + { "R 0x91c0408" }, + { "R 0x91c0608" }, + { "R 0x91c0808" }, + { "R 0x91c0a08" }, + { "R 0x91c0c08" }, + { "R 0x91c0e08" }, + { "R 0x91c1008" }, + { "R 0x91c1208" }, + { "R 0x91c1408" }, + { "R 0x91c1608" }, + { "R 0x91c1808" }, + { "R 0x91c1a08" }, + { "R 0x91c1c08" }, + { "R 0x91c1e08" }, + { "R 0x91d8008" }, + { "R 0x91d8088" }, + { "R 0x91d8108" }, + { "R 0x91d8188" }, + { "R 0x91d8208" }, + { "R 0x91d8288" }, + { "R 0x91d8308" }, + { "R 0x91d8388" }, + { "R 0x91d8408" }, + { "R 0x91d8488" }, + { "R 0x91d8508" }, + { "R 0x91d8588" }, + { "R 0x91d8608" }, + { "R 0x91d8688" }, + { "R 0x91d8708" }, + { "R 0x91d8788" }, + { "R 0x91e1008" }, + { "R 0x91e1088" }, + { "R 0x91e1108" }, + { "R 0x91e3008" }, + { "R 0x91e3010" }, + { "R 0x91e4008" }, + { "R 0x91e4010" }, + { "R 0x91e5008" }, + { "R 0x91e5010" }, + { "R 0x91e6008" }, + { "R 0x91e6010" }, + { "R 0x91e7008" }, + { "R 0x91e7010" }, + { "R 0x91e8008" }, + { "R 0x91e8010" }, + { "R 0x91e9008" }, + { "R 0x91e9010" }, + { "R 0x91ea008" }, + { "R 0x91ea010" }, + { "R 0x91eb008" }, + { "R 0x91eb010" }, + { "R 0x91ec008" }, + { "R 0x91ec010" }, + { "R 0x91ed008" }, + { "R 0x91ed010" }, + { "R 0x91ee008" }, + { "R 0x91ee010" }, + { "R 0x91ef008" }, + { "R 0x91ef010" }, + { "R 0x91f0008" }, + { "R 0x91f0010" }, + { "R 0x91f1008" }, + { "R 0x91f1010" }, + { "R 0x91f2008" }, + { "R 0x91f2010" }, + { "R 0x91f3008" }, + { "R 0x91f3010" }, + { "R 0x91f4008" }, + { "R 0x91f4010" }, + { "R 0x91f5008" }, + { "R 0x91f5010" }, + { "R 0x91f6008" }, + { "R 0x91f6010" }, + { "R 0x9220344 9" }, + { "R 0x9220370 7" }, + { "R 0x9220480" }, + { "R 0x9222400 26" }, + { "R 0x9222470 5" }, + { "R 0x922320c" }, + { "R 0x9223214 2" }, + { "R 0x9223220 4" }, + { "R 0x9223308" }, + { "R 0x9223318" }, + { "R 0x922358c" }, + { "R 0x9234010" }, + { "R 0x923801c 8" }, + { "R 0x9238050" }, + { "R 0x9238100 7" }, + { "R 0x923c004" }, + { "R 0x923c014" }, + { "R 0x923c020" }, + { "R 0x923c030" }, + { "R 0x923c05c 3" }, + { "R 0x923c074" }, + { "R 0x923c088" }, + { "R 0x923c0a0" }, + { "R 0x923c0b0" }, + { "R 0x923c0c0" }, + { "R 0x923c0d0" }, + { "R 0x923c0e0" }, + { "R 0x923c0f0" }, + { "R 0x923c100" }, + { "R 0x923d064" }, + { "R 0x9240008 6" }, + { "R 0x9240028" }, + { "R 0x924203c 6" }, + { "R 0x9242058 7" }, + { "R 0x924208c" }, + { "R 0x92420b0" }, + { "R 0x92420b8 3" }, + { "R 0x92420f4" }, + { "R 0x92420fc 7" }, + { "R 0x9242324 14" }, + { "R 0x9242410" }, + { "R 0x92430a8" }, + { "R 0x9248004 7" }, + { "R 0x9248024" }, + { "R 0x9248040" }, + { "R 0x9248048" }, + { "R 0x9249064" }, + { "R 0x924c000" }, + { "R 0x924c030 3" }, + { "R 0x924c040 3" }, + { "R 0x924c054 2" }, + { "R 0x924c078" }, + { "R 0x924c108" }, + { "R 0x924c110" }, + { "R 0x9250020" }, + { "R 0x9251054" }, + { "R 0x9252014 3" }, + { "R 0x9252028 17" }, + { "R 0x9252070 8" }, + { "R 0x9252098" }, + { "R 0x92520a0" }, + { "R 0x92520b4" }, + { "R 0x92520c0 4" }, + { "R 0x92520f4 10" }, + { "R 0x9252120 12" }, + { "R 0x925802c" }, + { "R 0x925809c 2" }, + { "R 0x92580a8 3" }, + { "R 0x92580b8" }, + { "R 0x92580c0 7" }, + { "R 0x92580e0" }, + { "R 0x92580e8" }, + { "R 0x92580f0" }, + { "R 0x92580f8" }, + { "R 0x9258100" }, + { "R 0x9258108" }, + { "R 0x9258110" }, + { "R 0x9258118" }, + { "R 0x9258120" }, + { "R 0x9258128" }, + { "R 0x9258210 3" }, + { "R 0x9259010" }, + { "R 0x9259070" }, + { "R 0x925b004" }, + { "R 0x926004c 10" }, + { "R 0x9260078" }, + { "R 0x926020c" }, + { "R 0x9260214" }, + { "R 0x9261084" }, + { "R 0x9262020" }, + { "R 0x9263020" }, + { "R 0x9264020" }, + { "R 0x9265020" }, + { "R 0x9320344 9" }, + { "R 0x9320370 7" }, + { "R 0x9320480" }, + { "R 0x9322400 26" }, + { "R 0x9322470 5" }, + { "R 0x932320c" }, + { "R 0x9323214 2" }, + { "R 0x9323220 4" }, + { "R 0x9323308" }, + { "R 0x9323318" }, + { "R 0x932358c" }, + { "R 0x9334010" }, + { "R 0x933801c 8" }, + { "R 0x9338050" }, + { "R 0x9338100 7" }, + { "R 0x933c004" }, + { "R 0x933c014" }, + { "R 0x933c020" }, + { "R 0x933c030" }, + { "R 0x933c05c 3" }, + { "R 0x933c074" }, + { "R 0x933c088" }, + { "R 0x933c0a0" }, + { "R 0x933c0b0" }, + { "R 0x933c0c0" }, + { "R 0x933c0d0" }, + { "R 0x933c0e0" }, + { "R 0x933c0f0" }, + { "R 0x933c100" }, + { "R 0x933d064" }, + { "R 0x9340008 6" }, + { "R 0x9340028" }, + { "R 0x934203c 6" }, + { "R 0x9342058 7" }, + { "R 0x934208c" }, + { "R 0x93420b0" }, + { "R 0x93420b8 3" }, + { "R 0x93420f4" }, + { "R 0x93420fc 7" }, + { "R 0x9342324 14" }, + { "R 0x9342410" }, + { "R 0x93430a8" }, + { "R 0x9348004 7" }, + { "R 0x9348024" }, + { "R 0x9348040" }, + { "R 0x9348048" }, + { "R 0x9349064" }, + { "R 0x934c000" }, + { "R 0x934c030 3" }, + { "R 0x934c040 3" }, + { "R 0x934c054 2" }, + { "R 0x934c078" }, + { "R 0x934c108" }, + { "R 0x934c110" }, + { "R 0x9350020" }, + { "R 0x9351054" }, + { "R 0x9352014 3" }, + { "R 0x9352028 17" }, + { "R 0x9352070 8" }, + { "R 0x9352098" }, + { "R 0x93520a0" }, + { "R 0x93520b4" }, + { "R 0x93520c0 4" }, + { "R 0x93520f4 10" }, + { "R 0x9352120 12" }, + { "R 0x935802c" }, + { "R 0x935809c 2" }, + { "R 0x93580a8 3" }, + { "R 0x93580b8" }, + { "R 0x93580c0 7" }, + { "R 0x93580e0" }, + { "R 0x93580e8" }, + { "R 0x93580f0" }, + { "R 0x93580f8" }, + { "R 0x9358100" }, + { "R 0x9358108" }, + { "R 0x9358110" }, + { "R 0x9358118" }, + { "R 0x9358120" }, + { "R 0x9358128" }, + { "R 0x9358210 3" }, + { "R 0x9359010" }, + { "R 0x9359070" }, + { "R 0x935b004" }, + { "R 0x936004c 10" }, + { "R 0x9360078" }, + { "R 0x936020c" }, + { "R 0x9360214" }, + { "R 0x9361084" }, + { "R 0x9362020" }, + { "R 0x9363020" }, + { "R 0x9364020" }, + { "R 0x9365020" }, + { "R 0x9420344 9" }, + { "R 0x9420370 7" }, + { "R 0x9420480" }, + { "R 0x9422400 26" }, + { "R 0x9422470 5" }, + { "R 0x942320c" }, + { "R 0x9423214 2" }, + { "R 0x9423220 4" }, + { "R 0x9423308" }, + { "R 0x9423318" }, + { "R 0x942358c" }, + { "R 0x9434010" }, + { "R 0x943801c 8" }, + { "R 0x9438050" }, + { "R 0x9438100 7" }, + { "R 0x943c004" }, + { "R 0x943c014" }, + { "R 0x943c020" }, + { "R 0x943c030" }, + { "R 0x943c05c 3" }, + { "R 0x943c074" }, + { "R 0x943c088" }, + { "R 0x943c0a0" }, + { "R 0x943c0b0" }, + { "R 0x943c0c0" }, + { "R 0x943c0d0" }, + { "R 0x943c0e0" }, + { "R 0x943c0f0" }, + { "R 0x943c100" }, + { "R 0x943d064" }, + { "R 0x9440008 6" }, + { "R 0x9440028" }, + { "R 0x944203c 6" }, + { "R 0x9442058 7" }, + { "R 0x944208c" }, + { "R 0x94420b0" }, + { "R 0x94420b8 3" }, + { "R 0x94420f4" }, + { "R 0x94420fc 7" }, + { "R 0x9442324 14" }, + { "R 0x9442410" }, + { "R 0x94430a8" }, + { "R 0x9448004 7" }, + { "R 0x9448024" }, + { "R 0x9448040" }, + { "R 0x9448048" }, + { "R 0x9449064" }, + { "R 0x944c000" }, + { "R 0x944c030 3" }, + { "R 0x944c040 3" }, + { "R 0x944c054 2" }, + { "R 0x944c078" }, + { "R 0x944c108" }, + { "R 0x944c110" }, + { "R 0x9450020" }, + { "R 0x9451054" }, + { "R 0x9452014 3" }, + { "R 0x9452028 17" }, + { "R 0x9452070 8" }, + { "R 0x9452098" }, + { "R 0x94520a0" }, + { "R 0x94520b4" }, + { "R 0x94520c0 4" }, + { "R 0x94520f4 10" }, + { "R 0x9452120 12" }, + { "R 0x945802c" }, + { "R 0x945809c 2" }, + { "R 0x94580a8 3" }, + { "R 0x94580b8" }, + { "R 0x94580c0 7" }, + { "R 0x94580e0" }, + { "R 0x94580e8" }, + { "R 0x94580f0" }, + { "R 0x94580f8" }, + { "R 0x9458100" }, + { "R 0x9458108" }, + { "R 0x9458110" }, + { "R 0x9458118" }, + { "R 0x9458120" }, + { "R 0x9458128" }, + { "R 0x9458210 3" }, + { "R 0x9459010" }, + { "R 0x9459070" }, + { "R 0x945b004" }, + { "R 0x946004c 10" }, + { "R 0x9460078" }, + { "R 0x946020c" }, + { "R 0x9460214" }, + { "R 0x9461084" }, + { "R 0x9462020" }, + { "R 0x9463020" }, + { "R 0x9464020" }, + { "R 0x9465020" }, + { "R 0x9520344 9" }, + { "R 0x9520370 7" }, + { "R 0x9520480" }, + { "R 0x9522400 26" }, + { "R 0x9522470 5" }, + { "R 0x952320c" }, + { "R 0x9523214 2" }, + { "R 0x9523220 4" }, + { "R 0x9523308" }, + { "R 0x9523318" }, + { "R 0x952358c" }, + { "R 0x9534010" }, + { "R 0x953801c 8" }, + { "R 0x9538050" }, + { "R 0x9538100 7" }, + { "R 0x953c004" }, + { "R 0x953c014" }, + { "R 0x953c020" }, + { "R 0x953c030" }, + { "R 0x953c05c 3" }, + { "R 0x953c074" }, + { "R 0x953c088" }, + { "R 0x953c0a0" }, + { "R 0x953c0b0" }, + { "R 0x953c0c0" }, + { "R 0x953c0d0" }, + { "R 0x953c0e0" }, + { "R 0x953c0f0" }, + { "R 0x953c100" }, + { "R 0x953d064" }, + { "R 0x9540008 6" }, + { "R 0x9540028" }, + { "R 0x954203c 6" }, + { "R 0x9542058 7" }, + { "R 0x954208c" }, + { "R 0x95420b0" }, + { "R 0x95420b8 3" }, + { "R 0x95420f4" }, + { "R 0x95420fc 7" }, + { "R 0x9542324 14" }, + { "R 0x9542410" }, + { "R 0x95430a8" }, + { "R 0x9548004 7" }, + { "R 0x9548024" }, + { "R 0x9548040" }, + { "R 0x9548048" }, + { "R 0x9549064" }, + { "R 0x954c000" }, + { "R 0x954c030 3" }, + { "R 0x954c040 3" }, + { "R 0x954c054 2" }, + { "R 0x954c078" }, + { "R 0x954c108" }, + { "R 0x954c110" }, + { "R 0x9550020" }, + { "R 0x9551054" }, + { "R 0x9552014 3" }, + { "R 0x9552028 17" }, + { "R 0x9552070 8" }, + { "R 0x9552098" }, + { "R 0x95520a0" }, + { "R 0x95520b4" }, + { "R 0x95520c0 4" }, + { "R 0x95520f4 10" }, + { "R 0x9552120 12" }, + { "R 0x955802c" }, + { "R 0x955809c 2" }, + { "R 0x95580a8 3" }, + { "R 0x95580b8" }, + { "R 0x95580c0 7" }, + { "R 0x95580e0" }, + { "R 0x95580e8" }, + { "R 0x95580f0" }, + { "R 0x95580f8" }, + { "R 0x9558100" }, + { "R 0x9558108" }, + { "R 0x9558110" }, + { "R 0x9558118" }, + { "R 0x9558120" }, + { "R 0x9558128" }, + { "R 0x9558210 3" }, + { "R 0x9559010" }, + { "R 0x9559070" }, + { "R 0x955b004" }, + { "R 0x956004c 10" }, + { "R 0x9560078" }, + { "R 0x956020c" }, + { "R 0x9560214" }, + { "R 0x9561084" }, + { "R 0x9562020" }, + { "R 0x9563020" }, + { "R 0x9564020" }, + { "R 0x9565020" }, + { "R 0x9620344 9" }, + { "R 0x9620370 7" }, + { "R 0x9620480" }, + { "R 0x9622400 26" }, + { "R 0x9622470 5" }, + { "R 0x962320c" }, + { "R 0x9623214 2" }, + { "R 0x9623220 4" }, + { "R 0x9623308" }, + { "R 0x9623318" }, + { "R 0x962358c" }, + { "R 0x9634010" }, + { "R 0x963801c 8" }, + { "R 0x9638050" }, + { "R 0x9638100 7" }, + { "R 0x963c004" }, + { "R 0x963c014" }, + { "R 0x963c020" }, + { "R 0x963c030" }, + { "R 0x963c05c 3" }, + { "R 0x963c074" }, + { "R 0x963c088" }, + { "R 0x963c0a0" }, + { "R 0x963c0b0" }, + { "R 0x963c0c0" }, + { "R 0x963c0d0" }, + { "R 0x963c0e0" }, + { "R 0x963c0f0" }, + { "R 0x963c100" }, + { "R 0x963d064" }, + { "R 0x9640008 6" }, + { "R 0x9640028" }, + { "R 0x964203c 6" }, + { "R 0x9642058 7" }, + { "R 0x964208c" }, + { "R 0x96420b0" }, + { "R 0x96420b8 3" }, + { "R 0x96420f4" }, + { "R 0x96420fc 7" }, + { "R 0x9642324 14" }, + { "R 0x9642410" }, + { "R 0x96430a8" }, + { "R 0x9648004 7" }, + { "R 0x9648024" }, + { "R 0x9648040" }, + { "R 0x9648048" }, + { "R 0x9649064" }, + { "R 0x964c000" }, + { "R 0x964c030 3" }, + { "R 0x964c040 3" }, + { "R 0x964c054 2" }, + { "R 0x964c078" }, + { "R 0x964c108" }, + { "R 0x964c110" }, + { "R 0x9650020" }, + { "R 0x9651054" }, + { "R 0x9652014 3" }, + { "R 0x9652028 17" }, + { "R 0x9652070 8" }, + { "R 0x9652098" }, + { "R 0x96520a0" }, + { "R 0x96520b4" }, + { "R 0x96520c0 4" }, + { "R 0x96520f4 10" }, + { "R 0x9652120 12" }, + { "R 0x965802c" }, + { "R 0x965809c 2" }, + { "R 0x96580a8 3" }, + { "R 0x96580b8" }, + { "R 0x96580c0 7" }, + { "R 0x96580e0" }, + { "R 0x96580e8" }, + { "R 0x96580f0" }, + { "R 0x96580f8" }, + { "R 0x9658100" }, + { "R 0x9658108" }, + { "R 0x9658110" }, + { "R 0x9658118" }, + { "R 0x9658120" }, + { "R 0x9658128" }, + { "R 0x9658210 3" }, + { "R 0x9659010" }, + { "R 0x9659070" }, + { "R 0x965b004" }, + { "R 0x966004c 10" }, + { "R 0x9660078" }, + { "R 0x966020c" }, + { "R 0x9660214" }, + { "R 0x9661084" }, + { "R 0x9662020" }, + { "R 0x9663020" }, + { "R 0x9664020" }, + { "R 0x9665020" }, + { "R 0x9720344 9" }, + { "R 0x9720370 7" }, + { "R 0x9720480" }, + { "R 0x9722400 26" }, + { "R 0x9722470 5" }, + { "R 0x972320c" }, + { "R 0x9723214 2" }, + { "R 0x9723220 4" }, + { "R 0x9723308" }, + { "R 0x9723318" }, + { "R 0x972358c" }, + { "R 0x9734010" }, + { "R 0x973801c 8" }, + { "R 0x9738050" }, + { "R 0x9738100 7" }, + { "R 0x973c004" }, + { "R 0x973c014" }, + { "R 0x973c020" }, + { "R 0x973c030" }, + { "R 0x973c05c 3" }, + { "R 0x973c074" }, + { "R 0x973c088" }, + { "R 0x973c0a0" }, + { "R 0x973c0b0" }, + { "R 0x973c0c0" }, + { "R 0x973c0d0" }, + { "R 0x973c0e0" }, + { "R 0x973c0f0" }, + { "R 0x973c100" }, + { "R 0x973d064" }, + { "R 0x9740008 6" }, + { "R 0x9740028" }, + { "R 0x974203c 6" }, + { "R 0x9742058 7" }, + { "R 0x974208c" }, + { "R 0x97420b0" }, + { "R 0x97420b8 3" }, + { "R 0x97420f4" }, + { "R 0x97420fc 7" }, + { "R 0x9742324 14" }, + { "R 0x9742410" }, + { "R 0x97430a8" }, + { "R 0x9748004 7" }, + { "R 0x9748024" }, + { "R 0x9748040" }, + { "R 0x9748048" }, + { "R 0x9749064" }, + { "R 0x974c000" }, + { "R 0x974c030 3" }, + { "R 0x974c040 3" }, + { "R 0x974c054 2" }, + { "R 0x974c078" }, + { "R 0x974c108" }, + { "R 0x974c110" }, + { "R 0x9750020" }, + { "R 0x9751054" }, + { "R 0x9752014 3" }, + { "R 0x9752028 17" }, + { "R 0x9752070 8" }, + { "R 0x9752098" }, + { "R 0x97520a0" }, + { "R 0x97520b4" }, + { "R 0x97520c0 4" }, + { "R 0x97520f4 10" }, + { "R 0x9752120 12" }, + { "R 0x975802c" }, + { "R 0x975809c 2" }, + { "R 0x97580a8 3" }, + { "R 0x97580b8" }, + { "R 0x97580c0 7" }, + { "R 0x97580e0" }, + { "R 0x97580e8" }, + { "R 0x97580f0" }, + { "R 0x97580f8" }, + { "R 0x9758100" }, + { "R 0x9758108" }, + { "R 0x9758110" }, + { "R 0x9758118" }, + { "R 0x9758120" }, + { "R 0x9758128" }, + { "R 0x9758210 3" }, + { "R 0x9759010" }, + { "R 0x9759070" }, + { "R 0x975b004" }, + { "R 0x976004c 10" }, + { "R 0x9760078" }, + { "R 0x976020c" }, + { "R 0x9760214" }, + { "R 0x9761084" }, + { "R 0x9762020" }, + { "R 0x9763020" }, + { "R 0x9764020" }, + { "R 0x9765020" }, + { "R 0x92a0304" }, + { "R 0x92a0080" }, + { "R 0x92a0310" }, + { "R 0x92a0400 2" }, + { "R 0x92a0410 6" }, + { "R 0x92a0430" }, + { "R 0x92a0440" }, + { "R 0x92a0448" }, + { "R 0x92a04a0" }, + { "R 0x92a04b0 4" }, + { "R 0x92a04d0 2" }, + { "R 0x92a1400" }, + { "R 0x92a1408" }, + { "R 0x92a2400 2" }, + { "R 0x92a2438 2" }, + { "R 0x92a2454" }, + { "R 0x92a3400 4" }, + { "R 0x92a3418 3" }, + { "R 0x92a4700" }, + { "R 0x92a53b0" }, + { "R 0x92a5804" }, + { "R 0x92a590c" }, + { "R 0x92a5a14" }, + { "R 0x92a5c0c" }, + { "R 0x92a5c18 2" }, + { "R 0x92a5c2c 2" }, + { "R 0x92a5c38" }, + { "R 0x92a5c4c" }, + { "R 0x92a5ca4" }, + { "R 0x92a5cac 3" }, + { "R 0x92a6400" }, + { "R 0x92a6418 2" }, + { "R 0x92a9100" }, + { "R 0x92a9110" }, + { "R 0x92a9120" }, + { "R 0x92a9180 2" }, + { "R 0x92a91a0" }, + { "R 0x92a91b0" }, + { "R 0x92a91c0 2" }, + { "R 0x92a91e0" }, + { "R 0x93a0304" }, + { "R 0x93a0080" }, + { "R 0x93a0310" }, + { "R 0x93a0400 2" }, + { "R 0x93a0410 6" }, + { "R 0x93a0430" }, + { "R 0x93a0440" }, + { "R 0x93a0448" }, + { "R 0x93a04a0" }, + { "R 0x93a04b0 4" }, + { "R 0x93a04d0 2" }, + { "R 0x93a1400" }, + { "R 0x93a1408" }, + { "R 0x93a2400 2" }, + { "R 0x93a2438 2" }, + { "R 0x93a2454" }, + { "R 0x93a3400 4" }, + { "R 0x93a3418 3" }, + { "R 0x93a4700" }, + { "R 0x93a53b0" }, + { "R 0x93a5804" }, + { "R 0x93a590c" }, + { "R 0x93a5a14" }, + { "R 0x93a5c0c" }, + { "R 0x93a5c18 2" }, + { "R 0x93a5c2c 2" }, + { "R 0x93a5c38" }, + { "R 0x93a5c4c" }, + { "R 0x93a5ca4" }, + { "R 0x93a5cac 3" }, + { "R 0x93a6400" }, + { "R 0x93a6418 2" }, + { "R 0x93a9100" }, + { "R 0x93a9110" }, + { "R 0x93a9120" }, + { "R 0x93a9180 2" }, + { "R 0x93a91a0" }, + { "R 0x93a91b0" }, + { "R 0x93a91c0 2" }, + { "R 0x93a91e0" }, + { "R 0x94a0304" }, + { "R 0x94a0080" }, + { "R 0x94a0310" }, + { "R 0x94a0400 2" }, + { "R 0x94a0410 6" }, + { "R 0x94a0430" }, + { "R 0x94a0440" }, + { "R 0x94a0448" }, + { "R 0x94a04a0" }, + { "R 0x94a04b0 4" }, + { "R 0x94a04d0 2" }, + { "R 0x94a1400" }, + { "R 0x94a1408" }, + { "R 0x94a2400 2" }, + { "R 0x94a2438 2" }, + { "R 0x94a2454" }, + { "R 0x94a3400 4" }, + { "R 0x94a3418 3" }, + { "R 0x94a4700" }, + { "R 0x94a53b0" }, + { "R 0x94a5804" }, + { "R 0x94a590c" }, + { "R 0x94a5a14" }, + { "R 0x94a5c0c" }, + { "R 0x94a5c18 2" }, + { "R 0x94a5c2c 2" }, + { "R 0x94a5c38" }, + { "R 0x94a5c4c" }, + { "R 0x94a5ca4" }, + { "R 0x94a5cac 3" }, + { "R 0x94a6400" }, + { "R 0x94a6418 2" }, + { "R 0x94a9100" }, + { "R 0x94a9110" }, + { "R 0x94a9120" }, + { "R 0x94a9180 2" }, + { "R 0x94a91a0" }, + { "R 0x94a91b0" }, + { "R 0x94a91c0 2" }, + { "R 0x94a91e0" }, + { "R 0x95a0304" }, + { "R 0x95a0080" }, + { "R 0x95a0310" }, + { "R 0x95a0400 2" }, + { "R 0x95a0410 6" }, + { "R 0x95a0430" }, + { "R 0x95a0440" }, + { "R 0x95a0448" }, + { "R 0x95a04a0" }, + { "R 0x95a04b0 4" }, + { "R 0x95a04d0 2" }, + { "R 0x95a1400" }, + { "R 0x95a1408" }, + { "R 0x95a2400 2" }, + { "R 0x95a2438 2" }, + { "R 0x95a2454" }, + { "R 0x95a3400 4" }, + { "R 0x95a3418 3" }, + { "R 0x95a4700" }, + { "R 0x95a53b0" }, + { "R 0x95a5804" }, + { "R 0x95a590c" }, + { "R 0x95a5a14" }, + { "R 0x95a5c0c" }, + { "R 0x95a5c18 2" }, + { "R 0x95a5c2c 2" }, + { "R 0x95a5c38" }, + { "R 0x95a5c4c" }, + { "R 0x95a5ca4" }, + { "R 0x95a5cac 3" }, + { "R 0x95a6400" }, + { "R 0x95a6418 2" }, + { "R 0x95a9100" }, + { "R 0x95a9110" }, + { "R 0x95a9120" }, + { "R 0x95a9180 2" }, + { "R 0x95a91a0" }, + { "R 0x95a91b0" }, + { "R 0x95a91c0 2" }, + { "R 0x95a91e0" }, + { "R 0x96a0304" }, + { "R 0x96a0080" }, + { "R 0x96a0310" }, + { "R 0x96a0400 2" }, + { "R 0x96a0410 6" }, + { "R 0x96a0430" }, + { "R 0x96a0440" }, + { "R 0x96a0448" }, + { "R 0x96a04a0" }, + { "R 0x96a04b0 4" }, + { "R 0x96a04d0 2" }, + { "R 0x96a1400" }, + { "R 0x96a1408" }, + { "R 0x96a2400 2" }, + { "R 0x96a2438 2" }, + { "R 0x96a2454" }, + { "R 0x96a3400 4" }, + { "R 0x96a3418 3" }, + { "R 0x96a4700" }, + { "R 0x96a53b0" }, + { "R 0x96a5804" }, + { "R 0x96a590c" }, + { "R 0x96a5a14" }, + { "R 0x96a5c0c" }, + { "R 0x96a5c18 2" }, + { "R 0x96a5c2c 2" }, + { "R 0x96a5c38" }, + { "R 0x96a5c4c" }, + { "R 0x96a5ca4" }, + { "R 0x96a5cac 3" }, + { "R 0x96a6400" }, + { "R 0x96a6418 2" }, + { "R 0x96a9100" }, + { "R 0x96a9110" }, + { "R 0x96a9120" }, + { "R 0x96a9180 2" }, + { "R 0x96a91a0" }, + { "R 0x96a91b0" }, + { "R 0x96a91c0 2" }, + { "R 0x96a91e0" }, + { "R 0x97a0304" }, + { "R 0x97a0080" }, + { "R 0x97a0310" }, + { "R 0x97a0400 2" }, + { "R 0x97a0410 6" }, + { "R 0x97a0430" }, + { "R 0x97a0440" }, + { "R 0x97a0448" }, + { "R 0x97a04a0" }, + { "R 0x97a04b0 4" }, + { "R 0x97a04d0 2" }, + { "R 0x97a1400" }, + { "R 0x97a1408" }, + { "R 0x97a2400 2" }, + { "R 0x97a2438 2" }, + { "R 0x97a2454" }, + { "R 0x97a3400 4" }, + { "R 0x97a3418 3" }, + { "R 0x97a4700" }, + { "R 0x97a53b0" }, + { "R 0x97a5804" }, + { "R 0x97a590c" }, + { "R 0x97a5a14" }, + { "R 0x97a5c0c" }, + { "R 0x97a5c18 2" }, + { "R 0x97a5c2c 2" }, + { "R 0x97a5c38" }, + { "R 0x97a5c4c" }, + { "R 0x97a5ca4" }, + { "R 0x97a5cac 3" }, + { "R 0x97a6400" }, + { "R 0x97a6418 2" }, + { "R 0x97a9100" }, + { "R 0x97a9110" }, + { "R 0x97a9120" }, + { "R 0x97a9180 2" }, + { "R 0x97a91a0" }, + { "R 0x97a91b0" }, + { "R 0x97a91c0 2" }, + { "R 0x97a91e0" }, + { "R 0x9b01e64" }, + { "R 0x9b01ea0" }, + { "R 0x9b01f30 2" }, + { "R 0x9b03e64" }, + { "R 0x9b03ea0" }, + { "R 0x9b03f30 2" }, + { "R 0x9b0527c" }, + { "R 0x9b05290" }, + { "R 0x9b054ec" }, + { "R 0x9b054f4" }, + { "R 0x9b05514" }, + { "R 0x9b0551c" }, + { "R 0x9b05524" }, + { "R 0x9b05548" }, + { "R 0x9b05550" }, + { "R 0x9b05558" }, + { "R 0x9b055b8" }, + { "R 0x9b055c0" }, + { "R 0x9b055ec" }, + { "R 0x9b05860" }, + { "R 0x9b05870" }, + { "R 0x9b058a0" }, + { "R 0x9b058a8" }, + { "R 0x9b058b0" }, + { "R 0x9b058b8" }, + { "R 0x9b058d8 2" }, + { "R 0x9b058f4" }, + { "R 0x9b058fc" }, + { "R 0x9b05920" }, + { "R 0x9b05928" }, + { "R 0x9b05944" }, + { "R 0x9b06604" }, + { "R 0x9b0660c" }, + { "R 0x9b41e64" }, + { "R 0x9b41ea0" }, + { "R 0x9b41f30 2" }, + { "R 0x9b43e64" }, + { "R 0x9b43ea0" }, + { "R 0x9b43f30 2" }, + { "R 0x9b4527c" }, + { "R 0x9b45290" }, + { "R 0x9b454ec" }, + { "R 0x9b454f4" }, + { "R 0x9b45514" }, + { "R 0x9b4551c" }, + { "R 0x9b45524" }, + { "R 0x9b45548" }, + { "R 0x9b45550" }, + { "R 0x9b45558" }, + { "R 0x9b455b8" }, + { "R 0x9b455c0" }, + { "R 0x9b455ec" }, + { "R 0x9b45860" }, + { "R 0x9b45870" }, + { "R 0x9b458a0" }, + { "R 0x9b458a8" }, + { "R 0x9b458b0" }, + { "R 0x9b458b8" }, + { "R 0x9b458d8 2" }, + { "R 0x9b458f4" }, + { "R 0x9b458fc" }, + { "R 0x9b45920" }, + { "R 0x9b45928" }, + { "R 0x9b45944" }, + { "R 0x9b46604" }, + { "R 0x9b4660c" }, + { "R 0x9b81e64" }, + { "R 0x9b81ea0" }, + { "R 0x9b81f30 2" }, + { "R 0x9b83e64" }, + { "R 0x9b83ea0" }, + { "R 0x9b83f30 2" }, + { "R 0x9b8527c" }, + { "R 0x9b85290" }, + { "R 0x9b854ec" }, + { "R 0x9b854f4" }, + { "R 0x9b85514" }, + { "R 0x9b8551c" }, + { "R 0x9b85524" }, + { "R 0x9b85548" }, + { "R 0x9b85550" }, + { "R 0x9b85558" }, + { "R 0x9b855b8" }, + { "R 0x9b855c0" }, + { "R 0x9b855ec" }, + { "R 0x9b85860" }, + { "R 0x9b85870" }, + { "R 0x9b858a0" }, + { "R 0x9b858a8" }, + { "R 0x9b858b0" }, + { "R 0x9b858b8" }, + { "R 0x9b858d8 2" }, + { "R 0x9b858f4" }, + { "R 0x9b858fc" }, + { "R 0x9b85920" }, + { "R 0x9b85928" }, + { "R 0x9b85944" }, + { "R 0x9b86604" }, + { "R 0x9b8660c" }, + { "R 0x9bc1e64" }, + { "R 0x9bc1ea0" }, + { "R 0x9bc1f30 2" }, + { "R 0x9bc3e64" }, + { "R 0x9bc3ea0" }, + { "R 0x9bc3f30 2" }, + { "R 0x9bc527c" }, + { "R 0x9bc5290" }, + { "R 0x9bc54ec" }, + { "R 0x9bc54f4" }, + { "R 0x9bc5514" }, + { "R 0x9bc551c" }, + { "R 0x9bc5524" }, + { "R 0x9bc5548" }, + { "R 0x9bc5550" }, + { "R 0x9bc5558" }, + { "R 0x9bc55b8" }, + { "R 0x9bc55c0" }, + { "R 0x9bc55ec" }, + { "R 0x9bc5860" }, + { "R 0x9bc5870" }, + { "R 0x9bc58a0" }, + { "R 0x9bc58a8" }, + { "R 0x9bc58b0" }, + { "R 0x9bc58b8" }, + { "R 0x9bc58d8 2" }, + { "R 0x9bc58f4" }, + { "R 0x9bc58fc" }, + { "R 0x9bc5920" }, + { "R 0x9bc5928" }, + { "R 0x9bc5944" }, + { "R 0x9bc6604" }, + { "R 0x9bc660c" }, + { "R 0x9c01e64" }, + { "R 0x9c01ea0" }, + { "R 0x9c01f30 2" }, + { "R 0x9c03e64" }, + { "R 0x9c03ea0" }, + { "R 0x9c03f30 2" }, + { "R 0x9c0527c" }, + { "R 0x9c05290" }, + { "R 0x9c054ec" }, + { "R 0x9c054f4" }, + { "R 0x9c05514" }, + { "R 0x9c0551c" }, + { "R 0x9c05524" }, + { "R 0x9c05548" }, + { "R 0x9c05550" }, + { "R 0x9c05558" }, + { "R 0x9c055b8" }, + { "R 0x9c055c0" }, + { "R 0x9c055ec" }, + { "R 0x9c05860" }, + { "R 0x9c05870" }, + { "R 0x9c058a0" }, + { "R 0x9c058a8" }, + { "R 0x9c058b0" }, + { "R 0x9c058b8" }, + { "R 0x9c058d8 2" }, + { "R 0x9c058f4" }, + { "R 0x9c058fc" }, + { "R 0x9c05920" }, + { "R 0x9c05928" }, + { "R 0x9c05944" }, + { "R 0x9c06604" }, + { "R 0x9c0660c" }, + { "R 0x9c41e64" }, + { "R 0x9c41ea0" }, + { "R 0x9c41f30 2" }, + { "R 0x9c43e64" }, + { "R 0x9c43ea0" }, + { "R 0x9c43f30 2" }, + { "R 0x9c4527c" }, + { "R 0x9c45290" }, + { "R 0x9c454ec" }, + { "R 0x9c454f4" }, + { "R 0x9c45514" }, + { "R 0x9c4551c" }, + { "R 0x9c45524" }, + { "R 0x9c45548" }, + { "R 0x9c45550" }, + { "R 0x9c45558" }, + { "R 0x9c455b8" }, + { "R 0x9c455c0" }, + { "R 0x9c455ec" }, + { "R 0x9c45860" }, + { "R 0x9c45870" }, + { "R 0x9c458a0" }, + { "R 0x9c458a8" }, + { "R 0x9c458b0" }, + { "R 0x9c458b8" }, + { "R 0x9c458d8 2" }, + { "R 0x9c458f4" }, + { "R 0x9c458fc" }, + { "R 0x9c45920" }, + { "R 0x9c45928" }, + { "R 0x9c45944" }, + { "R 0x9c46604" }, + { "R 0x9c4660c" }, +}; + +static const struct dcc_link_config lemans_link_configs[] = { + { + .link_list = 6, + .entries = lemans_dcc_entries, + .num_entries = ARRAY_SIZE(lemans_dcc_entries), + }, +}; + +static const struct dcc_config lemans_config = { + .lists = lemans_link_configs, + .num_lists = ARRAY_SIZE(lemans_link_configs), +}; + +static const struct dcc_pdata lemans_pdata = { + .base = 0x040ff000, + .size = 0x00001000, + .ram_base = 0x040b8800, + .ram_size = 0x00006000, + .dcc_offset = 0x38800, + .map_ver = 0x3, + .config = &lemans_config, +}; + +#endif /* _QCOM_DCC_LEMANS_CONFIG_H */ diff --git a/drivers/misc/qcom-dcc-pakala-config.h b/drivers/misc/qcom-dcc-pakala-config.h new file mode 100644 index 0000000000000..25e6221805d27 --- /dev/null +++ b/drivers/misc/qcom-dcc-pakala-config.h @@ -0,0 +1,1167 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_PAKALA_CONFIG_H +#define _QCOM_DCC_PAKALA_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry pakala_dcc_entries_ll6[] = { + { "R 0x16801000 2" }, + { "R 0x18880258 10" }, + { "R 0x18880288 6" }, + { "R 0x188802a8 10" }, + { "R 0x18880328 6" }, + { "R 0x188803d8 10" }, + { "R 0x18880408 2" }, + { "R 0x19880258 10" }, + { "R 0x19880288 6" }, + { "R 0x198802a8 10" }, + { "R 0x19880328 6" }, + { "R 0x198803d8 10" }, + { "R 0x19880408 2" }, + { "R 0x188b0000 4" }, + { "R 0x188b0050 2" }, + { "R 0x188b00e8 36" }, + { "R 0x188b0788 2" }, + { "R 0x188b0c18 2" }, + { "R 0x198b0000 4" }, + { "R 0x198b0050 2" }, + { "R 0x198b00e8 36" }, + { "R 0x198b0788 2" }, + { "R 0x198b0c18 2" }, + { "R 0x17988814 2" }, + { "R 0x17998814 2" }, + { "R 0x179d2000 3" }, + { "R 0x179d2020 3" }, + { "R 0x179d2040 2" }, + { "R 0x179d2060 2" }, + { "R 0x179d2080 2" }, + { "R 0x179d20a0" }, + { "R 0x179d20b0" }, + { "R 0x179d20c0" }, + { "R 0x179d2200 2" }, + { "R 0x179d2220 2" }, + { "R 0x179d2280 2" }, + { "R 0x179d22f0" }, + { "R 0x179d2304" }, + { "R 0x179d2310" }, + { "R 0x179d2400 4" }, + { "R 0x179d2420" }, + { "R 0x179d2428 2" }, + { "R 0x179d2440 2" }, + { "R 0x179d2520 2" }, + { "R 0x179d2600 2" }, + { "R 0x179d2710 2" }, + { "R 0x179d2720 2" }, + { "R 0x179d2740 2" }, + { "R 0x179d3080 2" }, + { "R 0x17846018 2" }, + { "R 0x17846060" }, + { "R 0x17846100 2" }, + { "R 0x17846110" }, + { "R 0x17847030 2" }, + { "R 0x17847040 2" }, + { "R 0x17847050 2" }, + { "R 0x17847060 2" }, + { "R 0x17847070 2" }, + { "R 0x17847080 2" }, + { "R 0x17847090 2" }, + { "R 0x178470a0 2" }, + { "R 0x178470b0 2" }, + { "R 0x178470c0 2" }, + { "R 0x17850000 2" }, + { "R 0x17850010 2" }, + { "R 0x17850030 2" }, + { "R 0x17850040" }, + { "R 0x17854000" }, + { "R 0x17854008 4" }, + { "R 0x179c8814 2" }, + { "R 0x179d0104" }, + { "R 0x179d0118 2" }, + { "R 0x179d0148 2" }, + { "R 0x179d1600" }, + { "R 0x179d1678" }, + { "R 0x179d1688 2" }, + { "R 0x179d1694 3" }, + { "R 0x179d1820 3" }, + { "R 0x17b70000" }, + { "R 0x17b70008 2" }, + { "R 0x17b71000" }, + { "R 0x17b71008 2" }, + { "R 0x164807f8" }, + { "R 0x16480810 3" }, + { "R 0x16483000 40" }, + { "R 0x16483a00 2" }, + { "R 0x16488908" }, + { "R 0x16488c18" }, + { "R 0x164a8908" }, + { "R 0x164a8c18" }, + { "R 0x164a07f8" }, + { "R 0x164a0810 3" }, + { "R 0x164a3000 40" }, + { "R 0x164a3a00 2" }, + { "R 0x16493000 40" }, + { "R 0x16493a00 2" }, + { "R 0x16498c18" }, + { "R 0x164b8c18" }, + { "R 0x164b3a00 2" }, + { "R 0x16440000 2" }, + { "R 0x16440020 3" }, + { "R 0x16440030" }, + { "R 0x1644003c" }, + { "R 0x16440044 3" }, + { "R 0x16440438" }, + { "R 0x16440500 5" }, + { "R 0x16562000 2" }, + { "R 0x16565004" }, + { "R 0x17000bd0" }, + { "R 0x170404a0" }, + { "R 0x170a0590" }, + { "R 0x170c0330" }, + { "R 0x170c0338" }, + { "R 0x170c0340" }, + { "R 0x170c0518" }, + { "R 0x170c0528" }, + { "R 0x170c0538" }, + { "R 0x170c0560 4" }, + { "R 0x17200bd0" }, + { "R 0x172404a0" }, + { "R 0x172a0590" }, + { "R 0x172c0330" }, + { "R 0x172c0338" }, + { "R 0x172c0340" }, + { "R 0x172c0518" }, + { "R 0x172c0528" }, + { "R 0x172c0538" }, + { "R 0x172c0560 4" }, + { "R 0x1641000c" }, + { "R 0x1641400c" }, + { "R 0x18830320 2" }, + { "R 0x19830320 2" }, + { "R 0x18040010 6" }, + { "R 0x18040040 10" }, + { "R 0x18040090 6" }, + { "R 0x18850020 2" }, + { "R 0x18850060 2" }, + { "R 0x188500a0 2" }, + { "R 0x188500e0 2" }, + { "R 0x18850120 2" }, + { "R 0x18850160 2" }, + { "R 0x189c1000" }, + { "R 0x199c1000" }, + { "R 0x18a30000 9" }, + { "R 0x18a30030" }, + { "R 0x18a3003c 2" }, + { "R 0x19a30000 9" }, + { "R 0x19a30030" }, + { "R 0x19a3003c 2" }, + { "R 0x24201040" }, + { "R 0x24201048" }, + { "R 0x24100010" }, + { "R 0x24100020 6" }, + { "R 0x24180010" }, + { "R 0x24180020 6" }, + { "R 0x24200010" }, + { "R 0x24200020 6" }, + { "R 0x24200410" }, + { "R 0x24200420 6" }, + { "R 0x24102010" }, + { "R 0x24102038" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102008 2" }, + { "R 0x24181010" }, + { "R 0x24181038" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181008 2" }, + { "R 0x24203010" }, + { "R 0x24203038" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203008 2" }, + { "R 0x24203410" }, + { "R 0x24203438" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203408 2" }, + { "R 0x24104018" }, + { "R 0x24104008" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104098" }, + { "R 0x24104088" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24182018" }, + { "R 0x24182008" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182098" }, + { "R 0x24182088" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24204018" }, + { "R 0x24204008" }, + { "R 0x24204010 2" }, + { "R 0x24204010 2" }, + { "R 0x24204010 2" }, + { "R 0x24204098" }, + { "R 0x24204088" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x16801000 2" }, + { "R 0x240ba050" }, + { "R 0x240ba164" }, + { "R 0x240ba280" }, + { "R 0x240ba288 8" }, + { "R 0x240ba2c0 2" }, + { "R 0x24bc0610 11" }, + { "R 0x24bc0640 2" }, + { "R 0x24bc06a0" }, + { "R 0x24fc0610 11" }, + { "R 0x24fc0640 2" }, + { "R 0x24fc06a0" }, + { "R 0x25bc0610 11" }, + { "R 0x25bc0640 2" }, + { "R 0x25bc06a0" }, + { "R 0x25fc0610 11" }, + { "R 0x25fc0640 2" }, + { "R 0x25fc06a0" }, + { "R 0x240a801c 2" }, + { "R 0x240a8038 3" }, + { "R 0x240a8058 5" }, + { "R 0x240a8074 4" }, + { "R 0x240a80a8" }, + { "R 0x240a80b8" }, + { "R 0x240a80ec 5" }, + { "R 0x240a8140" }, + { "R 0x240a8164 2" }, + { "R 0x240a81c4 2" }, + { "R 0x240a81dc 2" }, + { "R 0x240a844c" }, + { "R 0x240a845c" }, + { "R 0x240a84c8 27" }, + { "R 0x240a9000 2" }, + { "R 0x240a9010 2" }, + { "R 0x240a9020 3" }, + { "R 0x240a9034 2" }, + { "R 0x240a9130 3" }, + { "R 0x240a9140 18" }, + { "R 0x240a91ac 6" }, + { "R 0x240a91c8" }, + { "R 0x240a920c" }, + { "R 0x240a9220 2" }, + { "R 0x240a9264" }, + { "R 0x240a9294 7" }, + { "R 0x240a92b8" }, + { "R 0x240a92f8" }, + { "R 0x24800004" }, + { "R 0x24801004" }, + { "R 0x24802004" }, + { "R 0x24803004" }, + { "R 0x24804004" }, + { "R 0x24805004" }, + { "R 0x24806004" }, + { "R 0x24807004" }, + { "R 0x24808004" }, + { "R 0x24809004" }, + { "R 0x2480a004" }, + { "R 0x2480b004" }, + { "R 0x2480c004" }, + { "R 0x2480d004" }, + { "R 0x2480e004" }, + { "R 0x2480f004" }, + { "R 0x24810004" }, + { "R 0x24811004" }, + { "R 0x24812004" }, + { "R 0x24813004" }, + { "R 0x24814004" }, + { "R 0x24815004" }, + { "R 0x24816004" }, + { "R 0x24817004" }, + { "R 0x24818004" }, + { "R 0x24819004" }, + { "R 0x2481a004" }, + { "R 0x2481b004" }, + { "R 0x2481c004" }, + { "R 0x2481d004" }, + { "R 0x2481e004" }, + { "R 0x2481f004" }, + { "R 0x24820004" }, + { "R 0x24821004" }, + { "R 0x24822004" }, + { "R 0x24823004" }, + { "R 0x24843350 2" }, + { "R 0x248433f4 11" }, + { "R 0x248434c0 6" }, + { "R 0x24843600" }, + { "R 0x2484360c" }, + { "R 0x24845040" }, + { "R 0x24845048" }, + { "R 0x24845050" }, + { "R 0x24845058" }, + { "R 0x24845060" }, + { "R 0x24845068" }, + { "R 0x24845070 4" }, + { "R 0x24845090 14" }, + { "R 0x248450cc 2" }, + { "R 0x24845240" }, + { "R 0x248452a0" }, + { "R 0x24845300" }, + { "R 0x24845310" }, + { "R 0x24845320" }, + { "R 0x24845330 3" }, + { "R 0x24847404" }, + { "R 0x2484740c 3" }, + { "R 0x24847448" }, + { "R 0x24847450" }, + { "R 0x24847458 2" }, + { "R 0x24847600" }, + { "R 0x24849000" }, + { "R 0x24849010" }, + { "R 0x2487c000" }, + { "R 0x2487c01c 3" }, + { "R 0x2487c030 8" }, + { "R 0x2487c054 2" }, + { "R 0x2487c078" }, + { "R 0x2487c108 9" }, + { "R 0x2487c20c 3" }, + { "R 0x248a600c 4" }, + { "R 0x248a6020 3" }, + { "R 0x248a6034 2" }, + { "R 0x248a6040" }, + { "R 0x248a6050" }, + { "R 0x248a6058" }, + { "R 0x248a6060 4" }, + { "R 0x248a7020" }, + { "R 0x248a7030 2" }, + { "R 0x248a7078 4" }, + { "R 0x248a708c 6" }, + { "R 0x248e002c" }, + { "R 0x248e009c 2" }, + { "R 0x248e00a8 3" }, + { "R 0x248e00b8" }, + { "R 0x248e00c0 7" }, + { "R 0x248e00e0" }, + { "R 0x248e00e8" }, + { "R 0x248e00f0" }, + { "R 0x248e00f8" }, + { "R 0x248e0100" }, + { "R 0x248e0108" }, + { "R 0x248e0110" }, + { "R 0x248e0118" }, + { "R 0x248e0120" }, + { "R 0x248e0128" }, + { "R 0x248e0150 4" }, + { "R 0x248e0164" }, + { "R 0x248e01e8" }, + { "R 0x248e1010" }, + { "R 0x248e1060 3" }, + { "R 0x248e1070" }, + { "R 0x248e1084 3" }, + { "R 0x248e3004" }, + { "R 0x248e300c" }, + { "R 0x248e4004" }, + { "R 0x248e4010 2" }, + { "R 0x248e4024 2" }, + { "R 0x248e4038 2" }, + { "R 0x248e600c 5" }, + { "R 0x248e700c 5" }, + { "R 0x248e9004" }, + { "R 0x248e9010 3" }, + { "R 0x248e9020 3" }, + { "R 0x248e9030 3" }, + { "R 0x248e9040 3" }, + { "R 0x248e9050 3" }, + { "R 0x248ea004" }, + { "R 0x248ea010 3" }, + { "R 0x248ea020 3" }, + { "R 0x248ea030 3" }, + { "R 0x248ea040 3" }, + { "R 0x248ea050 3" }, + { "R 0x248f001c" }, + { "R 0x248f0050" }, + { "R 0x248f0058" }, + { "R 0x24c00004" }, + { "R 0x24c01004" }, + { "R 0x24c02004" }, + { "R 0x24c03004" }, + { "R 0x24c04004" }, + { "R 0x24c05004" }, + { "R 0x24c06004" }, + { "R 0x24c07004" }, + { "R 0x24c08004" }, + { "R 0x24c09004" }, + { "R 0x24c0a004" }, + { "R 0x24c0b004" }, + { "R 0x24c0c004" }, + { "R 0x24c0d004" }, + { "R 0x24c0e004" }, + { "R 0x24c0f004" }, + { "R 0x24c10004" }, + { "R 0x24c11004" }, + { "R 0x24c12004" }, + { "R 0x24c13004" }, + { "R 0x24c14004" }, + { "R 0x24c15004" }, + { "R 0x24c16004" }, + { "R 0x24c17004" }, + { "R 0x24c18004" }, + { "R 0x24c19004" }, + { "R 0x24c1a004" }, + { "R 0x24c1b004" }, + { "R 0x24c1c004" }, + { "R 0x24c1d004" }, + { "R 0x24c1e004" }, + { "R 0x24c1f004" }, + { "R 0x24c20004" }, + { "R 0x24c21004" }, + { "R 0x24c22004" }, + { "R 0x24c23004" }, + { "R 0x24c43350 2" }, + { "R 0x24c433f4 11" }, + { "R 0x24c434c0 6" }, + { "R 0x24c43600" }, + { "R 0x24c4360c" }, + { "R 0x24c45040" }, + { "R 0x24c45048" }, + { "R 0x24c45050" }, + { "R 0x24c45058" }, + { "R 0x24c45060" }, + { "R 0x24c45068" }, + { "R 0x24c45070 4" }, + { "R 0x24c45090 14" }, + { "R 0x24c450cc 2" }, + { "R 0x24c45240" }, + { "R 0x24c452a0" }, + { "R 0x24c45300" }, + { "R 0x24c45310" }, + { "R 0x24c45320" }, + { "R 0x24c45330 3" }, + { "R 0x24c47404" }, + { "R 0x24c4740c 3" }, + { "R 0x24c47448" }, + { "R 0x24c47450" }, + { "R 0x24c47458 2" }, + { "R 0x24c47600" }, + { "R 0x24c49000" }, + { "R 0x24c49010" }, + { "R 0x24c7c000" }, + { "R 0x24c7c01c 3" }, + { "R 0x24c7c030 8" }, + { "R 0x24c7c054 2" }, + { "R 0x24c7c078" }, + { "R 0x24c7c108 9" }, + { "R 0x24c7c20c 3" }, + { "R 0x24ca600c 4" }, + { "R 0x24ca6020 3" }, + { "R 0x24ca6034 2" }, + { "R 0x24ca6040" }, + { "R 0x24ca6050" }, + { "R 0x24ca6058" }, + { "R 0x24ca6060 4" }, + { "R 0x24ca7020" }, + { "R 0x24ca7030 2" }, + { "R 0x24ca7078 4" }, + { "R 0x24ca708c 6" }, + { "R 0x24ce002c" }, + { "R 0x24ce009c 2" }, + { "R 0x24ce00a8 3" }, + { "R 0x24ce00b8" }, + { "R 0x24ce00c0 7" }, + { "R 0x24ce00e0" }, + { "R 0x24ce00e8" }, + { "R 0x24ce00f0" }, + { "R 0x24ce00f8" }, + { "R 0x24ce0100" }, + { "R 0x24ce0108" }, + { "R 0x24ce0110" }, + { "R 0x24ce0118" }, + { "R 0x24ce0120" }, + { "R 0x24ce0128" }, + { "R 0x24ce0150 4" }, + { "R 0x24ce0164" }, + { "R 0x24ce01e8" }, + { "R 0x24ce1010" }, + { "R 0x24ce1060 3" }, + { "R 0x24ce1070" }, + { "R 0x24ce1084 3" }, + { "R 0x24ce3004" }, + { "R 0x24ce300c" }, + { "R 0x24ce4004" }, + { "R 0x24ce4010 2" }, + { "R 0x24ce4024 2" }, + { "R 0x24ce4038 2" }, + { "R 0x24ce600c 5" }, + { "R 0x24ce700c 5" }, + { "R 0x24ce9004" }, + { "R 0x24ce9010 3" }, + { "R 0x24ce9020 3" }, + { "R 0x24ce9030 3" }, + { "R 0x24ce9040 3" }, + { "R 0x24ce9050 3" }, + { "R 0x24cea004" }, + { "R 0x24cea010 3" }, + { "R 0x24cea020 3" }, + { "R 0x24cea030 3" }, + { "R 0x24cea040 3" }, + { "R 0x24cea050 3" }, + { "R 0x24cf001c" }, + { "R 0x24cf0050" }, + { "R 0x24cf0058" }, + { "R 0x25800004" }, + { "R 0x25801004" }, + { "R 0x25802004" }, + { "R 0x25803004" }, + { "R 0x25804004" }, + { "R 0x25805004" }, + { "R 0x25806004" }, + { "R 0x25807004" }, + { "R 0x25808004" }, + { "R 0x25809004" }, + { "R 0x2580a004" }, + { "R 0x2580b004" }, + { "R 0x2580c004" }, + { "R 0x2580d004" }, + { "R 0x2580e004" }, + { "R 0x2580f004" }, + { "R 0x25810004" }, + { "R 0x25811004" }, + { "R 0x25812004" }, + { "R 0x25813004" }, + { "R 0x25814004" }, + { "R 0x25815004" }, + { "R 0x25816004" }, + { "R 0x25817004" }, + { "R 0x25818004" }, + { "R 0x25819004" }, + { "R 0x2581a004" }, + { "R 0x2581b004" }, + { "R 0x2581c004" }, + { "R 0x2581d004" }, + { "R 0x2581e004" }, + { "R 0x2581f004" }, + { "R 0x25820004" }, + { "R 0x25821004" }, + { "R 0x25822004" }, + { "R 0x25823004" }, + { "R 0x25843350 2" }, + { "R 0x258433f4 11" }, + { "R 0x258434c0 6" }, + { "R 0x25843600" }, + { "R 0x2584360c" }, + { "R 0x25845040" }, + { "R 0x25845048" }, + { "R 0x25845050" }, + { "R 0x25845058" }, + { "R 0x25845060" }, + { "R 0x25845068" }, + { "R 0x25845070 4" }, + { "R 0x25845090 14" }, + { "R 0x258450cc 2" }, + { "R 0x25845240" }, + { "R 0x258452a0" }, + { "R 0x25845300" }, + { "R 0x25845310" }, + { "R 0x25845320" }, + { "R 0x25845330 3" }, + { "R 0x25847404" }, + { "R 0x2584740c 3" }, + { "R 0x25847448" }, + { "R 0x25847450" }, + { "R 0x25847458 2" }, + { "R 0x25847600" }, + { "R 0x25849000" }, + { "R 0x25849010" }, + { "R 0x2587c000" }, + { "R 0x2587c01c 3" }, + { "R 0x2587c030 8" }, + { "R 0x2587c054 2" }, + { "R 0x2587c078" }, + { "R 0x2587c108 9" }, + { "R 0x2587c20c 3" }, + { "R 0x258a600c 4" }, + { "R 0x258a6020 3" }, + { "R 0x258a6034 2" }, + { "R 0x258a6040" }, + { "R 0x258a6050" }, + { "R 0x258a6058" }, + { "R 0x258a6060 4" }, + { "R 0x258a7020" }, + { "R 0x258a7030 2" }, + { "R 0x258a7078 4" }, + { "R 0x258a708c 6" }, + { "R 0x258e002c" }, + { "R 0x258e009c 2" }, + { "R 0x258e00a8 3" }, + { "R 0x258e00b8" }, + { "R 0x258e00c0 7" }, + { "R 0x258e00e0" }, + { "R 0x258e00e8" }, + { "R 0x258e00f0" }, + { "R 0x258e00f8" }, + { "R 0x258e0100" }, + { "R 0x258e0108" }, + { "R 0x258e0110" }, + { "R 0x258e0118" }, + { "R 0x258e0120" }, + { "R 0x258e0128" }, + { "R 0x258e0150 4" }, + { "R 0x258e0164" }, + { "R 0x258e01e8" }, + { "R 0x258e1010" }, + { "R 0x258e1060 3" }, + { "R 0x258e1070" }, + { "R 0x258e1084 3" }, + { "R 0x258e3004" }, + { "R 0x258e300c" }, + { "R 0x258e4004" }, + { "R 0x258e4010 2" }, + { "R 0x258e4024 2" }, + { "R 0x258e4038 2" }, + { "R 0x258e600c 5" }, + { "R 0x258e700c 5" }, + { "R 0x258e9004" }, + { "R 0x258e9010 3" }, + { "R 0x258e9020 3" }, + { "R 0x258e9030 3" }, + { "R 0x258e9040 3" }, + { "R 0x258e9050 3" }, + { "R 0x258ea004" }, + { "R 0x258ea010 3" }, + { "R 0x258ea020 3" }, + { "R 0x258ea030 3" }, + { "R 0x258ea040 3" }, + { "R 0x258ea050 3" }, + { "R 0x258f001c" }, + { "R 0x258f0050" }, + { "R 0x258f0058" }, + { "R 0x25c00004" }, + { "R 0x25c01004" }, + { "R 0x25c02004" }, + { "R 0x25c03004" }, + { "R 0x25c04004" }, + { "R 0x25c05004" }, + { "R 0x25c06004" }, + { "R 0x25c07004" }, + { "R 0x25c08004" }, + { "R 0x25c09004" }, + { "R 0x25c0a004" }, + { "R 0x25c0b004" }, + { "R 0x25c0c004" }, + { "R 0x25c0d004" }, + { "R 0x25c0e004" }, + { "R 0x25c0f004" }, + { "R 0x25c10004" }, + { "R 0x25c11004" }, + { "R 0x25c12004" }, + { "R 0x25c13004" }, + { "R 0x25c14004" }, + { "R 0x25c15004" }, + { "R 0x25c16004" }, + { "R 0x25c17004" }, + { "R 0x25c18004" }, + { "R 0x25c19004" }, + { "R 0x25c1a004" }, + { "R 0x25c1b004" }, + { "R 0x25c1c004" }, + { "R 0x25c1d004" }, + { "R 0x25c1e004" }, + { "R 0x25c1f004" }, + { "R 0x25c20004" }, + { "R 0x25c21004" }, + { "R 0x25c22004" }, + { "R 0x25c23004" }, + { "R 0x25c43350 2" }, + { "R 0x25c433f4 11" }, + { "R 0x25c434c0 6" }, + { "R 0x25c43600" }, + { "R 0x25c4360c" }, + { "R 0x25c45040" }, + { "R 0x25c45048" }, + { "R 0x25c45050" }, + { "R 0x25c45058" }, + { "R 0x25c45060" }, + { "R 0x25c45068" }, + { "R 0x25c45070 4" }, + { "R 0x25c45090 14" }, + { "R 0x25c450cc 2" }, + { "R 0x25c45240" }, + { "R 0x25c452a0" }, + { "R 0x25c45300" }, + { "R 0x25c45310" }, + { "R 0x25c45320" }, + { "R 0x25c45330 3" }, + { "R 0x25c47404" }, + { "R 0x25c4740c 3" }, + { "R 0x25c47448" }, + { "R 0x25c47450" }, + { "R 0x25c47458 2" }, + { "R 0x25c47600" }, + { "R 0x25c49000" }, + { "R 0x25c49010" }, + { "R 0x25c7c000" }, + { "R 0x25c7c01c 3" }, + { "R 0x25c7c030 8" }, + { "R 0x25c7c054 2" }, + { "R 0x25c7c078" }, + { "R 0x25c7c108 9" }, + { "R 0x25c7c20c 3" }, + { "R 0x25ca600c 4" }, + { "R 0x25ca6020 3" }, + { "R 0x25ca6034 2" }, + { "R 0x25ca6040" }, + { "R 0x25ca6050" }, + { "R 0x25ca6058" }, + { "R 0x25ca6060 4" }, + { "R 0x25ca7020" }, + { "R 0x25ca7030 2" }, + { "R 0x25ca7078 4" }, + { "R 0x25ca708c 6" }, + { "R 0x25ce002c" }, + { "R 0x25ce009c 2" }, + { "R 0x25ce00a8 3" }, + { "R 0x25ce00b8" }, + { "R 0x25ce00c0 7" }, + { "R 0x25ce00e0" }, + { "R 0x25ce00e8" }, + { "R 0x25ce00f0" }, + { "R 0x25ce00f8" }, + { "R 0x25ce0100" }, + { "R 0x25ce0108" }, + { "R 0x25ce0110" }, + { "R 0x25ce0118" }, + { "R 0x25ce0120" }, + { "R 0x25ce0128" }, + { "R 0x25ce0150 4" }, + { "R 0x25ce0164" }, + { "R 0x25ce01e8" }, + { "R 0x25ce1010" }, + { "R 0x25ce1060 3" }, + { "R 0x25ce1070" }, + { "R 0x25ce1084 3" }, + { "R 0x25ce3004" }, + { "R 0x25ce300c" }, + { "R 0x25ce4004" }, + { "R 0x25ce4010 2" }, + { "R 0x25ce4024 2" }, + { "R 0x25ce4038 2" }, + { "R 0x25ce600c 5" }, + { "R 0x25ce700c 5" }, + { "R 0x25ce9004" }, + { "R 0x25ce9010 3" }, + { "R 0x25ce9020 3" }, + { "R 0x25ce9030 3" }, + { "R 0x25ce9040 3" }, + { "R 0x25ce9050 3" }, + { "R 0x25cea004" }, + { "R 0x25cea010 3" }, + { "R 0x25cea020 3" }, + { "R 0x25cea030 3" }, + { "R 0x25cea040 3" }, + { "R 0x25cea050 3" }, + { "R 0x25cf001c" }, + { "R 0x25cf0050" }, + { "R 0x25cf0058" }, + { "R 0x240a0008 2" }, + { "R 0x240a1008 2" }, + { "R 0x248e0070 7" }, + { "R 0x248e0094 2" }, + { "R 0x248e012c 9" }, + { "R 0x248e0160" }, + { "R 0x248e0364 2" }, + { "R 0x24ce0070 7" }, + { "R 0x24ce0094 2" }, + { "R 0x24ce012c 9" }, + { "R 0x24ce0160" }, + { "R 0x24ce0364 2" }, + { "R 0x258e0070 7" }, + { "R 0x258e0094 2" }, + { "R 0x258e012c 9" }, + { "R 0x258e0160" }, + { "R 0x258e0364 2" }, + { "R 0x25ce0070 7" }, + { "R 0x25ce0094 2" }, + { "R 0x25ce012c 9" }, + { "R 0x25ce0160" }, + { "R 0x25ce0364 2" }, + { "R 0x248e0358" }, + { "R 0x24ce0358" }, + { "R 0x258e0358" }, + { "R 0x25ce0358" }, + { "R 0x248e0008" }, + { "R 0x24ce0008" }, + { "R 0x258e0008" }, + { "R 0x25ce0008" }, + { "R 0x24076b00 2" }, + { "R 0x24076b0c 2" }, + { "R 0x24076b18 2" }, + { "R 0x24076b24 2" }, + { "R 0x24076b30 2" }, + { "R 0x24076b3c 2" }, + { "R 0x24076b48 2" }, + { "R 0x24076b54 2" }, + { "R 0x24076b60 2" }, + { "R 0x24076b6c 2" }, + { "R 0x24076b78 2" }, + { "R 0x24076b84 2" }, + { "R 0x24076b90 2" }, + { "R 0x24076b9c 2" }, + { "R 0x24076ba8 2" }, + { "R 0x24076bb4 2" }, + { "R 0x24076bc0 2" }, + { "R 0x24076bcc 2" }, + { "R 0x24076bd8 2" }, + { "R 0x24076be4 2" }, + { "R 0x24076bf0 2" }, + { "R 0x24076bfc 2" }, + { "R 0x24076c08 2" }, + { "R 0x24076c14 2" }, + { "R 0x24076c20 2" }, + { "R 0x24076c2c 2" }, + { "R 0x24076c38 2" }, + { "R 0x24076c44 2" }, + { "R 0x24076c50 2" }, + { "R 0x24076c5c 2" }, + { "R 0x24076c68 2" }, + { "R 0x24076c74 2" }, + { "R 0x24076950" }, + { "R 0x240760a4" }, + { "R 0x248720b0" }, + { "R 0x258720b0" }, + { "R 0x24c720b0" }, + { "R 0x25c720b0" }, +}; + +static const struct dcc_register_entry pakala_dcc_entries_ll4[] = { + { "R 0x16801000 2" }, + { "R 0x240e0010" }, + { "R 0x240e0020 8" }, + { "R 0x240e0248" }, + { "R 0x24330010" }, + { "R 0x24330020 8" }, + { "R 0x24330248" }, + { "R 0x240e1018" }, + { "R 0x240e1008" }, + { "R 0x240e1010 2" }, + { "R 0x24331018" }, + { "R 0x24331008" }, + { "R 0x24331010 2" }, + { "R 0x1780010" }, + { "R 0x1780020 8" }, + { "R 0x1780248" }, + { "R 0x1782018" }, + { "R 0x1782008" }, + { "R 0x1782010 2" }, + { "R 0x1783018" }, + { "R 0x1783008" }, + { "R 0x1783010 2" }, + { "R 0x1680010" }, + { "R 0x1680020 8" }, + { "R 0x1681048" }, + { "R 0x1682018" }, + { "R 0x1682008" }, + { "R 0x1682010 2" }, + { "R 0x16e0010" }, + { "R 0x16e0020 8" }, + { "R 0x16e0248" }, + { "R 0x16e1018" }, + { "R 0x16e1008" }, + { "R 0x16e1010 2" }, + { "R 0x16e1098" }, + { "R 0x16e1088" }, + { "R 0x16e1090 2" }, + { "R 0x16e1118" }, + { "R 0x16e1108" }, + { "R 0x16e1110 2" }, + { "R 0x1700010" }, + { "R 0x1700020 8" }, + { "R 0x1700248" }, + { "R 0x1702018" }, + { "R 0x1702008" }, + { "R 0x1702010 2" }, + { "R 0x1702218" }, + { "R 0x1702208" }, + { "R 0x1702210 2" }, + { "R 0x1702118" }, + { "R 0x1702108" }, + { "R 0x1702110 2" }, + { "R 0x1600010" }, + { "R 0x1600020 8" }, + { "R 0x1600248 2" }, + { "R 0x1600258" }, + { "R 0x1602018" }, + { "R 0x1602008" }, + { "R 0x1602010 2" }, + { "R 0x1602098" }, + { "R 0x1602088" }, + { "R 0x1602090 2" }, + { "R 0x1602118" }, + { "R 0x1602108" }, + { "R 0x1602110 2" }, + { "R 0x1602198" }, + { "R 0x1602188" }, + { "R 0x1602190 2" }, + { "R 0x1602218" }, + { "R 0x1602208" }, + { "R 0x1602210 2" }, + { "R 0x1602098" }, + { "R 0x1602088" }, + { "R 0x1602090 2" }, + { "R 0x1500010" }, + { "R 0x1500020 8" }, + { "R 0x1500248" }, + { "R 0x1500448" }, + { "R 0x1502018" }, + { "R 0x1502008" }, + { "R 0x1502010 2" }, + { "R 0x1502098" }, + { "R 0x1502088" }, + { "R 0x1502090 2" }, + { "R 0x16e00010" }, + { "R 0x16e00020 8" }, + { "R 0x16e00248" }, + { "R 0x16e01018" }, + { "R 0x16e01008" }, + { "R 0x16e01010 2" }, + { "R 0x1b600010" }, + { "R 0x1b600020 8" }, + { "R 0x1b600248" }, + { "R 0x1b601018" }, + { "R 0x1b601008" }, + { "R 0x1b601010 2" }, + { "R 0x16000104 30" }, + { "R 0x16000204 29" }, + { "R 0x16000384 30" }, + { "R 0xb291024" }, + { "R 0xc201244" }, + { "R 0xc202244" }, + { "R 0xbde1034 2" }, + { "R 0xb201020 2" }, + { "R 0xb211020 2" }, + { "R 0xb221020 2" }, + { "R 0xb231020 2" }, + { "R 0xb204520" }, + { "R 0xb200000" }, + { "R 0xb210000" }, + { "R 0xb220000" }, + { "R 0xb230000" }, + { "R 0x16500010" }, + { "R 0x16510010" }, + { "R 0x16520010" }, + { "R 0x16530010" }, + { "R 0x16500030" }, + { "R 0x16510030" }, + { "R 0x16520030" }, + { "R 0x16530030" }, + { "R 0x16500038" }, + { "R 0x16510038" }, + { "R 0x16520038" }, + { "R 0x16530038" }, + { "R 0x16500040" }, + { "R 0x16510040" }, + { "R 0x16520040" }, + { "R 0x16530040" }, + { "R 0x16500048" }, + { "R 0x16500400 3" }, + { "R 0x16510400 3" }, + { "R 0x16520400 3" }, + { "R 0x16530400 3" }, + { "R 0x16510d3c" }, + { "R 0x16510d54" }, + { "R 0x16510d6c" }, + { "R 0x16510d84" }, + { "R 0x16510d9c" }, + { "R 0x16510db4" }, + { "R 0x16510dcc" }, + { "R 0x16510de4" }, + { "R 0x16510dfc" }, + { "R 0x16510e14" }, + { "R 0x16510e2c" }, + { "R 0x16510e44" }, + { "R 0x16510e5c" }, + { "R 0x16510e74" }, + { "R 0x16510e8c" }, + { "R 0x16510ea4" }, + { "R 0x16510fdc" }, + { "R 0x16510ff4" }, + { "R 0x1651100c" }, + { "R 0x16511024" }, + { "R 0x1651103c" }, + { "R 0x16511054" }, + { "R 0x1651106c" }, + { "R 0x16511084" }, + { "R 0x1651109c" }, + { "R 0x165110b4" }, + { "R 0x165110cc" }, + { "R 0x165110e4" }, + { "R 0x165110fc" }, + { "R 0x16511114" }, + { "R 0x1651112c" }, + { "R 0x16511144" }, + { "R 0x1651127c" }, + { "R 0x16511294" }, + { "R 0x165112ac" }, + { "R 0x165112c4" }, + { "R 0x165112dc" }, + { "R 0x165112f4" }, + { "R 0x1651130c" }, + { "R 0x16511324" }, + { "R 0x1651133c" }, + { "R 0x16511354" }, + { "R 0x1651136c" }, + { "R 0x16511384" }, + { "R 0x1651139c" }, + { "R 0x165113b4" }, + { "R 0x165113cc" }, + { "R 0x165113e4" }, + { "R 0x1651151c" }, + { "R 0x16511534" }, + { "R 0x1651154c" }, + { "R 0x16511564" }, + { "R 0x1651157c" }, + { "R 0x16511594" }, + { "R 0x165115ac" }, + { "R 0x165115c4" }, + { "R 0x165115dc" }, + { "R 0x165115f4" }, + { "R 0x1651160c" }, + { "R 0x16511624" }, + { "R 0x1651163c" }, + { "R 0x16511654" }, + { "R 0x1651166c" }, + { "R 0x16511684" }, + { "R 0x110004 2" }, + { "R 0x11003c 3" }, + { "R 0x176040" }, + { "R 0x10c0000 4" }, + { "R 0x10c1000 2" }, + { "R 0x10c1010 7" }, + { "R 0x10c1100 3" }, + { "R 0x10c1110 5" }, + { "R 0x10c1130 2" }, + { "R 0x10c113c 2" }, + { "R 0x10c1148 3" }, + { "R 0x10c1800 11" }, + { "R 0x10c2000" }, + { "R 0x10cf004" }, + { "R 0x16801000 2" }, +}; + +static const struct dcc_link_config pakala_link_configs[] = { + { + .link_list = 6, + .entries = pakala_dcc_entries_ll6, + .num_entries = ARRAY_SIZE(pakala_dcc_entries_ll6), + }, + { + .link_list = 4, + .entries = pakala_dcc_entries_ll4, + .num_entries = ARRAY_SIZE(pakala_dcc_entries_ll4), + }, +}; + +static const struct dcc_config pakala_config = { + .lists = pakala_link_configs, + .num_lists = ARRAY_SIZE(pakala_link_configs), +}; + +static const struct dcc_pdata pakala_pdata = { + .base = 0x100ff000, + .size = 0x00001000, + .ram_base = 0x10084000, + .ram_size = 0x4000, + .dcc_offset = 0x4000, + .map_ver = 0x3, + .config = &pakala_config, +}; + +#endif /* _QCOM_DCC_PAKALA_CONFIG_H */ diff --git a/drivers/misc/qcom-dcc-shikra-config.h b/drivers/misc/qcom-dcc-shikra-config.h new file mode 100644 index 0000000000000..fdf3d0c34695c --- /dev/null +++ b/drivers/misc/qcom-dcc-shikra-config.h @@ -0,0 +1,677 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_SHIKRA_CONFIG_H +#define _QCOM_DCC_SHIKRA_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry shikra_dcc_entries_ll2[] = { + /* timer */ + { "R 0x17421000 2" }, + /* clock */ + { "R 0x1400000 10" }, + { "R 0x1401000 10" }, + { "R 0x1402000 10" }, + { "R 0x1403000 10" }, + { "R 0x1404000 10" }, + { "R 0x1405000 10" }, + { "R 0x1406000 10" }, + { "R 0x1407000 10" }, + { "R 0x1408000 10" }, + { "R 0x1409000 9" }, + { "R 0x140a000 10" }, + { "R 0x140b000 10" }, + { "R 0x140c000 10" }, + { "R 0x141001c" }, + { "R 0x14103d0" }, + { "R 0x1414024" }, + { "R 0x1415034 2" }, + { "R 0x141f02c" }, + { "R 0x141f15c" }, + { "R 0x141f28c" }, + { "R 0x141f3bc" }, + { "R 0x141f4ec" }, + { "R 0x141f61c" }, + { "R 0x141f74c" }, + { "R 0x141f87c" }, + { "R 0x141f9ac" }, + { "R 0x141fadc" }, + { "R 0x141fc0c" }, + { "R 0x1427024" }, + { "R 0x1432034" }, + { "R 0x1434028" }, + { "R 0x1434154" }, + { "R 0x143c018" }, + { "R 0x1446024" }, + { "R 0x1446154" }, + { "R 0x1449018" }, + { "R 0x14b4014" }, + { "R 0x146b000 14" }, + { "R 0xfa80000 6" }, + { "R 0xfa8001c 2" }, + { "R 0xfa80028" }, + { "R 0xfa80034 2" }, + { "R 0xfa80080 3" }, + { "R 0xfa84000 6" }, + { "R 0xfa8401c 2" }, + { "R 0xfa84028" }, + { "R 0xfa84034 2" }, + { "R 0xfa84080 3" }, + { "R 0xfa88000 6" }, + { "R 0xfa8801c 2" }, + { "R 0xfa88028" }, + { "R 0xfa88034 2" }, + { "R 0xfa88080 3" }, + { "R 0x440c000" }, + { "R 0x440c008" }, + { "R 0x440c040 9" }, + { "R 0x440c068 2" }, + /* global_cpr */ + { "R 0x1648000 2" }, + { "R 0x16480e0" }, + { "R 0x1648100" }, + { "R 0x1648120" }, + { "R 0x1648140" }, + { "R 0x1648200" }, + { "R 0x164880c 4" }, + { "R 0x164c000 2" }, + { "R 0x164c0e0" }, + { "R 0x164c100" }, + { "R 0x164c120" }, + { "R 0x164c140" }, + { "R 0x164c200" }, + { "R 0x164c80c 4" }, + { "R 0x1b44268 7" }, + { "R 0x1b44288 11" }, + { "R 0x1b442d0" }, + /* cpr */ + { "R 0xfd9001c 3" }, + { "R 0xfd90090" }, + { "R 0xfd900b0 2" }, + { "R 0xfd900d8" }, + { "R 0xfd900e8" }, + { "R 0xfd90300" }, + { "R 0xfd90320" }, + { "R 0xfd90348 3" }, + { "R 0xfd90360" }, + { "R 0xfd90368 2" }, + { "R 0xfd9101c 3" }, + { "R 0xfd91090" }, + { "R 0xfd910b0 2" }, + { "R 0xfd910d8" }, + { "R 0xfd910e8" }, + { "R 0xfd91300" }, + { "R 0xfd91320" }, + { "R 0xfd91348 3" }, + { "R 0xfd91360" }, + { "R 0xfd91368 2" }, + { "R 0xfd9201c 3" }, + { "R 0xfd92090" }, + { "R 0xfd920b0 2" }, + { "R 0xfd920d8" }, + { "R 0xfd920e8" }, + { "R 0xfd92300" }, + { "R 0xfd92320" }, + { "R 0xfd92348 4" }, + { "R 0xfd92360" }, + { "R 0xfd92368 2" }, + { "R 0xfd98004" }, + { "R 0xfd98018 3" }, + { "R 0xf900c14 2" }, + { "R 0xfba0008" }, + { "R 0xfba0020 2" }, + { "R 0xfba0070" }, + { "R 0xfba0810" }, + { "R 0xfba3500" }, + { "R 0xfba3a84 2" }, + { "R 0xfa90004" }, + { "R 0xfa92004" }, + { "R 0xfa94004" }, + { "R 0xfba3a84 3" }, + { "R 0xfd90200 12" }, + { "R 0xfd91200 12" }, + { "R 0xfd92200 12" }, + { "R 0xfba3500 40" }, + /* cpucp */ + { "R 0xfd80110" }, + { "R 0xfd9001c" }, + { "R 0xfd90090" }, + { "R 0xfd900b0" }, + { "R 0xfd900d8" }, + { "R 0xfd900e8" }, + { "R 0xfd90300" }, + { "R 0xfd90320" }, + { "R 0xfd90348" }, + { "R 0xfd9101c" }, + { "R 0xfd91090" }, + { "R 0xfd910b0" }, + { "R 0xfd910d8" }, + { "R 0xfd910e8" }, + { "R 0xfd91300" }, + { "R 0xfd91320" }, + { "R 0xfd91348" }, + { "R 0xfd9201c" }, + { "R 0xfd92090" }, + { "R 0xfd920b0" }, + { "R 0xfd920d8" }, + { "R 0xfd920e8" }, + { "R 0xfd92300" }, + { "R 0xfd92320" }, + { "R 0xfd92348" }, + { "R 0xfd98004" }, + { "R 0xfd98018" }, + { "R 0xf900c00" }, + { "R 0xfb00000" }, + { "R 0xfba0000" }, + { "R 0xf800000" }, + { "R 0xf810000" }, + { "R 0xf820000" }, + { "R 0xf830000" }, + { "R 0xf840000" }, + { "R 0xf850000" }, + { "R 0xf860000" }, + { "R 0xf870000" }, + { "R 0xfd91000" }, + { "R 0xfd92000" }, + { "R 0xf880000" }, + { "R 0xfd90000" }, + { "R 0xf900c18" }, + { "R 0xfd9134c" }, + { "R 0xfd9234c" }, + { "R 0xfd9034c" }, + { "R 0xfba3a84" }, + { "R 0xfba3a88" }, + { "R 0xfba3a8c" }, + { "R 0xfd91020" }, + { "R 0xfd92020" }, + { "R 0xfd90020" }, + /* modem */ + { "R 0x6080400 3" }, + { "R 0x6080410 2" }, + { "R 0x6080060 5" }, + { "R 0x61f100c" }, + { "R 0x143314c" }, + { "R 0x6140400 3" }, + { "R 0x6082028" }, + { "R 0x6080304" }, + { "R 0xd2f010" }, + { "R 0x6104000 8" }, + { "R 0x6140208 3" }, + { "R 0x6140228 3" }, + { "R 0x6140248 3" }, + { "R 0x6140268 3" }, + { "R 0x6140288 3" }, + { "R 0x6140400 3" }, + { "R 0x6082028" }, + { "R 0x6080304" }, + { "R 0x6140200" }, + { "R 0x6140404" }, + { "R 0x608030c" }, + /* ICB - SYSTEM_NOC */ + { "R 0x1880000" }, + { "R 0x1880004" }, + { "R 0x1880008" }, + { "R 0x1880010" }, + { "R 0x1880020" }, + { "R 0x1880024" }, + { "R 0x1880028" }, + { "R 0x188002c" }, + { "R 0x1880030" }, + { "R 0x1880034" }, + { "R 0x1880038" }, + { "R 0x188003c" }, + { "R 0x1880240" }, + { "R 0x1880248" }, + { "R 0x1881018" }, + { "R 0x1881008" }, + { "R 0x1881010 2" }, + { "R 0x1881098" }, + { "R 0x1881088" }, + { "R 0x1881090 2" }, + { "R 0x1881118" }, + { "R 0x1881108" }, + { "R 0x1881110 2" }, + { "R 0x1881198" }, + { "R 0x1881188" }, + { "R 0x1881190 2" }, + { "R 0x1881218" }, + { "R 0x1881208" }, + { "R 0x1881210 2" }, + /* ICB - CONFIG_NOC */ + { "R 0x1900000" }, + { "R 0x1900004" }, + { "R 0x1900008" }, + { "R 0x1900010" }, + { "R 0x1900020" }, + { "R 0x1900024" }, + { "R 0x1900028" }, + { "R 0x190002c" }, + { "R 0x1900030" }, + { "R 0x1900034" }, + { "R 0x1900038" }, + { "R 0x190003c" }, + { "R 0x1900240" }, + { "R 0x1900244" }, + { "R 0x1900248" }, + { "R 0x190024c" }, + { "R 0x1901018" }, + { "R 0x1901008" }, + { "R 0x1901010 2" }, + { "R 0x1901118" }, + { "R 0x1901108" }, + { "R 0x1901110 2" }, + { "R 0x1901218" }, + { "R 0x1901208" }, + { "R 0x1901210 2" }, + { "R 0x1901318" }, + { "R 0x1901308" }, + { "R 0x1901310 2" }, + /* ICB - MEMNOC */ + { "R 0xd00000" }, + { "R 0xd00004" }, + { "R 0xd00008" }, + { "R 0xd00010" }, + { "R 0xd00020" }, + { "R 0xd00024" }, + { "R 0xd00028" }, + { "R 0xd0002c" }, + { "R 0xd00030" }, + { "R 0xd00034" }, + { "R 0xd00038" }, + { "R 0xd0003c" }, + { "R 0xd40000" }, + { "R 0xd40004" }, + { "R 0xd40008" }, + { "R 0xd40010" }, + { "R 0xd40020" }, + { "R 0xd40024" }, + { "R 0xd40028" }, + { "R 0xd4002c" }, + { "R 0xd40030" }, + { "R 0xd40034" }, + { "R 0xd40038" }, + { "R 0xd4003c" }, + { "R 0xd00240" }, + { "R 0xd00248" }, + { "R 0xd40440" }, + { "R 0xd40448" }, + { "R 0xd41018" }, + { "R 0xd41008" }, + { "R 0xd41010 2" }, + { "R 0xd01018" }, + { "R 0xd01008" }, + { "R 0xd01010 2" }, + /* ICB - DC_NOC */ + { "R 0xce5018" }, + { "R 0xce5008" }, + { "R 0xce5010 2" }, + { "R 0xce0010" }, + { "R 0xce0020 8" }, + { "R 0xce0248" }, + /* ICB - QoS - system noc */ + { "R 0x18d1010" }, + { "R 0x18d2010" }, + { "R 0x18d3010" }, + { "R 0x18d4010" }, + { "R 0x18d5010" }, + { "R 0x18d6010" }, + { "R 0x18d7010" }, + { "R 0x18d8010" }, + { "R 0x18d9010" }, + { "R 0x18da010" }, + { "R 0x18db010" }, + { "R 0x18dc010" }, + { "R 0x18dd010" }, + { "R 0x18de010" }, + { "R 0x18df010" }, + { "R 0x18e0010" }, + { "R 0x18e1010" }, + { "R 0x18e2010" }, + { "R 0x18e3010" }, + { "R 0x18e4010" }, + { "R 0x18e5010" }, + { "R 0x18e6010" }, + { "R 0x18e7010" }, + { "R 0x18e8010" }, + { "R 0x18e9010" }, + { "R 0x18ea010" }, + /* ICB - QoS - mem noc */ + { "R 0xd28010" }, + { "R 0xd2a010" }, + { "R 0xd2b010" }, + { "R 0xd2c010" }, + { "R 0xd2d010" }, + { "R 0xd2e010" }, + { "R 0xd2f010" }, + /* ddr */ + { "R 0x1089180 2" }, + { "R 0x10804d4" }, + { "R 0x10804b8 2" }, + { "R 0x1089100" }, + { "R 0x1089110" }, + { "R 0x1089120" }, + { "R 0x10891a0" }, + { "R 0x108340c" }, + { "R 0x1083404" }, + { "R 0x1083410" }, + { "R 0x1083408" }, + { "R 0x1083400" }, + { "R 0x1086418" }, + { "R 0x1086400" }, + { "R 0x1086420" }, + { "R 0x1086410" }, + { "R 0x10891c0" }, + { "R 0x10891e0" }, + { "R 0x1085b14" }, + { "R 0x1085b10" }, + { "R 0x1085b0c" }, + { "R 0x1085b00" }, + { "R 0x10853b0" }, + { "R 0x1085b1c" }, + { "R 0x1085b08" }, + { "R 0x1085b38" }, + { "R 0x1085b30" }, + { "R 0x1085b2c" }, + { "R 0x1085804" }, + { "R 0x1085b28" }, + { "R 0x1085b18" }, + { "R 0x1085230" }, + { "R 0x1085210" }, + { "R 0xc800b0 2" }, + { "R 0xcb6000" }, + { "R 0x1286074 5" }, + { "R 0x1286260 5" }, + { "R 0xc80018" }, + { "R 0xc80108" }, + { "R 0xc840e0 2" }, + { "R 0xcba070 2" }, + { "R 0xcba054" }, + { "R 0xcba078 2" }, + { "R 0xcba058" }, + { "R 0xcba080" }, + { "R 0xcba084" }, + { "R 0xcba05c" }, + { "R 0xcba088" }, + { "R 0xcba08c" }, + { "R 0xcba060" }, + { "R 0xcba090 2" }, + { "R 0xcba064" }, + { "R 0xcba098 2" }, + { "R 0x1090018" }, + { "R 0x1090110 4" }, + { "R 0x1090004" }, + { "R 0x10900a0" }, + { "R 0x1090170" }, + { "R 0x1090180 4" }, + { "R 0x1090078" }, + { "R 0x1090150 4" }, + { "R 0x1090080" }, + { "R 0x1090088" }, + { "R 0x1090090" }, + { "R 0x1090070 2" }, + { "R 0x10900b0" }, + { "R 0x1090130" }, + { "R 0x1090140" }, + { "R 0x1090030 3" }, + { "R 0x1090044" }, + { "R 0x1090144" }, + { "R 0x1090040 3" }, + { "R 0x10900c8 2" }, + { "R 0x1090050" }, + { "R 0x1090128 2" }, + { "R 0x10900e4 5" }, + { "R 0x1090124" }, + { "R 0x1090100" }, + { "R 0xe90018" }, + { "R 0xe90110 4" }, + { "R 0xe90004" }, + { "R 0xe900a0" }, + { "R 0xe90170" }, + { "R 0xe90180 4" }, + { "R 0xe90078" }, + { "R 0xe90150" }, + { "R 0xe90080" }, + { "R 0xe90154" }, + { "R 0xe90088" }, + { "R 0xe90158" }, + { "R 0xe90090" }, + { "R 0xe9015c" }, + { "R 0xe90070 2" }, + { "R 0xe900b0" }, + { "R 0xe90130" }, + { "R 0xe90034" }, + { "R 0xe90140" }, + { "R 0xe90038" }, + { "R 0xe90030" }, + { "R 0xe90044" }, + { "R 0xe90144" }, + { "R 0xe90048" }, + { "R 0xe90040" }, + { "R 0xe900c8 2" }, + { "R 0xe90050" }, + { "R 0xe90128 2" }, + { "R 0xe900e4 3" }, + { "R 0xe900f0 2" }, + { "R 0xe90124" }, + { "R 0xe90100" }, + { "R 0xf90018" }, + { "R 0xf90110 4" }, + { "R 0xf90004" }, + { "R 0xf900a0" }, + { "R 0xf90170" }, + { "R 0xf90180 4" }, + { "R 0xf90078" }, + { "R 0xf90150 4" }, + { "R 0xf90080" }, + { "R 0xf90088" }, + { "R 0xf90090" }, + { "R 0xf90070 2" }, + { "R 0xf900b0" }, + { "R 0xf90130 2" }, + { "R 0xf90140" }, + { "R 0xf90038" }, + { "R 0xf90030" }, + { "R 0xf90044" }, + { "R 0xf90144" }, + { "R 0xf90048" }, + { "R 0xf90040" }, + { "R 0xf900c8 2" }, + { "R 0xf90050" }, + { "R 0xf90128 2" }, + { "R 0xf900e4 5" }, + { "R 0xf90124" }, + { "R 0xf90100" }, + { "R 0xcba218" }, + { "R 0xcba050" }, + { "R 0xcba210" }, + { "R 0xcba280" }, + { "R 0xcba180 4" }, + { "R 0xcba214" }, + { "R 0xcba004" }, + { "R 0xcba000" }, + { "R 0xcba014 2" }, + { "R 0xcba020 2" }, + { "R 0xcba010" }, + { "R 0xcba288 7" }, + { "R 0xcba150 2" }, + { "R 0xcba200" }, + { "R 0xcba140 2" }, + { "R 0xcba230 2" }, + { "R 0xcba0c8 2" }, + { "R 0xcba0b0 4" }, + { "R 0xcba240 2" }, + { "R 0xcba250 4" }, + { "R 0xcba100 5" }, + { "R 0xcba120 3" }, + { "R 0xcba130" }, + { "R 0xcba134" }, + { "R 0xcba270" }, + { "R 0xc35008" }, + { "R 0xc350b4" }, + { "R 0xc35100" }, + { "R 0x1059070" }, + { "R 0x103801c 7" }, + { "R 0x1023318" }, + { "R 0x1020488" }, + { "R 0x1020480" }, + { "R 0x1023594" }, + { "R 0x102358c" }, + { "R 0x10223a0" }, + { "R 0x1022398" }, + { "R 0x10223ac" }, + { "R 0x10223a4" }, + { "R 0x128007c" }, + { "R 0x128107c" }, + { "R 0x128207c" }, + { "R 0x128307c" }, + { "R 0x128407c" }, + { "R 0x128507c" }, + { "R 0x12800a4" }, + { "R 0x12810a4" }, + { "R 0x12820a4" }, + { "R 0x12830a4" }, + { "R 0x12840a4" }, + { "R 0x12850a4" }, + { "R 0x1280100" }, + { "R 0x1281100" }, + { "R 0x1282100" }, + { "R 0x1283100" }, + { "R 0x1284100" }, + { "R 0x1285100" }, + { "R 0x128011c" }, + { "R 0x128111c" }, + { "R 0x128211c" }, + { "R 0x128311c" }, + { "R 0x128411c" }, + { "R 0x128511c" }, + { "R 0x1280568" }, + { "R 0x1281568" }, + { "R 0x1282568" }, + { "R 0x1283568" }, + { "R 0x1284568" }, + { "R 0x1285568" }, + { "R 0x128082c" }, + { "R 0x128182c" }, + { "R 0x128282c" }, + { "R 0x128382c" }, + { "R 0x128482c" }, + { "R 0x128582c" }, + { "R 0x128007c" }, + { "R 0x128107c" }, + { "R 0x128207c" }, + { "R 0x128307c" }, + { "R 0x128407c" }, + { "R 0x128507c" }, + { "R 0x12800a4" }, + { "R 0x12810a4" }, + { "R 0x12820a4" }, + { "R 0x12830a4" }, + { "R 0x12840a4" }, + { "R 0x12850a4" }, + { "R 0xc80058 2" }, + { "R 0xc800c8" }, + { "R 0xc800d4" }, + { "R 0xc80114" }, + { "R 0xc80104 2" }, + { "R 0xc800b0 2" }, + { "R 0xc80098" }, + { "R 0xd00248" }, +}; + +static const struct dcc_register_entry shikra_dcc_entries_ll3[] = { + /* gpu */ + { "R 0x599106c" }, + { "R 0x599100c" }, + { "R 0x59910a4" }, + { "R 0x5991054" }, + { "R 0x5991098 2" }, + { "R 0x5991078" }, + { "R 0x5991508" }, + { "R 0x599150c" }, + { "R 0x143600c" }, + { "R 0x1471000" }, + { "R 0x1436018" }, + /* cdsp */ + { "R 0xb3b0208 3" }, + { "R 0xb3b0228 3" }, + { "R 0xb3b0248 3" }, + { "R 0xb3b0268 3" }, + { "R 0xb3b0290" }, + { "R 0xb3b02b0" }, + { "R 0xb3b0400 3" }, + { "R 0xb302028" }, + { "R 0xb300304" }, + { "R 0xb3b0200" }, + { "R 0xb3b0404" }, + { "R 0x608030c" }, + /* apps_pcu */ + { "R 0xf800024" }, + { "R 0xf800040" }, + { "R 0xf80004c" }, + { "R 0xf800054" }, + { "R 0xf810024" }, + { "R 0xf810040" }, + { "R 0xf81004c" }, + { "R 0xf810054" }, + { "R 0xf820024" }, + { "R 0xf820040" }, + { "R 0xf82004c" }, + { "R 0xf820054" }, + { "R 0xf830024" }, + { "R 0xf830040" }, + { "R 0xf83004c" }, + { "R 0xf830054" }, + { "R 0xf880024" }, + { "R 0xf880040" }, + { "R 0xf880098" }, + { "R 0xfa80000 2" }, + { "R 0xfa84000 2" }, + { "R 0xfa88000 2" }, + { "R 0xf880200" }, + { "R 0xf8801b4 3" }, + { "R 0xf880044 3" }, + { "R 0xf880054" }, + { "R 0xf88006c" }, + { "R 0xf880070 4" }, + { "R 0xfd90348 2" }, + { "R 0xfd91348 2" }, + { "R 0xfd92348 2" }, + { "R 0xfd800fc" }, + { "R 0xfd800ec" }, + { "R 0xfd8010c" }, + { "R 0xfd91060 8" }, + { "R 0xfd92064 8" }, +}; + +static const struct dcc_link_config shikra_link_configs[] = { + { + .link_list = 2, + .entries = shikra_dcc_entries_ll2, + .num_entries = ARRAY_SIZE(shikra_dcc_entries_ll2), + }, + { + .link_list = 3, + .entries = shikra_dcc_entries_ll3, + .num_entries = ARRAY_SIZE(shikra_dcc_entries_ll3), + }, +}; + +static const struct dcc_config shikra_config = { + .lists = shikra_link_configs, + .num_lists = ARRAY_SIZE(shikra_link_configs), +}; + +static const struct dcc_pdata shikra_pdata = { + .base = 0x080ff000, + .size = 0x00001000, + .ram_base = 0x08086000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x3, + .config = &shikra_config, +}; + +#endif /* _QCOM_DCC_SHIKRA_CONFIG_H */ diff --git a/drivers/misc/qcom-dcc-talos-config.h b/drivers/misc/qcom-dcc-talos-config.h new file mode 100644 index 0000000000000..2c2316ae37853 --- /dev/null +++ b/drivers/misc/qcom-dcc-talos-config.h @@ -0,0 +1,792 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_TALOS_CONFIG_H +#define _QCOM_DCC_TALOS_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry talos_dcc_entries[] = { + { "R 0x9680000" }, + { "R 0x9680004" }, + { "R 0x9681000" }, + { "R 0x9681004" }, + { "R 0x9681008" }, + { "R 0x968100c" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x968101c" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102c" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103c" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812c" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813c" }, + { "R 0x9698500" }, + { "R 0x9698504" }, + { "R 0x9698508" }, + { "R 0x969850c" }, + { "R 0x9698510" }, + { "R 0x9698514" }, + { "R 0x9698518" }, + { "R 0x969851c" }, + { "R 0x9698700" }, + { "R 0x9698704" }, + { "R 0x9698708" }, + { "R 0x969870c" }, + { "R 0x9698714" }, + { "R 0x9698718" }, + { "R 0x969871c" }, + { "R 0x1620204" }, + { "R 0x1620240" }, + { "R 0x1620248" }, + { "R 0x1620288" }, + { "R 0x162028C" }, + { "R 0x1620290" }, + { "R 0x1620294" }, + { "R 0x16202A8" }, + { "R 0x16202AC" }, + { "R 0x16202B0" }, + { "R 0x16202B4" }, + { "R 0x1620300" }, + { "R 0x1700204" }, + { "R 0x1700240" }, + { "R 0x1700248" }, + { "R 0x1700288" }, + { "R 0x1700290" }, + { "R 0x1700300" }, + { "R 0x1700304" }, + { "R 0x1700308" }, + { "R 0x170030C" }, + { "R 0x1700310" }, + { "R 0x1700314" }, + { "R 0x1700C08" }, + { "R 0x1700C10" }, + { "R 0x1700C20" }, + { "R 0x1700C24" }, + { "R 0x1700C28" }, + { "R 0x1700C2C" }, + { "R 0x1700C30" }, + { "R 0x1700C34" }, + { "R 0x1700C38" }, + { "R 0x1700C3C" }, + { "R 0x1740240" }, + { "R 0x1740248" }, + { "R 0x1740288" }, + { "R 0x1740290" }, + { "R 0x1740300" }, + { "R 0x1740304" }, + { "R 0x1740308" }, + { "R 0x174030C" }, + { "R 0x1740310" }, + { "R 0x1740314" }, + { "R 0x1740004" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020" }, + { "R 0x1740024" }, + { "R 0x1740028" }, + { "R 0x174002C" }, + { "R 0x1740030" }, + { "R 0x1740034" }, + { "R 0x1740038" }, + { "R 0x174003C" }, + { "R 0x9698204" }, + { "R 0x9698240" }, + { "R 0x9698244" }, + { "R 0x9698248" }, + { "R 0x969824C" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x9681018" }, + { "R 0x968101C" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102C" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103C" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812C" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813C" }, + { "R 0x62BE2004" }, + { "R 0x62BE2040" }, + { "R 0x62BE2048" }, + { "R 0x62BE2088" }, + { "R 0x62BE2090" }, + { "R 0x62BE2100" }, + { "R 0x62BE2104" }, + { "R 0x62BE2108" }, + { "R 0x62BE210C" }, + { "R 0x62BE2110" }, + { "R 0x62BE2114" }, + { "R 0x62BE2118" }, + { "R 0x62BE0010" }, + { "R 0x62BE0020" }, + { "R 0x62BE0024" }, + { "R 0x62BE0028" }, + { "R 0x62BE002C" }, + { "R 0x62BE0030" }, + { "R 0x62BE0034" }, + { "R 0x62BE0038" }, + { "R 0x62BE003C" }, + { "R 0x9160204" }, + { "R 0x9160240" }, + { "R 0x9160248" }, + { "R 0x9160288" }, + { "R 0x9160290" }, + { "R 0x9160300" }, + { "R 0x9160304" }, + { "R 0x9160308" }, + { "R 0x916030C" }, + { "R 0x9160310" }, + { "R 0x9160314" }, + { "R 0x9160318" }, + { "R 0x9160008" }, + { "R 0x9160010" }, + { "R 0x9160020" }, + { "R 0x9160024" }, + { "R 0x9160028" }, + { "R 0x916002C" }, + { "R 0x9160030" }, + { "R 0x9160034" }, + { "R 0x9160038" }, + { "R 0x916003C" }, + { "R 0x1620500 4" }, + { "R 0x1620700 4" }, + { "R 0x1620300" }, + { "R 0x1620F00 2" }, + { "R 0x1620B00 2" }, + { "R 0x1700B00 2" }, + { "R 0x1700700 3" }, + { "R 0x9163100" }, + { "R 0x96AA100" }, + { "R 0x9050008" }, + { "R 0x9050068" }, + { "R 0x9050078" }, + { "R 0x18200400" }, + { "R 0x18200404" }, + { "R 0x18200408" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200D0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + { "R 0x1822000c" }, + { "R 0x18220d14" }, + { "R 0x18220fb4" }, + { "R 0x18221254" }, + { "R 0x182214f4" }, + { "R 0x18221794" }, + { "R 0x18221a34" }, + { "R 0x18221cd4" }, + { "R 0x18221f74" }, + { "R 0x18220d18" }, + { "R 0x18220fb8" }, + { "R 0x18221258" }, + { "R 0x182214f8" }, + { "R 0x18221798" }, + { "R 0x18221a38" }, + { "R 0x18221cd8" }, + { "R 0x18221f78" }, + { "R 0x18220d00" }, + { "R 0x18220d04" }, + { "R 0x18220d1c" }, + { "R 0x18220fbc" }, + { "R 0x1822125c" }, + { "R 0x182214fc" }, + { "R 0x1822179c" }, + { "R 0x18221a3c" }, + { "R 0x18221cdc" }, + { "R 0x18221f7c" }, + { "R 0x18221274" }, + { "R 0x18221288" }, + { "R 0x1822129c" }, + { "R 0x182212b0" }, + { "R 0x182212c4" }, + { "R 0x182212d8" }, + { "R 0x182212ec" }, + { "R 0x18221300" }, + { "R 0x18221314" }, + { "R 0x18221328" }, + { "R 0x1822133c" }, + { "R 0x18221350" }, + { "R 0x18221364" }, + { "R 0x18221378" }, + { "R 0x1822138c" }, + { "R 0x182213a0" }, + { "R 0x18221514" }, + { "R 0x18221528" }, + { "R 0x1822153c" }, + { "R 0x18221550" }, + { "R 0x18221564" }, + { "R 0x18221578" }, + { "R 0x1822158c" }, + { "R 0x182215a0" }, + { "R 0x182215b4" }, + { "R 0x182215c8" }, + { "R 0x182215dc" }, + { "R 0x182215f0" }, + { "R 0x18221604" }, + { "R 0x18221618" }, + { "R 0x1822162c" }, + { "R 0x18221640" }, + { "R 0x182217b4" }, + { "R 0x182217c8" }, + { "R 0x182217dc" }, + { "R 0x182217f0" }, + { "R 0x18221804" }, + { "R 0x18221818" }, + { "R 0x1822182c" }, + { "R 0x18221840" }, + { "R 0x18221854" }, + { "R 0x18221868" }, + { "R 0x1822187c" }, + { "R 0x18221890" }, + { "R 0x182218a4" }, + { "R 0x182218b8" }, + { "R 0x182218cc" }, + { "R 0x182218e0" }, + { "R 0x18221a54" }, + { "R 0x18221a68" }, + { "R 0x18221a7c" }, + { "R 0x18221a90" }, + { "R 0x18221aa4" }, + { "R 0x18221ab8" }, + { "R 0x18221acc" }, + { "R 0x18221ae0" }, + { "R 0x18221af4" }, + { "R 0x18221b08" }, + { "R 0x18221b1c" }, + { "R 0x18221b30" }, + { "R 0x18221b44" }, + { "R 0x18221b58" }, + { "R 0x18221b6c" }, + { "R 0x18221b80" }, + { "R 0x18221cf4" }, + { "R 0x18221d08" }, + { "R 0x18221d1c" }, + { "R 0x18221d30" }, + { "R 0x18221d44" }, + { "R 0x18221d58" }, + { "R 0x18221d6c" }, + { "R 0x18221d80" }, + { "R 0x18221d94" }, + { "R 0x18221da8" }, + { "R 0x18221dbc" }, + { "R 0x18221dd0" }, + { "R 0x18221de4" }, + { "R 0x18221df8" }, + { "R 0x18221e0c" }, + { "R 0x18221e20" }, + { "R 0x18221f94" }, + { "R 0x18221fa8" }, + { "R 0x18221fbc" }, + { "R 0x18221fd0" }, + { "R 0x18221fe4" }, + { "R 0x18221ff8" }, + { "R 0x1822200c" }, + { "R 0x18222020" }, + { "R 0x18222034" }, + { "R 0x18222048" }, + { "R 0x1822205c" }, + { "R 0x18222070" }, + { "R 0x18222084" }, + { "R 0x18222098" }, + { "R 0x182220ac" }, + { "R 0x182220c0" }, + { "R 0x18221278" }, + { "R 0x1822128c" }, + { "R 0x182212a0" }, + { "R 0x182212b4" }, + { "R 0x182212c8" }, + { "R 0x182212dc" }, + { "R 0x182212f0" }, + { "R 0x18221304" }, + { "R 0x18221318" }, + { "R 0x1822132c" }, + { "R 0x18221340" }, + { "R 0x18221354" }, + { "R 0x18221368" }, + { "R 0x1822137c" }, + { "R 0x18221390" }, + { "R 0x182213a4" }, + { "R 0x18221518" }, + { "R 0x1822152c" }, + { "R 0x18221540" }, + { "R 0x18221554" }, + { "R 0x18221568" }, + { "R 0x1822157c" }, + { "R 0x18221590" }, + { "R 0x182215a4" }, + { "R 0x182215b8" }, + { "R 0x182215cc" }, + { "R 0x182215e0" }, + { "R 0x182215f4" }, + { "R 0x18221608" }, + { "R 0x1822161c" }, + { "R 0x18221630" }, + { "R 0x18221644" }, + { "R 0x182217b8" }, + { "R 0x182217cc" }, + { "R 0x182217e0" }, + { "R 0x182217f4" }, + { "R 0x18221808" }, + { "R 0x1822181c" }, + { "R 0x18221830" }, + { "R 0x18221844" }, + { "R 0x18221858" }, + { "R 0x1822186c" }, + { "R 0x18221880" }, + { "R 0x18221894" }, + { "R 0x182218a8" }, + { "R 0x182218bc" }, + { "R 0x182218d0" }, + { "R 0x182218e4" }, + { "R 0x18221a58" }, + { "R 0x18221a6c" }, + { "R 0x18221a80" }, + { "R 0x18221a94" }, + { "R 0x18221aa8" }, + { "R 0x18221abc" }, + { "R 0x18221ad0" }, + { "R 0x18221ae4" }, + { "R 0x18221af8" }, + { "R 0x18221b0c" }, + { "R 0x18221b20" }, + { "R 0x18221b34" }, + { "R 0x18221b48" }, + { "R 0x18221b5c" }, + { "R 0x18221b70" }, + { "R 0x18221b84" }, + { "R 0x18221cf8" }, + { "R 0x18221d0c" }, + { "R 0x18221d20" }, + { "R 0x18221d34" }, + { "R 0x18221d48" }, + { "R 0x18221d5c" }, + { "R 0x18221d70" }, + { "R 0x18221d84" }, + { "R 0x18221d98" }, + { "R 0x18221dac" }, + { "R 0x18221dc0" }, + { "R 0x18221dd4" }, + { "R 0x18221de8" }, + { "R 0x18221dfc" }, + { "R 0x18221e10" }, + { "R 0x18221e24" }, + { "R 0x18221f98" }, + { "R 0x18221fac" }, + { "R 0x18221fc0" }, + { "R 0x18221fd4" }, + { "R 0x18221fe8" }, + { "R 0x18221ffc" }, + { "R 0x18222010" }, + { "R 0x18222024" }, + { "R 0x18222038" }, + { "R 0x1822204c" }, + { "R 0x18222060" }, + { "R 0x18222074" }, + { "R 0x18222088" }, + { "R 0x1822209c" }, + { "R 0x182220b0" }, + { "R 0x182220c4" }, + { "R 0x18000024" }, + { "R 0x18000040" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x180800F8" }, + { "R 0x18080104" }, + { "R 0x1808011C" }, + { "R 0x18080128" }, + { "R 0x90b0280" }, + { "R 0x90b0288" }, + { "R 0x90b028c" }, + { "R 0x90b0290" }, + { "R 0x90b0294" }, + { "R 0x90b0298" }, + { "R 0x90b029c" }, + { "R 0x90b02a0" }, + { "R 0x18321700" }, + { "R 0x18322C18" }, + { "R 0x18323700" }, + { "R 0x18324C18" }, + { "R 0x18325F00" }, + { "R 0x18327418" }, + { "R 0x9236028" }, + { "R 0x923602C" }, + { "R 0x9236030" }, + { "R 0x9236034" }, + { "R 0x9236038" }, + { "R 0x9232100" }, + { "R 0x92360b0" }, + { "R 0x9236044" }, + { "R 0x9236048" }, + { "R 0x923604c" }, + { "R 0x9236050" }, + { "R 0x923e030" }, + { "R 0x923e034" }, + { "R 0x9241000" }, + { "R 0x9248058" }, + { "R 0x924805c" }, + { "R 0x9248060" }, + { "R 0x9248064" }, + { "R 0x9260410" }, + { "R 0x92e0410" }, + { "R 0x9260414" }, + { "R 0x92e0414" }, + { "R 0x9260418" }, + { "R 0x92e0418" }, + { "R 0x9260420" }, + { "R 0x9260424" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92e0420" }, + { "R 0x92e0424" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x9600000" }, + { "R 0x9601000" }, + { "R 0x9602000" }, + { "R 0x9603000" }, + { "R 0x9604000" }, + { "R 0x9605000" }, + { "R 0x9606000" }, + { "R 0x9607000" }, + { "R 0x9608000" }, + { "R 0x9609000" }, + { "R 0x960a000" }, + { "R 0x960b000" }, + { "R 0x960c000" }, + { "R 0x960d000" }, + { "R 0x960e000" }, + { "R 0x960f000" }, + { "R 0x9610000" }, + { "R 0x9611000" }, + { "R 0x9612000" }, + { "R 0x9613000" }, + { "R 0x9614000" }, + { "R 0x9615000" }, + { "R 0x9616000" }, + { "R 0x9617000" }, + { "R 0x9618000" }, + { "R 0x9619000" }, + { "R 0x961a000" }, + { "R 0x961b000" }, + { "R 0x961c000" }, + { "R 0x961d000" }, + { "R 0x961e000" }, + { "R 0x961f000" }, + { "R 0x9600004" }, + { "R 0x9601004" }, + { "R 0x9602004" }, + { "R 0x9603004" }, + { "R 0x9604004" }, + { "R 0x9605004" }, + { "R 0x9606004" }, + { "R 0x9607004" }, + { "R 0x9608004" }, + { "R 0x9609004" }, + { "R 0x960a004" }, + { "R 0x960b004" }, + { "R 0x960c004" }, + { "R 0x960d004" }, + { "R 0x960e004" }, + { "R 0x960f004" }, + { "R 0x9610004" }, + { "R 0x9611004" }, + { "R 0x9612004" }, + { "R 0x9613004" }, + { "R 0x9614004" }, + { "R 0x9615004" }, + { "R 0x9616004" }, + { "R 0x9617004" }, + { "R 0x9618004" }, + { "R 0x9619004" }, + { "R 0x961a004" }, + { "R 0x961b004" }, + { "R 0x961c004" }, + { "R 0x961d004" }, + { "R 0x961e004" }, + { "R 0x961f004" }, + { "R 0x9266418" }, + { "R 0x92e6418" }, + { "R 0x9265804" }, + { "R 0x92e5804" }, + { "R 0x92604b8" }, + { "R 0x92e04b8" }, + { "R 0x0C201244 1" }, + { "R 0x0C202244 1" }, + { "R 0x18100C18 1" }, + { "R 0x18101C18 1" }, + { "R 0x18300000 1" }, + { "R 0x183A3A84 2" }, + { "R 0x18393A84 2" }, + { "R 0x00100000" }, + { "R 0x00100004" }, + { "R 0x00100008" }, + { "R 0x0010000C" }, + { "R 0x00100010" }, + { "R 0x00100014" }, + { "R 0x00100018" }, + { "R 0x0010001C" }, + { "R 0x00100020" }, + { "R 0x00100024" }, + { "R 0x00100028" }, + { "R 0x0010002C" }, + { "R 0x00100030" }, + { "R 0x00100034" }, + { "R 0x00100100" }, + { "R 0x00100104" }, + { "R 0x00100108" }, + { "R 0x0010010C" }, + { "R 0x00101000" }, + { "R 0x00101004" }, + { "R 0x00101008" }, + { "R 0x0010100C" }, + { "R 0x00101010" }, + { "R 0x00101014" }, + { "R 0x00101018" }, + { "R 0x0010101C" }, + { "R 0x00101020" }, + { "R 0x00101024" }, + { "R 0x00101028" }, + { "R 0x0010102C" }, + { "R 0x00101030" }, + { "R 0x00101034" }, + { "R 0x00102000" }, + { "R 0x00102004" }, + { "R 0x00102008" }, + { "R 0x0010200C" }, + { "R 0x00102010" }, + { "R 0x00102014" }, + { "R 0x00102018" }, + { "R 0x0010201C" }, + { "R 0x00102020" }, + { "R 0x00102024" }, + { "R 0x00102028" }, + { "R 0x0010202C" }, + { "R 0x00102030" }, + { "R 0x00102034" }, + { "R 0x00103000" }, + { "R 0x00103004" }, + { "R 0x00103008" }, + { "R 0x0010300C" }, + { "R 0x00103010" }, + { "R 0x00103014" }, + { "R 0x00103018" }, + { "R 0x0010301C" }, + { "R 0x00103020" }, + { "R 0x00103024" }, + { "R 0x00103028" }, + { "R 0x0010302C" }, + { "R 0x00103030" }, + { "R 0x00103034" }, + { "R 0x00113000" }, + { "R 0x00113004" }, + { "R 0x00113008" }, + { "R 0x0011300C" }, + { "R 0x00113010" }, + { "R 0x00113014" }, + { "R 0x00113018" }, + { "R 0x0011301C" }, + { "R 0x00113020" }, + { "R 0x00113024" }, + { "R 0x00113028" }, + { "R 0x0011302C" }, + { "R 0x00113030" }, + { "R 0x00113034" }, + { "R 0x0011A000" }, + { "R 0x0011A004" }, + { "R 0x0011A008" }, + { "R 0x0011A00C" }, + { "R 0x0011A010" }, + { "R 0x0011A014" }, + { "R 0x0011A018" }, + { "R 0x0011A01C" }, + { "R 0x0011A020" }, + { "R 0x0011A024" }, + { "R 0x0011A028" }, + { "R 0x0011A02C" }, + { "R 0x0011A030" }, + { "R 0x0011A034" }, + { "R 0x0011B000" }, + { "R 0x0011B004" }, + { "R 0x0011B008" }, + { "R 0x0011B00C" }, + { "R 0x0011B010" }, + { "R 0x0011B014" }, + { "R 0x0011B018" }, + { "R 0x0011B01C" }, + { "R 0x0011B020" }, + { "R 0x0011B024" }, + { "R 0x0011B028" }, + { "R 0x0011B02C" }, + { "R 0x0011B030" }, + { "R 0x0011B034" }, + { "R 0x00174000" }, + { "R 0x00174004" }, + { "R 0x00174008" }, + { "R 0x0017400C" }, + { "R 0x00174010" }, + { "R 0x00174014" }, + { "R 0x00174018" }, + { "R 0x0017401C" }, + { "R 0x00174020" }, + { "R 0x00174024" }, + { "R 0x00174028" }, + { "R 0x0017402C" }, + { "R 0x00174030" }, + { "R 0x00174034" }, + { "R 0x00176000" }, + { "R 0x00176004" }, + { "R 0x00176008" }, + { "R 0x0017600C" }, + { "R 0x00176010" }, + { "R 0x00176014" }, + { "R 0x00176018" }, + { "R 0x0017601C" }, + { "R 0x00176020" }, + { "R 0x00176024" }, + { "R 0x00176028" }, + { "R 0x0017602C" }, + { "R 0x00176030" }, + { "R 0x00176034" }, + { "R 0x0010401C" }, + { "R 0x00183024" }, + { "R 0x00144168" }, + { "R 0x0011702C" }, + { "R 0x0010904C" }, + { "R 0x00189038" }, + { "R 0x001443E8" }, + { "R 0x001442B8" }, + { "R 0x00105060" }, + { "R 0x00141024" }, + { "R 0x00145038" }, + { "R 0x00109004" }, + { "R 0x00189004" }, + { "R 0x00190004" }, + { "R 0x0C2A0000" }, + { "R 0x0C2A0004" }, + { "R 0x0C2A0008" }, + { "R 0x0C2A000C" }, + { "R 0x0C2A0010" }, + { "R 0x0C2A0014" }, + { "R 0x0C2A0018" }, + { "R 0x0C2A001C" }, + { "R 0x0C2A0020" }, + { "R 0x0C2A0024" }, + { "R 0x0C2A0028" }, + { "R 0x0C2A002C" }, + { "R 0x0C2A0030" }, + { "R 0x0C2A0034" }, + { "R 0x0C2A1000" }, + { "R 0x0C2A1004" }, + { "R 0x0C2A1008" }, + { "R 0x0C2A100C" }, + { "R 0x0C2A1010" }, + { "R 0x0C2A1014" }, + { "R 0x0C2A1018" }, + { "R 0x0C2A101C" }, + { "R 0x0C2A1020" }, + { "R 0x0C2A1024" }, + { "R 0x0C2A1028" }, + { "R 0x0C2A102C" }, + { "R 0x0C2A1030" }, + { "R 0x0C2A2260" }, + { "R 0x0C2A2264" }, + { "R 0x0C2A3008" }, + { "R 0x0C2A300C" }, + { "R 0x0C2A3010" }, + { "R 0x0C2A3014" }, + { "R 0x0C2A3024" }, + { "R 0x0C2A2034" }, + { "R 0x0C2A214C" }, + { "R 0x0C2A2150" }, + { "R 0x0C2A2154" }, + { "R 0x0C2630A0 4" }, + { "R 0x0C2630B0 4" }, + { "R 0x0C2630C0 4" }, + { "R 0x0C2630D0 4" }, + { "R 0x1800005C 1" }, + { "R 0x1801005C 1" }, + { "R 0x1802005C 1" }, + { "R 0x1803005C 1" }, + { "R 0x1804005C 1" }, + { "R 0x1805005C 1" }, + { "R 0x1806005C 1" }, + { "R 0x1807005C 1" }, + { "R 0x3d96000" }, + { "R 0x3d96004" }, +}; + +static const struct dcc_link_config talos_link_configs[] = { + { + .link_list = 3, + .entries = talos_dcc_entries, + .num_entries = ARRAY_SIZE(talos_dcc_entries), + }, +}; + +static const struct dcc_config talos_config = { + .lists = talos_link_configs, + .num_lists = ARRAY_SIZE(talos_link_configs), +}; + +static const struct dcc_pdata talos_pdata = { + .base = 0x010a2000, + .size = 0x00001000, + .ram_base = 0x010ae000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x1, + .config = &talos_config, +}; + +#endif /* _QCOM_DCC_TALOS_CONFIG_H */ diff --git a/drivers/misc/qcom-dcc.c b/drivers/misc/qcom-dcc.c new file mode 100644 index 0000000000000..d38c5f4a680b6 --- /dev/null +++ b/drivers/misc/qcom-dcc.c @@ -0,0 +1,1614 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* + * DCC(Data Capture and Compare) is a DMA engine designed for debugging + * purposes. + * In case of a system crash or manual software triggers by the user the + * DCC hardware stores the value at the register addresses which can be + * used for debugging purposes. + * The DCC driver provides the user with debugfs interface to configure the + * register addresses. The options that the DCC hardware provides include + * reading from registers, writing to registers, first reading and then + * writing to registers and looping through the values of the same + * register. + * + * In certain cases a register write needs to be executed for accessing the + * rest of the registers, also the user might want to record the changing + * values of a register with time for which he has the option to use the + * loop feature. + * + * The options mentioned above are exposed to the user by debugfs files + * once the driver is probed. The details and usage of this debugfs files + * are documented in Documentation/ABI/testing/debugfs-driver-dcc. + * + * As an example let us consider a couple of debug scenarios where DCC has + * been proved to be effective for debugging purposes:- + * + * i)TimeStamp Related Issue + * + * On SC7180, there was a coresight timestamp issue where it would + * occasionally be all 0 instead of proper timestamp values. + * + * Proper timestamp: + * Idx:3373; ID:10; I_TIMESTAMP : Timestamp.; Updated val = + * 0x13004d8f5b7aa; CC=0x9e + * + * Zero timestamp: + * Idx:3387; ID:10; I_TIMESTAMP : Timestamp.; Updated val = 0x0; CC=0xa2 + * + * Now this is a non-fatal issue and doesn't need a system reset, but still + * needs to be rootcaused and fixed for those who do care about coresight + * etm traces. + * Since this is a timestamp issue, we would be looking for any timestamp + * related clocks and such. + * + * We get all the clk register details from IP documentation and configure + * it via DCC config debugfs node. Before that we set the current + * linked list. + * + * Program the linked list with the addresses + * echo R 0x10c004 > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c008 > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c00c > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c010 > /sys/kernel/debug/qcom-dcc/../3/config + * ..... and so on for other timestamp related clk registers + * + * Other way of specifying is in "addr len" pair, in below case it + * specifies to capture 4 words starting 0x10C004 + * + * echo R 0x10C004 4 > /sys/kernel/debug/qcom-dcc/../3/config + * + * Configuration can be saved to a file and reuse it later. + * cat /sys/kernel/debug/qcom-dcc/../3/config > config_3 + * Post reboot, write the file to config. + * echo config_3 > /sys/kernel/debug/qcom-dcc/../3/config + * + * Enable DCC + * echo 1 > /sys/kernel/debug/qcom-dcc/../3/enable + * + * Run the timestamp test for working case + * + * Send SW trigger + * echo 1 > /sys/kernel/debug/qcom-dcc/../trigger + * + * Read SRAM + * cat /dev/dcc_sram > dcc_sram1.bin + * + * Run the timestamp test for non-working case + * + * Send SW trigger + * echo 1 > /sys/kernel/debug/qcom-dcc/../trigger + * + * Read SRAM + * cat /dev/dcc_sram > dcc_sram2.bin + * + * Get the parser from + * https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/tools/-/tree/opensource-tools.lnx.1.0.r176-rel/dcc_parser + * + * Parse the SRAM bin + * python dcc_parser.py -s dcc_sram1.bin --v2 -o output/ python + * dcc_parser.py -s dcc_sram2.bin --v2 -o output/ + * + * Sample parsed output of dcc_sram1.bin: + * + * + * 03/14/21 + * Linux DCC Parser + * + * + * + * + * + * + * next_ll_offset : 0x1c + * + * ii)NOC register errors + * + * A particular class of registers called NOC which are functional + * registers was reporting errors while logging the values.To trace these + * errors the DCC has been used effectively. + * The steps followed were similar to the ones mentioned above. + * In addition to NOC registers a few other dependent registers were + * configured in DCC to monitor it's values during a crash. A look at the + * dependent register values revealed that the crash was happening due to a + * secured access to one of these dependent registers. + * All these debugging activity and finding the root cause was achieved + * using DCC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qcom-dcc.h" + +#define STATUS_READY_TIMEOUT 5000 /* microseconds */ + +/* DCC registers */ +#define DCC_HW_INFO 0x04 +#define DCC_LL_NUM_INFO 0x10 +#define DCC_LL_LOCK 0x00 +#define DCC_LL_CFG 0x04 +#define DCC_LL_BASE 0x08 +#define DCC_FD_BASE 0x0c +#define DCC_LL_OFFSET 0x80 +#define DCC_LL_TIMEOUT 0x10 +#define DCC_LL_INT_ENABLE 0x18 +#define DCC_LL_INT_STATUS 0x1c +#define DCC_LL_SW_TRIGGER 0x2c +#define DCC_LL_BUS_ACCESS_STATUS 0x30 + +/* Default value used if a bit 6 in the HW_INFO register is set. */ +#define DCC_FIX_LOOP_OFFSET 16 + +/* Mask to find version info from HW_Info register */ +#define DCC_VER_INFO_MASK BIT(9) + +#define MAX_DCC_OFFSET GENMASK(9, 2) +#define MAX_DCC_LEN GENMASK(6, 0) +#define MAX_LOOP_CNT GENMASK(7, 0) +#define MAX_LOOP_ADDR 10 + +#define DCC_ADDR_DESCRIPTOR 0x00 +#define DCC_ADDR_LIMIT 27 +#define DCC_WORD_SIZE sizeof(u32) +#define DCC_ADDR_RANGE_MASK GENMASK(31, 4) +#define DCC_LOOP_DESCRIPTOR BIT(30) +#define DCC_RD_MOD_WR_DESCRIPTOR BIT(31) +#define DCC_LINK_DESCRIPTOR GENMASK(31, 30) +#define DCC_STATUS_MASK GENMASK(1, 0) +#define DCC_LOCK_MASK BIT(0) +#define DCC_LOOP_OFFSET_MASK BIT(6) +#define DCC_TRIGGER_MASK BIT(9) + +#define DCC_WRITE_MASK BIT(15) +#define DCC_WRITE_OFF_MASK GENMASK(7, 0) +#define DCC_WRITE_LEN_MASK GENMASK(14, 8) + +#define DCC_READ_IND 0x00 +#define DCC_WRITE_IND (BIT(28)) + +#define DCC_AHB_IND 0x00 +#define DCC_APB_IND BIT(29) + +#define DCC_MAX_LINK_LIST 8 + +#define DCC_VER_MASK2 GENMASK(5, 0) + +#define DCC_SRAM_WORD_LENGTH 4 + +#define DCC_RD_MOD_WR_ADDR 0xC105E + +#define MEM_MAP_VER1 0x1 +#define MEM_MAP_VER2 0x2 +#define MEM_MAP_VER3 0x3 + +#define LINE_BUFFER_MAX_SZ 50 +enum dcc_descriptor_type { + DCC_READ_TYPE, + DCC_LOOP_TYPE, + DCC_READ_WRITE_TYPE, + DCC_WRITE_TYPE +}; + +/** + * struct dcc_config_entry - configuration information related to each dcc instruction + * @base: Base address of the register to be configured in dcc + * @offset: Offset to the base address to be configured in dcc + * @len: Length of the address in words of 4 bytes to be configured in dcc + * @loop_cnt: The number of times to loop on the register address in case + of loop instructions + * @write_val: The value to be written on the register address in case of + write instructions + * @mask: Mask corresponding to the value to be written in case of + write instructions + * @apb_bus: Type of bus to be used for the instruction, can be either + 'apb' if 1 or 'ahb' if 0 + * @desc_type: Stores the type of dcc instruction + * @list: This is used to append this instruction to the list of + instructions + */ +struct dcc_config_entry { + u32 base; + u32 offset; + u32 len; + u32 loop_cnt; + u32 write_val; + u32 mask; + bool apb_bus; + enum dcc_descriptor_type desc_type; + struct list_head list; +}; + +/** + * struct dcc_drvdata - configuration information related to a dcc device + * @base: Base Address of the dcc device + * @dev: The device attached to the driver data + * @mutex: Lock to protect access and manipulation of dcc_drvdata + * @ram_base: Base address for the SRAM dedicated for the dcc device + * @ram_size: Total size of the SRAM dedicated for the dcc device + * @ram_offset: Offset to the SRAM dedicated for dcc device + * @ram_cfg: Used for address limit calculation for dcc + * @ram_start: Starting address of DCC SRAM + * @mem_map_ver: Memory map version of DCC hardware + * @sram_dev: Miscellaneous device equivalent of dcc SRAM + * @cfg_head: Points to the head of the linked list of addresses + * @dbg_dir: The dcc debugfs directory under which all the debugfs files are placed + * @max_link_list: Total number of linkedlists supported by the DCC configuration + * @loop_shift: Loop offset bits range for the addresses + * @enable_bitmap: Bitmap to capture the enabled status of each linked list of addresses + */ +struct dcc_drvdata { + void __iomem *base; + void __iomem *ram_base; + struct device *dev; + /* Lock to protect access and manipulation of dcc_drvdata */ + struct mutex mutex; + size_t ram_size; + u32 ram_offset; + unsigned int ram_cfg; + unsigned int ram_start; + u64 mem_map_ver; + struct miscdevice sram_dev; + struct list_head *cfg_head; + struct dentry *dbg_dir; + size_t max_link_list; + u8 loop_shift; + unsigned long *enable_bitmap; + char **temp_buff_ptr; +}; + +struct dcc_cfg_attr { + u32 addr; + u32 prev_addr; + u32 prev_off; + u32 link; + u32 sram_offset; +}; + +struct dcc_cfg_loop_attr { + u32 loop_cnt; + u32 loop_len; + u32 loop_off; + bool loop_start; +}; + +static inline u32 dcc_status(int version) +{ + return version == 1 ? 0x0c : 0x1c; +} + +static inline u32 dcc_list_offset(int version) +{ + if (version == 1) + return 0x1c; + else if (version == 2) + return 0x2c; + else + return 0x34; +} + +static inline void dcc_list_writel(struct dcc_drvdata *drvdata, + u32 val, u32 ll, u32 off) +{ + u32 offset = dcc_list_offset(drvdata->mem_map_ver) + off; + + writel(val, drvdata->base + ll * DCC_LL_OFFSET + offset); +} + +static inline u32 dcc_list_readl(struct dcc_drvdata *drvdata, u32 ll, u32 off) +{ + u32 offset = dcc_list_offset(drvdata->mem_map_ver) + off; + + return readl(drvdata->base + ll * DCC_LL_OFFSET + offset); +} + +static void dcc_sram_write_auto(struct dcc_drvdata *drvdata, + u32 val, u32 *off) +{ + /* If the overflow condition is met increment the offset + * and return to indicate that overflow has occurred + */ + if (*off > drvdata->ram_size - 4) { + *off += 4; + return; + } + + writel(val, drvdata->ram_base + *off); + + *off += 4; +} + +static int dcc_sw_trigger(struct dcc_drvdata *drvdata) +{ + void __iomem *addr; + int i; + u32 status; + u32 ll_cfg; + u32 tmp_ll_cfg; + u32 val; + int ret = 0; + + mutex_lock(&drvdata->mutex); + + for (i = 0; i < drvdata->max_link_list; i++) { + if (!test_bit(i, drvdata->enable_bitmap)) + continue; + ll_cfg = dcc_list_readl(drvdata, i, DCC_LL_CFG); + if (drvdata->mem_map_ver == MEM_MAP_VER3) + tmp_ll_cfg = ll_cfg & ~BIT(8); + else + tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK; + + dcc_list_writel(drvdata, tmp_ll_cfg, i, DCC_LL_CFG); + dcc_list_writel(drvdata, 1, i, DCC_LL_SW_TRIGGER); + dcc_list_writel(drvdata, ll_cfg, i, DCC_LL_CFG); + } + + addr = drvdata->base + dcc_status(drvdata->mem_map_ver); + if (readl_poll_timeout(addr, val, !FIELD_GET(DCC_STATUS_MASK, val), + 1, STATUS_READY_TIMEOUT)) { + dev_err(drvdata->dev, "DCC is busy after receiving sw trigger\n"); + ret = -EBUSY; + goto out_unlock; + } + + for (i = 0; i < drvdata->max_link_list; i++) { + if (!test_bit(i, drvdata->enable_bitmap)) + continue; + + status = dcc_list_readl(drvdata, i, DCC_LL_BUS_ACCESS_STATUS); + if (!status) + continue; + + dev_err(drvdata->dev, "Read access error for list %d err: 0x%x\n", + i, status); + ll_cfg = dcc_list_readl(drvdata, i, DCC_LL_CFG); + if (drvdata->mem_map_ver == MEM_MAP_VER3) + tmp_ll_cfg = ll_cfg & ~BIT(8); + else + tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK; + + dcc_list_writel(drvdata, tmp_ll_cfg, i, DCC_LL_CFG); + dcc_list_writel(drvdata, DCC_STATUS_MASK, i, DCC_LL_BUS_ACCESS_STATUS); + dcc_list_writel(drvdata, ll_cfg, i, DCC_LL_CFG); + ret = -ENODATA; + break; + } + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static void dcc_ll_cfg_reset_link(struct dcc_cfg_attr *cfg) +{ + cfg->addr = 0x00; + cfg->link = 0; + cfg->prev_off = 0; + cfg->prev_addr = cfg->addr; +} + +static void dcc_emit_read_write(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg) +{ + if (cfg->link) { + /* + * write new offset = 1 to continue + * processing the list + */ + + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + /* Reset link and prev_off */ + dcc_ll_cfg_reset_link(cfg); + } + + cfg->addr = DCC_RD_MOD_WR_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->mask, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->write_val, &cfg->sram_offset); + + cfg->addr = 0; +} + +static void dcc_emit_loop(struct dcc_drvdata *drvdata, struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg, + struct dcc_cfg_loop_attr *cfg_loop, + u32 *total_len) +{ + int loop; + + /* Check if we need to write link of prev entry */ + if (cfg->link) + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + if (cfg_loop->loop_start) { + loop = (cfg->sram_offset - cfg_loop->loop_off) / 4; + loop |= (cfg_loop->loop_cnt << drvdata->loop_shift) & + GENMASK(DCC_ADDR_LIMIT, drvdata->loop_shift); + loop |= DCC_LOOP_DESCRIPTOR; + *total_len += (*total_len - cfg_loop->loop_len) * cfg_loop->loop_cnt; + + dcc_sram_write_auto(drvdata, loop, &cfg->sram_offset); + + cfg_loop->loop_start = false; + cfg_loop->loop_len = 0; + cfg_loop->loop_off = 0; + } else { + cfg_loop->loop_start = true; + cfg_loop->loop_cnt = entry->loop_cnt - 1; + cfg_loop->loop_len = *total_len; + cfg_loop->loop_off = cfg->sram_offset; + } + + /* Reset link and prev_off */ + dcc_ll_cfg_reset_link(cfg); +} + +static void dcc_emit_write(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg) +{ + u32 off; + + if (cfg->link) { + /* + * write new offset = 1 to continue + * processing the list + */ + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + /* Reset link and prev_off */ + cfg->addr = 0x00; + cfg->prev_off = 0; + cfg->prev_addr = cfg->addr; + } + + off = entry->offset / 4; + /* write new offset-length pair to correct position */ + cfg->link |= ((off & DCC_WRITE_OFF_MASK) | DCC_WRITE_MASK | + FIELD_PREP(DCC_WRITE_LEN_MASK, entry->len)); + cfg->link |= DCC_LINK_DESCRIPTOR; + + /* Address type */ + cfg->addr = (entry->base >> 4) & GENMASK(DCC_ADDR_LIMIT, 0); + if (entry->apb_bus) + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND | DCC_APB_IND; + else + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND | DCC_AHB_IND; + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->write_val, &cfg->sram_offset); + + cfg->addr = 0x00; + cfg->link = 0; +} + +static int dcc_emit_read(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg, + u32 *pos, u32 *total_len) +{ + u32 off; + u32 temp_off; + + cfg->addr = (entry->base >> 4) & GENMASK(27, 0); + + if (entry->apb_bus) + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND | DCC_APB_IND; + else + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND | DCC_AHB_IND; + + off = entry->offset / 4; + + *total_len += entry->len * 4; + + if (!cfg->prev_addr || cfg->prev_addr != cfg->addr || cfg->prev_off > off) { + /* Check if we need to write prev link entry */ + if (cfg->link) + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + dev_dbg(drvdata->dev, "DCC: sram address 0x%x\n", cfg->sram_offset); + + /* Write address */ + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + /* Reset link and prev_off */ + cfg->link = 0; + cfg->prev_off = 0; + } + + if ((off - cfg->prev_off) > 0xff || entry->len > MAX_DCC_LEN) { + dev_err(drvdata->dev, "DCC: Programming error Base: 0x%x, offset 0x%x\n", + entry->base, entry->offset); + return -EINVAL; + } + + if (cfg->link) { + /* + * link already has one offset-length so new + * offset-length needs to be placed at + * bits [29:15] + */ + *pos = 15; + + /* Clear bits [31:16] */ + cfg->link &= GENMASK(14, 0); + } else { + /* + * link is empty, so new offset-length needs + * to be placed at bits [15:0] + */ + *pos = 0; + cfg->link = 1 << 15; + } + + /* write new offset-length pair to correct position */ + temp_off = (off - cfg->prev_off) & GENMASK(7, 0); + cfg->link |= (temp_off | ((entry->len << 8) & GENMASK(14, 8))) << *pos; + + cfg->link |= DCC_LINK_DESCRIPTOR; + + if (*pos) { + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + cfg->link = 0; + } + + cfg->prev_off = off + entry->len - 1; + cfg->prev_addr = cfg->addr; + return 0; +} + +static int dcc_emit_config(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + int ret; + u32 total_len, pos; + struct dcc_config_entry *entry; + struct dcc_cfg_attr cfg = {0}; + struct dcc_cfg_loop_attr cfg_loop = {0}; + + cfg.sram_offset = drvdata->ram_cfg * 4; + total_len = 0; + + list_for_each_entry(entry, &drvdata->cfg_head[curr_list], list) { + switch (entry->desc_type) { + case DCC_READ_WRITE_TYPE: + dcc_emit_read_write(drvdata, entry, &cfg); + break; + + case DCC_LOOP_TYPE: + dcc_emit_loop(drvdata, entry, &cfg, &cfg_loop, &total_len); + break; + + case DCC_WRITE_TYPE: + dcc_emit_write(drvdata, entry, &cfg); + break; + + case DCC_READ_TYPE: + ret = dcc_emit_read(drvdata, entry, &cfg, &pos, &total_len); + if (ret) + goto err; + break; + } + } + + if (cfg.link) + dcc_sram_write_auto(drvdata, cfg.link, &cfg.sram_offset); + + if (cfg_loop.loop_start) { + dev_err(drvdata->dev, "DCC: Programming error: Loop unterminated\n"); + ret = -EINVAL; + goto err; + } + + /* Handling special case of list ending with a rd_mod_wr */ + if (cfg.addr == DCC_RD_MOD_WR_DESCRIPTOR) { + cfg.addr = (DCC_RD_MOD_WR_ADDR) & GENMASK(27, 0); + cfg.addr |= DCC_ADDR_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg.addr, &cfg.sram_offset); + } + + /* Setting zero to indicate end of the list */ + cfg.link = DCC_LINK_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg.link, &cfg.sram_offset); + + /* Check if sram offset exceeds the ram size */ + if (cfg.sram_offset > drvdata->ram_size) + goto overstep; + + /* Update ram_cfg and check if the data will overstep */ + drvdata->ram_cfg = (cfg.sram_offset + total_len) / 4; + + if (cfg.sram_offset + total_len > drvdata->ram_size) { + cfg.sram_offset += total_len; + goto overstep; + } + + drvdata->ram_start = cfg.sram_offset / 4; + return 0; +overstep: + ret = -EINVAL; + memset_io(drvdata->ram_base, 0, drvdata->ram_size); + +err: + return ret; +} + +static bool dcc_valid_list(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + u32 lock_reg; + + if (list_empty(&drvdata->cfg_head[curr_list])) + return false; + + if (test_bit(curr_list, drvdata->enable_bitmap)) { + dev_err(drvdata->dev, "List %d is already enabled\n", curr_list); + return false; + } + + lock_reg = dcc_list_readl(drvdata, curr_list, DCC_LL_LOCK); + if (lock_reg & DCC_LOCK_MASK) { + dev_err(drvdata->dev, "List %d is already locked\n", curr_list); + return false; + } + + return true; +} + +static bool is_dcc_enabled(struct dcc_drvdata *drvdata) +{ + int list; + + for (list = 0; list < drvdata->max_link_list; list++) + if (test_bit(list, drvdata->enable_bitmap)) + return true; + + return false; +} + +static int dcc_enable(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + int ret; + u32 ram_cfg_base; + + mutex_lock(&drvdata->mutex); + + if (!dcc_valid_list(drvdata, curr_list)) { + ret = -EINVAL; + goto out_unlock; + } + + /* Fill dcc sram with the poison value. + * This helps in understanding bus + * hang from registers returning a zero + */ + if (!is_dcc_enabled(drvdata)) + memset_io(drvdata->ram_base, 0xde, drvdata->ram_size); + + /* 1. Take ownership of the list */ + dcc_list_writel(drvdata, DCC_LOCK_MASK, curr_list, DCC_LL_LOCK); + + /* 2. Program linked-list in the SRAM */ + ram_cfg_base = drvdata->ram_cfg; + ret = dcc_emit_config(drvdata, curr_list); + if (ret) { + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_LOCK); + goto out_unlock; + } + + /* 3. Program DCC_RAM_CFG reg */ + dcc_list_writel(drvdata, ram_cfg_base + + drvdata->ram_offset / 4, curr_list, DCC_LL_BASE); + dcc_list_writel(drvdata, drvdata->ram_start + + drvdata->ram_offset / 4, curr_list, DCC_FD_BASE); + dcc_list_writel(drvdata, 0xFFF, curr_list, DCC_LL_TIMEOUT); + + /* 4. Clears interrupt status register */ + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_INT_ENABLE); + dcc_list_writel(drvdata, (BIT(0) | BIT(1) | BIT(2)), + curr_list, DCC_LL_INT_STATUS); + + set_bit(curr_list, drvdata->enable_bitmap); + + /* 5. Configure trigger */ + if (drvdata->mem_map_ver == MEM_MAP_VER3) + dcc_list_writel(drvdata, BIT(8), + curr_list, DCC_LL_CFG); + else + dcc_list_writel(drvdata, DCC_TRIGGER_MASK, + curr_list, DCC_LL_CFG); + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static void dcc_disable(struct dcc_drvdata *drvdata, int curr_list) +{ + mutex_lock(&drvdata->mutex); + + if (!test_bit(curr_list, drvdata->enable_bitmap)) + goto out_unlock; + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_CFG); + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_BASE); + dcc_list_writel(drvdata, 0, curr_list, DCC_FD_BASE); + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_LOCK); + clear_bit(curr_list, drvdata->enable_bitmap); +out_unlock: + mutex_unlock(&drvdata->mutex); +} + +static u32 dcc_filp_curr_list(const struct file *filp) +{ + struct dentry *dentry = file_dentry(filp); + int curr_list, ret; + + ret = kstrtoint(dentry->d_parent->d_name.name, 0, &curr_list); + if (ret) + return ret; + + return curr_list; +} + +static ssize_t enable_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char *buf; + int curr_list = dcc_filp_curr_list(filp); + struct dcc_drvdata *drvdata = filp->private_data; + + if (curr_list < 0) + return curr_list; + + mutex_lock(&drvdata->mutex); + if (test_bit(curr_list, drvdata->enable_bitmap)) + buf = "Y\n"; + else + buf = "N\n"; + mutex_unlock(&drvdata->mutex); + + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); +} + +static ssize_t enable_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + int ret = 0, curr_list; + bool val; + struct dcc_drvdata *drvdata = filp->private_data; + + curr_list = dcc_filp_curr_list(filp); + if (curr_list < 0) + return curr_list; + + ret = kstrtobool_from_user(userbuf, count, &val); + if (ret < 0) + return ret; + + if (val) { + ret = dcc_enable(drvdata, curr_list); + if (ret) + return ret; + } else { + dcc_disable(drvdata, curr_list); + } + + return count; +} + +static const struct file_operations enable_fops = { + .read = enable_read, + .write = enable_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t trigger_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + int ret; + unsigned int val; + struct dcc_drvdata *drvdata = filp->private_data; + + ret = kstrtouint_from_user(user_buf, count, 0, &val); + if (ret < 0) + return ret; + + if (val != 1) + return -EINVAL; + + ret = dcc_sw_trigger(drvdata); + if (ret < 0) + return ret; + + return count; +} + +static const struct file_operations trigger_fops = { + .write = trigger_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static int dcc_config_add(struct dcc_drvdata *drvdata, unsigned int addr, + unsigned int len, bool apb_bus, int curr_list) +{ + int ret = 0; + struct dcc_config_entry *entry, *pentry; + unsigned int base, offset; + + mutex_lock(&drvdata->mutex); + + if (!len || len > drvdata->ram_size / DCC_WORD_SIZE) { + dev_err(drvdata->dev, "DCC: Invalid length\n"); + ret = -EINVAL; + goto out_unlock; + } + + base = addr & DCC_ADDR_RANGE_MASK; + + if (!list_empty(&drvdata->cfg_head[curr_list])) { + pentry = list_last_entry(&drvdata->cfg_head[curr_list], + struct dcc_config_entry, list); + + if (pentry->desc_type == DCC_READ_TYPE && + addr >= (pentry->base + pentry->offset) && + addr <= (pentry->base + pentry->offset + MAX_DCC_OFFSET)) { + /* Re-use base address from last entry */ + base = pentry->base; + + if ((pentry->len * 4 + pentry->base + pentry->offset) + == addr) { + len += pentry->len; + + if (len > MAX_DCC_LEN) + pentry->len = MAX_DCC_LEN; + else + pentry->len = len; + + addr = pentry->base + pentry->offset + + pentry->len * 4; + len -= pentry->len; + } + } + } + + offset = addr - base; + + while (len) { + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto out_unlock; + } + + entry->base = base; + entry->offset = offset; + entry->len = min_t(u32, len, MAX_DCC_LEN); + entry->desc_type = DCC_READ_TYPE; + entry->apb_bus = apb_bus; + INIT_LIST_HEAD(&entry->list); + list_add_tail(&entry->list, + &drvdata->cfg_head[curr_list]); + + len -= entry->len; + offset += MAX_DCC_LEN * 4; + } + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static ssize_t dcc_config_add_read(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + bool bus; + int len, nval; + unsigned int base; + char apb_bus[4]; + + nval = sscanf(buf, "%x %i %3s", &base, &len, apb_bus); + if (nval <= 0 || nval > 3) + return -EINVAL; + + if (nval == 1) { + len = 1; + bus = false; + } else if (nval == 2) { + bus = false; + } else if (!strcmp("apb", apb_bus)) { + bus = true; + } else if (!strcmp("ahb", apb_bus)) { + bus = false; + } else { + return -EINVAL; + } + + return dcc_config_add(drvdata, base, len, bus, curr_list); +} + +static void dcc_config_reset(struct dcc_drvdata *drvdata) +{ + struct dcc_config_entry *entry, *temp; + int curr_list; + + mutex_lock(&drvdata->mutex); + + for (curr_list = 0; curr_list < drvdata->max_link_list; curr_list++) { + list_for_each_entry_safe(entry, temp, + &drvdata->cfg_head[curr_list], list) { + list_del(&entry->list); + } + } + drvdata->ram_start = 0; + drvdata->ram_cfg = 0; + mutex_unlock(&drvdata->mutex); +} + +static ssize_t config_reset_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + unsigned int val; + int ret; + struct dcc_drvdata *drvdata = filp->private_data; + + ret = kstrtouint_from_user(user_buf, count, 0, &val); + if (ret < 0) + return ret; + + if (val) + dcc_config_reset(drvdata); + + return count; +} + +static const struct file_operations config_reset_fops = { + .write = config_reset_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t ready_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char *buf; + struct dcc_drvdata *drvdata = filp->private_data; + + if (!is_dcc_enabled(drvdata)) + return -EINVAL; + + if (!FIELD_GET(BIT(1), readl(drvdata->base + dcc_status(drvdata->mem_map_ver)))) + buf = "Y\n"; + else + buf = "N\n"; + + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf) + 1); +} + +static const struct file_operations ready_fops = { + .read = ready_read, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t loop_offset_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char buf[4]; + struct dcc_drvdata *drvdata = filp->private_data; + + snprintf(buf, sizeof(buf), "%d", drvdata->loop_shift); + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf) + 1); +} + +static const struct file_operations loop_offset_fops = { + .read = loop_offset_read, + .open = simple_open, + .llseek = generic_file_llseek, +}; +static int dcc_add_loop(struct dcc_drvdata *drvdata, unsigned long loop_cnt, int curr_list) +{ + struct dcc_config_entry *entry; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->loop_cnt = min_t(u32, loop_cnt, MAX_LOOP_CNT); + entry->desc_type = DCC_LOOP_TYPE; + INIT_LIST_HEAD(&entry->list); + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); + + return 0; +} + +static ssize_t dcc_config_add_loop(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + int ret, i = 0; + char *token, *input; + char delim[2] = " "; + unsigned int val[MAX_LOOP_ADDR]; + + input = buf; + + while ((token = strsep(&input, delim)) && i < MAX_LOOP_ADDR) { + ret = kstrtouint(token, 0, &val[i++]); + if (ret) + return ret; + } + + if (token) { + dev_err(drvdata->dev, "Max limit %u of loop address exceeded\n", + MAX_LOOP_ADDR); + return -EINVAL; + } + + if (val[1] < 1 || val[1] > 8 || val[1] > (i - 2)) + return -EINVAL; + + ret = dcc_add_loop(drvdata, val[0], curr_list); + if (ret) + return ret; + + for (i = 0; i < val[1]; i++) + dcc_config_add(drvdata, val[i + 2], 1, false, curr_list); + + return dcc_add_loop(drvdata, 1, curr_list); +} + +static int dcc_rd_mod_wr_add(struct dcc_drvdata *drvdata, unsigned int mask, + unsigned int val, int curr_list) +{ + int ret = 0; + struct dcc_config_entry *entry; + + mutex_lock(&drvdata->mutex); + + if (list_empty(&drvdata->cfg_head[curr_list])) { + dev_err(drvdata->dev, "DCC: No read address programmed\n"); + ret = -EPERM; + goto out_unlock; + } + + entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto out_unlock; + } + + entry->desc_type = DCC_READ_WRITE_TYPE; + entry->mask = mask; + entry->write_val = val; + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static ssize_t dcc_config_add_read_write(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + int ret; + int nval; + unsigned int addr, mask, val; + + nval = sscanf(buf, "%x %x %x", &addr, &mask, &val); + + if (nval <= 1 || nval > 3) + return -EINVAL; + + ret = dcc_config_add(drvdata, addr, 1, false, curr_list); + if (ret) + return ret; + + return dcc_rd_mod_wr_add(drvdata, mask, val, curr_list); +} + +static int dcc_add_write(struct dcc_drvdata *drvdata, unsigned int addr, + unsigned int write_val, int apb_bus, int curr_list) +{ + struct dcc_config_entry *entry; + + entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->desc_type = DCC_WRITE_TYPE; + entry->base = addr & GENMASK(31, 4); + entry->offset = addr - entry->base; + entry->write_val = write_val; + entry->len = 1; + entry->apb_bus = apb_bus; + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); + + return 0; +} + +static ssize_t dcc_config_add_write(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + bool bus; + int nval; + unsigned int addr, write_val; + char apb_bus[4]; + + nval = sscanf(buf, "%x %x %3s", &addr, &write_val, apb_bus); + + if (nval <= 1 || nval > 3) + return -EINVAL; + + if (nval == 2) + bus = false; + + if (nval == 3) { + if (!strcmp("apb", apb_bus)) + bus = true; + else if (!strcmp("ahb", apb_bus)) + bus = false; + else + return -EINVAL; + } + + return dcc_add_write(drvdata, addr, write_val, bus, curr_list); +} + +static int config_show(struct seq_file *m, void *data) +{ + struct dcc_drvdata *drvdata = m->private; + struct dcc_config_entry *entry, *next_entry, *prev_entry, *loop_entry; + int index = 0, curr_list, i; + unsigned int loop_val[MAX_LOOP_ADDR]; + + curr_list = dcc_filp_curr_list(m->file); + if (curr_list < 0) + return curr_list; + + mutex_lock(&drvdata->mutex); + + list_for_each_entry(entry, &drvdata->cfg_head[curr_list], list) { + index++; + switch (entry->desc_type) { + case DCC_READ_WRITE_TYPE: + prev_entry = list_prev_entry(entry, list); + seq_printf(m, "RW 0x%x 0x%x 0x%x\n", + prev_entry->base + prev_entry->offset, + entry->mask, + entry->write_val); + break; + case DCC_LOOP_TYPE: + loop_entry = entry; + loop_val[0] = loop_entry->loop_cnt; + loop_entry = list_next_entry(loop_entry, list); + for (i = 0; i < (MAX_LOOP_ADDR-2); + i++, loop_entry = list_next_entry(loop_entry, list)) { + if (loop_entry->desc_type == DCC_READ_TYPE) { + loop_val[i+2] = loop_entry->base + loop_entry->offset; + } else if (loop_entry->desc_type == DCC_LOOP_TYPE) { + loop_val[i+2] = loop_entry->loop_cnt; + loop_val[1] = i; + entry = loop_entry; + break; + } + } + seq_printf(m, "L 0x%x 0x%x", loop_val[0], loop_val[1]); + for (i = 0; i < loop_val[1]; i++) + seq_printf(m, " 0x%x", loop_val[i+2]); + seq_puts(m, "\n"); + break; + case DCC_WRITE_TYPE: + seq_printf(m, "W 0x%x 0x%x %s\n", + entry->base + entry->offset, + entry->write_val, + entry->apb_bus ? "apb":"ahb"); + break; + case DCC_READ_TYPE: + if (entry->len == 1) { + next_entry = list_next_entry(entry, list); + if (next_entry && next_entry->desc_type == DCC_READ_WRITE_TYPE) + continue; + } + seq_printf(m, "R 0x%x 0x%x %s\n", + entry->base + entry->offset, + entry->len, + entry->apb_bus ? "apb":"ahb"); + } + } + mutex_unlock(&drvdata->mutex); + return 0; +} + +static int config_open(struct inode *inode, struct file *file) +{ + struct dcc_drvdata *drvdata = inode->i_private; + + return single_open(file, config_show, drvdata); +} + +static ssize_t config_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + int ret, curr_list; + char *token, *line; + char *buf, *bufp, *temp_buff; + char *delim = " "; + struct dcc_drvdata *drvdata = filp->f_inode->i_private; + ssize_t processed_len = 0; + + if (count == 0) + return -EINVAL; + buf = kzalloc(count+1, GFP_KERNEL); + if (buf) + bufp = buf; + else + return -ENOMEM; + + ret = copy_from_user(buf, user_buf, count); + if (ret) + goto err; + + curr_list = dcc_filp_curr_list(filp); + if (curr_list < 0) { + ret = curr_list; + goto err; + } + + while (bufp[0] != '\0') { + /* Parse line by line */ + line = strsep(&bufp, "\n"); + /* When one complete line could be parsed */ + if (line && bufp) { + processed_len += strlen(line) + 1; + if (drvdata->temp_buff_ptr && drvdata->temp_buff_ptr[curr_list]) { + temp_buff = drvdata->temp_buff_ptr[curr_list]; + /* Size of combined string must not be greater than + * allowed line size. + */ + if (strlen(line) + strlen(temp_buff) + 1 > LINE_BUFFER_MAX_SZ) { + dev_err(drvdata->dev, "Invalid input\n"); + ret = -EINVAL; + goto err; + } + strlcat(temp_buff, line, PAGE_SIZE); + line = temp_buff; + kfree(temp_buff); + drvdata->temp_buff_ptr[curr_list] = NULL; + } + + token = strsep(&line, delim); + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, line, curr_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, line, curr_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, line, curr_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, line, curr_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret) + goto err; + } else { + /* Save the incomplete line to a temporary buffer and rejoin it later */ + if (!drvdata->temp_buff_ptr) { + drvdata->temp_buff_ptr = devm_kcalloc(drvdata->dev, + drvdata->max_link_list, + sizeof(char *), + GFP_KERNEL); + if (!drvdata->temp_buff_ptr) { + ret = -ENOMEM; + goto err; + } + } + drvdata->temp_buff_ptr[curr_list] = kzalloc(LINE_BUFFER_MAX_SZ, + GFP_KERNEL); + temp_buff = drvdata->temp_buff_ptr[curr_list]; + if (!temp_buff) { + ret = -ENOMEM; + goto err; + } + if ((count - processed_len) >= LINE_BUFFER_MAX_SZ) { + dev_err(drvdata->dev, "Invalid input\n"); + ret = -EINVAL; + goto err; + } + memcpy(temp_buff, line, count - processed_len); + temp_buff[count - processed_len + 1] = '\0'; + processed_len += (strlen(temp_buff) + 1); + break; + } + } + + kfree(buf); + return processed_len; + +err: + kfree(buf); + if (drvdata->temp_buff_ptr && drvdata->temp_buff_ptr[curr_list]) { + kfree(drvdata->temp_buff_ptr[curr_list]); + drvdata->temp_buff_ptr[curr_list] = NULL; + } + return ret; +} + +static const struct file_operations config_fops = { + .open = config_open, + .read = seq_read, + .write = config_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static void dcc_delete_debug_dir(struct dcc_drvdata *drvdata) +{ + debugfs_remove_recursive(drvdata->dbg_dir); +}; + +static void dcc_create_debug_dir(struct dcc_drvdata *drvdata) +{ + int i; + char list_num[10]; + struct dentry *dcc_dev, *list; + struct device *dev = drvdata->dev; + + drvdata->dbg_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + dcc_dev = debugfs_create_dir(dev_name(dev), drvdata->dbg_dir); + + for (i = 0; i < drvdata->max_link_list; i++) { + snprintf(list_num, sizeof(list_num), "%d", i); + list = debugfs_create_dir(list_num, dcc_dev); + debugfs_create_file("enable", 0600, list, drvdata, &enable_fops); + debugfs_create_file("config", 0600, list, drvdata, &config_fops); + } + + debugfs_create_file("trigger", 0200, drvdata->dbg_dir, drvdata, &trigger_fops); + debugfs_create_file("ready", 0400, drvdata->dbg_dir, drvdata, &ready_fops); + debugfs_create_file("config_reset", 0200, drvdata->dbg_dir, drvdata, &config_reset_fops); + debugfs_create_file("loop_offset", 0400, drvdata->dbg_dir, drvdata, &loop_offset_fops); +} + +static ssize_t dcc_sram_read(struct file *file, char __user *data, + size_t len, loff_t *ppos) +{ + unsigned char *buf; + struct dcc_drvdata *drvdata; + + drvdata = container_of(file->private_data, struct dcc_drvdata, + sram_dev); + + /* EOF check */ + if (*ppos >= drvdata->ram_size) + return 0; + + if ((*ppos + len) > drvdata->ram_size) + len = (drvdata->ram_size - *ppos); + + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy_fromio(buf, drvdata->ram_base + *ppos, len); + + if (copy_to_user(data, buf, len)) { + kfree(buf); + return -EFAULT; + } + + *ppos += len; + + kfree(buf); + + return len; +} + +static void dcc_configure_list(struct dcc_drvdata *drvdata, + const struct dcc_config *config) +{ + const struct dcc_link_config *link; + const struct dcc_register_entry *entry; + char *token, *bufp, *buf_orig; + char *delim = " "; + int ret, i, j, configured; + size_t len; + + if (!config || !config->num_lists) + return; + + for (i = 0; i < config->num_lists; i++) { + link = &config->lists[i]; + + if (link->link_list >= drvdata->max_link_list) { + dev_err(drvdata->dev, "Invalid link list index %d\n", link->link_list); + continue; + } + + configured = 0; + + for (j = 0; j < link->num_entries; j++) { + entry = &link->entries[j]; + + len = strlen(entry->config); + buf_orig = kzalloc(len + 1, GFP_KERNEL); + if (!buf_orig) + return; + + strscpy(buf_orig, entry->config, len + 1); + bufp = buf_orig; + + token = strsep(&bufp, delim); + if (!bufp) { + dev_err(drvdata->dev, "Malformed entry: \"%s\"\n", + entry->config); + kfree(buf_orig); + continue; + } + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, bufp, link->link_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, bufp, link->link_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, bufp, link->link_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, bufp, link->link_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret >= 0) + configured++; + + kfree(buf_orig); + } + + if (configured) + dcc_enable(drvdata, link->link_list); + } +} + +static const struct file_operations dcc_sram_fops = { + .owner = THIS_MODULE, + .read = dcc_sram_read, +}; + +static int dcc_sram_dev_init(struct dcc_drvdata *drvdata) +{ + drvdata->sram_dev.minor = MISC_DYNAMIC_MINOR; + drvdata->sram_dev.name = "dcc_sram"; + drvdata->sram_dev.fops = &dcc_sram_fops; + + return misc_register(&drvdata->sram_dev); +} + +static void dcc_sram_dev_exit(struct dcc_drvdata *drvdata) +{ + misc_deregister(&drvdata->sram_dev); +} + +static int dcc_probe(struct platform_device *pdev) +{ + u32 val; + int ret = 0, i; + struct device *dev = &pdev->dev; + struct dcc_drvdata *drvdata; + const struct dcc_pdata *pdata = dev_get_platdata(dev); + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &pdev->dev; + platform_set_drvdata(pdev, drvdata); + + drvdata->base = devm_ioremap(dev, pdata->base, pdata->size); + if (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); + + drvdata->ram_base = devm_ioremap(dev, pdata->ram_base, pdata->ram_size); + if (IS_ERR(drvdata->ram_base)) + return PTR_ERR(drvdata->ram_base); + + drvdata->ram_size = pdata->ram_size; + drvdata->ram_offset = pdata->dcc_offset; + drvdata->mem_map_ver = pdata->map_ver; + + switch (drvdata->mem_map_ver) { + case MEM_MAP_VER3: + case MEM_MAP_VER2: + drvdata->max_link_list = readl(drvdata->base + DCC_LL_NUM_INFO); + if (!drvdata->max_link_list) + return -EINVAL; + break; + case MEM_MAP_VER1: + drvdata->max_link_list = DCC_MAX_LINK_LIST; + break; + default: + dev_err(drvdata->dev, "Unsupported memory map version.\n"); + return -EINVAL; + } + + val = readl(drvdata->base + DCC_HW_INFO); + /* Either set the fixed loop offset or calculate + * it from the total number of words in dcc_sram. + * Max consecutive addresses dcc can loop is + * equivalent to the words in dcc_sram. + */ + if (val & DCC_LOOP_OFFSET_MASK) + drvdata->loop_shift = DCC_FIX_LOOP_OFFSET; + else + drvdata->loop_shift = get_bitmask_order((drvdata->ram_offset + + drvdata->ram_size) / DCC_SRAM_WORD_LENGTH - 1); + + mutex_init(&drvdata->mutex); + + drvdata->enable_bitmap = devm_kcalloc(dev, BITS_TO_LONGS(drvdata->max_link_list), + sizeof(*drvdata->enable_bitmap), GFP_KERNEL); + if (!drvdata->enable_bitmap) + return -ENOMEM; + + drvdata->cfg_head = devm_kcalloc(dev, drvdata->max_link_list, + sizeof(*drvdata->cfg_head), GFP_KERNEL); + if (!drvdata->cfg_head) + return -ENOMEM; + + for (i = 0; i < drvdata->max_link_list; i++) + INIT_LIST_HEAD(&drvdata->cfg_head[i]); + + ret = dcc_sram_dev_init(drvdata); + if (ret) { + dev_err(drvdata->dev, "DCC: sram node not registered.\n"); + return ret; + } + + dcc_create_debug_dir(drvdata); + dcc_configure_list(drvdata, pdata->config); + + return 0; +} + +static void dcc_remove(struct platform_device *pdev) +{ + struct dcc_drvdata *drvdata = platform_get_drvdata(pdev); + + dcc_delete_debug_dir(drvdata); + dcc_sram_dev_exit(drvdata); + dcc_config_reset(drvdata); +} + +static struct platform_driver dcc_driver = { + .probe = dcc_probe, + .remove = dcc_remove, + .driver = { + .name = "qcom-dcc", + }, +}; + +module_platform_driver(dcc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver"); diff --git a/drivers/misc/qcom-dcc.h b/drivers/misc/qcom-dcc.h new file mode 100644 index 0000000000000..ce8551141062d --- /dev/null +++ b/drivers/misc/qcom-dcc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_H +#define _QCOM_DCC_H + +#include + +struct dcc_register_entry { + const char *config; +}; + +struct dcc_link_config { + int link_list; + const struct dcc_register_entry *entries; + int num_entries; +}; + +struct dcc_config { + const struct dcc_link_config *lists; + int num_lists; +}; + +struct dcc_pdata { + phys_addr_t base; + resource_size_t size; + phys_addr_t ram_base; + resource_size_t ram_size; + u32 dcc_offset; + u8 map_ver; + const struct dcc_config *config; +}; + +#endif diff --git a/drivers/mmc/core/crypto.c b/drivers/mmc/core/crypto.c index fec4fbf16a5b6..a5a90bfc634ee 100644 --- a/drivers/mmc/core/crypto.c +++ b/drivers/mmc/core/crypto.c @@ -15,7 +15,7 @@ void mmc_crypto_set_initial_state(struct mmc_host *host) { /* Reset might clear all keys, so reprogram all the keys. */ - if (host->caps2 & MMC_CAP2_CRYPTO) + if ((host->caps2 & MMC_CAP2_CRYPTO) && !(host->caps2 & MMC_CAP2_CRYPTO_NO_REPROG)) blk_crypto_reprogram_all_keys(&host->crypto_profile); } diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 0882ce74e0c9b..a979eb7b0453c 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -286,6 +286,7 @@ struct sdhci_msm_host { /* core, iface, cal and sleep clocks */ struct clk_bulk_data bulk_clks[4]; #ifdef CONFIG_MMC_CRYPTO + struct clk *ice_clk; /* ICE clock */ struct qcom_ice *ice; #endif unsigned long clk_rate; @@ -1959,6 +1960,7 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, } mmc->caps2 |= MMC_CAP2_CRYPTO; + mmc->caps2 |= MMC_CAP2_CRYPTO_NO_REPROG; return 0; } @@ -2638,6 +2640,11 @@ static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host) usleep_range(200, 210); reset_control_put(reset); +#ifdef CONFIG_MMC_CRYPTO + if (host->mmc->caps2 & MMC_CAP2_CRYPTO) + blk_crypto_reprogram_all_keys(&host->mmc->crypto_profile); +#endif + return ret; } @@ -2703,6 +2710,17 @@ static int sdhci_msm_probe(struct platform_device *pdev) return ret; } +#ifdef CONFIG_MMC_CRYPTO + /* Setup ICE clock */ + msm_host->ice_clk = devm_clk_get(&pdev->dev, "ice"); + if (!IS_ERR(msm_host->ice_clk)) { + /* Vote for max. clk rate for max. performance */ + ret = clk_set_rate(msm_host->ice_clk, INT_MAX); + if (ret) + dev_err(&pdev->dev, "ice clk set rate failed (%d)\n", ret); + } +#endif + /* Setup main peripheral bus clock */ clk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(clk)) { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index ac7d6d3e205a1..59fa8779e4e46 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -67,6 +67,9 @@ /* SDC4_STATUS bits */ #define SDC4_STATUS_DLL_LOCK BIT(7) +/* SDCC_USR_CTL bits */ +#define SDCC_USR_CTL_DDR_BYPASS BIT(30) + /* RGMII_IO_MACRO_CONFIG2 fields */ #define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17) #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16) @@ -81,11 +84,18 @@ #define SGMII_10M_RX_CLK_DVDR 0x31 +#define ETHQOS_MAX_NOC_CLKS 3 + struct ethqos_emac_por { unsigned int offset; unsigned int value; }; +struct ethqos_noc_clk_cfg { + const char *id; + unsigned long rate; +}; + struct ethqos_emac_driver_data { const struct ethqos_emac_por *rgmii_por; unsigned int num_rgmii_por; @@ -95,6 +105,8 @@ struct ethqos_emac_driver_data { const char *link_clk_name; struct dwmac4_addrs dwmac4_addrs; bool needs_sgmii_loopback; + const struct ethqos_noc_clk_cfg *noc_clk_cfg; + unsigned int num_noc_clks; }; struct qcom_ethqos { @@ -109,6 +121,9 @@ struct qcom_ethqos { bool rgmii_config_loopback_en; bool has_emac_ge_3; bool needs_sgmii_loopback; + + struct clk_bulk_data noc_clks[ETHQOS_MAX_NOC_CLKS]; + int num_noc_clks; }; static u32 rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) @@ -183,7 +198,15 @@ static int ethqos_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i, if (rate < 0) return rate; - return clk_set_rate(ethqos->link_clk, rate * 2); + /* Clock Rate Requirements: + * MAC added delay: 250/50/5 Mhz for 1G/100M/10M + * No MAC delay (DLL bypass): 250/25/2.5 Mhz for 1G/100M/10M + */ + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII || + speed == SPEED_1000) + rate *= 2; + + return clk_set_rate(ethqos->link_clk, rate); } static void @@ -303,6 +326,36 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = { }, }; +static const struct ethqos_noc_clk_cfg shikra_noc_clks[] = { + { "axi", 120000000 }, + { "axi-noc", 120000000 }, + { "pcie-tile-axi-noc", 120000000 }, +}; + +static const struct ethqos_emac_driver_data shikra_data = { + .dma_addr_width = 36, + .has_emac_ge_3 = true, + .noc_clk_cfg = shikra_noc_clks, + .num_noc_clks = ARRAY_SIZE(shikra_noc_clks), + .rgmii_config_loopback_en = false, + .dwmac4_addrs = { + .dma_chan = 0x00008100, + .dma_chan_offset = 0x1000, + .mtl_chan = 0x00008000, + .mtl_chan_offset = 0x1000, + .mtl_ets_ctrl = 0x00008010, + .mtl_ets_ctrl_offset = 0x1000, + .mtl_txq_weight = 0x00008018, + .mtl_txq_weight_offset = 0x1000, + .mtl_send_slp_cred = 0x0000801c, + .mtl_send_slp_cred_offset = 0x1000, + .mtl_high_cred = 0x00008020, + .mtl_high_cred_offset = 0x1000, + .mtl_low_cred = 0x00008024, + .mtl_low_cred_offset = 0x1000, + }, +}; + static int ethqos_dll_configure(struct qcom_ethqos *ethqos) { struct device *dev = ðqos->pdev->dev; @@ -371,9 +424,8 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) return 0; } -static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) +static void ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) { - struct device *dev = ðqos->pdev->dev; unsigned int prg_rclk_dly, loopback; unsigned int phase_shift; @@ -384,11 +436,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) /* Select RGMII, write 0 to interface select */ rgmii_clrmask(ethqos, RGMII_CONFIG_INTF_SEL, RGMII_IO_MACRO_CONFIG); - if (speed != SPEED_1000 && speed != SPEED_100 && speed != SPEED_10) { - dev_err(dev, "Invalid speed %d\n", speed); - return -EINVAL; - } - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); if (speed == SPEED_1000) { @@ -411,8 +458,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) RGMII_IO_MACRO_CONFIG2); /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ - if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || - ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) phase_shift = 0; else phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; @@ -479,8 +525,40 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback, RGMII_IO_MACRO_CONFIG); +} - return 0; +static void ethqos_rgmii_id_macro_init(struct qcom_ethqos *ethqos, int speed) +{ + rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_1000) + rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + else + rgmii_clrmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); + + if (ethqos->has_emac_ge_3) + rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); + else + rgmii_setmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); + + rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_1000) + rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); + else + rgmii_setmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); + + if (!ethqos->rgmii_config_loopback_en) + rgmii_clrmask(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); + + rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); } static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, @@ -501,6 +579,21 @@ static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, ethqos_set_func_clk_en(ethqos); + /* For rgmii-id mode, the PHY should add the required delays. + * Therefore, power down the DLL and program it in bypass mode. + * Program the IO_MACRO as per the settings recommended by the + * programming guide for bypass mode. This will ensure that the + * MAC core doesn't add any additional delays. + */ + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID) { + rgmii_setmask(ethqos, SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); + rgmii_setmask(ethqos, SDCC_USR_CTL_DDR_BYPASS, SDCC_USR_CTL); + + ethqos_rgmii_id_macro_init(ethqos, speed); + + return; + } + /* Initialize the DLL first */ /* Set DLL_RST */ @@ -645,6 +738,17 @@ static int ethqos_clks_config(void *priv, bool enabled) return ret; } + if (ethqos->num_noc_clks) { + ret = clk_bulk_prepare_enable(ethqos->num_noc_clks, + ethqos->noc_clks); + if (ret) { + dev_err(ðqos->pdev->dev, + "NOC clocks enable failed: %d\n", ret); + clk_disable_unprepare(ethqos->link_clk); + return ret; + } + } + /* Enable functional clock to prevent DMA reset to timeout due * to lacking PHY clock after the hardware block has been power * cycled. The actual configuration will be adjusted once @@ -653,6 +757,9 @@ static int ethqos_clks_config(void *priv, bool enabled) qcom_ethqos_set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); } else { + if (ethqos->num_noc_clks) + clk_bulk_disable_unprepare(ethqos->num_noc_clks, + ethqos->noc_clks); clk_disable_unprepare(ethqos->link_clk); } @@ -681,6 +788,37 @@ static void ethqos_ptp_clk_freq_config(struct stmmac_priv *priv) netdev_dbg(priv->dev, "PTP rate %lu\n", plat_dat->clk_ptp_rate); } +/* + * Some SoCs gate interconnect access to the System NOC behind dedicated + * clocks. Acquire them, set their required rates, and store the result in + * ethqos so ethqos_clks_config() can enable/disable them at runtime. + */ +static int qcom_ethqos_init_noc_clks(struct qcom_ethqos *ethqos, + const struct ethqos_emac_driver_data *data) +{ + struct device *dev = ðqos->pdev->dev; + unsigned int i; + int ret; + + for (i = 0; i < data->num_noc_clks; i++) + ethqos->noc_clks[i].id = data->noc_clk_cfg[i].id; + ethqos->num_noc_clks = data->num_noc_clks; + + ret = devm_clk_bulk_get(dev, ethqos->num_noc_clks, ethqos->noc_clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get NOC clocks\n"); + + for (i = 0; i < data->num_noc_clks; i++) { + ret = clk_set_rate(ethqos->noc_clks[i].clk, + data->noc_clk_cfg[i].rate); + if (ret) + dev_warn(dev, "Failed to set %s rate: %d\n", + data->noc_clk_cfg[i].id, ret); + } + + return 0; +} + static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -740,6 +878,12 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->has_emac_ge_3 = data->has_emac_ge_3; ethqos->needs_sgmii_loopback = data->needs_sgmii_loopback; + if (data->num_noc_clks) { + ret = qcom_ethqos_init_noc_clks(ethqos, data); + if (ret) + return ret; + } + ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii"); if (IS_ERR(ethqos->link_clk)) return dev_err_probe(dev, PTR_ERR(ethqos->link_clk), @@ -801,6 +945,7 @@ static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data}, { .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data}, { .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data}, + { .compatible = "qcom,shikra-ethqos", .data = &shikra_data}, { .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data}, { } }; diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 410a7ee076a02..7dc07339b9579 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -3294,9 +3294,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags); clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); - ath11k_core_qmi_firmware_ready(ab); - set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); - + if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { + ret = ath11k_core_qmi_firmware_ready(ab); + if (ret) { + set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); + break; + } + set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); + } break; case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: break; diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 742d4fd1b598c..4bbfaaa446ec0 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1793,29 +1793,6 @@ int ath12k_core_pre_init(struct ath12k_base *ab) return 0; } -static int ath12k_core_panic_handler(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct ath12k_base *ab = container_of(nb, struct ath12k_base, - panic_nb); - - return ath12k_hif_panic_handler(ab); -} - -static int ath12k_core_panic_notifier_register(struct ath12k_base *ab) -{ - ab->panic_nb.notifier_call = ath12k_core_panic_handler; - - return atomic_notifier_chain_register(&panic_notifier_list, - &ab->panic_nb); -} - -static void ath12k_core_panic_notifier_unregister(struct ath12k_base *ab) -{ - atomic_notifier_chain_unregister(&panic_notifier_list, - &ab->panic_nb); -} - static inline bool ath12k_core_hw_group_create_ready(struct ath12k_hw_group *ag) { @@ -2231,18 +2208,13 @@ int ath12k_core_init(struct ath12k_base *ab) struct ath12k_hw_group *ag; int ret; - ret = ath12k_core_panic_notifier_register(ab); - if (ret) - ath12k_warn(ab, "failed to register panic handler: %d\n", ret); - mutex_lock(&ath12k_hw_group_mutex); ag = ath12k_core_hw_group_assign(ab); if (!ag) { mutex_unlock(&ath12k_hw_group_mutex); ath12k_warn(ab, "unable to get hw group\n"); - ret = -ENODEV; - goto err_unregister_notifier; + return -ENODEV; } mutex_unlock(&ath12k_hw_group_mutex); @@ -2267,8 +2239,6 @@ int ath12k_core_init(struct ath12k_base *ab) err_unassign_hw_group: ath12k_core_hw_group_unassign(ab); -err_unregister_notifier: - ath12k_core_panic_notifier_unregister(ab); return ret; } @@ -2277,7 +2247,6 @@ void ath12k_core_deinit(struct ath12k_base *ab) { ath12k_core_hw_group_destroy(ab->ag); ath12k_core_hw_group_unassign(ab); - ath12k_core_panic_notifier_unregister(ab); } void ath12k_core_free(struct ath12k_base *ab) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index fc5127b5c1a37..d41b8a556ea2c 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -1138,8 +1137,6 @@ struct ath12k_base { #endif /* CONFIG_ACPI */ - struct notifier_block panic_nb; - struct ath12k_hw_group *ag; struct ath12k_wsi_info wsi_info; enum ath12k_firmware_mode fw_mode; diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index f8cfc7bb29dd7..6596089d41688 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -205,7 +205,7 @@ struct ath12k_pdev_dp { #define DP_REO_CMD_RING_SIZE 256 #define DP_REO_STATUS_RING_SIZE 2048 #define DP_RXDMA_BUF_RING_SIZE 4096 -#define DP_RX_MAC_BUF_RING_SIZE 2048 +#define DP_RX_MAC_BUF_RING_SIZE 4096 #define DP_RXDMA_REFILL_RING_SIZE 2048 #define DP_RXDMA_ERR_DST_RING_SIZE 1024 #define DP_RXDMA_MON_STATUS_RING_SIZE 1024 diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index 47d009a0d61fe..2660b4c7449be 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -570,6 +570,8 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); rcu_assign_pointer(dp_peer->link_peers[peer->link_id], peer); + WRITE_ONCE(dp_peer->link_peers_map, + READ_ONCE(dp_peer->link_peers_map) | BIT(peer->link_id)); rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer); @@ -632,6 +634,8 @@ void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_ peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); + WRITE_ONCE(dp_peer->link_peers_map, + READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id)); rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index f5067e66f1e18..7c9709bf717b4 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -140,6 +140,7 @@ struct ath12k_dp_peer { /* Info used in MMIC verification of * RX fragments */ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; + unsigned long link_peers_map; struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS]; struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1]; struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 06e74124e57eb..8fa0e90b45316 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -1384,10 +1384,9 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc pubsta = peer ? peer->sta : NULL; - if (pubsta && pubsta->valid_links) { - status->link_valid = 1; - status->link_id = peer->hw_links[rxcb->hw_link_id]; - } + status->link_valid = 0; + if (pubsta && pubsta->valid_links) + ath12k_hw_set_rx_link_id(dp->hw_params, peer, rxcb, status); ath12k_dbg(dp->ab, ATH12K_DBG_DATA, "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c index a164563fff289..c0c3d2f047ef0 100644 --- a/drivers/net/wireless/ath/ath12k/hal.c +++ b/drivers/net/wireless/ath/ath12k/hal.c @@ -828,8 +828,8 @@ void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len) { struct hal_tlv_64_hdr *tlv64 = tlv; - tlv64->tl = le64_encode_bits(tag, HAL_TLV_HDR_TAG) | - le64_encode_bits(len, HAL_TLV_HDR_LEN); + tlv64->tl = le64_encode_bits(tag, HAL_TLV_64_HDR_TAG) | + le64_encode_bits(len, HAL_TLV_64_HDR_LEN); return tlv64->value; } @@ -846,26 +846,44 @@ void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len) } EXPORT_SYMBOL(ath12k_hal_encode_tlv32_hdr); -u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc) +void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid) { struct hal_tlv_64_hdr *tlv64 = tlv; - u16 tag; - tag = le64_get_bits(tlv64->tl, HAL_SRNG_TLV_HDR_TAG); - *desc = tlv64->value; + if (tag) + *tag = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_TAG); + if (len) + *len = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_LEN); + if (usrid) + *usrid = le64_get_bits(tlv64->tl, HAL_TLV_64_USR_ID); - return tag; + return tlv64->value; } EXPORT_SYMBOL(ath12k_hal_decode_tlv64_hdr); -u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc) +void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid) { struct hal_tlv_hdr *tlv32 = tlv; - u16 tag; - tag = le32_get_bits(tlv32->tl, HAL_SRNG_TLV_HDR_TAG); - *desc = tlv32->value; + if (tag) + *tag = le32_get_bits(tlv32->tl, HAL_TLV_HDR_TAG); + if (len) + *len = le32_get_bits(tlv32->tl, HAL_TLV_HDR_LEN); + if (usrid) + *usrid = le32_get_bits(tlv32->tl, HAL_TLV_USR_ID); - return tag; + return tlv32->value; } EXPORT_SYMBOL(ath12k_hal_decode_tlv32_hdr); + +u32 ath12k_hal_get_tlv64_hdr_align(void) +{ + return HAL_TLV_64_ALIGN; +} +EXPORT_SYMBOL(ath12k_hal_get_tlv64_hdr_align); + +u32 ath12k_hal_get_tlv32_hdr_align(void) +{ + return HAL_TLV_ALIGN; +} +EXPORT_SYMBOL(ath12k_hal_get_tlv32_hdr_align); diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h index 21c551d8b2481..ba2c22fb2982b 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -1441,10 +1441,12 @@ struct hal_ops { u8 *rbm, u32 *msdu_cnt); void *(*reo_cmd_enc_tlv_hdr)(void *tlv, u64 tag, u64 len); u16 (*reo_status_dec_tlv_hdr)(void *tlv, void **desc); + void *(*mon_rx_status_dec_tlv_hdr)(void *tlv, u16 *tag, u16 *len, u16 *usrid); + u32 (*get_tlv_hdr_align)(void); }; #define HAL_TLV_HDR_TAG GENMASK(9, 1) -#define HAL_TLV_HDR_LEN GENMASK(25, 10) +#define HAL_TLV_HDR_LEN GENMASK(21, 10) #define HAL_TLV_USR_ID GENMASK(31, 26) #define HAL_TLV_ALIGN 4 @@ -1464,9 +1466,6 @@ struct hal_tlv_64_hdr { u8 value[]; } __packed; -#define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1) -#define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10) - dma_addr_t ath12k_hal_srng_get_tp_addr(struct ath12k_base *ab, struct hal_srng *srng); dma_addr_t ath12k_hal_srng_get_hp_addr(struct ath12k_base *ab, @@ -1556,6 +1555,8 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get(struct ath12k_hal *hal, void *rx_desc, u8 *rbm, u32 *msdu_cnt); void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len); void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len); -u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc); -u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc); +void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid); +void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid); +u32 ath12k_hal_get_tlv64_hdr_align(void); +u32 ath12k_hal_get_tlv32_hdr_align(void); #endif diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h index 4de8667690e91..aecdb0c5f2858 100644 --- a/drivers/net/wireless/ath/ath12k/hif.h +++ b/drivers/net/wireless/ath/ath12k/hif.h @@ -30,7 +30,6 @@ struct ath12k_hif_ops { void (*ce_irq_enable)(struct ath12k_base *ab); void (*ce_irq_disable)(struct ath12k_base *ab); void (*get_ce_msi_idx)(struct ath12k_base *ab, u32 ce_id, u32 *msi_idx); - int (*panic_handler)(struct ath12k_base *ab); void (*coredump_download)(struct ath12k_base *ab); }; @@ -149,14 +148,6 @@ static inline void ath12k_hif_power_down(struct ath12k_base *ab, bool is_suspend ab->hif.ops->power_down(ab, is_suspend); } -static inline int ath12k_hif_panic_handler(struct ath12k_base *ab) -{ - if (!ab->hif.ops->panic_handler) - return NOTIFY_DONE; - - return ab->hif.ops->panic_handler(ab); -} - static inline void ath12k_hif_coredump_download(struct ath12k_base *ab) { if (ab->hif.ops->coredump_download) diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index d135b29363788..86fb8b7196135 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -13,6 +13,10 @@ #include "wmi.h" #include "hal.h" +struct ath12k_dp_peer; +struct ath12k_skb_rxcb; +struct ieee80211_rx_status; + /* Target configuration defines */ /* Num VDEVS per radio */ @@ -243,6 +247,9 @@ struct ath12k_hw_ops { bool (*dp_srng_is_tx_comp_ring)(int ring_num); bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif, struct ieee80211_mgmt *mgmt); + void (*set_rx_link_id)(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status); }; static inline @@ -273,6 +280,15 @@ static inline int ath12k_hw_mac_id_to_srng_id(const struct ath12k_hw_params *hw, return 0; } +static inline void ath12k_hw_set_rx_link_id(const struct ath12k_hw_params *hw, + struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status) +{ + if (hw->hw_ops->set_rx_link_id) + hw->hw_ops->set_rx_link_id(dp_peer, rxcb, status); +} + struct ath12k_fw_ie { __le32 id; __le32 len; diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index af354bef5c0d7..4bbbaf4a99c60 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1238,9 +1238,13 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) /* cleanup dp peer */ spin_lock_bh(&dp_hw->peer_lock); dp_peer = peer->dp_peer; - peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); - rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); - rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); + if (dp_peer) { + peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); + rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); + WRITE_ONCE(dp_peer->link_peers_map, + READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id)); + rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); + } spin_unlock_bh(&dp_hw->peer_lock); ath12k_dp_link_peer_rhash_delete(dp, peer); @@ -4361,12 +4365,68 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif, return ret; } +static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) +{ + struct ath12k *ar = arvif->ar; + struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; + enum wmi_sta_powersave_param param; + struct ieee80211_bss_conf *info; + enum wmi_sta_ps_mode psmode; + int ret; + int timeout; + bool enable_ps; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + enable_ps = arvif->ahvif->ps; + if (enable_ps) { + psmode = WMI_STA_PS_MODE_ENABLED; + param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + + timeout = conf->dynamic_ps_timeout; + if (timeout == 0) { + info = ath12k_mac_get_link_bss_conf(arvif); + if (!info) { + ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", + vif->addr, arvif->link_id); + return; + } + + /* firmware doesn't like 0 */ + timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; + } + + ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, + timeout); + if (ret) { + ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", + arvif->vdev_id, ret); + return; + } + } else { + psmode = WMI_STA_PS_MODE_DISABLED; + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", + arvif->vdev_id, psmode ? "enable" : "disable"); + + ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); + if (ret) + ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", + psmode, arvif->vdev_id, ret); +} + void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 changed) { struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); unsigned long links = ahvif->links_map; + struct ieee80211_vif_cfg *vif_cfg; struct ieee80211_bss_conf *info; struct ath12k_link_vif *arvif; struct ieee80211_sta *sta; @@ -4430,63 +4490,26 @@ void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, } } } -} -EXPORT_SYMBOL(ath12k_mac_op_vif_cfg_changed); - -static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) -{ - struct ath12k *ar = arvif->ar; - struct ieee80211_vif *vif = arvif->ahvif->vif; - struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; - enum wmi_sta_powersave_param param; - struct ieee80211_bss_conf *info; - enum wmi_sta_ps_mode psmode; - int ret; - int timeout; - bool enable_ps; - lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + if (changed & BSS_CHANGED_PS) { + links = ahvif->links_map; + vif_cfg = &vif->cfg; - if (vif->type != NL80211_IFTYPE_STATION) - return; + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + if (!arvif || !arvif->ar) + continue; - enable_ps = arvif->ahvif->ps; - if (enable_ps) { - psmode = WMI_STA_PS_MODE_ENABLED; - param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + ar = arvif->ar; - timeout = conf->dynamic_ps_timeout; - if (timeout == 0) { - info = ath12k_mac_get_link_bss_conf(arvif); - if (!info) { - ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", - vif->addr, arvif->link_id); - return; + if (ar->ab->hw_params->supports_sta_ps) { + ahvif->ps = vif_cfg->ps; + ath12k_mac_vif_setup_ps(arvif); } - - /* firmware doesn't like 0 */ - timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; - } - - ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, - timeout); - if (ret) { - ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", - arvif->vdev_id, ret); - return; } - } else { - psmode = WMI_STA_PS_MODE_DISABLED; } - - ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", - arvif->vdev_id, psmode ? "enable" : "disable"); - - ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); - if (ret) - ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", - psmode, arvif->vdev_id, ret); } +EXPORT_SYMBOL(ath12k_mac_op_vif_cfg_changed); static bool ath12k_mac_supports_tpc(struct ath12k *ar, struct ath12k_vif *ahvif, const struct cfg80211_chan_def *chandef) @@ -4691,7 +4714,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, { struct ath12k_vif *ahvif = arvif->ahvif; struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); - struct ieee80211_vif_cfg *vif_cfg = &vif->cfg; struct ath12k_link_vif *tx_arvif; struct cfg80211_chan_def def; u32 param_id, param_value; @@ -5029,12 +5051,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, } ath12k_mac_fils_discovery(arvif, info); - - if (changed & BSS_CHANGED_PS && - ar->ab->hw_params->supports_sta_ps) { - ahvif->ps = vif_cfg->ps; - ath12k_mac_vif_setup_ps(arvif); - } } static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif, @@ -13584,6 +13600,7 @@ int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, struct ath12k *ar; struct ieee80211_supported_band *sband; struct survey_info *ar_survey; + int orig_idx = idx; lockdep_assert_wiphy(hw->wiphy); @@ -13618,7 +13635,7 @@ int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx, return -ENOENT; } - ar_survey = &ar->survey[idx]; + ar_survey = &ar->survey[orig_idx]; ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]); diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index d9a22d6afbb02..45704c8264894 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -537,6 +538,8 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) int i, j, n, ret, num_vectors = 0; u32 user_base_data = 0, base_vector = 0, base_idx; struct ath12k_ext_irq_grp *irq_grp; + bool threaded_napi = false; + int irq; base_idx = ATH12K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX; ret = ath12k_pci_get_user_msi_assignment(ab, "DP", @@ -546,6 +549,10 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) if (ret < 0) return ret; + irq = ath12k_pci_get_msi_irq(ab->dev, base_vector); + if (irq >= 0) + threaded_napi = !irq_can_set_affinity(irq); + for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { irq_grp = &ab->ext_irq_grp[i]; u32 num_irq = 0; @@ -560,6 +567,8 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi, ath12k_pci_ext_grp_napi_poll); + if (threaded_napi) + netif_threaded_enable(irq_grp->napi_ndev); if (ab->hw_params->ring_mask->tx[i] || ab->hw_params->ring_mask->rx[i] || @@ -578,7 +587,7 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab) for (j = 0; j < irq_grp->num_irq; j++) { int irq_idx = irq_grp->irqs[j]; int vector = (i % num_vectors) + base_vector; - int irq = ath12k_pci_get_msi_irq(ab->dev, vector); + irq = ath12k_pci_get_msi_irq(ab->dev, vector); ab->irq_num[irq_idx] = irq; @@ -1469,13 +1478,6 @@ void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend) ath12k_pci_sw_reset(ab_pci->ab, false); } -static int ath12k_pci_panic_handler(struct ath12k_base *ab) -{ - ath12k_pci_sw_reset(ab, false); - - return NOTIFY_OK; -} - static const struct ath12k_hif_ops ath12k_pci_hif_ops = { .start = ath12k_pci_start, .stop = ath12k_pci_stop, @@ -1493,7 +1495,6 @@ static const struct ath12k_hif_ops ath12k_pci_hif_ops = { .ce_irq_enable = ath12k_pci_hif_ce_irq_enable, .ce_irq_disable = ath12k_pci_hif_ce_irq_disable, .get_ce_msi_idx = ath12k_pci_get_ce_msi_idx, - .panic_handler = ath12k_pci_panic_handler, #ifdef CONFIG_ATH12K_COREDUMP .coredump_download = ath12k_pci_coredump_download, #endif diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c index 7dd4a49d64d5f..c84c42a3d3774 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c @@ -1565,16 +1565,17 @@ ath12k_wifi7_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon, static enum hal_rx_mon_status ath12k_wifi7_dp_mon_rx_parse_status_tlv(struct ath12k_pdev_dp *dp_pdev, struct ath12k_mon_data *pmon, - const struct hal_tlv_64_hdr *tlv) + const void *tlv) { struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info; - const void *tlv_data = tlv->value; - u32 info[7], userid; - u16 tlv_tag, tlv_len; + struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev); + struct ath12k_hal *hal = &ar->ab->hal; + u16 tlv_tag, tlv_len, userid; + void *tlv_data; + u32 info[7]; - tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG); - tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN); - userid = le64_get_bits(tlv->tl, HAL_TLV_64_USR_ID); + tlv_data = hal->ops->mon_rx_status_dec_tlv_hdr((void *)tlv, &tlv_tag, + &tlv_len, &userid); if (ppdu_info->tlv_aggr.in_progress && ppdu_info->tlv_aggr.tlv_tag != tlv_tag) { ath12k_wifi7_dp_mon_parse_eht_sig_hdr(ppdu_info, @@ -2930,11 +2931,12 @@ static enum dp_mon_status_buf_state ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng, struct dp_rxdma_mon_ring *rx_ring) { + struct ath12k_hal *hal = &ab->hal; struct ath12k_skb_rxcb *rxcb; - struct hal_tlv_64_hdr *tlv; struct sk_buff *skb; void *status_desc; dma_addr_t paddr; + u16 tlv_tag; u32 cookie; int buf_id; u8 rbm; @@ -2959,8 +2961,8 @@ ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); - tlv = (struct hal_tlv_64_hdr *)skb->data; - if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != HAL_RX_STATUS_BUFFER_DONE) + hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag, NULL, NULL); + if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE) return DP_MON_STATUS_NO_DMA; return DP_MON_STATUS_REPLINISH; @@ -2972,41 +2974,40 @@ ath12k_wifi7_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev, struct sk_buff *skb) { struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev); - struct hal_tlv_64_hdr *tlv; + struct ath12k_hal *hal = &ar->ab->hal; + u8 *tlv_value, *tlv = skb->data; struct ath12k_skb_rxcb *rxcb; enum hal_rx_mon_status hal_status; u16 tlv_tag, tlv_len; - u8 *ptr = skb->data; + u32 tlv_hdr_len; + + tlv_hdr_len = hal->ops->get_tlv_hdr_align(); do { - tlv = (struct hal_tlv_64_hdr *)ptr; - tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG); + tlv_value = hal->ops->mon_rx_status_dec_tlv_hdr(tlv, &tlv_tag, + &tlv_len, NULL); /* The actual length of PPDU_END is the combined length of many PHY * TLVs that follow. Skip the TLV header and * rx_rxpcu_classification_overview that follows the header to get to * next TLV. */ - if (tlv_tag == HAL_RX_PPDU_END) tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview); - else - tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN); hal_status = ath12k_wifi7_dp_mon_rx_parse_status_tlv(dp_pdev, pmon, tlv); if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable && ath12k_wifi7_dp_mon_parse_rx_dest_tlv(dp_pdev, pmon, hal_status, - tlv->value)) + tlv_value)) return HAL_RX_MON_STATUS_PPDU_DONE; - ptr += sizeof(*tlv) + tlv_len; - ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN); + tlv = PTR_ALIGN(tlv + tlv_len + tlv_hdr_len, tlv_hdr_len); - if ((ptr - skb->data) > skb->len) + if (unlikely(tlv - skb->data > skb->len || + skb->len - (tlv - skb->data) < tlv_hdr_len)) break; - } while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) || (hal_status == HAL_RX_MON_STATUS_BUF_ADDR) || (hal_status == HAL_RX_MON_STATUS_MPDU_START) || @@ -3056,15 +3057,16 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id, int buf_id, srng_id, num_buffs_reaped = 0; enum dp_mon_status_buf_state reap_status; struct dp_rxdma_mon_ring *rx_ring; + struct ath12k_hal *hal = &ab->hal; struct ath12k_mon_data *pmon; struct ath12k_skb_rxcb *rxcb; - struct hal_tlv_64_hdr *tlv; void *rx_mon_status_desc; struct hal_srng *srng; struct ath12k_dp *dp; struct sk_buff *skb; struct ath12k *ar; dma_addr_t paddr; + u16 tlv_tag; u32 cookie; u8 rbm; @@ -3109,14 +3111,13 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); - tlv = (struct hal_tlv_64_hdr *)skb->data; - if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != - HAL_RX_STATUS_BUFFER_DONE) { + hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag, + NULL, NULL); + if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE) { pmon->buf_state = DP_MON_STATUS_NO_DMA; ath12k_warn(ab, - "mon status DONE not set %llx, buf_id %d\n", - le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG), - buf_id); + "mon status DONE not set %x, buf_id %d\n", + tlv_tag, buf_id); /* RxDMA status done bit might not be set even * though tp is moved by HW. */ diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index cb9dd8cb28b67..95d87dd67872f 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -5,6 +5,7 @@ */ #include "dp_rx.h" +#include "../dp_peer.h" #include "../dp_tx.h" #include "../peer.h" #include "hal_qcn9274.h" @@ -2315,3 +2316,35 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab, return tlv_tag == HAL_RX_MPDU_START; } + +void +ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status) +{ + status->link_valid = 1; + status->link_id = dp_peer->hw_links[rxcb->hw_link_id]; +} + +void +ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status) +{ + struct ath12k_dp_link_peer *link_peer; + unsigned long links_map; + int i; + + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "ath12k set rx link id called without rcu lock"); + + links_map = READ_ONCE(dp_peer->link_peers_map); + for_each_set_bit(i, &links_map, ATH12K_NUM_MAX_LINKS) { + link_peer = rcu_dereference(dp_peer->link_peers[i]); + if (link_peer && link_peer->peer_id == rxcb->peer_id) { + status->link_valid = 1; + status->link_id = link_peer->link_id; + return; + } + } +} diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h index 8aa79faf567fd..1d3a4788a2dd9 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h @@ -57,4 +57,10 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab, struct hal_rx_desc *rx_desc); int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab, struct ath12k_dp_rx_tid_rxq *rx_tid); +void ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status); +void ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer, + struct ath12k_skb_rxcb *rxcb, + struct ieee80211_rx_status *status); #endif diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c index 8cebb229ebed8..7cf00fda996f3 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c @@ -455,7 +455,7 @@ static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcc2072(void *tlv, void **desc) struct hal_reo_get_queue_stats_status_qcc2072 *status_tlv; u16 tag; - tag = ath12k_hal_decode_tlv32_hdr(tlv, (void **)&status_tlv); + status_tlv = ath12k_hal_decode_tlv32_hdr(tlv, &tag, NULL, NULL); /* * actual desc of REO status entry starts after tlv32_padding, * see hal_reo_get_queue_stats_status_qcc2072 @@ -506,6 +506,8 @@ const struct hal_ops hal_qcc2072_ops = { .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv32_hdr, .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcc2072, + .mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv32_hdr, + .get_tlv_hdr_align = ath12k_hal_get_tlv32_hdr_align, }; u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072(void) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c index 9d5180ef83b48..052b59265af85 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c @@ -950,6 +950,15 @@ void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_da rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_qcn9274(rx_desc); } +static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcn9274(void *tlv, void **desc) +{ + u16 tag; + + *desc = ath12k_hal_decode_tlv64_hdr(tlv, &tag, NULL, NULL); + + return tag; +} + const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = { .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM, .wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN | @@ -1138,5 +1147,7 @@ const struct hal_ops hal_qcn9274_ops = { .rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get, .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr, - .reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcn9274, + .mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .get_tlv_hdr_align = ath12k_hal_get_tlv64_hdr_align, }; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h index 0d19a9cbb68ce..6d69851e529d8 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h @@ -140,6 +140,38 @@ struct rx_mpdu_start_qcn9274 { __le32 res1; } __packed; +struct rx_mpdu_start_qcc2072 { + __le32 info0; + __le32 info2; + __le32 reo_queue_desc_lo; + __le32 info1; + __le32 pn[4]; + __le32 info4; + __le32 peer_meta_data; + __le16 ast_index; + __le16 sw_peer_id; + __le16 info3; + __le16 phy_ppdu_id; + __le32 info5; + __le32 info6; + __le16 frame_ctrl; + __le16 duration; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctrl; + u8 addr4[ETH_ALEN]; + __le16 qos_ctrl; + __le32 ht_ctrl; + __le32 info7; + __le32 res0; + __le32 res1; + __le32 res2; + __le32 info8; + __le32 res3; + __le32 res4; +} __packed; + #define QCN9274_MPDU_START_SELECT_MPDU_START_TAG BIT(0) #define QCN9274_MPDU_START_SELECT_INFO0_REO_QUEUE_DESC_LO BIT(1) #define QCN9274_MPDU_START_SELECT_INFO1_PN_31_0 BIT(2) @@ -1492,7 +1524,7 @@ struct hal_rx_desc_qcc2072 { struct rx_msdu_end_qcn9274 msdu_end; u8 rx_padding0[RX_BE_PADDING0_BYTES]; __le32 mpdu_start_tag; - struct rx_mpdu_start_qcn9274 mpdu_start; + struct rx_mpdu_start_qcc2072 mpdu_start; struct rx_pkt_hdr_tlv_qcc2072 pkt_hdr_tlv; u8 msdu_payload[]; }; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c index efbbc1cbd3e42..61be8443e46ee 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c @@ -756,6 +756,15 @@ int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal) return 0; } +static u16 ath12k_hal_reo_status_dec_tlv_hdr_wcn7850(void *tlv, void **desc) +{ + u16 tag; + + *desc = ath12k_hal_decode_tlv64_hdr(tlv, &tag, NULL, NULL); + + return tag; +} + const struct ath12k_hal_tcl_to_wbm_rbm_map ath12k_hal_tcl_to_wbm_rbm_map_wcn7850[DP_TCL_NUM_RING_MAX] = { { @@ -821,5 +830,7 @@ const struct hal_ops hal_wcn7850_ops = { .rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get, .rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get, .reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr, - .reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_wcn7850, + .mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr, + .get_tlv_hdr_align = ath12k_hal_get_tlv64_hdr_align, }; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c index 3d59fa452ec03..d9fdd2fc82986 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c @@ -158,6 +158,7 @@ static const struct ath12k_hw_ops qcn9274_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_qcn9274, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_qcn9274, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_qcn9274, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_qcn9274, }; static const struct ath12k_hw_ops wcn7850_ops = { @@ -168,6 +169,7 @@ static const struct ath12k_hw_ops wcn7850_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, }; static const struct ath12k_hw_ops qcc2072_ops = { @@ -178,6 +180,7 @@ static const struct ath12k_hw_ops qcc2072_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, }; #define ATH12K_TX_RING_MASK_0 0x1 diff --git a/drivers/net/wwan/Makefile b/drivers/net/wwan/Makefile index 3960c0ae2445c..b6c6fc9ce0f5f 100644 --- a/drivers/net/wwan/Makefile +++ b/drivers/net/wwan/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_WWAN_HWSIM) += wwan_hwsim.o obj-$(CONFIG_MHI_WWAN_CTRL) += mhi_wwan_ctrl.o obj-$(CONFIG_MHI_WWAN_MBIM) += mhi_wwan_mbim.o +CFLAGS_qcom_bam_dmux.o := -I$(src) obj-$(CONFIG_QCOM_BAM_DMUX) += qcom_bam_dmux.o obj-$(CONFIG_RPMSG_WWAN_CTRL) += rpmsg_wwan_ctrl.o obj-$(CONFIG_IOSM) += iosm/ diff --git a/drivers/net/wwan/qcom_bam_dmux.c b/drivers/net/wwan/qcom_bam_dmux.c index 6a5b22589af48..0d3865f612157 100644 --- a/drivers/net/wwan/qcom_bam_dmux.c +++ b/drivers/net/wwan/qcom_bam_dmux.c @@ -22,6 +22,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "trace-bam-dmux.h" + #define BAM_DMUX_BUFFER_SIZE SZ_2K #define BAM_DMUX_HDR_SIZE sizeof(struct bam_dmux_hdr) #define BAM_DMUX_MAX_DATA_SIZE (BAM_DMUX_BUFFER_SIZE - BAM_DMUX_HDR_SIZE) @@ -278,6 +281,7 @@ static int bam_dmux_netdev_open(struct net_device *netdev) struct bam_dmux_netdev *bndev = netdev_priv(netdev); int ret; + trace_bam_dmux_channel(bndev->dmux->dev, bndev->ch, "local_open"); ret = bam_dmux_send_cmd(bndev, BAM_DMUX_CMD_OPEN); if (ret) return ret; @@ -290,6 +294,7 @@ static int bam_dmux_netdev_stop(struct net_device *netdev) { struct bam_dmux_netdev *bndev = netdev_priv(netdev); + trace_bam_dmux_channel(bndev->dmux->dev, bndev->ch, "local_close"); netif_stop_queue(netdev); bam_dmux_send_cmd(bndev, BAM_DMUX_CMD_CLOSE); return 0; @@ -542,6 +547,7 @@ static void bam_dmux_cmd_open(struct bam_dmux *dmux, struct bam_dmux_hdr *hdr) struct net_device *netdev = dmux->netdevs[hdr->ch]; dev_dbg(dmux->dev, "open channel: %u\n", hdr->ch); + trace_bam_dmux_channel(dmux->dev, hdr->ch, "remote_open"); if (__test_and_set_bit(hdr->ch, dmux->remote_channels)) { dev_warn(dmux->dev, "Channel already open: %u\n", hdr->ch); @@ -561,6 +567,7 @@ static void bam_dmux_cmd_close(struct bam_dmux *dmux, struct bam_dmux_hdr *hdr) struct net_device *netdev = dmux->netdevs[hdr->ch]; dev_dbg(dmux->dev, "close channel: %u\n", hdr->ch); + trace_bam_dmux_channel(dmux->dev, hdr->ch, "remote_close"); if (!__test_and_clear_bit(hdr->ch, dmux->remote_channels)) { dev_err(dmux->dev, "Channel not open: %u\n", hdr->ch); @@ -590,6 +597,8 @@ static void bam_dmux_rx_callback(void *data) goto out; } + trace_bam_dmux_rx(dmux->dev, hdr->ch, hdr->cmd, hdr->len); + switch (hdr->cmd) { case BAM_DMUX_CMD_DATA: bam_dmux_cmd_data(skb_dma); @@ -624,16 +633,20 @@ static bool bam_dmux_power_on(struct bam_dmux *dmux) if (IS_ERR(dmux->rx)) { dev_err(dev, "Failed to request RX DMA channel: %pe\n", dmux->rx); dmux->rx = NULL; + trace_bam_dmux_power(dev, true, false); return false; } dmaengine_slave_config(dmux->rx, &dma_rx_conf); for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { - if (!bam_dmux_skb_dma_queue_rx(&dmux->rx_skbs[i], GFP_KERNEL)) + if (!bam_dmux_skb_dma_queue_rx(&dmux->rx_skbs[i], GFP_KERNEL)) { + trace_bam_dmux_power(dev, true, false); return false; + } } dma_async_issue_pending(dmux->rx); + trace_bam_dmux_power(dev, true, true); return true; } @@ -669,6 +682,7 @@ static void bam_dmux_power_off(struct bam_dmux *dmux) } bam_dmux_free_skbs(dmux->rx_skbs, DMA_FROM_DEVICE); + trace_bam_dmux_power(dmux->dev, false, true); } static irqreturn_t bam_dmux_pc_irq(int irq, void *data) @@ -677,6 +691,7 @@ static irqreturn_t bam_dmux_pc_irq(int irq, void *data) bool new_state = !dmux->pc_state; dev_dbg(dmux->dev, "pc: %u\n", new_state); + trace_bam_dmux_pc(dmux->dev, dmux->pc_state, new_state); if (new_state) { if (bam_dmux_power_on(dmux)) @@ -722,8 +737,11 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) /* Wait until previous power down was acked */ if (!wait_for_completion_timeout(&dmux->pc_ack_completion, - BAM_DMUX_REMOTE_TIMEOUT)) + BAM_DMUX_REMOTE_TIMEOUT)) { + trace_bam_dmux_resume_step(dev, "prev_ack", -ETIMEDOUT); return -ETIMEDOUT; + } + trace_bam_dmux_resume_step(dev, "prev_ack", 0); /* Vote for power state */ bam_dmux_pc_vote(dmux, true); @@ -732,33 +750,42 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) if (!wait_for_completion_timeout(&dmux->pc_ack_completion, BAM_DMUX_REMOTE_TIMEOUT)) { bam_dmux_pc_vote(dmux, false); + trace_bam_dmux_resume_step(dev, "ack", -ETIMEDOUT); return -ETIMEDOUT; } + trace_bam_dmux_resume_step(dev, "ack", 0); /* Wait until we're up */ if (!wait_event_timeout(dmux->pc_wait, dmux->pc_state, BAM_DMUX_REMOTE_TIMEOUT)) { bam_dmux_pc_vote(dmux, false); + trace_bam_dmux_resume_step(dev, "bam_up", -ETIMEDOUT); return -ETIMEDOUT; } + trace_bam_dmux_resume_step(dev, "bam_up", 0); /* Ensure that we actually initialized successfully */ if (!dmux->rx) { bam_dmux_pc_vote(dmux, false); + trace_bam_dmux_resume_step(dev, "bam_up", -ENXIO); return -ENXIO; } /* Request TX channel if necessary */ - if (dmux->tx) + if (dmux->tx) { + trace_bam_dmux_resume_step(dev, "tx_chan", 0); return 0; + } dmux->tx = dma_request_chan(dev, "tx"); if (IS_ERR(dmux->tx)) { dev_err(dev, "Failed to request TX DMA channel: %pe\n", dmux->tx); dmux->tx = NULL; bam_dmux_runtime_suspend(dev); + trace_bam_dmux_resume_step(dev, "tx_chan", -ENXIO); return -ENXIO; } + trace_bam_dmux_resume_step(dev, "tx_chan", 0); return 0; } diff --git a/drivers/net/wwan/trace-bam-dmux.h b/drivers/net/wwan/trace-bam-dmux.h new file mode 100644 index 0000000000000..b9a2b4b534e79 --- /dev/null +++ b/drivers/net/wwan/trace-bam-dmux.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM qcom_bam_dmux + +#if !defined(__QCOM_BAM_DMUX_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) +#define __QCOM_BAM_DMUX_TRACE_H__ + +#include +#include + +/* + * Fired at the top of bam_dmux_pc_irq() when the modem toggles its BAM + * power-control SMSM bit. + * old_state: dmux->pc_state before the edge (0 = BAM was off) + * new_state: !old_state (what we are transitioning to) + * + * Downstream equivalent (BAM_DMUX_LOG): + * "bam_dmux_smsm_cb: 0x%08x -> 0x%08x" + "reconnect / disconnect / init" + */ +TRACE_EVENT(bam_dmux_pc, + TP_PROTO(const struct device *dev, bool old_state, bool new_state), + TP_ARGS(dev, old_state, new_state), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(bool, old_state) + __field(bool, new_state) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->old_state = old_state; + __entry->new_state = new_state; + ), + TP_printk("%s: pc %s -> %s", + __get_str(dev_name), + __entry->old_state ? "on" : "off", + __entry->new_state ? "on" : "off") +); + +/* + * Fired at the end of bam_dmux_power_on() and bam_dmux_power_off() to + * record whether the BAM DMA channel setup/teardown succeeded. + * on: true = power_on, false = power_off + * success: only meaningful when on=true; false means DMA channel + * request or RX buffer queueing failed + * + * Downstream equivalent: + * "reconnect_to_bam: disconnect tx/rx, device reset, sps_connect tx/rx" + * "disconnect_to_bam: disconnect tx, disconnect rx, device reset" + */ +TRACE_EVENT(bam_dmux_power, + TP_PROTO(const struct device *dev, bool on, bool success), + TP_ARGS(dev, on, success), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(bool, on) + __field(bool, success) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->on = on; + __entry->success = success; + ), + TP_printk("%s: power %s%s", + __get_str(dev_name), + __entry->on ? "on" : "off", + __entry->on ? (__entry->success ? " ok" : " failed") : "") +); + +/* + * Fired at the completion of each step inside bam_dmux_runtime_resume(). + * result=0 means the step passed; negative errno means it failed/timed out. + * + * Steps in order: + * "prev_ack" - waited for previous power-down to be acked by modem + * "ack" - voted for power and waited for modem's ack + * "bam_up" - waited for modem to signal BAM is powered (pc_state=true) + * "tx_chan" - requested TX DMA channel + * + * Downstream equivalent (BAM_DMUX_LOG): + * "ul_wakeup waiting for previous ack" + * "ul_wakeup waiting for wakeup ack" + * "ul_wakeup waiting completion" + * "ul_wakeup complete" + */ +TRACE_EVENT(bam_dmux_resume_step, + TP_PROTO(const struct device *dev, const char *step, int result), + TP_ARGS(dev, step, result), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __string(step, step) + __field(int, result) + ), + TP_fast_assign( + __assign_str(dev_name); + __assign_str(step); + __entry->result = result; + ), + TP_printk("%s: resume %s: %d", + __get_str(dev_name), __get_str(step), __entry->result) +); + +/* + * Fired on every channel open and close event, from both the modem side + * (CMD_OPEN/CMD_CLOSE) and the local netdev side (ndo_open/ndo_stop). + * + * event: "remote_open" - modem sent CMD_OPEN + * "remote_close" - modem sent CMD_CLOSE + * "local_open" - AP opened the netdev (sent CMD_OPEN to modem) + * "local_close" - AP stopped the netdev (sent CMD_CLOSE to modem) + * + * Downstream equivalent (BAM_DMUX_LOG / BAM_DMUX_INFO): + * "handle_bam_mux_cmd: opening cid N PC enabled" + * "msm_bam_dmux_open: opening/opened ch N" + * "msm_bam_dmux_close: closing/closed ch N" + */ +TRACE_EVENT(bam_dmux_channel, + TP_PROTO(const struct device *dev, u8 ch, const char *event), + TP_ARGS(dev, ch, event), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u8, ch) + __string(event, event) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->ch = ch; + __assign_str(event); + ), + TP_printk("%s: ch %u %s", + __get_str(dev_name), __entry->ch, __get_str(event)) +); + +/* + * Fired in bam_dmux_rx_callback() for every valid inbound packet after + * magic and channel validation. For data packets, len is the payload + * length. For control packets (OPEN/CLOSE), len is 0. + * + * Downstream equivalent (BAM_DMUX_INFO via handle_bam_mux_cmd): + * "handle_bam_mux_cmd: magic 33fc signal %x cmd %d pad %d ch %d len %d" + */ +TRACE_EVENT(bam_dmux_rx, + TP_PROTO(const struct device *dev, u8 ch, u8 cmd, u16 len), + TP_ARGS(dev, ch, cmd, len), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u8, ch) + __field(u8, cmd) + __field(u16, len) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->ch = ch; + __entry->cmd = cmd; + __entry->len = len; + ), + TP_printk("%s: rx ch %u cmd %u len %u", + __get_str(dev_name), __entry->ch, __entry->cmd, __entry->len) +); + +#endif /* __QCOM_BAM_DMUX_TRACE_H__ */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace-bam-dmux + +#include diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 06722259d2e37..6fad88232b47f 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -1169,17 +1169,6 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp) dw_pcie_dbi_ro_wr_dis(pci); - /* - * The iMSI-RX module does not support receiving MSI or MSI-X generated - * by the Root Port. If iMSI-RX is used as the MSI controller, remove - * the MSI and MSI-X capabilities of the Root Port to allow the drivers - * to fall back to INTx instead. - */ - if (pp->use_imsi_rx && !pp->keep_rp_msi_en) { - dw_pcie_remove_capability(pci, PCI_CAP_ID_MSI); - dw_pcie_remove_capability(pci, PCI_CAP_ID_MSIX); - } - return 0; } EXPORT_SYMBOL_GPL(dw_pcie_setup_rc); diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index d8eb52857f69c..19daadee65f7c 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -2309,6 +2309,7 @@ static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8550", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-x1e80100", .data = &cfg_sc8280xp }, + { .compatible = "qcom,shikra-pcie", .data = &cfg_1_9_0 }, { } }; diff --git a/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c b/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c index 488e1ec34a7fb..b9912f0225550 100644 --- a/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c +++ b/drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c @@ -63,6 +63,8 @@ #define TC9563_TX_MARGIN_MIN_UA 400000 +#define TC9563_GPIO_NONE (-1) + /* * From TC9563 PORSYS rev 0.2, figure 1.1 POR boot sequence * wait for 10ms for the internal osc frequency to stabilize. @@ -92,6 +94,10 @@ struct tc9563_pwrctrl_cfg { u8 nfts[2]; /* GEN1 & GEN2 */ bool disable_dfe; bool disable_port; + + int ep_reset_gpio; + int ep_pwr_en_gpio; + }; #define TC9563_PWRCTL_MAX_SUPPLY 6 @@ -257,6 +263,89 @@ static int tc9563_pwrctrl_disable_port(struct tc9563_pwrctrl *tc9563, ARRAY_SIZE(common_pwroff_seq)); } +static int tc9563_pwrctrl_ep_pwr_en(struct tc9563_pwrctrl *tc9563, + enum tc9563_pwrctrl_ports port, + bool enable, int ep_pwr_en_gpio) +{ + u32 ep_pwr_en_gpio_mask, val; + int ret; + + if (ep_pwr_en_gpio == TC9563_GPIO_NONE) + return 0; + + ep_pwr_en_gpio_mask = BIT(ep_pwr_en_gpio); + + /* Set TC9563 GPIO as output */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_GPIO_CONFIG, + &val); + if (ret) + return ret; + + val &= ~ep_pwr_en_gpio_mask; + + ret = tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_GPIO_CONFIG, + val); + if (ret) + return ret; + + /* Toggle 0->1 to enable power */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_RESET_GPIO, + &val); + if (ret) + return ret; + + val = enable ? (val | ep_pwr_en_gpio_mask) : (val & ~ep_pwr_en_gpio_mask); + + return tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_RESET_GPIO, val); + +} + +static int tc9563_pwrctrl_ep_assert_deassert_reset(struct tc9563_pwrctrl *tc9563, + enum tc9563_pwrctrl_ports port, + bool deassert, int ep_reset_gpio) +{ + u32 ep_reset_gpio_mask, val; + int ret; + + if (ep_reset_gpio == TC9563_GPIO_NONE) { + switch (port) { + case TC9563_DSP1: + ep_reset_gpio = 0x2; + break; + case TC9563_DSP2: + ep_reset_gpio = 0x3; + break; + default: + return 0; + } + } + + ep_reset_gpio_mask = BIT(ep_reset_gpio); + + /* Set TC9563 GPIO as output */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_GPIO_CONFIG, + &val); + if (ret) + return ret; + + val &= ~ep_reset_gpio_mask; + + ret = tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_GPIO_CONFIG, + val); + if (ret) + return ret; + + /* Assert-deassert endpoint reset */ + ret = tc9563_pwrctrl_i2c_read(tc9563->client, TC9563_RESET_GPIO, + &val); + if (ret) + return ret; + + val = deassert ? (val | ep_reset_gpio_mask) : (val & ~ep_reset_gpio_mask); + + return tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_RESET_GPIO, val); +} + static int tc9563_pwrctrl_set_l0s_l1_entry_delay(struct tc9563_pwrctrl *tc9563, enum tc9563_pwrctrl_ports port, bool is_l1, u32 ns) @@ -401,28 +490,17 @@ static int tc9563_pwrctrl_set_nfts(struct tc9563_pwrctrl *tc9563, ARRAY_SIZE(nfts_seq)); } -static int tc9563_pwrctrl_assert_deassert_reset(struct tc9563_pwrctrl *tc9563, - bool deassert) -{ - int ret, val; - - ret = tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_GPIO_CONFIG, - TC9563_GPIO_MASK); - if (ret) - return ret; - - val = deassert ? TC9563_GPIO_DEASSERT_BITS : 0; - - return tc9563_pwrctrl_i2c_write(tc9563->client, TC9563_RESET_GPIO, val); -} - static int tc9563_pwrctrl_parse_device_dt(struct tc9563_pwrctrl *tc9563, struct device_node *node, enum tc9563_pwrctrl_ports port) { struct tc9563_pwrctrl_cfg *cfg = &tc9563->cfg[port]; + struct of_phandle_args args; int ret; + cfg->ep_reset_gpio = TC9563_GPIO_NONE; + cfg->ep_pwr_en_gpio = TC9563_GPIO_NONE; + /* Disable port if the status of the port is disabled. */ if (!of_device_is_available(node)) { cfg->disable_port = true; @@ -437,6 +515,18 @@ static int tc9563_pwrctrl_parse_device_dt(struct tc9563_pwrctrl *tc9563, if (ret && ret != -EINVAL) return ret; + ret = of_parse_phandle_with_fixed_args(node, "ep-pwr-en-gpios", 2, 0, &args); + if (ret && ret != -ENOENT) + return ret; + else if (!ret) + cfg->ep_pwr_en_gpio = args.args[0]; + + ret = of_parse_phandle_with_fixed_args(node, "reset-gpios", 2, 0, &args); + if (ret && ret != -ENOENT) + return ret; + else if (!ret) + cfg->ep_reset_gpio = args.args[0]; + ret = of_property_read_u32(node, "toshiba,tx-amplitude-microvolt", &cfg->tx_amp); if (ret && ret != -EINVAL) return ret; @@ -479,18 +569,28 @@ static int tc9563_pwrctrl_power_on(struct pci_pwrctrl *pwrctrl) fsleep(TC9563_OSC_STAB_DELAY_US); - ret = tc9563_pwrctrl_assert_deassert_reset(tc9563, false); - if (ret) - goto power_off; - for (i = 0; i < TC9563_MAX; i++) { cfg = &tc9563->cfg[i]; + ret = tc9563_pwrctrl_disable_port(tc9563, i); if (ret) { dev_err(dev, "Disabling port failed\n"); goto power_off; } + ret = tc9563_pwrctrl_ep_assert_deassert_reset(tc9563, i, false, + cfg->ep_reset_gpio); + if (ret) { + dev_err(dev, "Assert EP reset failed\n"); + goto power_off; + } + + ret = tc9563_pwrctrl_ep_pwr_en(tc9563, i, true, cfg->ep_pwr_en_gpio); + if (ret) { + dev_err(dev, "Enabling EP Power failed\n"); + goto power_off; + } + ret = tc9563_pwrctrl_set_l0s_l1_entry_delay(tc9563, i, false, cfg->l0s_delay); if (ret) { dev_err(dev, "Setting L0s entry delay failed\n"); @@ -520,11 +620,17 @@ static int tc9563_pwrctrl_power_on(struct pci_pwrctrl *pwrctrl) dev_err(dev, "Disabling DFE failed\n"); goto power_off; } + + ret = tc9563_pwrctrl_ep_assert_deassert_reset(tc9563, i, true, + cfg->ep_reset_gpio); + if (ret) { + dev_err(dev, "De-assert EP reset failed\n"); + goto power_off; + } + } - ret = tc9563_pwrctrl_assert_deassert_reset(tc9563, true); - if (!ret) - return 0; + return 0; power_off: tc9563_pwrctrl_power_off(&tc9563->pwrctrl); @@ -602,7 +708,7 @@ static int tc9563_pwrctrl_probe(struct platform_device *pdev) port++; ret = tc9563_pwrctrl_parse_device_dt(tc9563, child1, port); - if (ret) + if (port + 1 >= TC9563_MAX || ret) break; } } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b09f27f7846fc..ee28d7c57c997 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2523,6 +2523,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, 0x0451, quirk_disable_aspm_l0s DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PASEMI, 0xa002, quirk_disable_aspm_l0s_l1); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HUAWEI, 0x1105, quirk_disable_aspm_l0s_l1); +static void quirk_disable_aspm_l1ss(struct pci_dev *dev) +{ + pci_disable_link_state(dev, PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_QCOM, 0x1103, quirk_disable_aspm_l1ss); + /* * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain * Link bit cleared after starting the link retrain process to allow this @@ -6415,3 +6421,13 @@ static void pci_mask_replay_timer_timeout(struct pci_dev *pdev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9750, pci_mask_replay_timer_timeout); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9755, pci_mask_replay_timer_timeout); #endif + +/* + * Renesas PCIe-to-USB bridge UPD720201 does not advertise D3cold + * capability by default until firmware is loaded post-enumeration. + */ +static void quirk_enable_d3cold(struct pci_dev *dev) +{ + dev->pme_support = dev->pme_support | (1 << PCI_D3cold); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RENESAS, 0x0014, quirk_enable_d3cold); diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index 6e5cc4086a9e2..4cf5d86647651 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -2,6 +2,7 @@ // Copyright (C) 2016-2020 Arm Limited // ARM CMN/CI interconnect PMU driver +#include #include #include #include @@ -19,11 +20,6 @@ #include /* Common register stuff */ -#define CMN_NODE_INFO 0x0000 -#define CMN_NI_NODE_TYPE GENMASK_ULL(15, 0) -#define CMN_NI_NODE_ID GENMASK_ULL(31, 16) -#define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32) - #define CMN_CHILD_INFO 0x0080 #define CMN_CI_CHILD_COUNT GENMASK_ULL(15, 0) #define CMN_CI_CHILD_PTR_OFFSET GENMASK_ULL(31, 16) @@ -243,37 +239,6 @@ enum cmn_revision { REV_CI700_R2P0, }; -enum cmn_node_type { - CMN_TYPE_INVALID, - CMN_TYPE_DVM, - CMN_TYPE_CFG, - CMN_TYPE_DTC, - CMN_TYPE_HNI, - CMN_TYPE_HNF, - CMN_TYPE_XP, - CMN_TYPE_SBSX, - CMN_TYPE_MPAM_S, - CMN_TYPE_MPAM_NS, - CMN_TYPE_RNI, - CMN_TYPE_RND = 0xd, - CMN_TYPE_RNSAM = 0xf, - CMN_TYPE_MTSX, - CMN_TYPE_HNP, - CMN_TYPE_CXRA = 0x100, - CMN_TYPE_CXHA, - CMN_TYPE_CXLA, - CMN_TYPE_CCRA, - CMN_TYPE_CCHA, - CMN_TYPE_CCLA, - CMN_TYPE_CCLA_RNI, - CMN_TYPE_HNS = 0x200, - CMN_TYPE_HNS_MPAM_S, - CMN_TYPE_HNS_MPAM_NS, - CMN_TYPE_APB = 0x1000, - /* Not a real node type */ - CMN_TYPE_WP = 0x7770 -}; - enum cmn_filter_select { SEL_NONE = -1, SEL_OCCUP1ID, diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 60a0ead127fa9..ea33025a40fd0 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -28,6 +28,19 @@ config PHY_QCOM_EDP Enable this driver to support the Qualcomm eDP PHY found in various Qualcomm chipsets. +config PHY_QCOM_MIPI_CSI2 + tristate "Qualcomm MIPI CSI2 PHY driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on OF + depends on COMMON_CLK + select GENERIC_PHY + select GENERIC_PHY_MIPI_DPHY + help + Enable this to support the MIPI CSI2 PHY driver found in various + Qualcomm chipsets. This PHY is used to connect MIPI CSI2 + camera sensors to the CSI Decoder in the Qualcomm Camera Subsystem + CAMSS. + config PHY_QCOM_IPQ4019_USB tristate "Qualcomm IPQ4019 USB PHY driver" depends on OF && (ARCH_QCOM || COMPILE_TEST) diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index b71a6a0bed3f1..382cb594b06b6 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -6,6 +6,11 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_M31_EUSB) += phy-qcom-m31-eusb2.o + +phy-qcom-mipi-csi2-objs += phy-qcom-mipi-csi2-core.o \ + phy-qcom-mipi-csi2-3ph-dphy.o +obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) += phy-qcom-mipi-csi2.o + obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c new file mode 100644 index 0000000000000..b1eb2b28b2da2 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0 + * + * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2016-2025 Linaro Ltd. + */ + +#include +#include +#include +#include + +#include "phy-qcom-mipi-csi2.h" + +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(offset, n) ((offset) + 0x4 * (n)) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE BIT(7) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID BIT(1) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL10_IRQ_CLEAR_CMD BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, n) ((offset) + 0xb0 + 0x4 * (n)) + +/* + * 3 phase CSI has 19 common status regs with only 0-10 being used + * and 11-18 being reserved. + */ +#define CSI_COMMON_STATUS_NUM 11 +/* + * There are a number of common control registers + * The offset to clear the CSIPHY IRQ status starts @ 22 + * So to clear CSI_COMMON_STATUS0 this is CSI_COMMON_CONTROL22, STATUS1 is + * CONTROL23 and so on + */ +#define CSI_CTRL_STATUS_INDEX 22 + +/* + * There are 43 COMMON_CTRL registers with regs after # 33 being reserved + */ +#define CSI_CTRL_MAX 33 + +#define CSIPHY_DEFAULT_PARAMS 0 +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 +#define CSIPHY_SKEW_CAL 7 + +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ +static const struct +mipi_csi2phy_lane_regs lane_regs_x1e80100[] = { + /* Power up lanes 2ph mode */ + {.reg_addr = 0x1014, .reg_data = 0xd5, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x101c, .reg_data = 0x7a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x00a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0000, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0038, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x002c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0034, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x001c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x003c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0004, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x005c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0060, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0064, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0e94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0ea0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e0c, .reg_data = 0xff, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e38, .reg_data = 0x1f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0e10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x04a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0400, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0438, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x042c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0434, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x041c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x043c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0404, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x045c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0460, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0464, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x08a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0800, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0838, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x082c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0834, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x081c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x083c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0804, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x085c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0860, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0864, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0c94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0ca0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c00, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c38, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0c10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c94, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c5c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c60, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c64, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, +}; + +static inline const struct mipi_csi2phy_device_regs * +csi2phy_dev_to_regs(struct mipi_csi2phy_device *csi2phy) +{ + return &csi2phy->soc_cfg->reg_info; +} + +static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + u32 tmp; + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); + csi2phy->hw_version = tmp; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); + csi2phy->hw_version |= (tmp << 8) & 0xFF00; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); + csi2phy->hw_version |= (tmp << 16) & 0xFF0000; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); + csi2phy->hw_version |= (tmp << 24) & 0xFF000000; + + dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 0x%08x\n", csi2phy->hw_version); +} + +/* + * phy_qcom_mipi_csi2_reset - Perform software reset on CSIPHY module + * @phy_qcom_mipi_csi2: CSIPHY device + */ +static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET, + csi2phy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); + usleep_range(5000, 8000); + writel(0x0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); +} + +/* + * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value + * + * Helper function to calculate settle count value. This is + * based on the CSI2 T_hs_settle parameter which in turn + * is calculated based on the CSI2 transmitter link frequency. + * + * Return settle count value or 0 if the CSI2 link frequency + * is not available + */ +static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate) +{ + u32 t_hs_prepare_max_ps; + u32 timer_period_ps; + u32 t_hs_settle_ps; + u8 settle_cnt; + u32 ui_ps; + + if (link_freq <= 0) + return 0; + + ui_ps = div_u64(PSEC_PER_SEC, link_freq); + ui_ps /= 2; + t_hs_prepare_max_ps = 85000 + 6 * ui_ps; + t_hs_settle_ps = t_hs_prepare_max_ps; + + timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate); + settle_cnt = t_hs_settle_ps / timer_period_ps - 6; + + return settle_cnt; +} + +static void +phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy, + u8 settle_cnt) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + const struct mipi_csi2phy_lane_regs *r = regs->init_seq; + int i, array_size = regs->lane_array_size; + u32 val; + + for (i = 0; i < array_size; i++, r++) { + switch (r->param_type) { + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + val = settle_cnt & 0xff; + break; + case CSIPHY_SKEW_CAL: + /* TODO: support application of skew from dt flag */ + continue; + default: + val = r->reg_data; + break; + } + writel(val, csi2phy->base + r->reg_addr); + if (r->delay_us) + udelay(r->delay_us); + } +} + +static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg; + u8 settle_cnt; + u8 val; + int i; + + settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate); + + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + for (i = 0; i < cfg->num_data_lanes; i++) + val |= BIT(lane_cfg->data[i].pos * 2); + + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + val = 0x02; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7)); + + val = 0x00; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); + + phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt); + + /* IRQ_MASK registers - disable all interrupts */ + for (i = CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) { + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, i)); + } + + return 0; +} + +static void +phy_qcom_mipi_csi2_lanes_disable(struct mipi_csi2phy_device *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); +} + +static const struct mipi_csi2phy_hw_ops phy_qcom_mipi_csi2_ops_3ph_1_0 = { + .hw_version_read = phy_qcom_mipi_csi2_hw_version_read, + .reset = phy_qcom_mipi_csi2_reset, + .lanes_enable = phy_qcom_mipi_csi2_lanes_enable, + .lanes_disable = phy_qcom_mipi_csi2_lanes_disable, +}; + +static const char * const x1e_clks[] = { + "core", + "timer" +}; + +static const char * const x1e_supplies[] = { + "vdda-0p9", + "vdda-1p2" +}; + +static const char * const x1e_genpd_names[] = { + "mx", + "mmcx", +}; + +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { + .ops = &phy_qcom_mipi_csi2_ops_3ph_1_0, + .reg_info = { + .init_seq = lane_regs_x1e80100, + .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100), + .common_regs_offset = 0x1000, + }, + .supply_names = (const char **)x1e_supplies, + .num_supplies = ARRAY_SIZE(x1e_supplies), + .clk_names = (const char **)x1e_clks, + .num_clk = ARRAY_SIZE(x1e_clks), + .opp_clk = x1e_clks[0], + .timer_clk = x1e_clks[1], + .genpd_names = (const char **)x1e_genpd_names, + .num_genpd_names = ARRAY_SIZE(x1e_genpd_names), +}; diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c new file mode 100644 index 0000000000000..47acf0d586a15 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Linaro Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "phy-qcom-mipi-csi2.h" + +static int +phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy, + s64 link_freq) +{ + struct device *dev = csi2phy->dev; + unsigned long opp_rate = link_freq / 4; + struct dev_pm_opp *opp; + long timer_rate; + int ret; + + opp = dev_pm_opp_find_freq_ceil(dev, &opp_rate); + if (IS_ERR(opp)) { + dev_err(csi2phy->dev, "Couldn't find ceiling for %lld Hz\n", + link_freq); + return PTR_ERR(opp); + } + + for (int i = 0; i < csi2phy->num_pds; i++) { + unsigned int perf = dev_pm_opp_get_required_pstate(opp, i); + + ret = dev_pm_genpd_set_performance_state(csi2phy->pds[i], perf); + if (ret) { + dev_err(csi2phy->dev, "Couldn't set perf state %u\n", + perf); + dev_pm_opp_put(opp); + return ret; + } + } + dev_pm_opp_put(opp); + + ret = dev_pm_opp_set_rate(dev, opp_rate); + if (ret) { + dev_err(csi2phy->dev, "dev_pm_opp_set_rate() fail\n"); + return ret; + } + + timer_rate = clk_round_rate(csi2phy->timer_clk, link_freq / 4); + if (timer_rate < 0) + return timer_rate; + + ret = clk_set_rate(csi2phy->timer_clk, timer_rate); + if (ret) + return ret; + + csi2phy->timer_clk_rate = timer_rate; + + return 0; +} + +static int phy_qcom_mipi_csi2_configure(struct phy *phy, + union phy_configure_opts *opts) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + struct phy_configure_opts_mipi_dphy *dphy_cfg = &opts->mipi_dphy; + struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg; + int ret; + int i; + + ret = phy_mipi_dphy_config_validate(dphy_cfg); + if (ret) + return ret; + + if (dphy_cfg->lanes < 1 || dphy_cfg->lanes > CSI2_MAX_DATA_LANES) + return -EINVAL; + + stream_cfg->link_freq = dphy_cfg->hs_clk_rate; + stream_cfg->num_data_lanes = dphy_cfg->lanes; + + for (i = 0; i < stream_cfg->num_data_lanes; i++) { + stream_cfg->lane_cfg.data[i].pol = dphy_cfg->lane_polarities[i]; + stream_cfg->lane_cfg.data[i].pos = dphy_cfg->lane_positions[i]; + } + + stream_cfg->lane_cfg.clk.pol = dphy_cfg->clock_lane_polarity; + stream_cfg->lane_cfg.clk.pos = dphy_cfg->clock_lane_position; + + return 0; +} + +static int phy_qcom_mipi_csi2_power_on(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + const struct mipi_csi2phy_hw_ops *ops = csi2phy->soc_cfg->ops; + struct device *dev = &phy->dev; + int ret; + + ret = regulator_bulk_enable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + if (ret) + return ret; + + ret = phy_qcom_mipi_csi2_set_clock_rates(csi2phy, csi2phy->stream_cfg.link_freq); + if (ret) + goto poweroff_phy; + + ret = clk_bulk_prepare_enable(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + if (ret) { + dev_err(dev, "failed to enable clocks, %d\n", ret); + goto poweroff_phy; + } + + ops->reset(csi2phy); + + ops->hw_version_read(csi2phy); + + return ops->lanes_enable(csi2phy, &csi2phy->stream_cfg); + +poweroff_phy: + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return ret; +} + +static int phy_qcom_mipi_csi2_power_off(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + int i; + + for (i = 0; i < csi2phy->num_pds; i++) + dev_pm_genpd_set_performance_state(csi2phy->pds[i], 0); + + clk_bulk_disable_unprepare(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return 0; +} + +static const struct phy_ops phy_qcom_mipi_csi2_ops = { + .configure = phy_qcom_mipi_csi2_configure, + .power_on = phy_qcom_mipi_csi2_power_on, + .power_off = phy_qcom_mipi_csi2_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *qcom_csi2_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct mipi_csi2phy_device *csi2phy = dev_get_drvdata(dev); + + if (args->args[0] != PHY_QCOM_CSI2_MODE_DPHY) { + dev_err(csi2phy->dev, "mode %d -EOPNOTSUPP\n", args->args[0]); + return ERR_PTR(-EOPNOTSUPP); + } + + csi2phy->phy_mode = args->args[0]; + + return csi2phy->phy; +} + +static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev) +{ + unsigned int i, num_clk, num_supplies, num_pds; + struct mipi_csi2phy_device *csi2phy; + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct phy *generic_phy; + int ret; + + csi2phy = devm_kzalloc(dev, sizeof(*csi2phy), GFP_KERNEL); + if (!csi2phy) + return -ENOMEM; + + csi2phy->dev = dev; + dev_set_drvdata(dev, csi2phy); + + csi2phy->soc_cfg = device_get_match_data(&pdev->dev); + + if (!csi2phy->soc_cfg) + return -EINVAL; + + num_clk = csi2phy->soc_cfg->num_clk; + csi2phy->clks = devm_kzalloc(dev, sizeof(*csi2phy->clks) * num_clk, GFP_KERNEL); + if (!csi2phy->clks) + return -ENOMEM; + + num_pds = csi2phy->soc_cfg->num_genpd_names; + if (!num_pds) + return -EINVAL; + + csi2phy->pds = devm_kzalloc(dev, sizeof(*csi2phy->pds) * num_pds, GFP_KERNEL); + if (!csi2phy->pds) + return -ENOMEM; + + for (i = 0; i < num_pds; i++) { + csi2phy->pds[i] = dev_pm_domain_attach_by_name(dev, + csi2phy->soc_cfg->genpd_names[i]); + if (IS_ERR(csi2phy->pds[i])) { + return dev_err_probe(dev, PTR_ERR(csi2phy->pds[i]), + "Failed to attach %s\n", + csi2phy->soc_cfg->genpd_names[i]); + } + } + csi2phy->num_pds = num_pds; + + for (i = 0; i < num_clk; i++) + csi2phy->clks[i].id = csi2phy->soc_cfg->clk_names[i]; + + ret = devm_clk_bulk_get(dev, num_clk, csi2phy->clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + csi2phy->timer_clk = devm_clk_get(dev, csi2phy->soc_cfg->timer_clk); + if (IS_ERR(csi2phy->timer_clk)) { + return dev_err_probe(dev, PTR_ERR(csi2phy->timer_clk), + "Failed to get timer clock\n"); + } + + ret = devm_pm_opp_set_clkname(dev, csi2phy->soc_cfg->opp_clk); + if (ret) + return dev_err_probe(dev, ret, "Failed to set opp clkname\n"); + + ret = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table in device tree\n"); + + num_supplies = csi2phy->soc_cfg->num_supplies; + csi2phy->supplies = devm_kzalloc(dev, sizeof(*csi2phy->supplies) * num_supplies, + GFP_KERNEL); + if (!csi2phy->supplies) + return -ENOMEM; + + for (i = 0; i < num_supplies; i++) + csi2phy->supplies[i].supply = csi2phy->soc_cfg->supply_names[i]; + + ret = devm_regulator_bulk_get(dev, num_supplies, csi2phy->supplies); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); + + csi2phy->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(csi2phy->base)) + return PTR_ERR(csi2phy->base); + + generic_phy = devm_phy_create(dev, NULL, &phy_qcom_mipi_csi2_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); + return dev_err_probe(dev, ret, "failed to create phy\n"); + } + csi2phy->phy = generic_phy; + + phy_set_drvdata(generic_phy, csi2phy); + + phy_provider = devm_of_phy_provider_register(dev, qcom_csi2_phy_xlate); + if (!IS_ERR(phy_provider)) + dev_dbg(dev, "Registered MIPI CSI2 PHY device\n"); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id phy_qcom_mipi_csi2_of_match_table[] = { + { .compatible = "qcom,x1e80100-csi2-phy", .data = &mipi_csi2_dphy_4nm_x1e }, + { } +}; +MODULE_DEVICE_TABLE(of, phy_qcom_mipi_csi2_of_match_table); + +static struct platform_driver phy_qcom_mipi_csi2_driver = { + .probe = phy_qcom_mipi_csi2_probe, + .driver = { + .name = "qcom-mipi-csi2-phy", + .of_match_table = phy_qcom_mipi_csi2_of_match_table, + }, +}; + +module_platform_driver(phy_qcom_mipi_csi2_driver); + +MODULE_DESCRIPTION("Qualcomm MIPI CSI2 PHY driver"); +MODULE_AUTHOR("Bryan O'Donoghue "); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..27607dea412f1 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * + * Qualcomm MIPI CSI2 CPHY/DPHY driver + * + * Copyright (C) 2025 Linaro Ltd. + */ +#ifndef __PHY_QCOM_MIPI_CSI2_H__ +#define __PHY_QCOM_MIPI_CSI2_H__ + +#include + +#define CSI2_MAX_DATA_LANES 4 + +struct mipi_csi2phy_lane { + u8 pos; + u8 pol; +}; + +struct mipi_csi2phy_lanes_cfg { + struct mipi_csi2phy_lane data[CSI2_MAX_DATA_LANES]; + struct mipi_csi2phy_lane clk; +}; + +struct mipi_csi2phy_stream_cfg { + s64 link_freq; + u8 num_data_lanes; + struct mipi_csi2phy_lanes_cfg lane_cfg; +}; + +struct mipi_csi2phy_device; + +struct mipi_csi2phy_hw_ops { + void (*hw_version_read)(struct mipi_csi2phy_device *csi2phy_dev); + void (*reset)(struct mipi_csi2phy_device *csi2phy_dev); + int (*lanes_enable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); + void (*lanes_disable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); +}; + +struct mipi_csi2phy_lane_regs { + const s32 reg_addr; + const s32 reg_data; + const u32 delay_us; + const u32 param_type; +}; + +struct mipi_csi2phy_device_regs { + const struct mipi_csi2phy_lane_regs *init_seq; + const int lane_array_size; + const u32 common_regs_offset; +}; + +struct mipi_csi2phy_soc_cfg { + const struct mipi_csi2phy_hw_ops *ops; + const struct mipi_csi2phy_device_regs reg_info; + + const char ** const supply_names; + const unsigned int num_supplies; + + const char ** const clk_names; + const unsigned int num_clk; + + const char * const opp_clk; + const char * const timer_clk; + + const char ** const genpd_names; + const unsigned int num_genpd_names; +}; + +struct mipi_csi2phy_device { + struct device *dev; + u8 phy_mode; + + struct phy *phy; + void __iomem *base; + + struct clk_bulk_data *clks; + struct clk *timer_clk; + u32 timer_clk_rate; + + struct regulator_bulk_data *supplies; + struct device **pds; + unsigned int num_pds; + + const struct mipi_csi2phy_soc_cfg *soc_cfg; + struct mipi_csi2phy_stream_cfg stream_cfg; + + u32 hw_version; +}; + +extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e; + +#endif /* __PHY_QCOM_MIPI_CSI2_H__ */ diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index cdcfad2e86b1d..6c5f56c2e1ffc 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -283,8 +283,8 @@ static const unsigned int qmp_v8_n3_usb43dpphy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_DP_AON_TOGGLE_ENABLE] = QPHY_V8_PCS_AON_DP_AON_TOGGLE_ENABLE, [QPHY_COM_RESETSM_CNTRL] = QSERDES_V8_COM_RESETSM_CNTRL, - [QPHY_COM_C_READY_STATUS] = QSERDES_V8_COM_C_READY_STATUS, - [QPHY_COM_CMN_STATUS] = QSERDES_V8_COM_CMN_STATUS, + [QPHY_COM_C_READY_STATUS] = QSERDES_V8_COM_C_READY_STATUS_N3, + [QPHY_COM_CMN_STATUS] = QSERDES_V8_COM_CMN_STATUS_N3, [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN, [QPHY_DP_PHY_STATUS] = QSERDES_V8_DP_PHY_STATUS, @@ -1386,10 +1386,10 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl[] = { }; static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE1, 0x10), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), @@ -1404,12 +1404,13 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x3b), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_RESETSM_CNTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP_EN, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x56), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_1, 0x40), @@ -1445,26 +1446,26 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_tx_tbl[] = { }; static const struct qmp_phy_init_tbl qmp_v8_n3p_dp_tx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x1a), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_VMODE_CTRL1, 0x40), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT1, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT2, 0x18), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCS_INTERFACE_SELECT1, 0x50), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_1, 0x0d), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x87), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL, 0x0f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_LVL_UPDATE_CTRL, 0x0f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRAN_DRVR_EMP_EN, 0x5f), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_EMP_POST1_LVL, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_EMP_POST1_LVL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_EMP_POST1_LVL, 0x2b), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_EMP_POST1_LVL, 0x2b), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_PRE1_EMPH, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_PRE1_EMPH, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_DRV_LVL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_DRV_LVL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_HIGHZ_DRVR_EN, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_HIGHZ_DRVR_EN, 0x3f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_2, 0x50), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_3, 0x51), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x0c), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_CAL_CTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_CAL_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_POST_CAL_OFFSET, 0x10), @@ -1589,11 +1590,12 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_hbr3[] = { static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_rbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x05), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x7a), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x8d), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x27), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x83), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x37), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x54), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x06), @@ -1601,16 +1603,17 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_rbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa4), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa7), }; static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x04), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x21), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xf6), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x18), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x08), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x46), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00), @@ -1627,7 +1630,8 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xf6), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x10), @@ -1637,9 +1641,9 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0xae), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xbf), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x17), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_RESETSM_CNTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), @@ -1647,8 +1651,8 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x63), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x25), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x5b), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06), @@ -1656,7 +1660,7 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x18), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x15), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x4f), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00), @@ -1675,19 +1679,19 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYS_CLK_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x3b), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x17), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0x84), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0x87), }; static const struct qmp_phy_init_tbl sc8280xp_usb43dp_serdes_tbl[] = { @@ -3145,6 +3149,30 @@ static int qmp_combo_configure_dp_swing(struct qmp_combo *qmp) return 0; } +static bool qmp_v8_combo_configure_dp_mode(struct qmp_combo *qmp) +{ + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; + u32 val; + + val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; + + if (dp_opts->lanes == 1 || dp_opts->lanes == 2) { + if (reverse) + val &= ~DP_PHY_PD_CTL_LANE_2_3_PWRDN; + else + val &= ~DP_PHY_PD_CTL_LANE_0_1_PWRDN; + } + + writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); + + writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); + + return reverse; +} + static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp) { const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; @@ -3324,16 +3352,70 @@ static void qmp_v4_dp_aux_init(struct qmp_combo *qmp) qmp->dp_dp_phy + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); } +static int qmp_v8_helper_configure_dp_phy(struct qmp_combo *qmp) +{ + const struct qmp_phy_cfg *cfg = qmp->cfg; + u32 status; + int ret; + + writel(0x0f, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG_1); + + qmp_v8_combo_configure_dp_mode(qmp); + + writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); + writel(0xa4, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); + + writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); + writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); + + ret = qmp->cfg->configure_dp_clocks(qmp); + if (ret) + return ret; + + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x05, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + + writel(0x20, qmp->dp_serdes + cfg->regs[QPHY_COM_RESETSM_CNTRL]); + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_C_READY_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(1)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + return 0; +} + static void qmp_v8_dp_aux_init(struct qmp_combo *qmp) { const struct qmp_phy_cfg *cfg = qmp->cfg; - writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | - DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, - qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); + writel(0x3f, qmp->dp_serdes + QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1); + + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, + qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); /* Turn on BIAS current for PHY/PLL */ - writel(0x1c, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); + writel(0x17, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG0); writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); @@ -3361,8 +3443,8 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp) writel(0x27, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); writel(0x27, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); - writel(0x20, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); - writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + writel(0x2b, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + writel(0x2b, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); qmp_combo_configure_dp_swing(qmp); } @@ -3370,48 +3452,41 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp) static int qmp_v8_configure_dp_clocks(struct qmp_combo *qmp) { const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; - u32 phy_vco_div; unsigned long pixel_freq; - const struct qmp_phy_cfg *cfg = qmp->cfg; switch (dp_opts->link_rate) { case 1620: - phy_vco_div = 0x4; pixel_freq = 1620000000UL / 2; break; case 2700: - phy_vco_div = 0x2; pixel_freq = 2700000000UL / 2; break; case 5400: - phy_vco_div = 0x4; pixel_freq = 5400000000UL / 4; break; case 8100: - phy_vco_div = 0x3; pixel_freq = 8100000000UL / 6; break; default: /* Other link rates aren't supported */ return -EINVAL; } - writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]); /* disable core reset tsync */ writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - writel(0x04, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC); - writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC); + writel(0x09, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC); + writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC); writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_CYC); - writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); + writel(0x33, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); writel(0x3e, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX2_TX3_LANE_CTL); writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX0_TX1_LANE_CTL); writel(0x01, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_CFG1); - writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); + writel(0x33, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN0_DRV_LVL); - writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN1_DRV_LVL); + writel(0x02, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN1_DRV_LVL); clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000); clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq); @@ -3558,7 +3633,7 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) u32 status; int ret; - ret = qmp_v456_configure_dp_phy(qmp); + ret = qmp_v8_helper_configure_dp_phy(qmp); if (ret < 0) return ret; @@ -3570,13 +3645,13 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) } else if (dp_opts->lanes == 2) { bias0_en = reverse ? 0x3f : 0x15; bias1_en = reverse ? 0x15 : 0x3f; - drvr0_en = 0x10; - drvr1_en = 0x10; + drvr0_en = 0x30; + drvr1_en = 0x30; } else { bias0_en = 0x3f; bias1_en = 0x3f; - drvr0_en = 0x34; - drvr1_en = 0x34; + drvr0_en = 0x30; + drvr1_en = 0x30; } writel(drvr0_en, qmp->dp_tx + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); @@ -3584,6 +3659,14 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) writel(drvr1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); writel(bias1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_TRANSCEIVER_BIAS_EN]); + writel(0x03, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + writel(0x23, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + writel(0x22, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + + writel(0x0a, qmp->dp_tx + QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL); + writel(0x0a, qmp->dp_tx2 + QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL); + + writel(0x3e, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); writel(0x08, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); udelay(100); writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); @@ -3591,16 +3674,24 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], status, - ((status & BIT(1)) > 0), + ((status & BIT(0)) > 0), 500, 10000)) return -ETIMEDOUT; - writel(0x00, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); - writel(0x00, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; - writel(0x2b, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); - writel(0x2b, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(1)) > 0), + 500, + 10000)) + return -ETIMEDOUT; return 0; } diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index d3effad7a074b..b0dcd888b7d94 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -2172,6 +2173,50 @@ static const struct qmp_phy_init_tbl sdx65_qmp_pcie_pcs_lane1_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), }; +static const struct qmp_phy_init_tbl shikra_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER2, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x6), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x9), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x3), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0xd), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x35), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_BUF_ENABLE, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x4), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CTRL_BY_PSM, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_EP_DIV, 0x19), +}; + static const struct qmp_phy_init_tbl sm8450_qmp_gen3_pcie_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), @@ -3386,6 +3431,11 @@ struct qmp_phy_cfg { /* resets to be requested */ const char * const *reset_list; int num_resets; + + /* nocsr resets to be requested */ + const char * const *nocsr_reset_list; + int num_nocsr_resets; + /* regulators to be requested */ const char * const *vreg_list; int num_vregs; @@ -3432,7 +3482,7 @@ struct qmp_pcie { int num_pipe_clks; struct reset_control_bulk_data *resets; - struct reset_control *nocsr_reset; + struct reset_control_bulk_data *nocsr_reset; struct regulator_bulk_data *vregs; struct phy *phy; @@ -3440,6 +3490,8 @@ struct qmp_pcie { struct clk_fixed_rate pipe_clk_fixed; struct clk_fixed_rate aux_clk_fixed; + + struct dev_pm_domain_list *pd_list; }; static bool qphy_checkbits(const void __iomem *base, u32 offset, u32 val) @@ -3476,7 +3528,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) /* list of clocks required by phy */ static const char * const qmp_pciephy_clk_l[] = { - "aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux", + "aux", "cfg_ahb", "ref", "refgen", "rchng", "phy_aux", "phy_b_aux", }; /* list of regulators */ @@ -3485,7 +3537,11 @@ static const char * const qmp_phy_vreg_l[] = { }; static const char * const sm8550_qmp_phy_vreg_l[] = { - "vdda-phy", "vdda-pll", "vdda-qref", + "vdda-phy", "vdda-pll", "vdda-refgen0p9", "vdda-refgen1p2", "vdda-qref","vdda-qref2", +}; + +static const char * const sa8775p_qmp_phy_vreg_l[] = { + "vdda-phy", "vdda-pll", "vdda-qref", "vdda-refgen", }; /* list of resets */ @@ -3497,6 +3553,18 @@ static const char * const sdm845_pciephy_reset_l[] = { "phy", }; +static const char * const sm8550_pciephy_nocsr_reset_l[] = { + "phy_nocsr", +}; + +static const char * const glymur_pciephy_reset_l[] = { + "phy", "phy_b" +}; + +static const char * const glymur_pciephy_nocsr_reset_l[] = { + "phy_nocsr", "phy_b_nocsr", +}; + static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = { .serdes = 0, .pcs = 0x1800, @@ -3853,8 +3921,8 @@ static const struct qmp_phy_cfg qcs8300_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -3911,6 +3979,32 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { .phy_status = PHYSTATUS, }; +static const struct qmp_phy_cfg shikra_pciephy_cfg = { + .lanes = 1, + + .offsets = &qmp_pcie_offsets_v2, + + .tbls = { + .serdes = shikra_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(shikra_pcie_serdes_tbl), + .tx = qcs615_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(qcs615_pcie_tx_tbl), + .rx = qcs615_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(qcs615_pcie_rx_tbl), + .pcs = qcs615_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(qcs615_pcie_pcs_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = pciephy_v2_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +}; + + static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { .lanes = 1, @@ -4480,6 +4574,8 @@ static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = { }, .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = sm8550_qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4512,6 +4608,8 @@ static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = { }, .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = sm8550_qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4563,8 +4661,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4604,14 +4702,43 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, .phy_status = PHYSTATUS_4_20, }; +static const struct qmp_phy_cfg x1e80100_qmp_gen3x2_pciephy_cfg = { + .lanes = 2, + + .offsets = &qmp_pcie_offsets_v5, + + .tbls = { + .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl), + .tx = sm8550_qmp_gen3x2_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl), + .rx = sm8550_qmp_gen3x2_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl), + .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl), + .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl, + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), + .regs = pciephy_v5_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +}; + static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { .lanes = 2, @@ -4634,8 +4761,10 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4667,8 +4796,10 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4698,8 +4829,10 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -4713,6 +4846,8 @@ static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v6_regs_layout, @@ -4741,6 +4876,8 @@ static const struct qmp_phy_cfg qmp_v8_gen3x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), .vreg_list = qmp_phy_vreg_l, .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v8_regs_layout, @@ -4756,8 +4893,10 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v8_50_regs_layout, @@ -4772,8 +4911,10 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), .regs = pciephy_v8_regs_layout, @@ -4781,6 +4922,23 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = { .phy_status = PHYSTATUS_4_20, }; +static const struct qmp_phy_cfg glymur_qmp_gen5x8_pciephy_cfg = { + .lanes = 8, + + .offsets = &qmp_pcie_offsets_v8_50, + + .reset_list = glymur_pciephy_reset_l, + .num_resets = ARRAY_SIZE(glymur_pciephy_reset_l), + .nocsr_reset_list = glymur_pciephy_nocsr_reset_l, + .num_nocsr_resets = ARRAY_SIZE(glymur_pciephy_nocsr_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), + + .regs = pciephy_v8_50_regs_layout, + + .phy_status = PHYSTATUS_4_20, +}; + static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls) { const struct qmp_phy_cfg *cfg = qmp->cfg; @@ -4900,7 +5058,7 @@ static int qmp_pcie_init(struct phy *phy) } } - ret = reset_control_assert(qmp->nocsr_reset); + ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset); if (ret) { dev_err(qmp->dev, "no-csr reset assert failed\n"); goto err_assert_reset; @@ -4937,7 +5095,7 @@ static int qmp_pcie_exit(struct phy *phy) const struct qmp_phy_cfg *cfg = qmp->cfg; if (qmp->nocsr_reset) - reset_control_assert(qmp->nocsr_reset); + reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset); else reset_control_bulk_assert(cfg->num_resets, qmp->resets); @@ -4981,7 +5139,7 @@ static int qmp_pcie_power_on(struct phy *phy) if (ret) return ret; - ret = reset_control_deassert(qmp->nocsr_reset); + ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_reset); if (ret) { dev_err(qmp->dev, "no-csr reset deassert failed\n"); goto err_disable_pipe_clk; @@ -5130,14 +5288,25 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp) for (i = 0; i < cfg->num_resets; i++) qmp->resets[i].id = cfg->reset_list[i]; - ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets); + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, + qmp->resets); if (ret) return dev_err_probe(dev, ret, "failed to get resets\n"); - qmp->nocsr_reset = devm_reset_control_get_optional_exclusive(dev, "phy_nocsr"); - if (IS_ERR(qmp->nocsr_reset)) - return dev_err_probe(dev, PTR_ERR(qmp->nocsr_reset), - "failed to get no-csr reset\n"); + if (!cfg->num_nocsr_resets) + return 0; + qmp->nocsr_reset = devm_kcalloc(dev, cfg->num_nocsr_resets, + sizeof(*qmp->nocsr_reset), GFP_KERNEL); + if (!qmp->nocsr_reset) + return -ENOMEM; + + for (i = 0; i < cfg->num_nocsr_resets; i++) + qmp->nocsr_reset[i].id = cfg->nocsr_reset_list[i]; + + ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets, + qmp->nocsr_reset); + if (ret) + return dev_err_probe(dev, ret, "failed to get no-csr reset\n"); return 0; } @@ -5481,6 +5650,16 @@ static int qmp_pcie_probe(struct platform_device *pdev) WARN_ON_ONCE(!qmp->cfg->pwrdn_ctrl); WARN_ON_ONCE(!qmp->cfg->phy_status); + ret = devm_pm_domain_attach_list(dev, NULL, &qmp->pd_list); + if (ret < 0 && ret != -EEXIST) { + dev_err(dev, "Failed to attach power domain\n"); + return ret; + } + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + ret = qmp_pcie_clk_init(qmp); if (ret) return ret; @@ -5543,6 +5722,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { }, { .compatible = "qcom,glymur-qmp-gen5x4-pcie-phy", .data = &glymur_qmp_gen5x4_pciephy_cfg, + }, { + .compatible = "qcom,glymur-qmp-gen5x8-pcie-phy", + .data = &glymur_qmp_gen5x8_pciephy_cfg, }, { .compatible = "qcom,ipq6018-qmp-pcie-phy", .data = &ipq6018_pciephy_cfg, @@ -5603,6 +5785,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { }, { .compatible = "qcom,sdx65-qmp-gen4x2-pcie-phy", .data = &sdx65_qmp_pciephy_cfg, + }, { + .compatible = "qcom,shikra-qmp-gen2x1-pcie-phy", + .data = &shikra_pciephy_cfg, }, { .compatible = "qcom,sm8150-qmp-gen3x1-pcie-phy", .data = &sm8250_qmp_gen3x1_pciephy_cfg, @@ -5647,7 +5832,7 @@ static const struct of_device_id qmp_pcie_of_match_table[] = { .data = &sm8750_qmp_gen3x2_pciephy_cfg, }, { .compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy", - .data = &sm8550_qmp_gen3x2_pciephy_cfg, + .data = &x1e80100_qmp_gen3x2_pciephy_cfg, }, { .compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy", .data = &x1e80100_qmp_gen4x2_pciephy_cfg, diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h index d8ac4c4a2c316..b35b486cfa566 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v8.h @@ -71,5 +71,7 @@ #define QSERDES_V8_COM_ADDITIONAL_MISC 0x1b4 #define QSERDES_V8_COM_CMN_STATUS 0x2c8 #define QSERDES_V8_COM_C_READY_STATUS 0x2f0 +#define QSERDES_V8_COM_CMN_STATUS_N3 0x314 +#define QSERDES_V8_COM_C_READY_STATUS_N3 0x33c #endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c index ab3055bb5b0c1..fc727e6ae1134 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c @@ -2019,6 +2019,9 @@ static const struct of_device_id qmp_usbc_of_match_table[] = { }, { .compatible = "qcom,sdm660-qmp-usb3-phy", .data = &sdm660_usb3phy_cfg, + }, { + .compatible = "qcom,shikra-qmp-usb3-phy", + .data = &qcs615_usb3phy_cfg, }, { .compatible = "qcom,sm6115-qmp-usb3-phy", .data = &qcm2290_usb3phy_cfg, diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index eb93015be841f..8014141e92f2a 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -381,6 +381,19 @@ static const struct qusb2_phy_cfg sdm660_phy_cfg = { .autoresume_en = BIT(3), }; +static const struct qusb2_phy_cfg shikra_phy_cfg = { + .tbl = qcs615_init_tbl, + .tbl_num = ARRAY_SIZE(qcs615_init_tbl), + .regs = ipq6018_regs_layout, + + .has_pll_test = true, + .se_clk_scheme_default = true, + .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), + .mask_core_ready = PLL_LOCKED, + .autoresume_en = BIT(3), + .update_tune1_with_efuse = false, +}; + static const struct qusb2_phy_cfg sm6115_phy_cfg = { .tbl = sm6115_init_tbl, .tbl_num = ARRAY_SIZE(sm6115_init_tbl), @@ -958,6 +971,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = { }, { .compatible = "qcom,sdm660-qusb2-phy", .data = &sdm660_phy_cfg, + }, { + .compatible = "qcom,shikra-qusb2-phy", + .data = &shikra_phy_cfg, }, { .compatible = "qcom,sm4250-qusb2-phy", .data = &sm6115_phy_cfg, diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 11db6564c44df..fd0add4e71da1 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -1240,12 +1240,12 @@ static int msm_gpio_irq_reqres(struct irq_data *d) /* * If the wakeup_enable bit is present and marked as available for the * requested GPIO, it should be enabled when the GPIO is marked as - * wake irq in order to allow the interrupt event to be transfered to - * the PDC HW. + * wake irq in order to allow the interrupt event to be transferred to + * the PDC/MPM HW. * While the name implies only the wakeup event, it's also required for * the interrupt event. */ - if (test_bit(d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { + if (g->intr_wakeup_present_bit) { u32 intr_cfg; raw_spin_lock_irqsave(&pctrl->lock, flags); @@ -1273,7 +1273,7 @@ static void msm_gpio_irq_relres(struct irq_data *d) unsigned long flags; /* Disable the wakeup_enable bit if it has been set in msm_gpio_irq_reqres() */ - if (test_bit(d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { + if (g->intr_wakeup_present_bit) { u32 intr_cfg; raw_spin_lock_irqsave(&pctrl->lock, flags); diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c index 8d2b8246170b4..e4c0abcd95b9f 100644 --- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c +++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c @@ -1836,9 +1836,7 @@ static const struct msm_pinctrl_soc_data x1e80100_pinctrl = { .ngroups = ARRAY_SIZE(x1e80100_groups), .ngpios = 239, .wakeirq_map = x1e80100_pdc_map, - /* TODO: Enabling PDC currently breaks GPIO interrupts */ - .nwakeirq_map = 0, - /* .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map), */ + .nwakeirq_map = ARRAY_SIZE(x1e80100_pdc_map), .egpio_func = 9, }; diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c index d260715fccf67..4479c874077c7 100644 --- a/drivers/power/reset/nvmem-reboot-mode.c +++ b/drivers/power/reset/nvmem-reboot-mode.c @@ -17,14 +17,19 @@ struct nvmem_reboot_mode { struct nvmem_cell *cell; }; -static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct nvmem_reboot_mode *nvmem_rbm; size_t buf_len; + u32 magic_32; void *buf; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot); buf = nvmem_cell_read(nvmem_rbm->cell, &buf_len); @@ -35,7 +40,7 @@ static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, if (buf_len > sizeof(magic)) return -EINVAL; - ret = nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len); + ret = nvmem_cell_write(nvmem_rbm->cell, &magic_32, sizeof(magic_32)); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c index 7e108982a582e..d0ed9431a0231 100644 --- a/drivers/power/reset/qcom-pon.c +++ b/drivers/power/reset/qcom-pon.c @@ -27,17 +27,22 @@ struct qcom_pon { long reason_shift; }; -static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct qcom_pon *pon = container_of (reboot, struct qcom_pon, reboot_mode); + u32 magic_32; int ret; + if (magic > U32_MAX || (magic << pon->reason_shift) > U32_MAX) + return -EINVAL; + + magic_32 = magic << pon->reason_shift; + ret = regmap_update_bits(pon->regmap, pon->baseaddr + PON_SOFT_RB_SPARE, GENMASK(7, pon->reason_shift), - magic << pon->reason_shift); + magic_32); if (ret < 0) dev_err(pon->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index d20e44db05325..0b9179100335f 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -3,6 +3,8 @@ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd */ +#define pr_fmt(fmt) "reboot-mode: " fmt + #include #include #include @@ -19,7 +21,7 @@ struct mode_info { const char *mode; - u32 magic; + u64 magic; struct list_head list; }; @@ -71,8 +73,7 @@ static const struct class reboot_mode_class = { .dev_groups = reboot_mode_groups, }; -static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, - const char *cmd) +static u64 get_reboot_mode_magic(struct reboot_mode_driver *reboot, const char *cmd) { const char *normal = "normal"; struct mode_info *info; @@ -104,7 +105,7 @@ static int reboot_mode_notify(struct notifier_block *this, unsigned long mode, void *cmd) { struct reboot_mode_driver *reboot; - unsigned int magic; + u64 magic; reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); magic = get_reboot_mode_magic(reboot, cmd); @@ -119,8 +120,16 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) struct reboot_mode_sysfs_data *priv; struct mode_info *sysfs_info; struct mode_info *info; + const char *dev_name; int ret; + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return -EINVAL; + dev_name = reboot->dev->driver->name; + } + priv = kzalloc_obj(*priv, GFP_KERNEL); if (!priv) return -ENOMEM; @@ -146,7 +155,7 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) priv->reboot_mode_device = device_create(&reboot_mode_class, NULL, 0, (void *)priv, "%s", - reboot->dev->driver->name); + dev_name); if (IS_ERR(priv->reboot_mode_device)) { ret = PTR_ERR(priv->reboot_mode_device); goto error; @@ -163,36 +172,51 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) /** * reboot_mode_register - register a reboot mode driver * @reboot: reboot mode driver + * @fwnode: Firmware node with reboot-mode configuration * * Returns: 0 on success or a negative error code on failure. */ -int reboot_mode_register(struct reboot_mode_driver *reboot) +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode) { struct mode_info *info; + struct device_node *np; struct property *prop; - struct device_node *np = reboot->dev->of_node; size_t len = strlen(PREFIX); + u32 magic_arg1; + u32 magic_arg2; int ret; + if (!fwnode) + return -EINVAL; + + np = to_of_node(fwnode); + if (!np) + return -EINVAL; + INIT_LIST_HEAD(&reboot->head); for_each_property_of_node(np, prop) { if (strncmp(prop->name, PREFIX, len)) continue; - info = devm_kzalloc(reboot->dev, sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { ret = -ENOMEM; goto error; } - if (of_property_read_u32(np, prop->name, &info->magic)) { - dev_err(reboot->dev, "reboot mode %s without magic number\n", - info->mode); - devm_kfree(reboot->dev, info); + if (of_property_read_u32(np, prop->name, &magic_arg1)) { + pr_err("reboot mode without magic number\n"); + kfree(info); continue; } + if (of_property_read_u32_index(np, prop->name, 1, &magic_arg2)) + magic_arg2 = 0; + + info->magic = magic_arg2; + info->magic = (info->magic << 32) | magic_arg1; + info->mode = kstrdup_const(prop->name + len, GFP_KERNEL); if (!info->mode) { ret = -ENOMEM; @@ -200,8 +224,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) } else if (info->mode[0] == '\0') { kfree_const(info->mode); ret = -EINVAL; - dev_err(reboot->dev, "invalid mode name(%s): too short!\n", - prop->name); + pr_err("invalid mode name(%s): too short!\n", prop->name); goto error; } @@ -218,6 +241,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) return 0; error: + kfree(info); reboot_mode_unregister(reboot); return ret; } @@ -237,8 +261,16 @@ static inline void reboot_mode_unregister_device(struct reboot_mode_driver *rebo { struct reboot_mode_sysfs_data *priv; struct device *reboot_mode_device; + const char *dev_name; - reboot_mode_device = class_find_device(&reboot_mode_class, NULL, reboot->dev->driver->name, + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return; + dev_name = reboot->dev->driver->name; + } + + reboot_mode_device = class_find_device(&reboot_mode_class, NULL, dev_name, reboot_mode_match_by_name); if (!reboot_mode_device) @@ -261,12 +293,16 @@ static inline void reboot_mode_unregister_device(struct reboot_mode_driver *rebo int reboot_mode_unregister(struct reboot_mode_driver *reboot) { struct mode_info *info; + struct mode_info *next; unregister_reboot_notifier(&reboot->reboot_notifier); reboot_mode_unregister_device(reboot); - list_for_each_entry(info, &reboot->head, list) + list_for_each_entry_safe(info, next, &reboot->head, list) { + list_del(&info->list); kfree_const(info->mode); + kfree(info); + } return 0; } @@ -290,11 +326,14 @@ int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver **dr; int rc; + if (!reboot->dev || !reboot->dev->of_node) + return -EINVAL; + dr = devres_alloc(devm_reboot_mode_release, sizeof(*dr), GFP_KERNEL); if (!dr) return -ENOMEM; - rc = reboot_mode_register(reboot); + rc = reboot_mode_register(reboot, of_fwnode_handle(reboot->dev->of_node)); if (rc) { devres_free(dr); return rc; diff --git a/drivers/power/reset/syscon-reboot-mode.c b/drivers/power/reset/syscon-reboot-mode.c index e0772c9f70f7a..3cbd000c51223 100644 --- a/drivers/power/reset/syscon-reboot-mode.c +++ b/drivers/power/reset/syscon-reboot-mode.c @@ -20,16 +20,21 @@ struct syscon_reboot_mode { u32 mask; }; -static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct syscon_reboot_mode *syscon_rbm; + u32 magic_32; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + syscon_rbm = container_of(reboot, struct syscon_reboot_mode, reboot); ret = regmap_update_bits(syscon_rbm->map, syscon_rbm->offset, - syscon_rbm->mask, magic); + syscon_rbm->mask, magic_32); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c index b55b4317e21b6..a68e6fb344fd6 100644 --- a/drivers/power/sequencing/pwrseq-qcom-wcn.c +++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c @@ -25,6 +25,7 @@ struct pwrseq_qcom_wcn_pdata { unsigned int gpio_enable_delay_ms; const struct pwrseq_target_data **targets; bool has_vddio; /* separate VDD IO regulator */ + bool bt_gpio_required; /* BT enable path requires a dedicated GPIO */ int (*match)(struct pwrseq_device *pwrseq, struct device *dev); }; @@ -383,6 +384,7 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn6855_of_data = { .pwup_delay_ms = 50, .gpio_enable_delay_ms = 5, .targets = pwrseq_qcom_wcn6855_targets, + .bt_gpio_required = true, }; static const char *const pwrseq_wcn7850_vregs[] = { @@ -400,6 +402,7 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = { .num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs), .pwup_delay_ms = 50, .targets = pwrseq_qcom_wcn_targets, + .bt_gpio_required = true, }; static int pwrseq_qcom_wcn_match_regulator(struct pwrseq_device *pwrseq, @@ -432,6 +435,26 @@ static int pwrseq_qcom_wcn_match_regulator(struct pwrseq_device *pwrseq, reg_node->parent->parent != ctx->of_node) return PWRSEQ_NO_MATCH; + /* + * If this is a Bluetooth consumer device but the bt-enable GPIO is not + * configured in the power sequencer (e.g. BT_EN is tied high via a + * hardware pull-up and therefore absent from the DT), don't match. + * The consumer driver will fall back to its legacy power control path + * and correctly set power_ctrl_enabled to false. + * + * Only apply this check for chips whose BT enable path requires a + * dedicated GPIO (bt_gpio_required). Chips like WCN3990 have no + * separate BT/WLAN enable pins by design and must always be matched + * even when bt_gpio is NULL. + * + * BT device nodes are conventionally named "bluetooth" in the DT, + * so use of_node_name_eq() as a generic check rather than enumerating + * specific compatible strings. + */ + if (ctx->pdata->bt_gpio_required && !ctx->bt_gpio && + of_node_name_eq(dev_node, "bluetooth")) + return PWRSEQ_NO_MATCH; + return PWRSEQ_MATCH_OK; } diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index 03c4c796d9931..e3a47c6534999 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -93,4 +93,17 @@ config DTPM_DEVFREQ help This enables support for device power limitation based on energy model. + +config QCOM_SPEL + tristate "Qualcomm SPEL Powercap driver" + depends on ARM64 || COMPILE_TEST + help + This enables support for the Qualcomm SoC Power and Electrical + Limits (SPEL) hardware, which allows power limits to be + enforced and monitored on Qualcomm SoCs. + + SPEL provides energy monitoring and power capping for multiple + domains including system, SoC, CPU clusters, GPU, and various + other subsystems. + endif diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile index 5ab0dce565b9a..8235fb9d3df60 100644 --- a/drivers/powercap/Makefile +++ b/drivers/powercap/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o obj-$(CONFIG_INTEL_RAPL_TPMI) += intel_rapl_tpmi.o obj-$(CONFIG_IDLE_INJECT) += idle_inject.o obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o +obj-$(CONFIG_QCOM_SPEL) += qcom_spel.o diff --git a/drivers/powercap/qcom_spel.c b/drivers/powercap/qcom_spel.c new file mode 100644 index 0000000000000..4dd91cf36ccca --- /dev/null +++ b/drivers/powercap/qcom_spel.c @@ -0,0 +1,776 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Qualcomm SPEL (SoC Power and Electrical Limits) Driver + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPEL register bitmasks */ +#define ENERGY_STATUS_MASK GENMASK(31, 0) + +#define POWER_LIMIT_MASK GENMASK(14, 0) +#define POWER_LIMIT_ENABLE BIT(31) + +#define TIME_WINDOW_MASK_L GENMASK(14, 0) +#define TIME_WINDOW_MASK_H GENMASK(22, 16) +#define TIME_WINDOW_MAX ((FIELD_MAX(TIME_WINDOW_MASK_H) << 15) | \ + FIELD_MAX(TIME_WINDOW_MASK_L)) + +#define ENERGY_UNIT_MASK GENMASK(19, 16) +#define TIME_UNIT_MASK GENMASK(11, 8) +#define POWER_UNIT_MASK GENMASK(2, 0) + +#define LIMITS_CAPABILITY_OFFSET 0x20 +#define ENERGY_RPT_UNIT_OFFSET 0x04 + +#define ENERGY_UNIT_SCALE 1000 + +#define SPEL_DOMAIN_NAME_LENGTH 16 + +/* Domain types */ +enum spel_domain_type { + SPEL_DOMAIN_SYS, + SPEL_DOMAIN_SOC, + SPEL_DOMAIN_CL0, + SPEL_DOMAIN_CL1, + SPEL_DOMAIN_CL2, + SPEL_DOMAIN_IGPU, + SPEL_DOMAIN_DGPU, + SPEL_DOMAIN_NSP, + SPEL_DOMAIN_MMCX, + SPEL_DOMAIN_INFRA, + SPEL_DOMAIN_DRAM, + SPEL_DOMAIN_MDM, + SPEL_DOMAIN_WLAN, + SPEL_DOMAIN_USB1, + SPEL_DOMAIN_USB2, + SPEL_DOMAIN_USB3, + SPEL_DOMAIN_MAX, +}; + +/* Power limit IDs */ +enum spel_power_limit_id { + POWER_LIMIT1, + POWER_LIMIT2, + POWER_LIMIT3, + POWER_LIMIT4, + POWER_LIMITS_MAX, +}; + +/* Unit types for conversion */ +enum unit_type { + POWER_UNIT, + ENERGY_UNIT, + TIME_UNIT, +}; + +/* Power limit operation types */ +enum pl_ops_type { + PL_LIMIT, + PL_TIME_WINDOW, +}; + +static const char * const pl_names[] = { + [POWER_LIMIT1] = "pl1", + [POWER_LIMIT2] = "pl2", + [POWER_LIMIT3] = "pl3", + [POWER_LIMIT4] = "pl4", +}; + +/** + * struct spel_domain_info - Domain configuration + * @name: Domain name + * @offset: Register offset in node base + */ +struct spel_domain_info { + const char *name; + u32 offset; +}; + +/* Domain configuration */ +static const struct spel_domain_info domain_info[SPEL_DOMAIN_MAX] = { + [SPEL_DOMAIN_SYS] = { "sys", 0x40 }, + [SPEL_DOMAIN_SOC] = { "soc", 0x00 }, + [SPEL_DOMAIN_CL0] = { "cl0", 0x5c }, + [SPEL_DOMAIN_CL1] = { "cl1", 0x60 }, + [SPEL_DOMAIN_CL2] = { "cl2", 0x64 }, + [SPEL_DOMAIN_IGPU] = { "igpu", 0x08 }, + [SPEL_DOMAIN_DGPU] = { "dgpu", 0x44 }, + [SPEL_DOMAIN_NSP] = { "nsp", 0x0c }, + [SPEL_DOMAIN_MMCX] = { "mmcx", 0x10 }, + [SPEL_DOMAIN_INFRA] = { "infra", 0x18 }, + [SPEL_DOMAIN_DRAM] = { "dram", 0x1c }, + [SPEL_DOMAIN_MDM] = { "mdm", 0x48 }, + [SPEL_DOMAIN_WLAN] = { "wlan", 0x4c }, + [SPEL_DOMAIN_USB1] = { "usb1", 0x50 }, + [SPEL_DOMAIN_USB2] = { "usb2", 0x54 }, + [SPEL_DOMAIN_USB3] = { "usb3", 0x58 }, +}; + +/** + * struct spel_constraint_info - Power limit constraint information + * @limit_offset: Register offset for power limit value + * @time_window_offset: Register offset for time window + * @supported_mask: Bit mask in capability register + * @domain_id: Domain this constraint applies to + * @pl_id: Power limit ID (PL1, PL2, etc.) + */ +struct spel_constraint_info { + u32 limit_offset; + u32 time_window_offset; + u32 supported_mask; + enum spel_domain_type domain_id; + int pl_id; +}; + +/* Constraint configuration */ +static const struct spel_constraint_info constraints[] = { + /* SYS domain constraints */ + { 0x10, 0x70, BIT(0), SPEL_DOMAIN_SYS, POWER_LIMIT1 }, + { 0x14, 0x74, BIT(1), SPEL_DOMAIN_SYS, POWER_LIMIT2 }, + { 0x18, 0x78, BIT(2), SPEL_DOMAIN_SYS, POWER_LIMIT3 }, + { 0x1c, 0x7c, BIT(3), SPEL_DOMAIN_SYS, POWER_LIMIT4 }, + /* SoC domain constraints */ + { 0x00, 0x60, BIT(4), SPEL_DOMAIN_SOC, POWER_LIMIT1 }, + { 0x04, 0x64, BIT(5), SPEL_DOMAIN_SOC, POWER_LIMIT2 }, + { 0x08, 0x68, BIT(6), SPEL_DOMAIN_SOC, POWER_LIMIT3 }, + { 0x0c, 0x6c, BIT(7), SPEL_DOMAIN_SOC, POWER_LIMIT4 }, +}; + +/** + * struct spel_domain - SPEL power domain + * @power_zone: Powercap zone + * @lock: Mutex protecting register access + * @sp: Parent sys domain + * @status_reg: Energy counter register + * @name: Domain name + * @id: Domain type ID + */ +struct spel_domain { + struct powercap_zone power_zone; + struct mutex lock; /* Protects register read/write operations */ + void *sp; + void __iomem *status_reg; + char name[SPEL_DOMAIN_NAME_LENGTH]; + enum spel_domain_type id; +}; + +/** + * struct spel_system - SPEL system + * @domains: Array of domains + * @power_zone: Parent powercap zone + * @node_base: Base address for node registers + * @constraint_base: Base address for constraint registers + * @config_base: Base address for config registers + * @control_type: Powercap control type + * @dev: Device pointer for logging + * @limits: Supported power limits per domain + * @power_unit: Power unit in microWatts (common for all domains) + * @energy_unit: Energy unit in nanoJoules (common for all domains) + * @time_unit: Time unit in microseconds (common for all domains) + */ +struct spel_system { + struct spel_domain *domains; + struct powercap_zone *power_zone; + void __iomem *node_base; + void __iomem *constraint_base; + void __iomem *config_base; + struct powercap_control_type *control_type; + struct device *dev; + int limits[SPEL_DOMAIN_MAX]; + unsigned int power_unit; + unsigned int energy_unit; + unsigned int time_unit; +}; + +#define power_zone_to_spel_domain(_zone) \ + container_of(_zone, struct spel_domain, power_zone) + +static bool is_pl_valid(struct spel_domain *sd, int pl) +{ + struct spel_system *sp = sd->sp; + + return !!(sp->limits[sd->id] & BIT(pl)); +} + +static int get_pl_ops_offset(struct spel_domain *sd, int pl, enum pl_ops_type pl_op) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(constraints); i++) { + const struct spel_constraint_info *ci = &constraints[i]; + + if (ci->domain_id == sd->id && ci->pl_id == pl) { + switch (pl_op) { + case PL_LIMIT: + return ci->limit_offset; + case PL_TIME_WINDOW: + return ci->time_window_offset; + default: + return -EOPNOTSUPP; + } + } + } + + return -EOPNOTSUPP; +} + +static u64 spel_unit_xlate(struct spel_domain *sd, enum unit_type type, + u64 value, int to_raw) +{ + struct spel_system *sp = sd->sp; + u64 units, scale; + + switch (type) { + case POWER_UNIT: + units = sp->power_unit; + scale = 1; + break; + case ENERGY_UNIT: + units = sp->energy_unit; + scale = ENERGY_UNIT_SCALE; + break; + case TIME_UNIT: + units = sp->time_unit; + scale = 1; + break; + default: + return value; + } + + if (to_raw) + return DIV_ROUND_CLOSEST_ULL(value * scale, units); + + value *= units; + return div64_u64(value, scale); +} + +static int spel_read_pl_data(struct spel_domain *sd, int pl, + enum pl_ops_type pl_op, bool xlate, u64 *data) +{ + struct spel_system *sp = sd->sp; + void __iomem *reg_addr; + u64 value; + int offset; + + if (!is_pl_valid(sd, pl)) + return -EINVAL; + + offset = get_pl_ops_offset(sd, pl, pl_op); + if (offset < 0) + return offset; + + guard(mutex)(&sd->lock); + + reg_addr = sp->constraint_base + offset; + value = readl(reg_addr); + + switch (pl_op) { + case PL_LIMIT: + value = FIELD_GET(POWER_LIMIT_MASK, value); + if (xlate) + *data = spel_unit_xlate(sd, POWER_UNIT, value, 0); + else + *data = value; + break; + case PL_TIME_WINDOW: + /* Decode time window: bits [22:16] are upper 7 bits, [14:0] are lower 15 bits */ + value = (FIELD_GET(TIME_WINDOW_MASK_H, value) << 15) | + FIELD_GET(TIME_WINDOW_MASK_L, value); + if (xlate) + *data = spel_unit_xlate(sd, TIME_UNIT, value, 0); + else + *data = value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int spel_write_pl_data(struct spel_domain *sd, int pl, + enum pl_ops_type pl_op, unsigned long long value) +{ + struct spel_system *sp = sd->sp; + void __iomem *reg_addr; + u64 reg_val, new_val; + int offset; + + if (!is_pl_valid(sd, pl)) + return -EINVAL; + + offset = get_pl_ops_offset(sd, pl, pl_op); + if (offset < 0) + return offset; + + guard(mutex)(&sd->lock); + + reg_addr = sp->constraint_base + offset; + reg_val = readl(reg_addr); + + switch (pl_op) { + case PL_LIMIT: + new_val = spel_unit_xlate(sd, POWER_UNIT, value, 1); + if (new_val > FIELD_MAX(POWER_LIMIT_MASK)) + return -EINVAL; + reg_val = (reg_val & ~POWER_LIMIT_MASK) | FIELD_PREP(POWER_LIMIT_MASK, new_val); + + /* + * Enable/Disable PL based on the value: + * - If value is 0, disable the PL (clear enable bit) + * - If value is non-zero, enable the PL (set enable bit) + */ + if (new_val == 0) + reg_val &= ~POWER_LIMIT_ENABLE; + else + reg_val |= POWER_LIMIT_ENABLE; + + writel(reg_val, reg_addr); + return 0; + + case PL_TIME_WINDOW: + /* + * Encode time window: upper 7 bits to [22:16], lower 15 bits to [14:0] + */ + new_val = spel_unit_xlate(sd, TIME_UNIT, value, 1); + if (new_val > TIME_WINDOW_MAX) + return -EINVAL; + /* Read-modify-write to preserve other bits */ + reg_val = (reg_val & ~(TIME_WINDOW_MASK_H | TIME_WINDOW_MASK_L)) | + FIELD_PREP(TIME_WINDOW_MASK_H, new_val >> 15) | + FIELD_PREP(TIME_WINDOW_MASK_L, new_val); + writel(reg_val, reg_addr); + + /* + * Time window register update doesn't trigger firmware interrupt. + * Write to the PL register with current value to trigger the interrupt. + */ + offset = get_pl_ops_offset(sd, pl, PL_LIMIT); + if (offset >= 0) { + reg_addr = sp->constraint_base + offset; + reg_val = readl(reg_addr); + writel(reg_val, reg_addr); + } + return 0; + + default: + return -EINVAL; + } +} + +static int spel_get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 value; + + value = readl(sd->status_reg); + + *energy_raw = spel_unit_xlate(sd, ENERGY_UNIT, value, 0); + + return 0; +} + +static int spel_get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy) +{ + struct spel_domain *sd = power_zone_to_spel_domain(pcd_dev); + + *energy = spel_unit_xlate(sd, ENERGY_UNIT, ENERGY_STATUS_MASK, 0); + + return 0; +} + +static int spel_release_zone(struct powercap_zone *power_zone) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + struct spel_system *sp = sd->sp; + + /* Free the domains array when the last zone (SYS domain) is released */ + if (sd->id == SPEL_DOMAIN_SYS) + kfree(sp->domains); + + return 0; +} + +static int spel_find_nr_power_limit(struct spel_domain *sd) +{ + int i, nr_pl = 0; + + for (i = 0; i < ARRAY_SIZE(pl_names); i++) { + if (is_pl_valid(sd, i)) + nr_pl++; + } + + return nr_pl; +} + +static const struct powercap_zone_ops zone_ops = { + .get_energy_uj = spel_get_energy_counter, + .get_max_energy_range_uj = spel_get_max_energy_counter, + .release = spel_release_zone, +}; + +static int spel_constraint_to_pl(struct spel_domain *sd, int cid) +{ + int i, id; + + for (i = 0, id = 0; i < ARRAY_SIZE(pl_names); i++) { + if (is_pl_valid(sd, i) && id++ == cid) + return i; + } + + return -EINVAL; +} + +static int spel_set_power_limit(struct powercap_zone *power_zone, int cid, + u64 power_limit) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + return spel_write_pl_data(sd, id, PL_LIMIT, power_limit); +} + +static int spel_get_power_limit(struct powercap_zone *power_zone, int cid, + u64 *data) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 val; + int ret, id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + ret = spel_read_pl_data(sd, id, PL_LIMIT, true, &val); + if (!ret) + *data = val; + + return ret; +} + +static int spel_set_time_window(struct powercap_zone *power_zone, int cid, + u64 window) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + return spel_write_pl_data(sd, id, PL_TIME_WINDOW, window); +} + +static int spel_get_time_window(struct powercap_zone *power_zone, int cid, + u64 *data) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 val; + int ret, id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + ret = spel_read_pl_data(sd, id, PL_TIME_WINDOW, true, &val); + if (!ret) + *data = val; + + return ret; +} + +static const char *spel_get_constraint_name(struct powercap_zone *power_zone, + int cid) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id >= 0 && id < ARRAY_SIZE(pl_names)) + return pl_names[id]; + + return NULL; +} + +static const struct powercap_zone_constraint_ops constraint_ops = { + .set_power_limit_uw = spel_set_power_limit, + .get_power_limit_uw = spel_get_power_limit, + .set_time_window_us = spel_set_time_window, + .get_time_window_us = spel_get_time_window, + .get_name = spel_get_constraint_name, +}; + +static void spel_init_domains(struct spel_system *sp) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct spel_domain *sd = &sp->domains[i]; + + sd->sp = sp; + snprintf(sd->name, SPEL_DOMAIN_NAME_LENGTH, "%s", + domain_info[i].name); + sd->id = i; + sd->status_reg = sp->node_base + domain_info[i].offset; + + /* PL1 is always supported (required for powercap registration) */ + sp->limits[i] = BIT(POWER_LIMIT1); + } +} + +static void spel_update_unit(struct spel_system *sp) +{ + u32 value, shift; + + /* Read power_unit and time_unit from offset 0x0 */ + value = readl(sp->config_base); + + /* + * Unit calculation: 1 / (2^shift) + * Masks limit: TIME_UNIT (4 bits, max 15), POWER_UNIT (3 bits, max 7). + */ + shift = FIELD_GET(POWER_UNIT_MASK, value); + sp->power_unit = 1000000 / (1 << shift); + + shift = FIELD_GET(TIME_UNIT_MASK, value); + /* + * Time window in register is in milliseconds. + */ + sp->time_unit = 1000 * (1 << shift); + + /* Read energy_unit from ENERGY_RPT_UNIT_OFFSET */ + value = readl(sp->config_base + ENERGY_RPT_UNIT_OFFSET); + + /* + * Unit calculation: 1 / (2^shift) + * Masks limit: ENERGY_UNIT (4 bits, max 15). + */ + shift = FIELD_GET(ENERGY_UNIT_MASK, value); + sp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << shift); + + dev_dbg(sp->dev, "Units: energy=%dnJ, time=%dus, power=%duW\n", + sp->energy_unit, sp->time_unit, sp->power_unit); +} + +static void spel_detect_powerlimit(struct spel_domain *sd) +{ + struct spel_system *sp = sd->sp; + u32 capabilities; + int i, j; + + capabilities = readl(sp->config_base + LIMITS_CAPABILITY_OFFSET); + + /* + * Detect power limits from hardware capabilities. + * Start from index 1 (POWER_LIMIT2) since PL1 is always enabled in spel_init_domains(). + */ + for (i = 1; i < ARRAY_SIZE(pl_names); i++) { + for (j = 0; j < ARRAY_SIZE(constraints); j++) { + const struct spel_constraint_info *ci = &constraints[j]; + + if (ci->domain_id == sd->id && ci->pl_id == i) { + if (capabilities & ci->supported_mask) + sp->limits[sd->id] |= BIT(i); + break; + } + } + } +} + +static int spel_init_system(struct spel_system *sp, struct device *dev) +{ + int i, ret; + + /* Read unit configuration (common for all domains) */ + spel_update_unit(sp); + + sp->domains = kcalloc(ARRAY_SIZE(domain_info), + sizeof(struct spel_domain), GFP_KERNEL); + if (!sp->domains) + return -ENOMEM; + + spel_init_domains(sp); + + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct spel_domain *sd = &sp->domains[i]; + + ret = devm_mutex_init(dev, &sd->lock); + if (ret) { + dev_err(dev, "Failed to initialize mutex for domain %s\n", sd->name); + kfree(sp->domains); + return ret; + } + + spel_detect_powerlimit(sd); + } + + return 0; +} + +static int spel_register_powercap(struct spel_system *sp) +{ + struct spel_domain *sd; + struct powercap_zone *power_zone; + int nr_pl, ret, i; + + /* Register SYS domain as parent zone */ + sd = &sp->domains[SPEL_DOMAIN_SYS]; + nr_pl = spel_find_nr_power_limit(sd); + + power_zone = powercap_register_zone(&sd->power_zone, + sp->control_type, sd->name, + NULL, &zone_ops, nr_pl, + &constraint_ops); + if (IS_ERR(power_zone)) { + dev_err(sp->dev, "Failed to register power zone %s\n", + sd->name); + return PTR_ERR(power_zone); + } + sp->power_zone = power_zone; + + /* Register other domains as children */ + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct powercap_zone *parent; + + if (i == SPEL_DOMAIN_SYS) + continue; + + sd = &sp->domains[i]; + + /* SOC is child of SYS, others are children of SOC */ + if (i == SPEL_DOMAIN_SOC) + parent = sp->power_zone; + else + parent = &sp->domains[SPEL_DOMAIN_SOC].power_zone; + + nr_pl = spel_find_nr_power_limit(sd); + power_zone = powercap_register_zone(&sd->power_zone, + sp->control_type, + sd->name, parent, + &zone_ops, nr_pl, + &constraint_ops); + + if (IS_ERR(power_zone)) { + dev_err(sp->dev, "Failed to register power_zone %s\n", + sd->name); + ret = PTR_ERR(power_zone); + goto err_cleanup; + } + } + + return 0; + +err_cleanup: + /* Unregister in reverse order: children first, then SOC, then SYS */ + for (i = i - 1; i >= 0; i--) + powercap_unregister_zone(sp->control_type, &sp->domains[i].power_zone); + + return ret; +} + +static int spel_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct spel_system *sp; + int ret; + + sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL); + if (!sp) + return -ENOMEM; + + sp->dev = dev; + + /* Map config registers (units, capabilities) */ + sp->config_base = devm_platform_ioremap_resource_byname(pdev, "config"); + if (IS_ERR(sp->config_base)) + return PTR_ERR(sp->config_base); + + /* Map constraint registers (power limits) */ + sp->constraint_base = devm_platform_ioremap_resource_byname(pdev, "constraints"); + if (IS_ERR(sp->constraint_base)) + return PTR_ERR(sp->constraint_base); + + /* Map spel domain registers (energy counters) */ + sp->node_base = devm_platform_ioremap_resource_byname(pdev, "nodes"); + if (IS_ERR(sp->node_base)) + return PTR_ERR(sp->node_base); + + sp->control_type = powercap_register_control_type(NULL, "qcom-spel", + NULL); + if (IS_ERR(sp->control_type)) { + dev_err(dev, "Failed to register control type\n"); + return PTR_ERR(sp->control_type); + } + + /* Initialize system and domains */ + ret = spel_init_system(sp, dev); + if (ret) { + dev_err(dev, "Failed to initialize system\n"); + goto err_unregister_control; + } + + ret = spel_register_powercap(sp); + if (ret) { + dev_err(dev, "Failed to register powercap zones\n"); + if (!sp->power_zone) + kfree(sp->domains); + goto err_unregister_control; + } + + platform_set_drvdata(pdev, sp); + + return 0; + +err_unregister_control: + powercap_unregister_control_type(sp->control_type); + return ret; +} + +static void spel_remove(struct platform_device *pdev) +{ + struct spel_system *sp = platform_get_drvdata(pdev); + int i; + + /* Unregister in reverse order: children first, then SOC, then SYS */ + for (i = ARRAY_SIZE(domain_info) - 1; i >= 0; i--) + powercap_unregister_zone(sp->control_type, &sp->domains[i].power_zone); + + powercap_unregister_control_type(sp->control_type); +} + +static const struct of_device_id spel_of_match[] = { + { .compatible = "qcom,glymur-spel" }, + { } +}; +MODULE_DEVICE_TABLE(of, spel_of_match); + +static struct platform_driver spel_driver = { + .probe = spel_probe, + .remove = spel_remove, + .driver = { + .name = "qcom_spel", + .of_match_table = spel_of_match, + }, +}; + +module_platform_driver(spel_driver); + +MODULE_DESCRIPTION("Qualcomm SPEL Powercap Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index b93640ca08b72..0a1f3d405aa4a 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -263,4 +263,13 @@ config PTP_NETC_V4_TIMER synchronization. It also supports periodic output signal (e.g. PPS) and external trigger timestamping. +config PTP_QCOM_CLOCK_TSC + tristate "Qualcomm TSC as PTP clock" + depends on COMMON_CLK && PTP_1588_CLOCK + help + This driver adds support for using the Qualcomm Timestamp Counter (TSC) + as a PTP clock the requires for time stamping of PTP packets. + It also registers interrupts for Event Timestamp Unit (ETU) and updates + the TSC timestamps to PTP clock event. + endmenu diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile index bdc47e284f14e..6789b2a517b1d 100644 --- a/drivers/ptp/Makefile +++ b/drivers/ptp/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_OCP) += ptp_ocp.o obj-$(CONFIG_PTP_DFL_TOD) += ptp_dfl_tod.o obj-$(CONFIG_PTP_S390) += ptp_s390.o obj-$(CONFIG_PTP_NETC_V4_TIMER) += ptp_netc.o +obj-$(CONFIG_PTP_QCOM_CLOCK_TSC) += ptp_qcom_tsc.o diff --git a/drivers/ptp/ptp_qcom_tsc.c b/drivers/ptp/ptp_qcom_tsc.c new file mode 100644 index 0000000000000..4df38665a56e6 --- /dev/null +++ b/drivers/ptp/ptp_qcom_tsc.c @@ -0,0 +1,842 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QCOM TSC PTP : Linux driver for Time Stamp Counter Hardware. + * + */ + +#define pr_fmt(fmt) "qcom_tsc: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offset definitions */ +#define TSCSS_TSC_CONTROL_CNTCR 0x0 +#define TSCSS_TSC_CONTROL_CNTCV_LO 0x8 +#define TSCSS_TSC_CONTROL_CNTCV_HI 0xC +#define TSCSS_TSC_CONTROL_CNTCV_FRAC 0x10 +#define TSCSS_TSC_SLEEP_INCR_VAL_LO 0x24 +#define TSCSS_TSC_SLEEP_INCR_VAL_HI 0x28 +#define TSCSS_TSC_DRIFT_CORRECT_INCR_VAL 0x2C +#define TSCSS_TSC_DRIFT_CORRECT_DURATION 0x30 +#define TSCSS_TSC_DRIFT_CORRECT_CMD 0x34 +#define TSCSS_TSC_ROLLOVER_VAL 0x3C +#define TSCSS_TSC_SPARE 0x40 +#define TSCSS_TSC_OFFSET_LO 0x50 +#define TSCSS_TSC_OFFSET_HI 0x54 +#define TSCSS_TSC_FUSA_CFG_STAT 0xF54 +#define TSCSS_TSC_READ_CNTCV_LO 0x1000 +#define TSCSS_TSC_READ_CNTCV_HI 0x1004 +#define TSCSS_TSC_HW_PRELOAD_VAL_LO 0x0060 +#define TSCSS_TSC_HW_PRELOAD_VAL_HI 0x0064 + +#define TSCSS_TSC_SLICE_ETU_CFG 0x0 +#define TSCSS_TSC_SLICE_ETU_STATUS 0x4 +#define TSCSS_ETU_SLICE_TSC_TS_LO 0x8 +#define TSCSS_ETU_SLICE_TSC_TS_HI 0xC +#define TSCSS_ETU_SLICE_TS_EVENT_TYPE 0x10 +#define TSCSS_ETU_SLICE_GCTR_TS_LO 0x20 +#define TSCSS_ETU_SLICE_GCTR_TS_HI 0x24 +#define TSCSS_ETU_SLICE_FIFO_CLR 0x30 +#define TSCSS_ETU_SLICE_SW_TRIG_CFG 0x34 +#define TSCSS_ETU_SLICE_TIMER_TRIG_PERIOD 0x38 +#define MAX_ETU_SLICE 16 + +#define DRIFT_CORRECT_MAX_PERIOD 0x1FFFF +#define DRIFT_CORRECT_MAX_RES 0x7FFFC0 + +#define TSC_PRELOAD_POLLING_DELAY_MS 100 +#define NSEC_SHFT 32 +#define NSEC_MASK GENMASK_ULL(31, 0) +#define NSEC 1000000000ULL +#define XO_MHZ 19200000 +#define TSCSS_TSC_ETU_SLICE_BASE(reg_base, num, offset) \ + (reg_base + num * 0x1000 + offset) + +struct qcom_etu_slice { + char name[10]; + struct ptp_clock *ptp_clock; + void __iomem *etu_baseaddr; + u64 etu_tsc_timestamp; + u64 last_sec; + u64 global_qtimer; + int extts_enable; + int extts_irq; + int extts_index; + int extts_event_sel; + int extts_slice_num; + int extts_event_type; + u32 etu_tsc_sec; + u32 etu_tsc_nsec; + u32 etu_gctr_sec; + u32 etu_gctr_nsec; + bool extts_present; +}; + +struct qcom_ptp_tsc { + struct device *dev; + void __iomem *baseaddr; + void __iomem *etu_baseaddr; + struct clk *tsc_cfg_ahb_clk; + struct clk *tsc_cntr_clk; + struct clk *tsc_etu_clk; + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_clock_info; + struct qcom_etu_slice etu_slice[MAX_ETU_SLICE]; + int pps_enable; + int total_etu_cnt; + bool tsc_nsec_update; + bool tsc_hw_preload; + spinlock_t reg_lock; + struct delayed_work tsc_preload_poll_work; + u32 configured_slice_mask; +}; + +static void tsc_preload_poll(struct work_struct *work) +{ + struct qcom_ptp_tsc *timer = container_of(work, struct qcom_ptp_tsc, + tsc_preload_poll_work.work); + u32 regval; + + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + /* Check for the HW_PRELOAD_STATUS and disable HW_PRELOAD */ + if (!(regval & BIT(14))) { + regval &= ~BIT(2); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + pr_info("TSC CNTCR: 0x%x HW_PRELOAD is disabled\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR)); + return; + } + + pr_debug("TSC CNTCR: 0x%x HW_PRELOAD_STATUS is not cleared\n", regval); + mod_delayed_work(system_highpri_wq, &timer->tsc_preload_poll_work, + msecs_to_jiffies(TSC_PRELOAD_POLLING_DELAY_MS)); +} + +static int qcom_ptp_tsc_is_enabled(void __iomem *addr) +{ + return readl_relaxed(addr + TSCSS_TSC_CONTROL_CNTCR) & BIT(0); +} + +static void qcom_tod_read(struct qcom_ptp_tsc *timer, struct timespec64 *ts) +{ + u64 temp, final; + u32 sec, nsec; + + if (!qcom_ptp_tsc_is_enabled(timer->baseaddr)) { + pr_debug("TSC is not enabled\n"); + return; + } + + sec = readl_relaxed(timer->baseaddr + TSCSS_TSC_READ_CNTCV_HI); + nsec = readl_relaxed(timer->baseaddr + TSCSS_TSC_READ_CNTCV_LO); + + pr_debug("CNTR_HI: 0x%x, sec %u\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI), sec); + pr_debug("CNTR_LO: 0x%x nsec %u\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO), nsec); + + if (timer->tsc_nsec_update) { + temp = sec; + final = (temp << NSEC_SHFT) | nsec; + sec = div_u64_rem(final, NSEC, &nsec); + pr_debug("tsc_nsec_update: %d, sec %u, nsec %u\n", + timer->tsc_nsec_update, sec, nsec); + } + + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + +static void qcom_ptp_enable_tsc_hw_preload(struct qcom_ptp_tsc *timer, struct timespec64 ts) +{ + u32 regval; + int timeout = 500; + + /* Enable HW_PRELOAD */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval |= BIT(2); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + /* Program PRELOAD registers */ + writel_relaxed(ts.tv_sec, timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_HI); + writel_relaxed(ts.tv_nsec, timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_LO); + + pr_debug("HW_PRELOAD_VAL_HI: 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_HI)); + pr_debug("HW_PRELOAD_VAL_LO: 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_LO)); + + /* Check for the HW_PRELOAD_STATUS and start poll thread */ + while (timeout-- > 0) { + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + if (regval & BIT(14)) { + pr_debug("TSC CNTR: 0x%x HW_PRELOAD is enabled\n", regval); + mod_delayed_work(system_highpri_wq, &timer->tsc_preload_poll_work, + msecs_to_jiffies(TSC_PRELOAD_POLLING_DELAY_MS)); + return; + } + udelay(1); + } + + pr_warn("TSC CNTR: 0x%x HW_PRELOAD enable failed\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR)); +} + +static int qcom_ptp_update_tsc_cntr(struct qcom_ptp_tsc *timer, + struct timespec64 offset) +{ + u64 timestamp = 0; + u32 regval; + + /* Update to 1ns resolution */ + if (timer->tsc_nsec_update) { + timestamp = offset.tv_sec * NSEC + offset.tv_nsec; + writel_relaxed((timestamp >> NSEC_SHFT), + timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI); + writel_relaxed(timestamp & NSEC_MASK, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO); + } else { + writel_relaxed(offset.tv_sec, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI); + writel_relaxed(offset.tv_nsec, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO); + } + + pr_debug("Timestamp %llu: sec: %lld, nsec: %ld\n", timestamp, + offset.tv_sec, offset.tv_nsec); + + pr_debug("CNTR_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI)); + pr_debug("CNTR_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO)); + + /* Enable the counter */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval |= BIT(0); + + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + return 0; +} + +static void qcom_ptp_update_tsc_offset(struct qcom_ptp_tsc *timer, + struct timespec64 offset) +{ + struct timespec64 tod; + u32 regval; + + if (timer->tsc_nsec_update) { + /* Read TOD and add delta */ + qcom_tod_read(timer, &tod); + tod = timespec64_add(tod, offset); + + pr_debug("%s disable the counter and re-init with tod+delta\n", __func__); + /* Disable the counter */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval &= ~BIT(0); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + /* Re-initialize the counter with updated time */ + qcom_ptp_update_tsc_cntr(timer, tod); + } else { + writel_relaxed(offset.tv_nsec, timer->baseaddr + TSCSS_TSC_OFFSET_LO); + writel_relaxed(offset.tv_sec, timer->baseaddr + TSCSS_TSC_OFFSET_HI); + + pr_debug("OFFSET_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_OFFSET_HI)); + pr_debug("OFFSET_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_OFFSET_LO)); + } + + pr_debug("CNTCV_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI)); + pr_debug("CNTCV_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO)); +} + +static int qcom_ptp_normal_drift_correction(struct qcom_ptp_tsc *timer, long delta) +{ + u64 regval = 0, period, subperiod = 4, res = 64, incval = 0, multiple, total_cycles; + bool is_jump; + + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + if (regval & BIT(1)) { + pr_debug("Previous drift correction is still in progress...\n"); + return -EINVAL; + } + + regval = 0; + + if (delta == 0) + return 0; + + if (delta < 0) { + /* Swallow the counter */ + delta = -delta; + regval &= ~BIT(31); + is_jump = false; + + if (delta > DRIFT_CORRECT_MAX_RES) { + period = DRIFT_CORRECT_MAX_PERIOD; + pr_debug("Delta(%ldns) > 8.3ms, program max swallow resolution\n", delta); + } else { + period = div_u64(delta, res); + } + } else { + /* Jump the counter */ + regval |= BIT(31); + is_jump = true; + + total_cycles = delta / res; + multiple = total_cycles / DRIFT_CORRECT_MAX_RES; + pr_debug("total_cycles = %lld multiple = %lld\n", total_cycles, multiple); + if (multiple == 0) { + if (delta < res) { + period = 1; + incval = res + delta; + } else { + period = div_u64(delta, res); + incval = res * 2; + } + } else { + pr_debug("Delta(%ldns) > 8.3ms, do nothing...\n", delta); + return 0; + } + } + + regval |= subperiod; + regval |= (period << 12); + + pr_debug("delta:%ld period:%lld subperiod:%lld is_jump:%d regval:0x%llx\n", + delta, period, subperiod, is_jump, regval); + + /* Update jump/swallow, period, subperiod */ + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_DURATION); + + /* Update the INCR VAL */ + writel_relaxed(incval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_INCR_VAL); + + /* Trigger the drift correction */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + regval |= BIT(0); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + + readl_poll_timeout(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD, + regval, !(regval & BIT(1)), 5, 500); + + pr_debug("duration = 0x%x incr_val = 0x%x cmd = 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_DURATION), + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_INCR_VAL), + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD)); + + return 0; +} + +/* + * PTP clock operations + */ +static int qcom_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + + return qcom_ptp_normal_drift_correction(timer, scaled_ppm_to_ppb(scaled_ppm)); +} + +static int qcom_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + unsigned long flags; + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + struct timespec64 offset; + + spin_lock_irqsave(&timer->reg_lock, flags); + + offset = ns_to_timespec64(delta); + pr_debug("sec: %lld, nsec: %ld\n", offset.tv_sec, offset.tv_nsec); + + qcom_ptp_update_tsc_offset(timer, offset); + spin_unlock_irqrestore(&timer->reg_lock, flags); + + return 0; +} + +static int qcom_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) +{ + unsigned long flags; + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + + spin_lock_irqsave(&timer->reg_lock, flags); + qcom_tod_read(timer, ts); + spin_unlock_irqrestore(&timer->reg_lock, flags); + return 0; +} + +/** + * qcom_ptp_settime - Set the current time on the hardware clock + * @ptp: ptp clock structure + * @ts: timespec64 containing the new time for the cycle counter + */ +static int qcom_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, ptp_clock_info); + struct timespec64 delta, tod; + struct timespec64 offset; + unsigned long flags; + int ret; + + spin_lock_irqsave(&timer->reg_lock, flags); + + pr_debug("TS.sec %lld TS.tv_nsec %ld\n", ts->tv_sec, ts->tv_nsec); + + if (!qcom_ptp_tsc_is_enabled(timer->baseaddr)) { + /* Update the Counter */ + offset.tv_sec = ts->tv_sec; + offset.tv_nsec = ts->tv_nsec; + + ret = qcom_ptp_update_tsc_cntr(timer, offset); + + spin_unlock_irqrestore(&timer->reg_lock, flags); + return ret; + } + + /* Get the current timer value */ + qcom_tod_read(timer, &tod); + + /* Subtract the current reported time from our desired time */ + delta = timespec64_sub((struct timespec64)*ts, tod); + + pr_debug("Delta.sec %lld delta.tv_nsec %ld\n", delta.tv_sec, delta.tv_nsec); + + /* Update the Counter */ + qcom_ptp_update_tsc_offset(timer, delta); + + spin_unlock_irqrestore(&timer->reg_lock, flags); + return 0; +} + +static void qcom_etu_event_handler(struct qcom_etu_slice *etu, struct qcom_ptp_tsc *timer) +{ + struct ptp_clock_event extts_event; + u64 ts, temp; + u32 regval; + + etu->etu_tsc_sec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TSC_TS_HI)); + + etu->etu_tsc_nsec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TSC_TS_LO)); + + if (!timer->tsc_nsec_update) { + ts = etu->etu_tsc_sec * NSEC + etu->etu_tsc_nsec; + } else { + temp = etu->etu_tsc_sec; + ts = (temp << NSEC_SHFT) | etu->etu_tsc_nsec; + } + + if (ts != etu->etu_tsc_timestamp) { + extts_event.type = PTP_CLOCK_EXTTS; + extts_event.index = etu->extts_index; + extts_event.timestamp = ts; + + pr_debug("type:%d index:%d timestamp:%llu\n", extts_event.type, + extts_event.index, extts_event.timestamp); + + ptp_clock_event(etu->ptp_clock, &extts_event); + } + etu->etu_tsc_timestamp = ts; + + pr_debug("etu_tsc_sec:%u etu_tsc_nsec:%u etu_tsc_timestamp:%llu\n", + etu->etu_tsc_sec, etu->etu_tsc_nsec, etu->etu_tsc_timestamp); + + etu->etu_gctr_sec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_GCTR_TS_HI)); + + etu->etu_gctr_nsec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_GCTR_TS_LO)); + + etu->extts_event_type = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TS_EVENT_TYPE)); + + /* Concatenate GCTR_TS_HI(31:0) & GCTR_TS_LO(31:8) and divide with 19.2MHz */ + etu->global_qtimer = (((u64)etu->etu_gctr_sec << 24) | + (etu->etu_gctr_nsec >> 8)) / XO_MHZ; + + pr_debug("etu_gctr_sec:%u etu_gctr_nsec:%u global_qtimer:%llx extts_event_type %d\n", + etu->etu_gctr_sec, etu->etu_gctr_nsec, + etu->global_qtimer, etu->extts_event_type); + + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); + regval &= ~BIT(17); + regval &= ~BIT(16); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); + + /* FIFO CLR */ + writel_relaxed(0x7, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_FIFO_CLR)); + + /* Enable GCTR_TS_EN & TSCTR_TS_EN*/ + regval |= BIT(16) | BIT(17); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); +} + +static irqreturn_t qcom_etu_summary_irq_handler(int irq, void *data) +{ + struct qcom_etu_slice *etu; + struct qcom_ptp_tsc *timer; + unsigned long mask; + u32 status; + int slice; + + timer = data; + mask = timer->configured_slice_mask; + + for_each_set_bit(slice, &mask, MAX_ETU_SLICE) { + etu = &timer->etu_slice[slice]; + status = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + slice, TSCSS_TSC_SLICE_ETU_STATUS)); + + if (etu->extts_enable && (status & GENMASK(5, 0))) + qcom_etu_event_handler(etu, timer); + } + + return IRQ_HANDLED; +} + +static void qcom_tsc_configure_etu(struct qcom_ptp_tsc *timer, int slice) +{ + void __iomem *base = timer->etu_baseaddr; + u32 regval; + + /* Register for the IRQ */ + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + regval |= (timer->etu_slice[slice].extts_event_sel << 4) & GENMASK(9, 4); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + /* Enable GCTR_TS_EN & TSCTR_TS_EN*/ + regval |= BIT(16) | BIT(17); + /* Interrupt MASK enable */ + regval |= BIT(31); + + /* Enable rising edge config */ + regval |= BIT(0); + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + /* Bitmask of configured slices.*/ + timer->configured_slice_mask |= BIT(slice); + + pr_debug("ETU_SLICE#%d: 0x%x\n", slice, + readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG))); +} + +static int qcom_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + struct timespec64 ts; + int slice; + + pr_debug("Request Type %d\n", rq->type); + + switch (rq->type) { + case PTP_CLK_REQ_PPS: + timer->pps_enable = 1; + return 0; + case PTP_CLK_REQ_EXTTS: + pr_debug("PTP_CLK_REQ_EXTTS: Request external Index %d\n", rq->extts.index); + + if (rq->extts.index >= timer->total_etu_cnt) + return -EINVAL; + else if (!on) + return 0; + + for (slice = 0; slice < MAX_ETU_SLICE; slice++) { + if (!timer->etu_slice[slice].extts_present) + continue; + + if (rq->extts.index == timer->etu_slice[slice].extts_index) { + pr_debug("slice %d, index %d, etu_index %d\n", slice, + rq->extts.index, timer->etu_slice[slice].extts_index); + qcom_tsc_configure_etu(timer, + timer->etu_slice[slice].extts_slice_num); + timer->etu_slice[slice].extts_enable = true; + } + + } + return 0; + case PTP_CLK_REQ_PEROUT: + if (timer->tsc_hw_preload) { + if (!rq->perout.period.sec) { + /* Get the current timer value */ + qcom_tod_read(timer, &ts); + } else { + pr_debug("PTP_CLK_REQ_PEROUT: sec:%lld nsec:%u\n", + rq->perout.period.sec, rq->perout.period.nsec); + ts.tv_sec = rq->perout.period.sec; + ts.tv_nsec = rq->perout.period.nsec; + } + + /* Preload TSC with tv_sec += 1 and tv_nsec = 0 values */ + ts.tv_sec += 1; + ts.tv_nsec = 0; + qcom_ptp_enable_tsc_hw_preload(timer, ts); + } + return 0; + default: + break; + } + + return -EOPNOTSUPP; +} + +static struct ptp_clock_info qcom_ptp_clock_info = { + .owner = THIS_MODULE, + .name = "QCOM TSC", + .max_adj = 999999999, + /* The number of external time stamp channels. */ + .n_ext_ts = 1, + .n_per_out = 1, + .pps = 1, + .adjfine = qcom_ptp_adjfine, + .adjtime = qcom_ptp_adjtime, + .gettime64 = qcom_ptp_gettime, + .settime64 = qcom_ptp_settime, + .enable = qcom_ptp_enable, +}; + +/* module operations */ + +static void qcom_ptp_tsc_remove(struct platform_device *pdev) +{ + struct qcom_ptp_tsc *timer = platform_get_drvdata(pdev); + + if (timer->ptp_clock) { + ptp_clock_unregister(timer->ptp_clock); + timer->ptp_clock = NULL; + } + + if (timer->tsc_etu_clk) + clk_disable_unprepare(timer->tsc_etu_clk); + + if (timer->tsc_cntr_clk) + clk_disable_unprepare(timer->tsc_cntr_clk); + + if (timer->tsc_cfg_ahb_clk) + clk_disable_unprepare(timer->tsc_cfg_ahb_clk); + +} + +static int qcom_tsc_etu_get_data(struct platform_device *pdev, + struct qcom_ptp_tsc *timer) +{ + struct device *dev = &pdev->dev; + struct resource *r_mem; + struct pinctrl *pinctrl; + int ret, cnt, i, summary_irq; + + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!r_mem) { + dev_err(&pdev->dev, "No ETU resource defined\n"); + return 0; + } + + timer->etu_baseaddr = devm_ioremap_resource(&pdev->dev, r_mem); + if (IS_ERR(timer->etu_baseaddr)) + return PTR_ERR(timer->etu_baseaddr); + + summary_irq = platform_get_irq_byname(pdev, "etu_summary_irq"); + + if (summary_irq > 0) { + ret = devm_request_irq(dev, summary_irq, + qcom_etu_summary_irq_handler, IRQF_TRIGGER_HIGH, + "etu_summary_irq", timer); + if (ret) { + dev_err(&pdev->dev, "Request_summary_irq failed:%d: err:%d\n", + summary_irq, ret); + return ret; + } + } + + cnt = of_property_count_elems_of_size(dev->of_node, "qcom,etu-event-sel", + sizeof(u32)); + pr_debug("Number of event-sel %d\n", cnt); + + for (i = 0; i < cnt; i++) { + const char *name; + u32 sel, slice; + + ret = of_property_read_u32_index(dev->of_node, "qcom,etu-event-sel", i, &sel); + if (ret) + break; + + ret = of_property_read_u32_index(dev->of_node, "qcom,etu-slice", i, &slice); + if (ret) { + pr_debug("etu-slice property does not exist, configure using sel value\n"); + slice = sel; + } + + timer->etu_slice[slice].etu_baseaddr = timer->etu_baseaddr; + timer->etu_slice[slice].extts_index = i; + timer->etu_slice[slice].extts_event_sel = sel; + timer->etu_slice[slice].extts_slice_num = slice; + of_property_read_string_index(dev->of_node, + "qcom,etu-event-names", i, &name); + + strscpy(timer->etu_slice[slice].name, name, sizeof(timer->etu_slice[slice].name)); + + timer->etu_slice[slice].extts_irq = summary_irq; + + pr_debug("sel: %d, index: %d, slice-num:%d slice-name: %s, IRQ: %d\n", sel, + timer->etu_slice[slice].extts_index, slice, + timer->etu_slice[slice].name, timer->etu_slice[slice].extts_irq); + + timer->etu_slice[slice].extts_present = true; + timer->etu_slice[slice].ptp_clock = timer->ptp_clock; + } + + timer->total_etu_cnt = cnt; + timer->ptp_clock_info.n_ext_ts = cnt; + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_info(&pdev->dev, "No default pinctrl found\n"); + + return 0; +} + +static int qcom_ptp_tsc_probe(struct platform_device *pdev) +{ + struct qcom_ptp_tsc *timer; + struct resource *r_mem; + u32 cntr_val; + int ret; + + timer = devm_kzalloc(&pdev->dev, sizeof(*timer), GFP_KERNEL); + if (!timer) + return -ENOMEM; + + timer->dev = &pdev->dev; + + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r_mem) { + dev_err(&pdev->dev, "no IO resource defined\n"); + return -ENXIO; + } + + timer->baseaddr = devm_ioremap_resource(&pdev->dev, r_mem); + if (IS_ERR(timer->baseaddr)) + return PTR_ERR(timer->baseaddr); + + spin_lock_init(&timer->reg_lock); + + timer->tsc_cfg_ahb_clk = devm_clk_get(&pdev->dev, "cfg_ahb"); + if (IS_ERR(timer->tsc_cfg_ahb_clk)) { + if (PTR_ERR(timer->tsc_cfg_ahb_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get CFG AHB clock\n"); + return PTR_ERR(timer->tsc_cfg_ahb_clk); + } + + timer->tsc_cntr_clk = devm_clk_get(&pdev->dev, "cntr"); + if (IS_ERR(timer->tsc_cntr_clk)) { + if (PTR_ERR(timer->tsc_cntr_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get Counter clock\n"); + return PTR_ERR(timer->tsc_cntr_clk); + } + + timer->tsc_etu_clk = devm_clk_get(&pdev->dev, "etu"); + if (IS_ERR(timer->tsc_etu_clk)) { + if (PTR_ERR(timer->tsc_etu_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get ETU clock\n"); + return PTR_ERR(timer->tsc_etu_clk); + } + + ret = clk_prepare_enable(timer->tsc_cfg_ahb_clk); + if (ret) { + pr_debug("Failed to enable AHB clock\n"); + return ret; + } + + ret = clk_prepare_enable(timer->tsc_cntr_clk); + if (ret) { + pr_debug("Failed to enable counter clock\n"); + return ret; + } + + ret = clk_prepare_enable(timer->tsc_etu_clk); + if (ret) { + pr_debug("Failed to enable etu clock\n"); + return ret; + } + + timer->tsc_nsec_update = of_property_read_bool(pdev->dev.of_node, + "qcom,tsc-nsec-update"); + + timer->tsc_hw_preload = of_property_read_bool(pdev->dev.of_node, + "qcom,tsc-hw-preload"); + + if (timer->tsc_hw_preload) + INIT_DEFERRABLE_WORK(&timer->tsc_preload_poll_work, tsc_preload_poll); + + timer->ptp_clock_info = qcom_ptp_clock_info; + + timer->ptp_clock = ptp_clock_register(&timer->ptp_clock_info, &pdev->dev); + if (IS_ERR(timer->ptp_clock)) { + ret = PTR_ERR(timer->ptp_clock); + dev_err(&pdev->dev, "Failed to register ptp clock\n"); + goto out; + } + + qcom_tsc_etu_get_data(pdev, timer); + + if (!timer->tsc_nsec_update) { + cntr_val = (timer->tsc_hw_preload ? 0x1D8 : 0x1CC); + writel_relaxed(0x3B9AC9FF, timer->baseaddr + TSCSS_TSC_ROLLOVER_VAL); + } else { + cntr_val = 0x18C; + } + + writel_relaxed(cntr_val, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + pr_info("TSC CNTR 0x%x tsc-nsec-update %d tsc-hw-preload %d\n", + readl_relaxed(timer->baseaddr), timer->tsc_nsec_update, timer->tsc_hw_preload); + + platform_set_drvdata(pdev, timer); + + return 0; +out: + timer->ptp_clock = NULL; + return ret; +} + +static const struct of_device_id tsc_of_match[] = { + { .compatible = "qcom,tsc", }, + { /* end of table */ } +}; +MODULE_DEVICE_TABLE(of, tsc_of_match); + +static struct platform_driver qcom_ptp_tsc_driver = { + .probe = qcom_ptp_tsc_probe, + .remove = qcom_ptp_tsc_remove, + .driver = { + .name = "qcom_ptp_tsc", + .of_match_table = tsc_of_match, + }, +}; + +module_platform_driver(qcom_ptp_tsc_driver); + +MODULE_DESCRIPTION("PTP QCOM TSC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ras/Kconfig b/drivers/ras/Kconfig index fc4f4bb94a4c6..61a2a05d9c949 100644 --- a/drivers/ras/Kconfig +++ b/drivers/ras/Kconfig @@ -33,6 +33,7 @@ if RAS source "arch/x86/ras/Kconfig" source "drivers/ras/amd/atl/Kconfig" +source "drivers/ras/aest/Kconfig" config RAS_FMPM tristate "FRU Memory Poison Manager" diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile index 11f95d59d3972..72411ee9deafd 100644 --- a/drivers/ras/Makefile +++ b/drivers/ras/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_RAS_CEC) += cec.o obj-$(CONFIG_RAS_FMPM) += amd/fmpm.o obj-y += amd/atl/ +obj-y += aest/ diff --git a/drivers/ras/aest/Kconfig b/drivers/ras/aest/Kconfig new file mode 100644 index 0000000000000..ca034255faddf --- /dev/null +++ b/drivers/ras/aest/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# ARM Error Source Table Support +# +# Copyright (c) 2025, Alibaba Group. +# + +config AEST + tristate "ARM AEST Driver" + depends on ACPI_AEST || OF_AEST + depends on RAS + help + The Arm Error Source Table (AEST) provides details on ACPI + extensions that enable kernel-first handling of errors in a + system that supports the Armv8 RAS extensions. + + If set, the kernel will report and log hardware errors. + +config OF_AEST + bool "ARM Error Source Table DT Support" + depends on ARM64_RAS_EXTN && OF + help + Enable support for discovering ARM RAS error sources using the + Device Tree based Arm Error Source Table (AEST) specification. + This allows the kernel to enumerate and manage hardware error + reporting blocks described in firmware for ARMv8 and later + systems. Select this option if your platform describes AEST + nodes in Device Tree and relies on RAS error handling. diff --git a/drivers/ras/aest/Makefile b/drivers/ras/aest/Makefile new file mode 100644 index 0000000000000..2997952901c05 --- /dev/null +++ b/drivers/ras/aest/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_AEST) += aest.o + +aest-y := aest-core.o +aest-y += aest-sysfs.o +aest-y += aest-inject.o +aest-y += aest-cmn.o + +obj-$(CONFIG_OF_AEST) += aest-of.o diff --git a/drivers/ras/aest/aest-cmn.c b/drivers/ras/aest/aest-cmn.c new file mode 100644 index 0000000000000..ad82ed163a8c5 --- /dev/null +++ b/drivers/ras/aest/aest-cmn.c @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table CMN700 Support + * + * Copyright (c) 2025, Alibaba Inc + */ + +#include + +#include "aest.h" + +/* + * CMN include 5 device types, each device type has an error group register set + * which contains a set of error records. The struct aest_cmn_700 represents + * one CMN Instance, and the struct aest_cmn_700_child represent one CMN device. + * The error record of CMN use memory-mapped single error record view, so one + * record is correspond to one AEST node, it means there will be hundreds of + * AEST node of CMN. As described in chapters 2.6.3.4 of Arm ACPI Spec[1], we + * use vendor define data to recognize the device type of an AEST node. So AEST + * driver can enumerate all CMN AEST node to initialize struct aest_cmn_700 and + * aest_cmn_700_child with HID, UID and other CMN info described in AEST or CMN + * register. + * + * Each CMN Instance has their own error interrupt and the struct aest_cmn_700 + * is passed to interrupt context. OS check error group register set to locate + * record which report error. All procedure is similar with chapters 3.8 in + * Arm CMN Spec[2]. + * + * The CMN RAS architecture is showed as follow: + * + * +----+ + * -->|XP | ...... + * | +----+ + * | + * | +----+ ...... + * | |HNI | +----------------+ + * | +----+ ->|record/AEST node| + * | | +----------------+ + * +------------+ | +----+ | . + * |CMN Instance|--| |HNF |---| . + * +------------+ | +----+ | . + * | | +----------------+ + * | +----+ ->|record/AEST node| + * | |SBSX| +----------------+ + * | +----+ ...... + * | + * | +----+ + * -->|CCG | ...... + * +----+ + * + * [1]: https://developer.arm.com/documentation/den0093/latest + * [2]: https://developer.arm.com/documentation/102308/latest + */ + +#define CMN_RAS_DEV_NUM 6 +#define CMN700_ERRGSR_NUM 8 +#define CMN_MAX_UID 8 +#define CMN_ERRDEVARCH 0x3FB8 +#define CMN_ERRDEVARCH_REV GENMASK(19, 16) +#define CMN_ERRGSR_OFFSET 0x3000 + +struct cmn_vendor_data { + int node_type; + int node_id; + int logic_id; +}; + +struct cmn_config { + int errgsr_num; + int dev_num; + int ras_ver; + const int *node_id_map; + const char *const *node_name; + int (*errgsr_mapping)(int errgsr_bit); + u64 (*errgsr_offset)(u64 hnd_ofset, int node_idx); +}; + +static const char *const cmn700_node_name[] = { + [CMN_TYPE_HNI] = "HNI", [CMN_TYPE_HNF] = "HNF", + [CMN_TYPE_XP] = "XP", [CMN_TYPE_SBSX] = "SBSX", + [CMN_TYPE_CXRA] = "RND", [CMN_TYPE_MTSX] = "MTSX", +}; + +static const int cmn700_node_id_map[] = { + [CMN_TYPE_HNI] = 1, [CMN_TYPE_HNF] = 2, [CMN_TYPE_XP] = 0, + [CMN_TYPE_SBSX] = 3, [CMN_TYPE_CXRA] = 4, [CMN_TYPE_MTSX] = 5, +}; + +static u64 cmn_dev_array[CMN_MAX_UID]; +static struct cmn_config *cmn_config; + +static u64 cmn700_errgsr_offset(u64 hnd_offset, int node_idx) +{ + return hnd_offset + CMN_ERRGSR_OFFSET + + (node_idx * 2) * CMN700_ERRGSR_NUM * 8; +} + +static struct cmn_config cmn700_config = { + .errgsr_num = CMN700_ERRGSR_NUM, + .dev_num = CMN_RAS_DEV_NUM, + .ras_ver = 1, + .node_name = cmn700_node_name, + .node_id_map = cmn700_node_id_map, + .errgsr_mapping = cmn700_errgsr_mapping, + .errgsr_offset = cmn700_errgsr_offset, +}; + +static acpi_status aest_cmn_700_resource_ioremap(struct acpi_resource *res, + void *data) +{ + struct acpi_resource_address64 addr64; + u32 *uid = data; + acpi_status status; + + status = acpi_resource_to_address64(res, &addr64); + if (ACPI_FAILURE(status) || (addr64.resource_type != ACPI_MEMORY_RANGE)) + return AE_OK; + + cmn_dev_array[*uid] = (u64)ioremap(addr64.address.minimum, + addr64.address.address_length); + + pr_debug("CMN device resource [%llx-%llx] ioremap to %llx\n", + addr64.address.minimum, addr64.address.maximum, + cmn_dev_array[*uid]); + + return AE_CTRL_TERMINATE; +} + +static acpi_status aest_cmn_get_dev_by_uid(acpi_handle handle, u32 level, + void *data, void **return_value) +{ + u32 *match_uid = data; + acpi_status status; + unsigned long long uid; + + status = acpi_evaluate_integer(handle, METHOD_NAME__UID, NULL, &uid); + if (ACPI_FAILURE(status)) { + pr_err("Do not find devive\n"); + return_ACPI_STATUS(status); + } + + if (uid != *match_uid) + return AE_OK; + + pr_debug("CMN device instance %llx, walk through resource\n", uid); + + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + aest_cmn_700_resource_ioremap, data); + + if (ACPI_FAILURE(status)) { + pr_err("Device do not have resource\n"); + return_ACPI_STATUS(status); + } + + return AE_CTRL_TERMINATE; +} + +static inline int aest_cmn_node_ver(void *base) +{ + return FIELD_GET(CMN_ERRDEVARCH_REV, + readl_relaxed(base + CMN_ERRDEVARCH)); +} + +static int aest_cmn_init_node(struct aest_device *adev, + struct aest_node *cmn_node, + struct acpi_aest_node *anode, u64 type, + u64 errgsr_addr) +{ + cmn_node->info = anode; + cmn_node->name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s", + cmn_config->node_name[type]); + if (!cmn_node->name) + return -ENOMEM; + cmn_node->errgsr = (void *)errgsr_addr; + cmn_node->type = anode->type; + cmn_node->adev = adev; + cmn_node->version = cmn_config->ras_ver; + cmn_node->errgsr_num = cmn_config->errgsr_num; + cmn_node->errgsr_mapping = cmn_config->errgsr_mapping; + cmn_node->record_count = cmn_node->errgsr_num * BITS_PER_LONG / 2; + cmn_node->record_implemented = devm_bitmap_zalloc( + adev->dev, cmn_node->record_count, GFP_KERNEL); + if (!cmn_node->record_implemented) + return -ENOMEM; + bitmap_set(cmn_node->record_implemented, 0, cmn_node->record_count); + + cmn_node->status_reporting = devm_bitmap_zalloc( + adev->dev, cmn_node->record_count, GFP_KERNEL); + if (!cmn_node->status_reporting) + return -ENOMEM; + bitmap_set(cmn_node->status_reporting, 0, cmn_node->record_count); + + cmn_node->records = devm_kcalloc(adev->dev, cmn_node->record_count, + sizeof(struct aest_record), + GFP_KERNEL); + if (!cmn_node->records) + return -ENOMEM; + + aest_node_dbg(cmn_node, "Node init with errgsr %llx\n", errgsr_addr); + + return 0; +} + +static int aest_cmn_reorgnize_node(struct aest_device *adev, + struct acpi_aest_node *anode, u64 base) +{ + struct aest_node *cmn_node; + u64 hnd_offset, cmn_node_offset, reg, logic_id, type, node_id; + u64 errgsr_addr, hnd_base; + struct aest_record *record; + int ret, node_index; + struct cmn_vendor_data *vendor_data; + + if (anode->interface_hdr->type != + ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED) { + aest_dev_err(adev, "CMN just use single memory mapping\n"); + return -ENODEV; + } + + hnd_offset = *((u64 *)anode->vendor->vendor_specific_data); + cmn_node_offset = *((u64 *)&anode->vendor->vendor_specific_data[8]); + + reg = readq_relaxed((void *)base + cmn_node_offset + CMN_NODE_INFO); + + logic_id = FIELD_GET(CMN_NI_LOGICAL_ID, reg); + type = FIELD_GET(CMN_NI_NODE_TYPE, reg); + node_id = FIELD_GET(CMN_NI_NODE_ID, reg); + + hnd_base = base + hnd_offset; + node_index = cmn_config->node_id_map[type]; + errgsr_addr = base + cmn_config->errgsr_offset(hnd_offset, node_index); + + // node not register, create it + cmn_node = &adev->nodes[node_index]; + if (!cmn_node->errgsr) { + ret = aest_cmn_init_node(adev, cmn_node, anode, type, + errgsr_addr); + if (ret) + return -ENOMEM; + } + + aest_dev_dbg(adev, "node type %llx, id %llx, offset %llx\n", type, + logic_id, cmn_node_offset); + + if (!test_bit(0, anode->record_implemented)) + clear_bit(logic_id, cmn_node->record_implemented); + + if (!test_bit(0, anode->status_reporting)) + clear_bit(logic_id, cmn_node->status_reporting); + + record = &cmn_node->records[logic_id]; + record->name = + devm_kasprintf(adev->dev, GFP_KERNEL, "record%lld", logic_id); + if (!record->name) + return -ENOMEM; + record->regs_base = devm_ioremap( + adev->dev, (resource_size_t)anode->interface_hdr->address, + sizeof(struct ras_ext_regs)); + if (!record->regs_base) + return -ENOMEM; + record->addressing_mode = test_bit(0, anode->addressing_mode); + record->node = cmn_node; + record->index = logic_id; + record->access = &aest_access[anode->interface_hdr->type]; + + vendor_data = devm_kzalloc(adev->dev, sizeof(struct cmn_vendor_data), + GFP_KERNEL); + vendor_data->node_type = type; + vendor_data->node_id = node_id; + vendor_data->logic_id = logic_id; + + record->vendor_data = vendor_data; + record->vendor_data_size = sizeof(struct cmn_vendor_data); + + aest_record_dbg(record, "base %llx\n", anode->interface_hdr->address); + + return 0; +} + +// reorgnize cmn node +static int aest_cmn_probe(struct aest_device *adev, struct aest_hnode *ahnode) +{ + acpi_status status; + u64 base; + int ret = 0; + struct acpi_aest_node *anode; + char name[9]; + + anode = list_first_entry(&ahnode->list, struct acpi_aest_node, list); + if (!anode) + return -ENODEV; + + if (!cmn_dev_array[anode->vendor->acpi_uid]) { + snprintf(name, 9, "%s", anode->vendor->acpi_hid); + status = acpi_get_devices(name, aest_cmn_get_dev_by_uid, + &anode->vendor->acpi_uid, NULL); + if (ACPI_FAILURE(status)) { + aest_dev_err(adev, "Can not find base\n"); + return_ACPI_STATUS(status); + } + } + base = cmn_dev_array[anode->vendor->acpi_uid]; + if (!base) { + aest_dev_err(adev, "Device base invalid\n"); + return -ENODEV; + } + + adev->type = anode->type; + adev->node_cnt = cmn_config->dev_num; + adev->nodes = devm_kcalloc(adev->dev, adev->node_cnt, + sizeof(struct aest_node), GFP_KERNEL); + if (!adev->nodes) + return -ENOMEM; + aest_set_name(adev, ahnode); + + list_for_each_entry(anode, &ahnode->list, list) { + ret = aest_cmn_reorgnize_node(adev, anode, base); + if (ret) + return ret; + } + + return 0; +} + +int aest_cmn700_probe(struct aest_device *adev, struct aest_hnode *ahnode) +{ + cmn_config = &cmn700_config; + + return aest_cmn_probe(adev, ahnode); +} diff --git a/drivers/ras/aest/aest-core.c b/drivers/ras/aest/aest-core.c new file mode 100644 index 0000000000000..9ce782a66edfc --- /dev/null +++ b/drivers/ras/aest/aest-core.c @@ -0,0 +1,1107 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "aest.h" + +DEFINE_PER_CPU(struct aest_device, percpu_adev); + +#undef pr_fmt +#define pr_fmt(fmt) "AEST: " fmt + +static bool aest_panic_on_ue; +module_param(aest_panic_on_ue, bool, 0644); +MODULE_PARM_DESC(aest_panic_on_ue, + "Panic on unrecoverable error: 0=off 1=on (default: 1)"); + +#ifdef CONFIG_DEBUG_FS +struct dentry *aest_debugfs; +#endif +/* + * This memory pool is only to be used to save AEST node in AEST irq context. + * There can be 500 AEST node at most. + */ +#define AEST_NODE_ALLOCED_MAX 500 + +#define AEST_LOG_PREFIX_BUFFER 64 + +BLOCKING_NOTIFIER_HEAD(aest_decoder_chain); + +static void aest_print(struct aest_event *event) +{ + static atomic_t seqno = { 0 }; + unsigned int curr_seqno; + char pfx_seq[AEST_LOG_PREFIX_BUFFER]; + int index; + struct ras_ext_regs *regs; + + curr_seqno = atomic_inc_return(&seqno); + snprintf(pfx_seq, sizeof(pfx_seq), "{%u}" HW_ERR, curr_seqno); + pr_info("%sHardware error from AEST %s\n", pfx_seq, event->node_name); + + switch (event->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: + /* + * For shared/global nodes (e.g. cluster L3 cache, DSU), + * id0 is the CPU that handled the interrupt — not the error + * source itself. The node_name already identifies the resource + * (e.g. "processor.cache.1"). Print a distinct message so the + * log is not confused with a per-PE CPU error. + */ + if (event->proc_flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) + pr_err("%s Error from shared processor resource (interrupt handled on CPU%d)\n", + pfx_seq, event->id0); + else + pr_err("%s Error from CPU%d\n", pfx_seq, event->id0); + break; + case ACPI_AEST_MEMORY_ERROR_NODE: + pr_err("%s Error from memory at SRAT proximity domain %#x\n", + pfx_seq, event->id0); + break; + case ACPI_AEST_SMMU_ERROR_NODE: + pr_err("%s Error from SMMU IORT node %#x subcomponent %#x\n", + pfx_seq, event->id0, event->id1); + break; + case ACPI_AEST_VENDOR_ERROR_NODE: + pr_err("%s Error from vendor hid %8.8s uid %#x\n", pfx_seq, + event->hid, event->id1); + break; + case ACPI_AEST_GIC_ERROR_NODE: + pr_err("%s Error from GIC type %#x instance %#x\n", pfx_seq, + event->id0, event->id1); + break; + default: + pr_err("%s Unknown AEST node type\n", pfx_seq); + return; + } + + index = event->index; + regs = &event->regs; + + pr_err("%s ERR%dFR: 0x%llx\n", pfx_seq, index, regs->err_fr); + pr_err("%s ERR%dCTRL: 0x%llx\n", pfx_seq, index, regs->err_ctlr); + pr_err("%s ERR%dSTATUS: 0x%llx\n", pfx_seq, index, regs->err_status); + if (regs->err_status & ERR_STATUS_AV) + pr_err("%s ERR%dADDR: 0x%llx\n", pfx_seq, index, + regs->err_addr); + + if (regs->err_status & ERR_STATUS_MV) { + pr_err("%s ERR%dMISC0: 0x%llx\n", pfx_seq, index, + regs->err_misc[0]); + pr_err("%s ERR%dMISC1: 0x%llx\n", pfx_seq, index, + regs->err_misc[1]); + pr_err("%s ERR%dMISC2: 0x%llx\n", pfx_seq, index, + regs->err_misc[2]); + pr_err("%s ERR%dMISC3: 0x%llx\n", pfx_seq, index, + regs->err_misc[3]); + } + + trace_arm_ras_ext_event(event->type, event->id0, event->id1, + event->index, event->hid, &event->regs, + event->vendor_data, event->vendor_data_size); +} + +static void aest_handle_memory_failure(u64 addr) +{ + unsigned long pfn; + + pfn = PHYS_PFN(addr); + + if (!pfn_valid(pfn)) { + pr_warn(HW_ERR "Invalid physical address: %#llx\n", addr); + return; + } + +#ifdef CONFIG_MEMORY_FAILURE + memory_failure(pfn, 0); +#endif +} + +static void init_aest_event(struct aest_event *event, + struct aest_record *record, + struct ras_ext_regs *regs) +{ + struct aest_node *node = record->node; + struct acpi_aest_node *info = node->info; + + event->type = node->type; + event->node_name = node->name; + switch (node->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: + if (info->processor->flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) + event->id0 = smp_processor_id(); + else + event->id0 = get_cpu_for_acpi_id( + info->processor->processor_id); + + event->id1 = info->processor->resource_type; + event->proc_flags = info->processor->flags; + break; + case ACPI_AEST_MEMORY_ERROR_NODE: + event->id0 = info->memory->srat_proximity_domain; + break; + case ACPI_AEST_SMMU_ERROR_NODE: + event->id0 = info->smmu->iort_node_reference; + event->id1 = info->smmu->subcomponent_reference; + break; + case ACPI_AEST_VENDOR_ERROR_NODE: + event->id0 = 0; + event->id1 = info->vendor->acpi_uid; + event->hid = info->vendor->acpi_hid; + break; + case ACPI_AEST_GIC_ERROR_NODE: + event->id0 = info->gic->interface_type; + event->id1 = info->gic->instance_id; + break; + default: + event->id0 = 0; + event->id1 = 0; + } + + memcpy(&event->regs, regs, sizeof(*regs)); + event->index = record->index; + event->addressing_mode = record->addressing_mode; + event->vendor_data_size = record->vendor_data_size; + event->vendor_data = record->vendor_data; +} + +static int aest_node_gen_pool_add(struct aest_device *adev, + struct aest_record *record, + struct ras_ext_regs *regs) +{ + struct aest_event *event; + + if (!adev->pool) + return -EINVAL; + + event = (void *)gen_pool_alloc(adev->pool, sizeof(*event)); + if (!event) + return -ENOMEM; + + memset(event, 0, sizeof(*event)); + init_aest_event(event, record, regs); + llist_add(&event->llnode, &adev->event_list); + + if (regs->err_status & ERR_STATUS_CE) + record->count.ce++; + if (regs->err_status & ERR_STATUS_DE) + record->count.de++; + if (regs->err_status & ERR_STATUS_UE) { + switch (regs->err_status & ERR_STATUS_UET) { + case ERR_STATUS_UET_UC: + record->count.uc++; + break; + case ERR_STATUS_UET_UEU: + record->count.ueu++; + break; + case ERR_STATUS_UET_UER: + record->count.uer++; + break; + case ERR_STATUS_UET_UEO: + record->count.ueo++; + break; + } + } + + return 0; +} + +static void aest_log(struct aest_record *record, struct ras_ext_regs *regs) +{ + struct aest_device *adev = record->node->adev; + + if (!aest_node_gen_pool_add(adev, record, regs)) + schedule_work(&adev->aest_work); +} + +void aest_register_decode_chain(struct notifier_block *nb) +{ + blocking_notifier_chain_register(&aest_decoder_chain, nb); +} +EXPORT_SYMBOL_GPL(aest_register_decode_chain); + +void aest_unregister_decode_chain(struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&aest_decoder_chain, nb); +} +EXPORT_SYMBOL_GPL(aest_unregister_decode_chain); + +static void aest_node_pool_process(struct work_struct *work) +{ + struct llist_node *head; + struct aest_event *event; + struct aest_device *adev = + container_of(work, struct aest_device, aest_work); + u64 status, addr; + + head = llist_del_all(&adev->event_list); + if (!head) + return; + + head = llist_reverse_order(head); + llist_for_each_entry(event, head, llnode) { + aest_print(event); + + status = event->regs.err_status; + if (!(event->regs.err_addr & ERR_ADDR_AI) && + (status & (ERR_STATUS_UE | ERR_STATUS_DE))) { + if (event->addressing_mode == AEST_ADDREESS_SPA) + addr = event->regs.err_addr & PHYS_MASK; + aest_handle_memory_failure(addr); + } + + blocking_notifier_call_chain(&aest_decoder_chain, 0, event); + gen_pool_free(adev->pool, (unsigned long)event, sizeof(*event)); + } +} + +static int aest_node_pool_init(struct aest_device *adev) +{ + unsigned long addr, size; + + size = ilog2(sizeof(struct aest_event)); + adev->pool = + devm_gen_pool_create(adev->dev, size, -1, dev_name(adev->dev)); + if (!adev->pool) + return -ENOMEM; + + size = PAGE_ALIGN(size * AEST_NODE_ALLOCED_MAX); + addr = (unsigned long)devm_kzalloc(adev->dev, size, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + return gen_pool_add(adev->pool, addr, size, -1); +} + +static void aest_panic(struct aest_record *record, struct ras_ext_regs *regs, + char *msg) +{ + struct aest_event event = { 0 }; + + init_aest_event(&event, record, regs); + + aest_print(&event); + + panic(msg); +} + +void aest_proc_record(struct aest_record *record, void *data, bool fake) +{ + struct ras_ext_regs regs = { 0 }; + int *count = data; + u64 ue; + + regs.err_status = record_read(record, ERXSTATUS); + if (!(regs.err_status & ERR_STATUS_V)) + return; + + (*count)++; + + if (regs.err_status & ERR_STATUS_AV) + regs.err_addr = record_read(record, ERXADDR); + + regs.err_fr = record_read(record, ERXFR); + regs.err_ctlr = record_read(record, ERXCTLR); + + if (regs.err_status & ERR_STATUS_MV) { + regs.err_misc[0] = record_read(record, ERXMISC0); + regs.err_misc[1] = record_read(record, ERXMISC1); + if (record->node->version >= ID_AA64PFR0_EL1_RAS_V1P1) { + regs.err_misc[2] = record_read(record, ERXMISC2); + regs.err_misc[3] = record_read(record, ERXMISC3); + } + + if (record->node->info->interface_hdr->flags & + AEST_XFACE_FLAG_CLEAR_MISC) { + record_write(record, ERXMISC0, 0); + record_write(record, ERXMISC1, 0); + if (record->node->version >= ID_AA64PFR0_EL1_RAS_V1P1) { + record_write(record, ERXMISC2, 0); + record_write(record, ERXMISC3, 0); + } + /* ce count is 0 if record do not support ce */ + } else if (record->ce.count > 0) + record_write(record, ERXMISC0, record->ce.reg_val); + } + + /* panic if unrecoverable and uncontainable error encountered */ + ue = FIELD_GET(ERR_STATUS_UET, regs.err_status); + if ((regs.err_status & ERR_STATUS_UE) && + (ue == ERR_STATUS_UET_UC || ue == ERR_STATUS_UET_UEU)) { + if (fake) + aest_record_info( + record, + "Simulated error! Skip panic due to fault injection\n"); + else if (aest_panic_on_ue) + aest_panic(record, ®s, + "AEST: unrecoverable error encountered"); + else + aest_record_err(record, "UE detected, panic suppressed\n"); + } + + aest_log(record, ®s); + + /* Write-one-to-clear the bits we've seen */ + regs.err_status &= ERR_STATUS_W1TC; + + /* Multi bit filed need to write all-ones to clear. */ + if (regs.err_status & ERR_STATUS_CE) + regs.err_status |= ERR_STATUS_CE; + + /* Multi bit filed need to write all-ones to clear. */ + if (regs.err_status & ERR_STATUS_UET) + regs.err_status |= ERR_STATUS_UET; + + record_write(record, ERXSTATUS, regs.err_status); +} + +void aest_node_foreach_record(void (*func)(struct aest_record *, void *, bool), + struct aest_node *node, void *data, + unsigned long *bitmap) +{ + int i; + + for_each_clear_bit(i, bitmap, node->record_count) { + aest_select_record(node, i); + + func(&node->records[i], data, false); + + aest_sync(node); + } +} + +static int aest_proc(struct aest_node *node) +{ + int count = 0, i, j, size = node->record_count, record_idx; + u64 err_group = 0; + + aest_node_dbg(node, "Poll bitmap %*pb\n", size, + node->record_implemented); + aest_node_foreach_record(aest_proc_record, node, &count, + node->record_implemented); + + if (!node->errgsr) + return count; + + aest_node_dbg(node, "Report bitmap %*pb\n", size, + node->status_reporting); + for (i = 0; i < BITS_TO_U64(size); i++) { + err_group = readq_relaxed((void *)node->errgsr + i * 8); + for_each_set_bit(j, (unsigned long *)&err_group, + BITS_PER_LONG) { + record_idx = + node->errgsr_mapping(i * BITS_PER_LONG + j); + aest_node_dbg(node, "errgsr[%d]: bit %d occur error\n", + i, record_idx); + /* + * Error group base is only valid in Memory Map node, + * so driver do not need to write select register and + * sync. + */ + if (test_bit(record_idx, node->status_reporting)) + continue; + aest_proc_record(&node->records[record_idx], &count, + false); + } + } + + return count; +} + +static irqreturn_t aest_irq_func(int irq, void *input) +{ + struct aest_device *adev = input; + int i; + + for (i = 0; i < adev->node_cnt; i++) { + if (!adev->nodes[i].record_count) + continue; + aest_proc(&adev->nodes[i]); + } + + return IRQ_HANDLED; +} + +static int aest_register_irq(struct aest_device *adev) +{ + int i, irq, ret; + char *irq_desc; + + irq_desc = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%s.", + dev_driver_string(adev->dev), + dev_name(adev->dev)); + if (!irq_desc) + return -ENOMEM; + + for (i = 0; i < MAX_GSI_PER_NODE; i++) { + irq = adev->irq[i]; + + if (!irq) + continue; + + if (irq_is_percpu_devid(irq)) { + ret = request_percpu_irq(irq, aest_irq_func, irq_desc, + adev->adev_oncore); + if (ret) + goto free; + } else { + ret = devm_request_irq(adev->dev, irq, aest_irq_func, 0, + irq_desc, adev); + if (ret) + return ret; + } + } + return 0; + +free: + for (; i >= 0; i--) { + irq = adev->irq[i]; + + if (irq_is_percpu_devid(irq)) + free_percpu_irq(irq, adev->adev_oncore); + } + + return ret; +} + +static void aest_enable_irq(struct aest_record *record) +{ + u64 err_ctlr; + struct aest_device *adev = record->node->adev; + + err_ctlr = record_read(record, ERXCTLR); + + if (adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]) + err_ctlr |= (ERR_CTLR_FI | ERR_CTLR_CFI); + if (adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]) + err_ctlr |= ERR_CTLR_UI; + + record_write(record, ERXCTLR, err_ctlr); +} + +static void aest_config_irq(struct aest_node *node) +{ + int i; + struct acpi_aest_node_interrupt_v2 *interrupt; + + if (!node->irq_config) + return; + + for (i = 0; i < node->info->interrupt_count; i++) { + interrupt = &node->info->interrupt[i]; + + if (interrupt->type == ACPI_AEST_NODE_FAULT_HANDLING) + writeq_relaxed(interrupt->gsiv, node->irq_config); + + if (interrupt->type == ACPI_AEST_NODE_ERROR_RECOVERY) + writeq_relaxed(interrupt->gsiv, node->irq_config + 8); + + aest_node_dbg(node, "config irq type %d gsiv %d at %llx", + interrupt->type, interrupt->gsiv, + (u64)node->irq_config); + } +} + +static enum ras_ce_threshold aest_get_ce_threshold(struct aest_record *record) +{ + u64 err_fr, err_fr_cec, err_fr_rp = -1; + + err_fr = record_read(record, ERXFR); + err_fr_cec = FIELD_GET(ERR_FR_CEC, err_fr); + err_fr_rp = FIELD_GET(ERR_FR_RP, err_fr); + + if (err_fr_cec == ERR_FR_CEC_0B_COUNTER) + return RAS_CE_THRESHOLD_0B; + else if (err_fr_rp == ERR_FR_RP_DOUBLE_COUNTER) + return RAS_CE_THRESHOLD_32B; + else if (err_fr_cec == ERR_FR_CEC_8B_COUNTER) + return RAS_CE_THRESHOLD_8B; + else if (err_fr_cec == ERR_FR_CEC_16B_COUNTER) + return RAS_CE_THRESHOLD_16B; + else + return UNKNOWN; +} + +static const struct ce_threshold_info ce_info[] = { + [RAS_CE_THRESHOLD_0B] = { 0 }, + [RAS_CE_THRESHOLD_8B] = { + .max_count = ERR_8B_CEC_MAX, + .mask = ERR_MISC0_8B_CEC, + .shift = ERR_MISC0_CEC_SHIFT, + }, + [RAS_CE_THRESHOLD_16B] = { + .max_count = ERR_16B_CEC_MAX, + .mask = ERR_MISC0_16B_CEC, + .shift = ERR_MISC0_CEC_SHIFT, + }, +}; + +static void aest_set_ce_threshold(struct aest_record *record) +{ + u64 err_misc0; + struct ce_threshold *ce = &record->ce; + const struct ce_threshold_info *info; + + record->threshold_type = aest_get_ce_threshold(record); + + switch (record->threshold_type) { + case RAS_CE_THRESHOLD_0B: + aest_record_dbg(record, "do not support CE threshold!\n"); + return; + case RAS_CE_THRESHOLD_8B: + aest_record_dbg(record, "support 8 bit CE threshold!\n"); + break; + case RAS_CE_THRESHOLD_16B: + aest_record_dbg(record, "support 16 bit CE threshold!\n"); + break; + case RAS_CE_THRESHOLD_32B: + aest_record_dbg(record, "not support 32 bit CE threshold!\n"); + break; + default: + aest_record_dbg(record, "Unknown misc0 ce threshold!\n"); + } + + err_misc0 = record_read(record, ERXMISC0); + info = &ce_info[record->threshold_type]; + ce->info = info; + + // Default CE threshold is 1. + ce->count = info->max_count; + ce->threshold = DEFAULT_CE_THRESHOLD; + ce->reg_val = err_misc0 | info->mask; + + record_write(record, ERXMISC0, ce->reg_val); + aest_record_dbg(record, "CE threshold is %llx, controlled by Kernel", + ce->threshold); +} + +static int get_aest_node_ver(struct aest_node *node) +{ + u64 reg; + void *devarch_base; + + if (node->type == ACPI_AEST_GIC_ERROR_NODE) { + devarch_base = ioremap(node->info->interface_hdr->address + + GIC_ERRDEVARCH, + PAGE_SIZE); + if (!devarch_base) + return 0; + + reg = readl_relaxed(devarch_base); + iounmap(devarch_base); + + return FIELD_GET(ERRDEVARCH_REV, reg); + } + + return FIELD_GET(ID_AA64PFR0_EL1_RAS_MASK, read_cpuid(ID_AA64PFR0_EL1)); +} + +static int aest_init_record(struct aest_record *record, int i, + struct aest_node *node) +{ + struct device *dev = node->adev->dev; + + record->name = devm_kasprintf(dev, GFP_KERNEL, "record%d", i); + if (!record->name) + return -ENOMEM; + + if (node->base) + record->regs_base = + node->base + sizeof(struct ras_ext_regs) * i; + + record->access = &aest_access[node->info->interface_hdr->type]; + record->addressing_mode = test_bit(i, node->info->addressing_mode); + record->index = i; + record->node = node; + + aest_record_dbg(record, "base: %p, index: %d, address mode: %x\n", + record->regs_base, record->index, + record->addressing_mode); + return 0; +} + +static void aest_online_record(struct aest_record *record, void *data, + bool __unused) +{ + if (record_read(record, ERXFR) & ERR_FR_CE) + aest_set_ce_threshold(record); + + aest_enable_irq(record); +} + +static void aest_online_oncore_node(struct aest_node *node) +{ + int count; + + count = aest_proc(node); + aest_node_dbg(node, "Find %d error on CPU%d before AEST probe\n", count, + smp_processor_id()); + + aest_node_foreach_record(aest_online_record, node, NULL, + node->record_implemented); + + aest_node_foreach_record(aest_online_record, node, NULL, + node->status_reporting); +} + +static void aest_online_oncore_dev(void *data) +{ + int fhi_irq, eri_irq, i; + struct aest_device *adev = this_cpu_ptr(data); + + for (i = 0; i < adev->node_cnt; i++) + aest_online_oncore_node(&adev->nodes[i]); + + fhi_irq = adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]; + if (fhi_irq > 0) + enable_percpu_irq(fhi_irq, IRQ_TYPE_NONE); + eri_irq = adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]; + if (eri_irq > 0) + enable_percpu_irq(eri_irq, IRQ_TYPE_NONE); +} + +static void aest_offline_oncore_dev(void *data) +{ + int fhi_irq, eri_irq; + struct aest_device *adev = this_cpu_ptr(data); + + fhi_irq = adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]; + if (fhi_irq > 0) + disable_percpu_irq(fhi_irq); + eri_irq = adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]; + if (eri_irq > 0) + disable_percpu_irq(eri_irq); +} + +static void aest_online_dev(struct aest_device *adev) +{ + int count, i; + struct aest_node *node; + + for (i = 0; i < adev->node_cnt; i++) { + node = &adev->nodes[i]; + + if (!node->name) + continue; + + count = aest_proc(node); + aest_node_dbg(node, "Find %d error before AEST probe\n", count); + + aest_config_irq(node); + + aest_node_foreach_record(aest_online_record, node, NULL, + node->record_implemented); + aest_node_foreach_record(aest_online_record, node, NULL, + node->status_reporting); + } +} + +static int aest_starting_cpu(unsigned int cpu) +{ + pr_debug("CPU%d starting\n", cpu); + aest_online_oncore_dev(&percpu_adev); + + return 0; +} + +static int aest_dying_cpu(unsigned int cpu) +{ + pr_debug("CPU%d dying\n", cpu); + aest_offline_oncore_dev(&percpu_adev); + + return 0; +} + +static void aest_device_remove(struct platform_device *pdev) +{ + struct aest_device *adev = platform_get_drvdata(pdev); + int i; + + platform_set_drvdata(pdev, NULL); + + if (adev->type != ACPI_AEST_PROCESSOR_ERROR_NODE) + return; + + on_each_cpu(aest_offline_oncore_dev, adev->adev_oncore, 1); + + for (i = 0; i < MAX_GSI_PER_NODE; i++) { + if (adev->irq[i]) + free_percpu_irq(adev->irq[i], adev->adev_oncore); + } +} + +static char *alloc_aest_node_name(struct aest_node *node) +{ + char *name; + + switch (node->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: + /* + * Shared/global processor nodes (e.g. cluster L3 cache, DSU) + * have processor_id=0 and use smp_processor_id() at error-log + * time — using processor_id in the name would produce the same + * "processor.0" string for every shared node and every CPU0 + * per-PE node, making logs ambiguous. + * + * For shared/global nodes, build the name from the resource + * type and the device id so each node gets a unique, meaningful + * name (e.g. "processor.cache.1", "processor.tlb.2"). + * + * For per-PE nodes, keep the original "processor." form. + */ + if (node->info->processor->flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) { + static const char *const res_name[] = { + [ACPI_AEST_CACHE_RESOURCE] = "cache", + [ACPI_AEST_TLB_RESOURCE] = "tlb", + [ACPI_AEST_GENERIC_RESOURCE] = "generic", + }; + u8 rtype = node->info->processor->resource_type; + const char *rstr = (rtype < ARRAY_SIZE(res_name) && + res_name[rtype]) ? res_name[rtype] : "unknown"; + + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, + "%s.%s.%d", + aest_node_name[node->type], + rstr, + node->adev->id); + } else { + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, + "%s.%d", + aest_node_name[node->type], + node->info->processor->processor_id); + } + break; + case ACPI_AEST_MEMORY_ERROR_NODE: + case ACPI_AEST_SMMU_ERROR_NODE: + case ACPI_AEST_VENDOR_ERROR_NODE: + case ACPI_AEST_GIC_ERROR_NODE: + case ACPI_AEST_PCIE_ERROR_NODE: + case ACPI_AEST_PROXY_ERROR_NODE: + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, "%s.%llx", + aest_node_name[node->type], + node->info->interface_hdr->address); + break; + default: + name = devm_kasprintf(node->adev->dev, GFP_KERNEL, "Unknown"); + } + + return name; +} + +static int aest_node_set_errgsr(struct aest_device *adev, + struct aest_node *node) +{ + struct acpi_aest_node *anode = node->info; + u64 errgsr_base = anode->common->error_group_register_base; + + if (anode->interface_hdr->type != ACPI_AEST_NODE_MEMORY_MAPPED) + return 0; + + if (!node->base) + return 0; + + if (!(anode->interface_hdr->flags & AEST_XFACE_FLAG_ERROR_GROUP)) { + node->errgsr = node->base + node->group->errgsr_offset; + return 0; + } + + if (!errgsr_base) + return -EINVAL; + + node->errgsr = devm_ioremap(adev->dev, errgsr_base, PAGE_SIZE); + if (!node->errgsr) + return -ENOMEM; + + return 0; +} + +static int aest_init_node(struct aest_device *adev, struct aest_node *node, + struct acpi_aest_node *anode) +{ + int i, ret; + u64 address, flags; + + node->adev = adev; + node->info = anode; + node->type = anode->type; + node->version = get_aest_node_ver(node); + node->errgsr_mapping = default_errgsr_mapping; + node->name = alloc_aest_node_name(node); + if (!node->name) + return -ENOMEM; + node->record_implemented = anode->record_implemented; + node->status_reporting = anode->status_reporting; + node->group = &aest_group_config[anode->interface_hdr->group_format]; + + address = anode->interface_hdr->address; + if (address) { + node->base = + devm_ioremap(adev->dev, address, node->group->size); + if (!node->base) + return -ENOMEM; + } + + flags = anode->interface_hdr->flags; + address = node->info->common->fault_inject_register_base; + if ((flags & AEST_XFACE_FLAG_FAULT_INJECT) && address) { + if (address - anode->interface_hdr->address < node->group->size) + node->inj = node->base + + (address - anode->interface_hdr->address); + else { + node->inj = devm_ioremap(adev->dev, address, PAGE_SIZE); + if (!node->inj) + return -ENOMEM; + } + } + + address = node->info->common->interrupt_config_register_base; + if ((flags & AEST_XFACE_FLAG_INT_CONFIG) && address) { + if (address - anode->interface_hdr->address < node->group->size) + node->irq_config = + node->base + + (address - anode->interface_hdr->address); + else { + node->irq_config = + devm_ioremap(adev->dev, address, PAGE_SIZE); + if (!node->irq_config) + return -ENOMEM; + } + } + + ret = aest_node_set_errgsr(adev, node); + if (ret) + return ret; + + node->record_count = anode->interface_hdr->error_record_count; + node->records = devm_kcalloc(adev->dev, node->record_count, + sizeof(struct aest_record), GFP_KERNEL); + if (!node->records) + return -ENOMEM; + + node->errgsr_num = DIV_ROUND_UP(node->record_count, BITS_PER_LONG); + for (i = 0; i < node->record_count; i++) { + ret = aest_init_record(&node->records[i], i, node); + if (ret) + return ret; + } + aest_node_dbg(node, "%d records, base: %llx, errgsr: %llx\n", + node->record_count, (u64)node->base, (u64)node->errgsr); + return 0; +} + +static int aest_init_nodes(struct aest_device *adev, struct aest_hnode *ahnode) +{ + struct acpi_aest_node *anode; + struct aest_node *node; + int ret, i = 0; + + adev->node_cnt = ahnode->count; + adev->nodes = devm_kcalloc(adev->dev, adev->node_cnt, + sizeof(struct aest_node), GFP_KERNEL); + if (!adev->nodes) + return -ENOMEM; + + list_for_each_entry(anode, &ahnode->list, list) { + adev->type = anode->type; + + node = &adev->nodes[i++]; + ret = aest_init_node(adev, node, anode); + if (ret) + return ret; + } + + return 0; +} + +static int __setup_ppi(struct aest_device *adev) +{ + int cpu, i; + struct aest_device *oncore_adev; + struct aest_node *oncore_node; + size_t size; + + adev->adev_oncore = &percpu_adev; + for_each_possible_cpu(cpu) { + oncore_adev = per_cpu_ptr(&percpu_adev, cpu); + memcpy(oncore_adev, adev, sizeof(struct aest_device)); + + oncore_adev->nodes = + devm_kcalloc(adev->dev, oncore_adev->node_cnt, + sizeof(struct aest_node), GFP_KERNEL); + if (!oncore_adev->nodes) + return -ENOMEM; + + size = adev->node_cnt * sizeof(struct aest_node); + memcpy(oncore_adev->nodes, adev->nodes, size); + for (i = 0; i < oncore_adev->node_cnt; i++) { + oncore_node = &oncore_adev->nodes[i]; + oncore_node->records = devm_kcalloc( + adev->dev, oncore_node->record_count, + sizeof(struct aest_record), GFP_KERNEL); + if (!oncore_node->records) + return -ENOMEM; + + size = oncore_node->record_count * + sizeof(struct aest_record); + memcpy(oncore_node->records, adev->nodes[i].records, + size); + } + + aest_dev_dbg(adev, "Init device on CPU%d.\n", cpu); + } + + return 0; +} + +static int aest_setup_irq(struct platform_device *pdev, + struct aest_device *adev) +{ + int fhi_irq, eri_irq; + + fhi_irq = platform_get_irq_byname_optional(pdev, AEST_FHI_NAME); + if (fhi_irq > 0) + adev->irq[0] = fhi_irq; + + eri_irq = platform_get_irq_byname_optional(pdev, AEST_ERI_NAME); + if (eri_irq > 0) + adev->irq[1] = eri_irq; + + /* Allocate and initialise the percpu device pointer for PPI */ + if (irq_is_percpu(fhi_irq) || irq_is_percpu(eri_irq)) + return __setup_ppi(adev); + + return 0; +} + +static struct aest_vendor_match vendor_match[] = { + { "ARMHC700", &aest_cmn700_probe }, + {}, +}; + +static int aest_vendor_probe(struct aest_device *adev, + struct aest_hnode *ahnode) +{ + int i; + struct acpi_aest_node *anode; + + anode = list_first_entry(&ahnode->list, struct acpi_aest_node, list); + if (!anode) + return -ENODEV; + + aest_dev_dbg(adev, "Try to probe vendor node %s\n", + anode->vendor->acpi_hid); + for (i = 0; i < ARRAY_SIZE(vendor_match); i++) { + if (!strncmp(vendor_match[i].hid, anode->vendor->acpi_hid, 8)) + return vendor_match[i].probe(adev, ahnode); + } + + return 0; +} + +static int aest_device_probe(struct platform_device *pdev) +{ + int ret; + struct aest_device *adev; + struct aest_hnode *ahnode; + + ahnode = *((struct aest_hnode **)pdev->dev.platform_data); + if (!ahnode) + return -ENODEV; + + adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + adev->dev = &pdev->dev; + adev->id = pdev->id; + aest_set_name(adev, ahnode); + + INIT_WORK(&adev->aest_work, aest_node_pool_process); + ret = aest_node_pool_init(adev); + if (ret) { + aest_dev_err(adev, "Failed init aest node pool.\n"); + return ret; + } + init_llist_head(&adev->event_list); + + if (ahnode->type == ACPI_AEST_VENDOR_ERROR_NODE) + ret = aest_vendor_probe(adev, ahnode); + else + ret = aest_init_nodes(adev, ahnode); + if (ret) + return ret; + + ret = aest_setup_irq(pdev, adev); + if (ret) + return ret; + + ret = aest_register_irq(adev); + if (ret) { + aest_dev_err(adev, "register irq failed\n"); + return ret; + } + + if (aest_dev_is_oncore(adev)) + ret = cpuhp_setup_state(CPUHP_AP_ARM_AEST_STARTING, + "drivers/acpi/arm64/aest:starting", + aest_starting_cpu, aest_dying_cpu); + else + aest_online_dev(adev); + if (ret) + return ret; + + platform_set_drvdata(pdev, adev); + + aest_dev_init_debugfs(adev); + + aest_dev_dbg(adev, "Node cnt: %x, id: %x\n", adev->node_cnt, adev->id); + + return 0; +} + +static struct platform_driver aest_driver = { + .driver = { + .name = "AEST", + }, + .probe = aest_device_probe, + .remove = aest_device_remove, +}; + +static int __init aest_init(void) +{ +#ifdef CONFIG_DEBUG_FS + aest_debugfs = debugfs_create_dir("aest", NULL); +#endif + + return platform_driver_register(&aest_driver); +} +module_init(aest_init); + +static void __exit aest_exit(void) +{ +#ifdef CONFIG_DEBUG_FS + debugfs_remove(aest_debugfs); +#endif + + platform_driver_unregister(&aest_driver); +} +module_exit(aest_exit); + +MODULE_DESCRIPTION("ARM AEST Driver"); +MODULE_AUTHOR("Ruidong Tian "); +MODULE_LICENSE("GPL"); diff --git a/drivers/ras/aest/aest-inject.c b/drivers/ras/aest/aest-inject.c new file mode 100644 index 0000000000000..fe6ccac8338e4 --- /dev/null +++ b/drivers/ras/aest/aest-inject.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2024, Alibaba Group. + */ + +#include "aest.h" + +static struct ras_ext_regs regs_inj; + +struct inj_attr { + struct attribute attr; + ssize_t (*show)(struct aest_node *n, struct inj_attr *a, char *b); + ssize_t (*store)(struct aest_node *n, struct inj_attr *a, const char *b, + size_t c); +}; + +struct aest_inject { + struct aest_node *node; + struct kobject kobj; +}; + +#define to_inj(k) container_of(k, struct aest_inject, kobj) +#define to_inj_attr(a) container_of(a, struct inj_attr, attr) + +static u64 aest_sysreg_read_inject(void *__unused, u32 offset) +{ + u64 *p = (u64 *)®s_inj; + + return p[offset/8]; +} + +static void aest_sysreg_write_inject(void *base, u32 offset, u64 val) +{ + u64 *p = (u64 *)®s_inj; + + p[offset/8] = val; +} + +static u64 aest_iomem_read_inject(void *base, u32 offset) +{ + u64 *p = (u64 *)®s_inj; + + return p[offset/8]; +} + +static void aest_iomem_write_inject(void *base, u32 offset, u64 val) +{ + u64 *p = (u64 *)®s_inj; + + p[offset/8] = val; +} + +static struct aest_access aest_access_inject[] = { + [ACPI_AEST_NODE_SYSTEM_REGISTER] = { + .read = aest_sysreg_read_inject, + .write = aest_sysreg_write_inject, + }, + + [ACPI_AEST_NODE_MEMORY_MAPPED] = { + .read = aest_iomem_read_inject, + .write = aest_iomem_write_inject, + }, + [ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED] = { + .read = aest_iomem_read_inject, + .write = aest_iomem_write_inject, + }, + { } +}; + +static int soft_inject_store(void *data, u64 val) +{ + int count = 0; + struct aest_record record_inj, *record = data; + struct aest_node node_inj, *node = record->node; + + memcpy(&node_inj, node, sizeof(*node)); + node_inj.name = "AEST-injection"; + + record_inj.access = &aest_access_inject[node->info->interface_hdr->type]; + record_inj.node = &node_inj; + record_inj.index = record->index; + + regs_inj.err_status |= ERR_STATUS_V; + + aest_proc_record(&record_inj, &count, true); + + if (count != 1) + return -EIO; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(soft_inject_ops, NULL, soft_inject_store, "%llu\n"); + +static int hard_inject_store(void *data, u64 val) +{ + struct aest_record *record = data; + struct aest_node *node = record->node; + + if (!node->inj) + return -EPERM; + + aest_select_record(node, record->index); + record_write(record, ERXPFGCTL, val); + record_write(record, ERXPFGCDN, 0x100); + aest_sync(node); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(hard_inject_ops, NULL, hard_inject_store, "%llu\n"); + +void aest_inject_init_debugfs(struct aest_record *record) +{ + struct dentry *inj; + + inj = debugfs_create_dir("inject", record->debugfs); + + debugfs_create_u64("err_fr", 0600, inj, ®s_inj.err_fr); + debugfs_create_u64("err_ctrl", 0600, inj, ®s_inj.err_ctlr); + debugfs_create_u64("err_status", 0600, inj, ®s_inj.err_status); + debugfs_create_u64("err_addr", 0600, inj, ®s_inj.err_addr); + debugfs_create_u64("err_misc0", 0600, inj, ®s_inj.err_misc[0]); + debugfs_create_u64("err_misc1", 0600, inj, ®s_inj.err_misc[1]); + debugfs_create_u64("err_misc2", 0600, inj, ®s_inj.err_misc[2]); + debugfs_create_u64("err_misc3", 0600, inj, ®s_inj.err_misc[3]); + debugfs_create_file("soft_inject", 0400, inj, record, &soft_inject_ops); + + if (record->node->inj) + debugfs_create_file("hard_inject", 0400, inj, record, &hard_inject_ops); +} diff --git a/drivers/ras/aest/aest-of.c b/drivers/ras/aest/aest-of.c new file mode 100644 index 0000000000000..939db2c417427 --- /dev/null +++ b/drivers/ras/aest/aest-of.c @@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include + +#undef pr_fmt +#define pr_fmt(fmt) "DT AEST: " fmt + +struct dt_aest_priv { + struct xarray aest_array; + u32 node_id; +}; + +static const struct of_device_id dt_aest_child_match[] = { + { .compatible = "arm,aest-processor", .data = (void *)ACPI_AEST_PROCESSOR_ERROR_NODE }, + { .compatible = "arm,aest-memory", .data = (void *)ACPI_AEST_MEMORY_ERROR_NODE }, + { .compatible = "arm,aest-smmu", .data = (void *)ACPI_AEST_SMMU_ERROR_NODE }, + { .compatible = "arm,aest-vendor", .data = (void *)ACPI_AEST_VENDOR_ERROR_NODE }, + { .compatible = "arm,aest-gic", .data = (void *)ACPI_AEST_GIC_ERROR_NODE }, + { .compatible = "arm,aest-pcie", .data = (void *)ACPI_AEST_PCIE_ERROR_NODE }, + { .compatible = "arm,aest-proxy", .data = (void *)ACPI_AEST_PROXY_ERROR_NODE }, + { } +}; + +static int dt_aest_node_type(struct device_node *np) +{ + const struct of_device_id *match; + + match = of_match_node(dt_aest_child_match, np); + if (!match) { + pr_warn("unknown compatible for %pOF\n", np); + return -EINVAL; + } + return (int)(uintptr_t)match->data; +} + +static struct aest_hnode *dt_aest_alloc_hnode(int node_type, u32 id) +{ + struct aest_hnode *ahnode; + + ahnode = kzalloc_obj(*ahnode, GFP_KERNEL); + if (!ahnode) + return NULL; + + INIT_LIST_HEAD(&ahnode->list); + ahnode->count = 0; + ahnode->id = id; + ahnode->type = node_type; + return ahnode; +} + +static int dt_aest_build_interface(struct device_node *np, + struct acpi_aest_node *anode) +{ + struct acpi_aest_node_interface_header *hdr; + struct acpi_aest_node_interface_common *common; + struct resource res; + struct resource named_res; + u32 gfmt = 0, flags = 0, nrec = 1; + u32 itype; + int ret; + size_t body_sz; + + /* + * Deduce interface type from the presence and count of reg entries: + * no reg -> system-register access (type 0) + * 1 range -> memory-mapped access (type 1) + * 2+ ranges -> single-record MMIO (type 2) + */ + if (!of_property_present(np, "reg")) + itype = ACPI_AEST_NODE_SYSTEM_REGISTER; + else if (of_property_count_elems_of_size(np, "reg", sizeof(u32)) <= + (of_n_addr_cells(np) + of_n_size_cells(np))) + itype = ACPI_AEST_NODE_MEMORY_MAPPED; + else + itype = ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED; + + of_property_read_u32(np, "arm,group-format", &gfmt); + of_property_read_u32(np, "arm,interface-flags", &flags); + of_property_read_u32(np, "arm,num-records", &nrec); + + switch (gfmt) { + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + body_sz = sizeof(struct acpi_aest_node_interface_16k); + break; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + body_sz = sizeof(struct acpi_aest_node_interface_64k); + break; + default: + body_sz = sizeof(struct acpi_aest_node_interface_4k); + break; + } + + hdr = kzalloc(sizeof(*hdr) + body_sz, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + /* Fill header */ + hdr->type = (u8)itype; + hdr->group_format = (u8)gfmt; + hdr->flags = flags; + hdr->error_record_count = nrec; + hdr->error_record_index = 0; + + if (itype != ACPI_AEST_NODE_SYSTEM_REGISTER) { + ret = of_address_to_resource(np, 0, &res); + if (ret) { + pr_err("node %pOF: missing 'reg' for MMIO interface\n", np); + kfree(hdr); + return ret; + } + hdr->address = res.start; + } + + switch (gfmt) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: { + struct acpi_aest_node_interface_4k *b = + (struct acpi_aest_node_interface_4k *)(hdr + 1); + of_property_read_u64(np, "arm,record-impl", + &b->error_record_implemented); + of_property_read_u64(np, "arm,status-reporting", + &b->error_status_reporting); + of_property_read_u64(np, "arm,addressing-mode", + &b->addressing_mode); + common = &b->common; + anode->record_implemented = + (unsigned long *)&b->error_record_implemented; + anode->status_reporting = + (unsigned long *)&b->error_status_reporting; + anode->addressing_mode = + (unsigned long *)&b->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_16K: { + struct acpi_aest_node_interface_16k *b = + (struct acpi_aest_node_interface_16k *)(hdr + 1); + of_property_read_u64_array(np, "arm,record-impl", + b->error_record_implemented, 4); + of_property_read_u64_array(np, "arm,status-reporting", + b->error_status_reporting, 4); + of_property_read_u64_array(np, "arm,addressing-mode", + b->addressing_mode, 4); + common = &b->common; + anode->record_implemented = + (unsigned long *)b->error_record_implemented; + anode->status_reporting = + (unsigned long *)b->error_status_reporting; + anode->addressing_mode = + (unsigned long *)b->addressing_mode; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_64K: { + struct acpi_aest_node_interface_64k *b = + (struct acpi_aest_node_interface_64k *)(hdr + 1); + of_property_read_u64_array(np, "arm,record-impl", + b->error_record_implemented, 14); + of_property_read_u64_array(np, "arm,status-reporting", + b->error_status_reporting, 14); + of_property_read_u64_array(np, "arm,addressing-mode", + b->addressing_mode, 14); + common = &b->common; + anode->record_implemented = + (unsigned long *)b->error_record_implemented; + anode->status_reporting = + (unsigned long *)b->error_status_reporting; + anode->addressing_mode = + (unsigned long *)b->addressing_mode; + break; + } + default: + pr_err("node %pOF: unsupported group-format %u\n", np, gfmt); + kfree(hdr); + return -EINVAL; + } + + if (!of_address_to_resource(np, of_property_match_string( + np, "reg-names", "fault-inject"), &named_res)) + common->fault_inject_register_base = named_res.start; + + if (!of_address_to_resource(np, of_property_match_string( + np, "reg-names", "err-group"), &named_res)) + common->error_group_register_base = named_res.start; + + if (!of_address_to_resource(np, of_property_match_string( + np, "reg-names", "irq-config"), &named_res)) + common->interrupt_config_register_base = named_res.start; + + anode->interface_hdr = hdr; + anode->common = common; + + return 0; +} + +static int dt_aest_build_interrupt(struct device_node *np, + struct acpi_aest_node *anode) +{ + struct acpi_aest_node_interrupt_v2 *irq_arr; + int fhi_irq, eri_irq, count = 0; + u32 fhi_flags = 0, eri_flags = 0; + + of_property_read_u32(np, "arm,fhi-flags", &fhi_flags); + of_property_read_u32(np, "arm,eri-flags", &eri_flags); + + fhi_irq = of_irq_get_byname(np, "fhi"); + if (fhi_irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (fhi_irq < 0 && fhi_irq != -EINVAL) { + const char *name = NULL; + + of_property_read_string(np, "interrupt-names", &name); + + pr_warn("node %pOF: failed to map FHI IRQ: %d (interrupt-names[0]=\"%s\", want \"%s\")\n", + np, fhi_irq, name ?: "", "fhi"); + } + eri_irq = of_irq_get_byname(np, "eri"); + if (eri_irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (eri_irq < 0 && eri_irq != -EINVAL) { + const char *name = NULL; + + of_property_read_string_index(np, "interrupt-names", 1, &name); + + pr_warn("node %pOF: failed to map ERI IRQ: %d (interrupt-names[1]=\"%s\", want \"%s\")\n", + np, eri_irq, name ?: "", "eri"); + } + + if (fhi_irq > 0) + count++; + if (eri_irq > 0) + count++; + + if (!count) { + anode->interrupt = NULL; + anode->interrupt_count = 0; + return 0; + } + + irq_arr = kcalloc(count, sizeof(*irq_arr), GFP_KERNEL); + if (!irq_arr) + return -ENOMEM; + + count = 0; + if (fhi_irq > 0) { + irq_arr[count].gsiv = fhi_irq; + irq_arr[count].flags = AEST_INTERRUPT_MODE | fhi_flags; + irq_arr[count].type = ACPI_AEST_NODE_FAULT_HANDLING; + count++; + } + if (eri_irq > 0) { + irq_arr[count].gsiv = eri_irq; + irq_arr[count].flags = eri_flags; + irq_arr[count].type = ACPI_AEST_NODE_ERROR_RECOVERY; + count++; + } + + anode->interrupt = irq_arr; + anode->interrupt_count = count; + return 0; +} + +static int dt_aest_build_node_specific(struct device_node *np, + struct acpi_aest_node *anode, + int node_type) +{ + switch (node_type) { + + case ACPI_AEST_PROCESSOR_ERROR_NODE: { + struct acpi_aest_processor *proc; + u32 rtype = 0, pflags = 0; + + proc = kzalloc_obj(*proc, GFP_KERNEL); + if (!proc) + return -ENOMEM; + + of_property_read_u32(np, "arm,resource-type", &rtype); + of_property_read_u32(np, "arm,processor-flags", &pflags); + + proc->resource_type = (u8)rtype; + proc->flags = (u8)pflags; + + /* Processor cache/TLB/generic sub-structure */ + switch (rtype) { + case ACPI_AEST_CACHE_RESOURCE: { + struct acpi_aest_processor_cache *c; + struct device_node *cache_np; + + c = kzalloc_obj(*c, GFP_KERNEL); + if (!c) { + kfree(proc); + return -ENOMEM; + } + + cache_np = of_parse_phandle(np, "arm,cache-ref", 0); + if (cache_np) { + c->cache_reference = cache_np->phandle; + of_node_put(cache_np); + } + anode->cache = c; + break; + } + case ACPI_AEST_TLB_RESOURCE: { + struct acpi_aest_processor_tlb *t; + + t = kzalloc_obj(*t, GFP_KERNEL); + if (!t) { + kfree(proc); + return -ENOMEM; + } + of_property_read_u32(np, "arm,tlb-level", + &t->tlb_level); + anode->tlb = t; + break; + } + default: { + struct acpi_aest_processor_generic *g; + + g = kzalloc_obj(*g, GFP_KERNEL); + if (!g) { + kfree(proc); + return -ENOMEM; + } + of_property_read_u32(np, "arm,resource-ref", + &g->resource); + anode->generic = g; + break; + } + } + anode->processor = proc; + break; + } + + case ACPI_AEST_MEMORY_ERROR_NODE: { + struct acpi_aest_memory *mem; + + mem = kzalloc_obj(*mem, GFP_KERNEL); + + if (!mem) + return -ENOMEM; + of_property_read_u32(np, "arm,proximity-domain", + &mem->srat_proximity_domain); + anode->memory = mem; + break; + } + + case ACPI_AEST_SMMU_ERROR_NODE: { + struct acpi_aest_smmu *smmu; + struct device_node *smmu_np; + + smmu = kzalloc_obj(*smmu, GFP_KERNEL); + + if (!smmu) + return -ENOMEM; + smmu_np = of_parse_phandle(np, "arm,smmu-ref", 0); + if (smmu_np) { + /* Use the DT node offset as the IORT reference */ + smmu->iort_node_reference = smmu_np->phandle; + of_node_put(smmu_np); + } + of_property_read_u32(np, "arm,smmu-subcomponent", + &smmu->subcomponent_reference); + anode->smmu = smmu; + break; + } + + case ACPI_AEST_VENDOR_ERROR_NODE: { + struct acpi_aest_vendor_v2 *vendor; + const char *hid = "ARMHC000"; + + vendor = kzalloc_obj(*vendor, GFP_KERNEL); + + if (!vendor) + return -ENOMEM; + of_property_read_string(np, "arm,vendor-hid", &hid); + strscpy(vendor->acpi_hid, hid, sizeof(vendor->acpi_hid)); + of_property_read_u32(np, "arm,vendor-uid", + &vendor->acpi_uid); + anode->vendor = vendor; + break; + } + + case ACPI_AEST_GIC_ERROR_NODE: { + struct acpi_aest_gic *gic; + + gic = kzalloc_obj(*gic, GFP_KERNEL); + + if (!gic) + return -ENOMEM; + of_property_read_u32(np, "arm,gic-type", + &gic->interface_type); + of_property_read_u32(np, "arm,gic-instance", + &gic->instance_id); + anode->gic = gic; + break; + } + + case ACPI_AEST_PCIE_ERROR_NODE: { + struct acpi_aest_pcie *pcie; + + pcie = kzalloc_obj(*pcie, GFP_KERNEL); + + if (!pcie) + return -ENOMEM; + of_property_read_u32(np, "arm,pcie-segment", + &pcie->iort_node_reference); + anode->pcie = pcie; + break; + } + + case ACPI_AEST_PROXY_ERROR_NODE: + /* No node-specific data for proxy nodes */ + anode->spec_pointer = NULL; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static struct acpi_aest_node * +dt_aest_alloc_anode(struct device_node *np, int node_type) +{ + struct acpi_aest_node *anode; + int ret; + + anode = kzalloc_obj(*anode, GFP_KERNEL); + if (!anode) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&anode->list); + anode->type = node_type; + + ret = dt_aest_build_interface(np, anode); + if (ret) + goto err_free; + + ret = dt_aest_build_node_specific(np, anode, node_type); + if (ret) + goto err_free; + + ret = dt_aest_build_interrupt(np, anode); + if (ret) + goto err_free; + + return anode; + +err_free: + kfree(anode->interface_hdr); + kfree(anode->spec_pointer); + kfree(anode->processor_spec_pointer); + kfree(anode); + return ERR_PTR(ret); +} + +static int dt_aest_init_one_node(struct device_node *np, + struct dt_aest_priv *priv) +{ + int node_type; + struct aest_hnode *ahnode; + struct acpi_aest_node *anode; + + node_type = dt_aest_node_type(np); + if (node_type < 0) { + pr_warn("unknown node type for %pOF, skipping\n", np); + return 0; + } + + ahnode = dt_aest_alloc_hnode(node_type, priv->node_id); + if (!ahnode) + return -ENOMEM; + + anode = dt_aest_alloc_anode(np, node_type); + if (IS_ERR(anode)) { + kfree(ahnode); + return PTR_ERR(anode); + } + + list_add_tail(&anode->list, &ahnode->list); + ahnode->count = 1; + + if (xa_err(xa_store(&priv->aest_array, priv->node_id, + ahnode, GFP_KERNEL))) { + kfree(anode); + kfree(ahnode); + return -ENOMEM; + } + priv->node_id++; + return 0; +} + +static int dt_aest_init_nodes(struct device_node *aest_root, + struct dt_aest_priv *priv) +{ + struct device_node *np; + int ret; + + for_each_available_child_of_node(aest_root, np) { + ret = dt_aest_init_one_node(np, priv); + if (ret) { + pr_err("failed to init node %pOF: %d\n", np, ret); + of_node_put(np); + return ret; + } + } + return 0; +} + +static struct platform_device *dt_aest_alloc_pdev(struct aest_hnode *ahnode, + int index) +{ + struct platform_device *pdev; + struct resource *res; + struct acpi_aest_node *anode; + int ret, size, j; + int irq[AEST_MAX_INTERRUPT_PER_NODE] = { 0 }; + + pdev = platform_device_alloc("AEST", index); + if (!pdev) + return ERR_PTR(-ENOMEM); + + res = kcalloc(ahnode->count + AEST_MAX_INTERRUPT_PER_NODE, + sizeof(*res), GFP_KERNEL); + if (!res) { + platform_device_put(pdev); + return ERR_PTR(-ENOMEM); + } + + j = 0; + list_for_each_entry(anode, &ahnode->list, list) { + if (anode->interface_hdr->type != + ACPI_AEST_NODE_SYSTEM_REGISTER) { + res[j].name = AEST_NODE_NAME; + res[j].start = anode->interface_hdr->address; + + switch (anode->interface_hdr->group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: + size = 4 * KB; break; + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + size = 16 * KB; break; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + size = 64 * KB; break; + default: + size = 4 * KB; + } + res[j].end = res[j].start + size - 1; + res[j].flags = IORESOURCE_MEM; + j++; + } + + if (anode->interrupt && anode->interrupt_count > 0) { + int k; + + for (k = 0; k < anode->interrupt_count && + k < AEST_MAX_INTERRUPT_PER_NODE; k++) { + + struct acpi_aest_node_interrupt_v2 *intr = + &anode->interrupt[k]; + int itype = intr->type; + int virq = intr->gsiv; + struct irq_data *irqd; + + if (!virq) + continue; + if (itype >= AEST_MAX_INTERRUPT_PER_NODE) + continue; + if (irq[itype] == virq) + continue; + irq[itype] = virq; + /* + * aest_config_irq() writes intr->gsiv directly + * to the hardware IRQ-config register, so it + * must hold the GIC hardware SPI number, not the + * Linux virtual IRQ. Convert here now that we + * have the virq in hand; the resource still gets + * the virq so devm_request_irq() works correctly. + */ + irqd = irq_get_irq_data(virq); + if (irqd) + intr->gsiv = irqd->hwirq; + + res[j].name = (itype == ACPI_AEST_NODE_FAULT_HANDLING) + ? AEST_FHI_NAME : AEST_ERI_NAME; + res[j].start = virq; + res[j].end = virq; + res[j].flags = IORESOURCE_IRQ; + j++; + } + } + } + + ret = platform_device_add_resources(pdev, res, j); + kfree(res); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = platform_device_add_data(pdev, &ahnode, sizeof(ahnode)); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = platform_device_add(pdev); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + return pdev; +} + +static int dt_aest_alloc_pdevs(struct dt_aest_priv *priv) +{ + struct aest_hnode *ahnode; + unsigned long i; + int ret = 0, index = 0; + + xa_for_each(&priv->aest_array, i, ahnode) { + struct platform_device *pdev = + dt_aest_alloc_pdev(ahnode, index++); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + pr_err("failed to alloc pdev for node %u: %d\n", + ahnode->id, ret); + break; + } + } + return ret; +} + +static int __init dt_aest_init(void) +{ + struct device_node *aest_root; + struct dt_aest_priv priv = {}; + int ret; + + if (!acpi_disabled) + return 0; + + aest_root = of_find_compatible_node(NULL, NULL, "arm,aest"); + if (!aest_root) + return 0; + + xa_init(&priv.aest_array); + + ret = dt_aest_init_nodes(aest_root, &priv); + of_node_put(aest_root); + if (ret) { + pr_err("failed to init AEST nodes: %d\n", ret); + return ret; + } + + ret = dt_aest_alloc_pdevs(&priv); + if (ret) { + pr_err("failed to alloc AEST pdevs: %d\n", ret); + return ret; + } + + pr_info("registered %u AEST error source(s) from DT\n", priv.node_id); + + return 0; +} +subsys_initcall_sync(dt_aest_init); diff --git a/drivers/ras/aest/aest-sysfs.c b/drivers/ras/aest/aest-sysfs.c new file mode 100644 index 0000000000000..b36190bb3b3e4 --- /dev/null +++ b/drivers/ras/aest/aest-sysfs.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include "aest.h" + +static void +aest_store_threshold(struct aest_record *record, void *data) +{ + u64 err_misc0, *threshold = data; + struct ce_threshold *ce = &record->ce; + + if (*threshold > ce->info->max_count) + return; + + ce->threshold = *threshold; + ce->count = ce->info->max_count - ce->threshold + 1; + + err_misc0 = record_read(record, ERXMISC0); + ce->reg_val = (err_misc0 & ~ce->info->mask) | + (ce->count << ce->info->shift); + + record_write(record, ERXMISC0, ce->reg_val); +} + +static void +aest_error_count(struct aest_record *record, void *data) +{ + struct record_count *count = data; + + count->ce += record->count.ce; + count->de += record->count.de; + count->uc += record->count.uc; + count->ueu += record->count.ueu; + count->uer += record->count.uer; + count->ueo += record->count.ueo; +} + +/******************************************************************************* + * + * Debugfs for AEST node + * + ******************************************************************************/ + +static int aest_node_err_count_show(struct seq_file *m, void *data) +{ + struct aest_node *node = m->private; + struct record_count count = { 0 }; + int i; + + for (i = 0; i < node->record_count; i++) + if (!test_bit(i, node->record_implemented)) + aest_error_count(&node->records[i], &count); + + seq_printf(m, "CE: %llu\n" + "DE: %llu\n" + "UC: %llu\n" + "UEU: %llu\n" + "UEO: %llu\n" + "UER: %llu\n", + count.ce, count.de, count.uc, count.ueu, + count.uer, count.ueo); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(aest_node_err_count); + +/******************************************************************************* + * + * Attribute for AEST record + * + ******************************************************************************/ + +#define DEFINE_AEST_DEBUGFS_ATTR(name, offset) \ +static int name##_get(void *data, u64 *val) \ +{ \ + struct aest_record *record = data; \ + *val = record_read(record, offset); \ + return 0; \ +} \ +static int name##_set(void *data, u64 val) \ +{ \ + struct aest_record *record = data; \ + record_write(record, offset, val); \ + return 0; \ +} \ +DEFINE_DEBUGFS_ATTRIBUTE(name##_ops, name##_get, name##_set, "%#llx\n") + +DEFINE_AEST_DEBUGFS_ATTR(err_fr, ERXFR); +DEFINE_AEST_DEBUGFS_ATTR(err_ctrl, ERXCTLR); +DEFINE_AEST_DEBUGFS_ATTR(err_status, ERXSTATUS); +DEFINE_AEST_DEBUGFS_ATTR(err_addr, ERXADDR); +DEFINE_AEST_DEBUGFS_ATTR(err_misc0, ERXMISC0); +DEFINE_AEST_DEBUGFS_ATTR(err_misc1, ERXMISC1); +DEFINE_AEST_DEBUGFS_ATTR(err_misc2, ERXMISC2); +DEFINE_AEST_DEBUGFS_ATTR(err_misc3, ERXMISC3); + +static int record_ce_threshold_get(void *data, u64 *val) +{ + struct aest_record *record = data; + + *val = record->ce.threshold; + return 0; +} + +static int record_ce_threshold_set(void *data, u64 val) +{ + u64 threshold = val; + struct aest_record *record = data; + + aest_store_threshold(record, &threshold); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(record_ce_threshold_ops, record_ce_threshold_get, + record_ce_threshold_set, "%llu\n"); + +static int aest_record_err_count_show(struct seq_file *m, void *data) +{ + struct aest_record *record = m->private; + struct record_count count = { 0 }; + + aest_error_count(record, &count); + + seq_printf(m, "CE: %llu\n" + "DE: %llu\n" + "UC: %llu\n" + "UEU: %llu\n" + "UEO: %llu\n" + "UER: %llu\n", + count.ce, count.de, count.uc, count.ueu, + count.uer, count.ueo); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(aest_record_err_count); + +static void aest_record_init_debugfs(struct aest_record *record) +{ + debugfs_create_file("err_fr", 0600, record->debugfs, record, + &err_fr_ops); + debugfs_create_file("err_ctrl", 0600, record->debugfs, record, + &err_ctrl_ops); + debugfs_create_file("err_status", 0600, record->debugfs, record, + &err_status_ops); + debugfs_create_file("err_addr", 0600, record->debugfs, record, + &err_addr_ops); + debugfs_create_file("err_misc0", 0600, record->debugfs, record, + &err_misc0_ops); + debugfs_create_file("err_misc1", 0600, record->debugfs, record, + &err_misc1_ops); + debugfs_create_file("err_misc2", 0600, record->debugfs, record, + &err_misc2_ops); + debugfs_create_file("err_misc3", 0600, record->debugfs, record, + &err_misc3_ops); + debugfs_create_file("err_count", 0400, record->debugfs, record, + &aest_record_err_count_fops); + debugfs_create_file("ce_threshold", 0600, record->debugfs, record, + &record_ce_threshold_ops); + aest_inject_init_debugfs(record); +} + +static void +aest_node_init_debugfs(struct aest_node *node) +{ + int i; + struct aest_record *record; + + debugfs_create_file("err_count", 0400, node->debugfs, node, + &aest_node_err_count_fops); + + for (i = 0; i < node->record_count; i++) { + record = &node->records[i]; + if (!record->name) + continue; + /* Skip records not implemented on this node. */ + if (test_bit(i, node->record_implemented)) + continue; + record->debugfs = debugfs_create_dir(record->name, + node->debugfs); + aest_record_init_debugfs(record); + } +} + +static void +aest_oncore_dev_init_debugfs(struct aest_device *adev) +{ + int cpu, i; + struct aest_node *node; + struct aest_device *percpu_dev; + char name[16]; + + for_each_possible_cpu(cpu) { + percpu_dev = per_cpu_ptr(adev->adev_oncore, cpu); + + snprintf(name, sizeof(name), "processor%u", cpu); + percpu_dev->debugfs = debugfs_create_dir(name, adev->debugfs); + + for (i = 0; i < adev->node_cnt; i++) { + node = &percpu_dev->nodes[i]; + + /* + * Use adev->nodes[i].name (the original) rather than + * node->name from the per-CPU copy. The per-CPU copy + * receives node->name via shallow memcpy in __setup_ppi; + * the original is the authoritative, guaranteed-valid + * string. + */ + node->debugfs = debugfs_create_dir(adev->nodes[i].name, + percpu_dev->debugfs); + aest_node_init_debugfs(node); + } + } +} + +void aest_dev_init_debugfs(struct aest_device *adev) +{ + int i; + struct aest_node *node; + + if (!aest_debugfs) + dev_err(adev->dev, "debugfs not enabled\n"); + + adev->debugfs = debugfs_create_dir(dev_name(adev->dev), aest_debugfs); + if (aest_dev_is_oncore(adev)) { + aest_oncore_dev_init_debugfs(adev); + return; + } + + for (i = 0; i < adev->node_cnt; i++) { + node = &adev->nodes[i]; + if (!node->name) + continue; + node->debugfs = debugfs_create_dir(node->name, adev->debugfs); + aest_node_init_debugfs(node); + } +} diff --git a/drivers/ras/aest/aest.h b/drivers/ras/aest/aest.h new file mode 100644 index 0000000000000..9704af97fee89 --- /dev/null +++ b/drivers/ras/aest/aest.h @@ -0,0 +1,423 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include +#include +#include + +#define MAX_GSI_PER_NODE 2 +#define DEFAULT_CE_THRESHOLD 1 + +#define record_read(record, offset) \ + record->access->read(record->regs_base, offset) +#define record_write(record, offset, val) \ + record->access->write(record->regs_base, offset, val) + +#define aest_dev_err(__adev, format, ...) \ + dev_err((__adev)->dev, format, ##__VA_ARGS__) +#define aest_dev_info(__adev, format, ...) \ + dev_info((__adev)->dev, format, ##__VA_ARGS__) +#define aest_dev_dbg(__adev, format, ...) \ + dev_dbg((__adev)->dev, format, ##__VA_ARGS__) + +#define aest_node_err(__node, format, ...) \ + dev_err((__node)->adev->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) +#define aest_node_info(__node, format, ...) \ + dev_info((__node)->adev->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) +#define aest_node_dbg(__node, format, ...) \ + dev_dbg((__node)->adev->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) + +#define aest_record_err(__record, format, ...) \ + dev_err((__record)->node->adev->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) +#define aest_record_info(__record, format, ...) \ + dev_info((__record)->node->adev->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) +#define aest_record_dbg(__record, format, ...) \ + dev_dbg((__record)->node->adev->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) + +#define ERXGROUP_4K_OFFSET 0xE00 +#define ERXGROUP_16K_OFFSET 0x3800 +#define ERXGROUP_64K_OFFSET 0xE000 +#define ERXGROUP_4K_SIZE (4 * KB) +#define ERXGROUP_16K_SIZE (16 * KB) +#define ERXGROUP_64K_SIZE (64 * KB) +#define ERXGROUP_4K_ERRGSR_NUM 1 +#define ERXGROUP_16K_ERRGSR_NUM 4 +#define ERXGROUP_64K_ERRGSR_NUM 14 + +#define ERXFR 0x0 +#define ERXCTLR 0x8 +#define ERXSTATUS 0x10 +#define ERXADDR 0x18 +#define ERXMISC0 0x20 +#define ERXMISC1 0x28 +#define ERXMISC2 0x30 +#define ERXMISC3 0x38 +#define ERXPFGF 0x800 +#define ERXPFGCTL 0x808 +#define ERXPFGCDN 0x810 + +#define GIC_ERRDEVARCH 0xFFBC + +extern struct dentry *aest_debugfs; + +struct aest_event { + struct llist_node llnode; + char *node_name; + u32 type; + /* + * Different nodes have different meanings: + * - Processor node : processor number. + * - Memory node : SRAT proximity domain. + * - SMMU node : IORT proximity domain. + * - GIC node : interface type. + */ + u32 id0; + /* + * Different nodes have different meanings: + * - Processor node : processor resource type. + * - Memory node : Non. + * - SMMU node : subcomponent reference. + * - Vendor node : Unique ID. + * - GIC node : instance identifier. + */ + u32 id1; + /* Vendor node : hardware ID. */ + char *hid; + u32 index; + /* Processor node: ACPI_AEST_PROC_FLAG_* bitmask (SHARED/GLOBAL) */ + u8 proc_flags; + u64 ce_threshold; + int addressing_mode; + struct ras_ext_regs regs; + + /* + * This field is used to store vendor specific data for decoding error + * record by EDAC driver. + */ + void *vendor_data; + size_t vendor_data_size; +}; + +struct aest_access { + u64 (*read)(void *base, u32 offset); + void (*write)(void *base, u32 offset, u64 val); +}; + +struct ce_threshold_info { + const u64 max_count; + const u64 mask; + const u64 shift; +}; + +struct ce_threshold { + const struct ce_threshold_info *info; + u64 count; + u64 threshold; + u64 reg_val; +}; + +struct record_count { + u64 ce; + u64 de; + u64 uc; + u64 uer; + u64 ueo; + u64 ueu; +}; + +struct aest_record { + char *name; + int index; + void __iomem *regs_base; + + /* + * This bit specifies the addressing mode to populate the ERR_ADDR + * register: + * 0b: Error record reports System Physical Addresses (SPA) in + * the ERR_ADDR register. + * 1b: Error record reports error node-specific Logical Addresses(LA) + * in the ERR_ADD register. OS must use other means to translate + * the reported LA into SPA + */ + int addressing_mode; + struct aest_node *node; + const struct aest_access *access; + + struct ce_threshold ce; + enum ras_ce_threshold threshold_type; + struct record_count count; + struct dentry *debugfs; + + void *vendor_data; + size_t vendor_data_size; +}; + +struct aest_group { + int type; + int errgsr_num; + size_t size; + u64 errgsr_offset; +}; + +static const struct aest_group aest_group_config[] = { + [ACPI_AEST_NODE_GROUP_FORMAT_4K] = { + .type = ACPI_AEST_NODE_GROUP_FORMAT_4K, + .errgsr_num = ERXGROUP_4K_ERRGSR_NUM, + .size = ERXGROUP_4K_SIZE, + .errgsr_offset = ERXGROUP_4K_OFFSET, + }, + [ACPI_AEST_NODE_GROUP_FORMAT_16K] = { + .type = ACPI_AEST_NODE_GROUP_FORMAT_16K, + .errgsr_num = ERXGROUP_16K_ERRGSR_NUM, + .size = ERXGROUP_16K_SIZE, + .errgsr_offset = ERXGROUP_16K_OFFSET, + }, + [ACPI_AEST_NODE_GROUP_FORMAT_64K] = { + .type = ACPI_AEST_NODE_GROUP_FORMAT_64K, + .errgsr_num = ERXGROUP_64K_ERRGSR_NUM, + .size = ERXGROUP_64K_SIZE, + .errgsr_offset = ERXGROUP_64K_OFFSET, + }, +}; + +struct aest_node { + char *name; + u8 type; + void *errgsr; + void *base; + void *inj; + void *irq_config; + + /* + * This bitmap indicates which of the error records within this error + * node must be polled for error status. + * Bit[n] of this field pertains to error record corresponding to + * index n in this error group. + * Bit[n] = 0b: Error record at index n needs to be polled. + * Bit[n] = 1b: Error record at index n do not needs to be polled. + */ + unsigned long *record_implemented; + /* + * This bitmap indicates which of the error records within this error + * node support error status reporting using ERRGSR register. + * Bit[n] of this field pertains to error record corresponding to + * index n in this error group. + * Bit[n] = 0b: Error record at index n supports error status reporting + * through ERRGSR.S. + * Bit[n] = 1b: Error record at index n does not support error reporting + * through the ERRGSR.S bit If this error record is + * implemented, then it must be polled explicitly for + * error events. + */ + unsigned long *status_reporting; + int version; + /* + * Usually bit[n] in errgsr indicates [n]th error record within this + * error node report error. But some compoent may have different rules. + * For example, CMN700 TRM 4.3.5.12 say: + * ``` Error occurs when the index is even and Fault + * occurs when the index is odd. ``` + * Bit[n]: record[n] report ERROR. + * Bit[n + 1]: record[n] report FAULT. + * errgsr_mapping function is used to map errgsr bit to record index + * for various components. + */ + int (*errgsr_mapping)(int errgsr_bit); + int errgsr_num; + + const struct aest_group *group; + struct aest_device *adev; + struct acpi_aest_node *info; + + int record_count; + struct aest_record *records; + struct dentry *debugfs; + struct aest_node __percpu *oncore_node; +}; + +struct aest_device { + struct device *dev; + u32 type; + int node_cnt; + struct aest_node *nodes; + u32 id; + int irq[MAX_GSI_PER_NODE]; + + struct work_struct aest_work; + struct gen_pool *pool; + struct llist_head event_list; + struct dentry *debugfs; + struct aest_device __percpu *adev_oncore; +}; + +static const char *const aest_node_name[] = { + [ACPI_AEST_PROCESSOR_ERROR_NODE] = "processor", + [ACPI_AEST_MEMORY_ERROR_NODE] = "memory", + [ACPI_AEST_SMMU_ERROR_NODE] = "smmu", + [ACPI_AEST_VENDOR_ERROR_NODE] = "vendor", + [ACPI_AEST_GIC_ERROR_NODE] = "gic", + [ACPI_AEST_PCIE_ERROR_NODE] = "pcie", + [ACPI_AEST_PROXY_ERROR_NODE] = "proxy", +}; + +struct aest_vendor_match { + char hid[ACPI_ID_LEN]; + int (*probe)(struct aest_device *adev, struct aest_hnode *anode); +}; + +static inline int aest_set_name(struct aest_device *adev, + struct aest_hnode *ahnode) +{ + adev->dev->init_name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s%d", + aest_node_name[ahnode->type], + adev->id); + if (!adev->dev->init_name) + return -ENOMEM; + + return 0; +} + +#define CASE_READ(res, x) \ + case (x): { \ + res = read_sysreg_s(SYS_##x##_EL1); \ + break; \ + } + +#define CASE_WRITE(val, x) \ + case (x): { \ + write_sysreg_s((val), SYS_##x##_EL1); \ + break; \ + } + +static inline u64 aest_sysreg_read(void *__unused, u32 offset) +{ + u64 res; + + switch (offset) { + CASE_READ(res, ERXFR) + CASE_READ(res, ERXCTLR) + CASE_READ(res, ERXSTATUS) + CASE_READ(res, ERXADDR) + CASE_READ(res, ERXMISC0) + CASE_READ(res, ERXMISC1) + CASE_READ(res, ERXMISC2) + CASE_READ(res, ERXMISC3) + CASE_READ(res, ERXPFGF) + CASE_READ(res, ERXPFGCTL) + CASE_READ(res, ERXPFGCDN) + default : + res = 0; + } + return res; +} + +static inline void aest_sysreg_write(void *base, u32 offset, u64 val) +{ + switch (offset) { + CASE_WRITE(val, ERXFR) + CASE_WRITE(val, ERXCTLR) + CASE_WRITE(val, ERXSTATUS) + CASE_WRITE(val, ERXADDR) + CASE_WRITE(val, ERXMISC0) + CASE_WRITE(val, ERXMISC1) + CASE_WRITE(val, ERXMISC2) + CASE_WRITE(val, ERXMISC3) + CASE_WRITE(val, ERXPFGF) + CASE_WRITE(val, ERXPFGCTL) + CASE_WRITE(val, ERXPFGCDN) + default : + return; + } +} + +static inline u64 aest_iomem_read(void *base, u32 offset) +{ + return readq_relaxed(base + offset); +} + +static inline void aest_iomem_write(void *base, u32 offset, u64 val) +{ + writeq_relaxed(val, base + offset); +} + +/* access type is decided by AEST interface type. */ +static const struct aest_access aest_access[] = { + [ACPI_AEST_NODE_SYSTEM_REGISTER] = { + .read = aest_sysreg_read, + .write = aest_sysreg_write, + }, + [ACPI_AEST_NODE_MEMORY_MAPPED] = { + .read = aest_iomem_read, + .write = aest_iomem_write, + }, + [ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED] = { + .read = aest_iomem_read, + .write = aest_iomem_write, + }, + { } +}; + +/* + * Each PE may has multi error record, you must selects an error + * record to be accessed through the Error Record System + * registers. + */ +static inline void aest_select_record(struct aest_node *node, int index) +{ + if (node->type == ACPI_AEST_PROCESSOR_ERROR_NODE) { + write_sysreg_s(index, SYS_ERRSELR_EL1); + isb(); + } +} + +/* Ensure all writes has taken effect. */ +static inline void aest_sync(struct aest_node *node) +{ + if (node->type == ACPI_AEST_PROCESSOR_ERROR_NODE) + isb(); +} + +static inline bool aest_dev_is_oncore(struct aest_device *adev) +{ + /* + * A processor node is "on-core" (uses PPI + cpuhp) only when its + * interrupt is a per-CPU PPI. A shared processor node (e.g. cluster + * L3 cache, DSU) uses an SPI and must follow the non-oncore path + * (aest_online_dev) so that aest_config_irq and aest_online_dev are + * called instead of cpuhp_setup_state. + */ + if (adev->type != ACPI_AEST_PROCESSOR_ERROR_NODE) + return false; + return irq_is_percpu(adev->irq[ACPI_AEST_NODE_FAULT_HANDLING]) || + irq_is_percpu(adev->irq[ACPI_AEST_NODE_ERROR_RECOVERY]); +} + +static inline int default_errgsr_mapping(int errgsr_bit) +{ + return errgsr_bit; +} + +static inline int cmn700_errgsr_mapping(int errgsr_bit) +{ + return errgsr_bit / 2; +} + +void aest_dev_init_debugfs(struct aest_device *adev); +void aest_inject_init_debugfs(struct aest_record *record); +void aest_proc_record(struct aest_record *record, void *data, bool fake); +void aest_node_foreach_record(void (*func)(struct aest_record *, void *, bool), + struct aest_node *node, void *data, + unsigned long *bitmap); + +int aest_cmn700_probe(struct aest_device *adev, struct aest_hnode *ahnode); diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c index 03df3db623346..c8858b745021c 100644 --- a/drivers/ras/ras.c +++ b/drivers/ras/ras.c @@ -115,6 +115,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event); EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event); EXPORT_TRACEPOINT_SYMBOL_GPL(non_standard_event); EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event); +#ifdef CONFIG_ARM64_RAS_EXTN +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_ras_ext_event); +#endif static int __init parse_ras_param(char *str) { diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c index cd94ed67621fe..3d425452a0b35 100644 --- a/drivers/regulator/qcom_usb_vbus-regulator.c +++ b/drivers/regulator/qcom_usb_vbus-regulator.c @@ -20,10 +20,35 @@ #define OTG_CFG 0x53 #define OTG_EN_SRC_CFG BIT(1) +#define PM4125_CMD_OTG 0x50 +#define PM4125_VBOOST_CFG 0x52 +#define PM4125_VBOOST_CFG_MASK GENMASK(1, 0) +#define PM4125_OTG_CFG 0x56 +#define PM4125_OTG_EN_SRC_CFG BIT(0) + +struct qcom_usb_vbus_reg_data { + u16 cmd_otg; + u16 otg_cfg; + u8 otg_en_src_cfg; + u16 csel_reg; + u8 csel_mask; + const unsigned int *curr_table; + unsigned int n_current_limits; + u16 vsel_reg; + u8 vsel_mask; + const unsigned int *volt_table; + unsigned int n_voltages; + const struct regulator_ops *ops; +}; + static const unsigned int curr_table[] = { 500000, 1000000, 1500000, 2000000, 2500000, 3000000, }; +static const unsigned int pm4125_vboost_table[] = { + 4250000, 4500000, 4750000, 5000000, +}; + static const struct regulator_ops qcom_usb_vbus_reg_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -32,19 +57,43 @@ static const struct regulator_ops qcom_usb_vbus_reg_ops = { .set_current_limit = regulator_set_current_limit_regmap, }; -static struct regulator_desc qcom_usb_vbus_rdesc = { - .name = "usb_vbus", - .ops = &qcom_usb_vbus_reg_ops, - .owner = THIS_MODULE, - .type = REGULATOR_VOLTAGE, +static const struct regulator_ops qcom_usb_vbus_pm4125_reg_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_table, +}; + +static const struct qcom_usb_vbus_reg_data pm8150b_data = { + .cmd_otg = CMD_OTG, + .otg_cfg = OTG_CFG, + .otg_en_src_cfg = OTG_EN_SRC_CFG, + .csel_reg = OTG_CURRENT_LIMIT_CFG, + .csel_mask = OTG_CURRENT_LIMIT_MASK, .curr_table = curr_table, .n_current_limits = ARRAY_SIZE(curr_table), + .ops = &qcom_usb_vbus_reg_ops, +}; + +static const struct qcom_usb_vbus_reg_data pm4125_data = { + .cmd_otg = PM4125_CMD_OTG, + .otg_cfg = PM4125_OTG_CFG, + .otg_en_src_cfg = PM4125_OTG_EN_SRC_CFG, + .vsel_reg = PM4125_VBOOST_CFG, + .vsel_mask = PM4125_VBOOST_CFG_MASK, + .volt_table = pm4125_vboost_table, + .n_voltages = ARRAY_SIZE(pm4125_vboost_table), + .ops = &qcom_usb_vbus_pm4125_reg_ops, }; static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct qcom_usb_vbus_reg_data *data; struct regulator_dev *rdev; + struct regulator_desc *rdesc; struct regmap *regmap; struct regulator_config config = { }; struct regulator_init_data *init_data; @@ -57,27 +106,51 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) return ret; } + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + regmap = dev_get_regmap(dev->parent, NULL); if (!regmap) { dev_err(dev, "Failed to get regmap\n"); return -ENOENT; } - init_data = of_get_regulator_init_data(dev, dev->of_node, - &qcom_usb_vbus_rdesc); + rdesc = devm_kzalloc(dev, sizeof(*rdesc), GFP_KERNEL); + if (!rdesc) + return -ENOMEM; + + rdesc->name = "usb_vbus"; + rdesc->ops = data->ops; + rdesc->owner = THIS_MODULE; + rdesc->type = REGULATOR_VOLTAGE; + rdesc->enable_reg = base + data->cmd_otg; + rdesc->enable_mask = OTG_EN; + + if (data->curr_table) { + rdesc->curr_table = data->curr_table; + rdesc->n_current_limits = data->n_current_limits; + rdesc->csel_reg = base + data->csel_reg; + rdesc->csel_mask = data->csel_mask; + } + + if (data->volt_table) { + rdesc->volt_table = data->volt_table; + rdesc->n_voltages = data->n_voltages; + rdesc->vsel_reg = base + data->vsel_reg; + rdesc->vsel_mask = data->vsel_mask; + } + + init_data = of_get_regulator_init_data(dev, dev->of_node, rdesc); if (!init_data) return -ENOMEM; - qcom_usb_vbus_rdesc.enable_reg = base + CMD_OTG; - qcom_usb_vbus_rdesc.enable_mask = OTG_EN; - qcom_usb_vbus_rdesc.csel_reg = base + OTG_CURRENT_LIMIT_CFG; - qcom_usb_vbus_rdesc.csel_mask = OTG_CURRENT_LIMIT_MASK; config.dev = dev; config.init_data = init_data; config.of_node = dev->of_node; config.regmap = regmap; - rdev = devm_regulator_register(dev, &qcom_usb_vbus_rdesc, &config); + rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(dev, "not able to register vbus reg %d\n", ret); @@ -85,13 +158,14 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) } /* Disable HW logic for VBUS enable */ - regmap_update_bits(regmap, base + OTG_CFG, OTG_EN_SRC_CFG, 0); + regmap_update_bits(regmap, base + data->otg_cfg, data->otg_en_src_cfg, 0); return 0; } static const struct of_device_id qcom_usb_vbus_regulator_match[] = { - { .compatible = "qcom,pm8150b-vbus-reg" }, + { .compatible = "qcom,pm8150b-vbus-reg", .data = &pm8150b_data }, + { .compatible = "qcom,pm4125-vbus-reg", .data = &pm4125_data }, { } }; MODULE_DEVICE_TABLE(of, qcom_usb_vbus_regulator_match); diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index c521c744e7dbe..4fb2163c06556 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -228,6 +228,7 @@ config QCOM_Q6V5_PAS select QCOM_PIL_INFO select QCOM_MDT_LOADER select QCOM_Q6V5_COMMON + select QCOM_QMI_TMD select QCOM_RPROC_COMMON select QCOM_SCM help diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c index e1a955476c9b3..1f406bfcb1f59 100644 --- a/drivers/remoteproc/qcom_common.c +++ b/drivers/remoteproc/qcom_common.c @@ -226,6 +226,9 @@ static void glink_subdev_stop(struct rproc_subdev *subdev, bool crashed) { struct qcom_rproc_glink *glink = to_glink_subdev(subdev); + if (!glink->edge) + return; + qcom_glink_smem_unregister(glink->edge); glink->edge = NULL; } @@ -337,6 +340,9 @@ static void smd_subdev_stop(struct rproc_subdev *subdev, bool crashed) { struct qcom_rproc_subdev *smd = to_smd_subdev(subdev); + if (!smd->edge) + return; + qcom_smd_unregister_edge(smd->edge); smd->edge = NULL; } diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 58d5b85e58cda..52247c17c38ac 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -20,6 +20,7 @@ #define Q6V5_LOAD_STATE_MSG_LEN 64 #define Q6V5_PANIC_DELAY_MS 200 +#define Q6V5_PING_TIMEOUT_MS 500 static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable) { @@ -234,6 +235,74 @@ unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5) } EXPORT_SYMBOL_GPL(qcom_q6v5_panic); +static irqreturn_t q6v5_pong_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + + complete(&q6v5->ping_done); + + return IRQ_HANDLED; +} + +int qcom_q6v5_ping_subsystem(struct qcom_q6v5 *q6v5) +{ + int ret; + int ping_failed = 0; + + reinit_completion(&q6v5->ping_done); + + /* Set master kernel Ping bit */ + ret = qcom_smem_state_update_bits(q6v5->ping_state, + BIT(q6v5->ping_bit), BIT(q6v5->ping_bit)); + if (ret) { + dev_err(q6v5->dev, "Failed to update ping bits\n"); + return ret; + } + + ret = wait_for_completion_timeout(&q6v5->ping_done, msecs_to_jiffies(Q6V5_PING_TIMEOUT_MS)); + if (!ret) { + ping_failed = -ETIMEDOUT; + dev_err(q6v5->dev, "Failed to get back pong\n"); + } + + /* Clear ping bit master kernel */ + ret = qcom_smem_state_update_bits(q6v5->ping_state, BIT(q6v5->ping_bit), 0); + if (ret) { + dev_err(q6v5->dev, "Failed to clear master kernel bits\n"); + return ret; + } + + return ping_failed; +} +EXPORT_SYMBOL_GPL(qcom_q6v5_ping_subsystem); + +int qcom_q6v5_ping_subsystem_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev) +{ + int ret = -ENODEV; + + q6v5->ping_state = devm_qcom_smem_state_get(&pdev->dev, "ping", &q6v5->ping_bit); + if (IS_ERR(q6v5->ping_state)) { + dev_err(&pdev->dev, "Failed to acquire smem state %ld\n", + PTR_ERR(q6v5->ping_state)); + return PTR_ERR(q6v5->ping_state); + } + + init_completion(&q6v5->ping_done); + + q6v5->pong_irq = platform_get_irq_byname(pdev, "pong"); + if (q6v5->pong_irq < 0) + return q6v5->pong_irq; + + ret = devm_request_threaded_irq(&pdev->dev, q6v5->pong_irq, NULL, + q6v5_pong_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 pong", q6v5); + if (ret) + dev_err(&pdev->dev, "Failed to acquire pong IRQ\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(qcom_q6v5_ping_subsystem_init); + /** * qcom_q6v5_init() - initializer of the q6v5 common struct * @q6v5: handle to be initialized diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h index 5a859c41896e9..5025ffc4dbe80 100644 --- a/drivers/remoteproc/qcom_q6v5.h +++ b/drivers/remoteproc/qcom_q6v5.h @@ -17,22 +17,26 @@ struct qcom_q6v5 { struct rproc *rproc; struct qcom_smem_state *state; + struct qcom_smem_state *ping_state; struct qmp *qmp; struct icc_path *path; unsigned stop_bit; + unsigned int ping_bit; int wdog_irq; int fatal_irq; int ready_irq; int handover_irq; int stop_irq; + int pong_irq; bool handover_issued; struct completion start_done; struct completion stop_done; + struct completion ping_done; int crash_reason; @@ -52,5 +56,7 @@ int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5); int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon); int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout); unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5); +int qcom_q6v5_ping_subsystem(struct qcom_q6v5 *q6v5); +int qcom_q6v5_ping_subsystem_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev); #endif diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 808e9609988d3..6c45193505bd4 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -5,6 +5,7 @@ * Copyright (C) 2016 Linaro Ltd * Copyright (C) 2014 Sony Mobile Communications AB * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -60,6 +62,7 @@ struct qcom_pas_data { int region_assign_count; bool region_assign_shared; int region_assign_vmid; + bool early_boot; }; struct qcom_pas { @@ -97,8 +100,9 @@ struct qcom_pas { phys_addr_t mem_reloc; phys_addr_t dtb_mem_reloc; phys_addr_t region_assign_phys[MAX_ASSIGN_COUNT]; + void *mem_region; - void *dtb_mem_region; + size_t mem_size; size_t dtb_mem_size; size_t region_assign_size[MAX_ASSIGN_COUNT]; @@ -117,6 +121,8 @@ struct qcom_pas { struct qcom_scm_pas_context *pas_ctx; struct qcom_scm_pas_context *dtb_pas_ctx; + + struct qmi_tmd_client *tmd_inst; }; static void qcom_pas_segment_dump(struct rproc *rproc, @@ -145,7 +151,16 @@ static void qcom_pas_minidump(struct rproc *rproc) if (rproc->dump_conf == RPROC_COREDUMP_DISABLED) return; + pas->mem_region = ioremap_wc(pas->mem_phys, pas->mem_size); + if (!pas->mem_region) { + dev_err(pas->dev, "unable to map memory region: %pa+%zx\n", + &pas->mem_phys, pas->mem_size); + return; + } + qcom_minidump(rproc, pas->minidump_id, qcom_pas_segment_dump); + iounmap(pas->mem_region); + pas->mem_region = NULL; } static int qcom_pas_pds_enable(struct qcom_pas *pas, struct device **pds, @@ -181,6 +196,18 @@ static void qcom_pas_pds_disable(struct qcom_pas *pas, struct device **pds, int i; for (i = 0; i < pd_count; i++) { + /* + * There is a race condition which occurs sometimes for RB8 platform when APPS + * removes it's vote on handover INT from fw - ADSP F/W side vote is not yet + * applied on the lcx and lmx rails because of which PMIC shutdowns shut and device + * goes into hung state. Carry this WA until a proper fix is finalized. + */ + if (of_device_is_compatible(dev_of_node(pas->dev), "qcom,sa8775p-adsp-pas")) { + /* Apply SVS_L1 vote to keep lcx and lmx rails ON */ + dev_pm_genpd_set_performance_state(pds[i], 192); + return; + } + dev_pm_genpd_set_performance_state(pds[i], 0); pm_runtime_put(pds[i]); } @@ -238,7 +265,7 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) } ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware, - pas->dtb_firmware_name, pas->dtb_mem_region, + pas->dtb_firmware_name, &pas->dtb_mem_reloc); if (ret) goto release_dtb_metadata; @@ -247,7 +274,9 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) return 0; release_dtb_metadata: - qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + if (pas->dtb_pas_id) + qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + release_firmware(pas->dtb_firmware); return ret; @@ -316,7 +345,7 @@ static int qcom_pas_start(struct rproc *rproc) } ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware, - pas->mem_region, &pas->mem_reloc); + &pas->mem_reloc); if (ret) goto release_pas_metadata; @@ -420,9 +449,15 @@ static int qcom_pas_stop(struct rproc *rproc) qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size); - handover = qcom_q6v5_unprepare(&pas->q6v5); - if (handover) - qcom_pas_handover(&pas->q6v5); + /* + * qcom_q6v5_prepare is not called in qcom_pas_attach, skip unprepare to + * avoid mismatch. + */ + if (pas->rproc->state != RPROC_ATTACHED) { + handover = qcom_q6v5_unprepare(&pas->q6v5); + if (handover) + qcom_pas_handover(&pas->q6v5); + } if (pas->smem_host_id) ret = qcom_smem_bust_hwspin_lock_by_host(pas->smem_host_id); @@ -507,6 +542,79 @@ static unsigned long qcom_pas_panic(struct rproc *rproc) return qcom_q6v5_panic(&pas->q6v5); } +static void qcom_pas_coredump(struct rproc *rproc) +{ + struct qcom_pas *pas = rproc->priv; + + pas->mem_region = ioremap_wc(pas->mem_phys, pas->mem_size); + if (!pas->mem_region) { + dev_err(pas->dev, "unable to map memory region: %pa+%zx\n", + &pas->mem_phys, pas->mem_size); + return; + } + + rproc_coredump(rproc); + iounmap(pas->mem_region); + pas->mem_region = NULL; +} + +static int qcom_pas_attach(struct rproc *rproc) +{ + int ret; + struct qcom_pas *pas = rproc->priv; + bool ready_state; + bool crash_state; + + pas->q6v5.running = true; + ret = irq_get_irqchip_state(pas->q6v5.fatal_irq, + IRQCHIP_STATE_LINE_LEVEL, &crash_state); + + if (ret) + goto disable_running; + + if (crash_state) { + dev_err(pas->dev, "Subsystem has crashed before driver probe\n"); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + ret = -EINVAL; + goto disable_running; + } + + ret = irq_get_irqchip_state(pas->q6v5.ready_irq, + IRQCHIP_STATE_LINE_LEVEL, &ready_state); + + if (ret) + goto disable_running; + + if (unlikely(!ready_state)) { + /* + * The bootloader may not support early boot, mark the state as + * RPROC_OFFLINE so that the PAS driver can load the firmware and + * start the remoteproc. + */ + dev_err(pas->dev, "Failed to get subsystem ready interrupt\n"); + pas->rproc->state = RPROC_OFFLINE; + ret = -EINVAL; + goto disable_running; + } + + ret = qcom_q6v5_ping_subsystem(&pas->q6v5); + + if (ret) { + dev_err(pas->dev, "Failed to ping subsystem, assuming device crashed\n"); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + goto disable_running; + } + + pas->q6v5.handover_issued = true; + + return 0; + +disable_running: + pas->q6v5.running = false; + + return ret; +} + static const struct rproc_ops qcom_pas_ops = { .unprepare = qcom_pas_unprepare, .start = qcom_pas_start, @@ -515,6 +623,8 @@ static const struct rproc_ops qcom_pas_ops = { .parse_fw = qcom_pas_parse_firmware, .load = qcom_pas_load, .panic = qcom_pas_panic, + .coredump = qcom_pas_coredump, + .attach = qcom_pas_attach, }; static const struct rproc_ops qcom_pas_minidump_ops = { @@ -620,6 +730,7 @@ static void qcom_pas_pds_detach(struct qcom_pas *pas, struct device **pds, size_ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) { + struct rproc *rproc = pas->rproc; struct resource res; int ret; @@ -631,12 +742,13 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) pas->mem_phys = pas->mem_reloc = res.start; pas->mem_size = resource_size(&res); - pas->mem_region = devm_ioremap_resource_wc(pas->dev, &res); - if (IS_ERR(pas->mem_region)) { - dev_err(pas->dev, "unable to map memory region: %pR\n", &res); - return PTR_ERR(pas->mem_region); - } + pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id, + pas->mem_phys, pas->mem_size); + if (IS_ERR(pas->pas_ctx)) + return PTR_ERR(pas->pas_ctx); + + pas->pas_ctx->use_tzmem = rproc->has_iommu; if (!pas->dtb_pas_id) return 0; @@ -648,11 +760,14 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) pas->dtb_mem_phys = pas->dtb_mem_reloc = res.start; pas->dtb_mem_size = resource_size(&res); - pas->dtb_mem_region = devm_ioremap_resource_wc(pas->dev, &res); - if (IS_ERR(pas->dtb_mem_region)) { - dev_err(pas->dev, "unable to map dtb memory region: %pR\n", &res); - return PTR_ERR(pas->dtb_mem_region); - } + + pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id, + pas->dtb_mem_phys, + pas->dtb_mem_size); + if (IS_ERR(pas->dtb_pas_ctx)) + return PTR_ERR(pas->dtb_pas_ctx); + + pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; return 0; } @@ -730,6 +845,49 @@ static void qcom_pas_unassign_memory_region(struct qcom_pas *pas) } } +static int qcom_pas_setup_tmd(struct qcom_pas *pas) +{ + struct device *dev = pas->dev; + struct device_node *np = dev->of_node; + const char **tmd_names; + int num_tmds, ret, i; + + if (!of_find_property(np, "tmd-names", NULL)) + return 0; + + /* Get the TMD names array */ + num_tmds = of_property_count_strings(np, "tmd-names"); + if (num_tmds <= 0) + return 0; + + tmd_names = devm_kcalloc(dev, num_tmds, sizeof(*tmd_names), GFP_KERNEL); + if (!tmd_names) + return -ENOMEM; + + for (i = 0; i < num_tmds; i++) { + ret = of_property_read_string_index(np, "tmd-names", i, + &tmd_names[i]); + if (ret) { + dev_err(dev, "Failed to read tmd-names[%d]: %d\n", i, ret); + return ret; + } + } + + pas->tmd_inst = qmi_tmd_init(dev, pas->info_name, tmd_names, num_tmds); + if (IS_ERR(pas->tmd_inst)) { + dev_err(dev, "Failed to register '%s'\n", pas->info_name); + + ret = PTR_ERR(pas->tmd_inst); + if (ret == -ENODEV) { + pas->tmd_inst = NULL; + return 0; + } + return ret; + } + + return 0; +} + static int qcom_pas_probe(struct platform_device *pdev) { const struct qcom_pas_data *desc; @@ -852,12 +1010,29 @@ static int qcom_pas_probe(struct platform_device *pdev) pas->pas_ctx->use_tzmem = rproc->has_iommu; pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; - ret = rproc_add(rproc); + + if (desc->early_boot) { + ret = qcom_q6v5_ping_subsystem_init(&pas->q6v5, pdev); + if (ret) + dev_warn(&pdev->dev, "Falling back to firmware load\n"); + else + pas->rproc->state = RPROC_DETACHED; + } + + ret = qcom_pas_setup_tmd(pas); if (ret) goto remove_ssr_sysmon; + ret = rproc_add(rproc); + if (ret) + goto remove_setup_tmd; + return 0; +remove_setup_tmd: + if (pas->tmd_inst) + qmi_tmd_exit(pas->tmd_inst); + remove_ssr_sysmon: qcom_remove_ssr_subdev(rproc, &pas->ssr_subdev); qcom_remove_sysmon_subdev(pas->sysmon); @@ -880,6 +1055,9 @@ static void qcom_pas_remove(struct platform_device *pdev) { struct qcom_pas *pas = platform_get_drvdata(pdev); + if (pas->tmd_inst) + qmi_tmd_exit(pas->tmd_inst); + rproc_del(pas->rproc); qcom_q6v5_deinit(&pas->q6v5); @@ -1572,8 +1750,26 @@ static const struct qcom_pas_data sm8750_mpss_resource = { .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, }; +static const struct qcom_pas_data kaanapali_soccp_resource = { + .crash_reason_smem = 656, + .firmware_name = "soccp.mbn", + .dtb_firmware_name = "soccp_dtb.mbn", + .pas_id = 51, + .dtb_pas_id = 0x41, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + NULL + }, + .ssr_name = "soccp", + .sysmon_name = "soccp", + .auto_boot = true, + .early_boot = true, +}; + static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,eliza-adsp-pas", .data = &sm8550_adsp_resource }, + { .compatible = "qcom,kaanapali-soccp-pas", .data = &kaanapali_soccp_resource }, { .compatible = "qcom,milos-adsp-pas", .data = &sm8550_adsp_resource }, { .compatible = "qcom,milos-cdsp-pas", .data = &milos_cdsp_resource }, { .compatible = "qcom,milos-mpss-pas", .data = &sm8450_mpss_resource }, diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 2caadbbcf8307..a292ce57fd4a4 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -128,6 +128,16 @@ config QCOM_QMI_HELPERS tristate depends on NET +config QCOM_QMI_TMD + bool "Qualcomm QMI TMD library" if COMPILE_TEST + depends on ARCH_QCOM + select QCOM_QMI_HELPERS + help + This enables the QMI-based Thermal Mitigation Device (TMD) library + for Qualcomm remote subsystems. The library manages TMD messaging and + handles QMI communication with remote processors (modem, CDSP) to + exchange mitigation state and apply thermal mitigation requests. + config QCOM_RAMP_CTRL tristate "Qualcomm Ramp Controller driver" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index b7f1d2a573674..5c7702db362cb 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o CFLAGS_pmic_pdcharger_ulog.o := -I$(src) +obj-$(CONFIG_QCOM_QMI_TMD) += qmi_tmd.o obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o qmi_helpers-y += qmi_encdec.o qmi_interface.o obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o @@ -23,10 +24,12 @@ obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o qcom_rpmh-y += rpmh-rsc.o qcom_rpmh-y += rpmh.o obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o -obj-$(CONFIG_QCOM_SMEM) += smem.o +qcom_smem-y += smem.o smem_dramc.o +obj-$(CONFIG_QCOM_SMEM) += qcom_smem.o obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o CFLAGS_smp2p.o := -I$(src) obj-$(CONFIG_QCOM_SMP2P) += smp2p.o +CFLAGS_smsm.o := -I$(src) obj-$(CONFIG_QCOM_SMSM) += smsm.o obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o obj-$(CONFIG_QCOM_SPM) += spm.o diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 597f9025e4228..e46975da7dba6 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -830,7 +830,7 @@ static const struct icc_bwmon_data msm8998_bwmon_data = { static const struct icc_bwmon_data sdm845_cpu_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .zone1_thres_count = 16, + .zone1_thres_count = 3, .zone3_thres_count = 1, .quirks = BWMON_HAS_GLOBAL_IRQ, .regmap_fields = sdm845_cpu_bwmon_reg_fields, @@ -849,7 +849,7 @@ static const struct icc_bwmon_data sdm845_llcc_bwmon_data = { static const struct icc_bwmon_data sc7280_llcc_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .zone1_thres_count = 16, + .zone1_thres_count = 3, .zone3_thres_count = 1, .quirks = BWMON_NEEDS_FORCE_CLEAR, .regmap_fields = sdm845_llcc_bwmon_reg_fields, diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 8948b5fd42d2a..733999867bbf6 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -2305,6 +2305,20 @@ static const struct llcc_slice_config sdm845_data[] = {{ }, }; +static const struct llcc_slice_config shikra_data[] = { + { + .usecase_id = LLCC_ECC, + .slice_id = 26, + .max_cap = 256, + .priority = 3, + .fixed_size = true, + .bonus_ways = 0x3, + .cache_mode = 0, + .activate_on_init = true, + .vict_prio = true, + }, +}; + static const struct llcc_slice_config sm6350_data[] = { { .usecase_id = LLCC_CPUSS, @@ -4575,6 +4589,16 @@ static const struct qcom_llcc_config sdm845_cfg[] = { }, }; +static const struct qcom_llcc_config shikra_cfg[] = { + { + .sct_data = shikra_data, + .size = ARRAY_SIZE(shikra_data), + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + .irq_configured = true, + }, +}; + static const struct qcom_llcc_config sm6350_cfg[] = { { .sct_data = sm6350_data, @@ -4752,6 +4776,11 @@ static const struct qcom_sct_config sdm845_cfgs = { .num_config = ARRAY_SIZE(sdm845_cfg), }; +static const struct qcom_sct_config shikra_cfgs = { + .llcc_config = shikra_cfg, + .num_config = ARRAY_SIZE(shikra_cfg), +}; + static const struct qcom_sct_config sm6350_cfgs = { .llcc_config = sm6350_cfg, .num_config = ARRAY_SIZE(sm6350_cfg), @@ -5632,6 +5661,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfgs }, { .compatible = "qcom,sdm670-llcc", .data = &sdm670_cfgs }, { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfgs }, + { .compatible = "qcom,shikra-llcc", .data = &shikra_cfgs }, { .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfgs }, { .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfgs }, { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfgs }, diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index c004d444d6985..33f3543f8e558 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -478,22 +479,31 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load); * @ctx: Pointer to the PAS (Peripheral Authentication Service) context * @fw: Firmware object representing the .mdt file * @firmware: Name of the firmware used to construct segment file names - * @mem_region: Memory region allocated for loading the firmware * @reloc_base: Physical address adjusted after relocation * * Return: 0 on success or a negative error code on failure. */ int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, - const char *firmware, void *mem_region, phys_addr_t *reloc_base) + const char *firmware, phys_addr_t *reloc_base) { + void *mem_region; int ret; ret = __qcom_mdt_pas_init(ctx->dev, fw, firmware, ctx->pas_id, ctx->mem_phys, ctx); if (ret) return ret; - return qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys, - ctx->mem_size, reloc_base); + mem_region = ioremap_wc(ctx->mem_phys, ctx->mem_size); + if (!mem_region) { + dev_err(ctx->dev, "unable to map memory region: %pa+%zx\n", &ctx->mem_phys, + ctx->mem_size); + return -EINVAL; + } + + ret = qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys, + ctx->mem_size, reloc_base); + iounmap(mem_region); + return ret; } EXPORT_SYMBOL_GPL(qcom_mdt_pas_load); diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 619bad2c27eeb..28ab8cbb5ef9e 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -373,7 +373,15 @@ static void pmic_glink_altmode_worker(struct work_struct *work) else conn_status = connector_status_disconnected; - drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status); + if (alt_port->hpd_irq) { + drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev, + connector_status_unknown, + DRM_CONNECTOR_DP_IRQ_HPD); + } else { + drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev, + conn_status, + DRM_CONNECTOR_NO_EXTRA_STATUS); + } } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_TUNNELING) { if (alt_port->svid == USB_TYPEC_TBT_SID) pmic_glink_altmode_enable_tbt(altmode, alt_port); diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 15636a8dc907a..cdd1edcf394c1 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -606,10 +606,17 @@ int geni_se_resources_off(struct geni_se *se) if (has_acpi_companion(se->dev)) return 0; - - ret = pinctrl_pm_select_sleep_state(se->dev); - if (ret) - return ret; + /* + * Select the "sleep" pinctrl state only when the serial engine is + * exclusively owned by this system processor. For shared controller + * configurations, another system processor may still be using the pins, + * and switching them to "sleep" can disrupt ongoing transfers. + */ + if (!se->multi_owner) { + ret = pinctrl_pm_select_sleep_state(se->dev); + if (ret) + return ret; + } geni_se_clks_off(se); return 0; diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index b99718e25f2fc..0dad1c493cc19 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -311,6 +311,24 @@ static const struct qcom_pdm_domain_data cdsp_root_pd = { .services = { NULL }, }; +static const struct qcom_pdm_domain_data cdsp1_root_pd = { + .domain = "msm/cdsp1/root_pd", + .instance_id = 125, + .services = { NULL }, +}; + +static const struct qcom_pdm_domain_data gpdsp_root_pd = { + .domain = "msm/gpdsp/root_pd", + .instance_id = 192, + .services = { NULL }, +}; + +static const struct qcom_pdm_domain_data gpdsp1_root_pd = { + .domain = "msm/gpdsp1/root_pd", + .instance_id = 241, + .services = { NULL }, +}; + static const struct qcom_pdm_domain_data slpi_root_pd = { .domain = "msm/slpi/root_pd", .instance_id = 90, @@ -426,6 +444,24 @@ static const struct qcom_pdm_domain_data *qcs615_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *qcs8300_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &cdsp_root_pd, + &gpdsp_root_pd, + NULL, +}; + +static const struct qcom_pdm_domain_data *sa8775p_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &cdsp_root_pd, + &cdsp1_root_pd, + &gpdsp_root_pd, + &gpdsp1_root_pd, + NULL, +}; + static const struct qcom_pdm_domain_data *sc7180_domains[] = { &adsp_audio_pd, &adsp_root_pd_pdr, @@ -463,6 +499,11 @@ static const struct qcom_pdm_domain_data *sc8280xp_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *shikra_cqm_domains[] = { + &mpss_wlan_pd, + NULL, +}; + /* Unlike SDM660, SDM630/636 lack CDSP */ static const struct qcom_pdm_domain_data *sdm630_domains[] = { &adsp_audio_pd, @@ -603,10 +644,15 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,qcm6490", .data = sc7280_domains, }, { .compatible = "qcom,qcs404", .data = qcs404_domains, }, { .compatible = "qcom,qcs615", .data = qcs615_domains, }, + { .compatible = "qcom,qcs8300", .data = qcs8300_domains, }, + { .compatible = "qcom,sa8775p", .data = sa8775p_domains, }, { .compatible = "qcom,sc7180", .data = sc7180_domains, }, { .compatible = "qcom,sc7280", .data = sc7280_domains, }, { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, }, + { .compatible = "qcom,shikra-cqm-som", .data = shikra_cqm_domains, }, + { .compatible = "qcom,shikra-cqs-som", .data = shikra_cqm_domains, }, + { .compatible = "qcom,shikra-iqs-som", .data = shikra_cqm_domains, }, { .compatible = "qcom,sdm630", .data = sdm630_domains, }, { .compatible = "qcom,sdm636", .data = sdm630_domains, }, { .compatible = "qcom,sda660", .data = sdm660_domains, }, diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index 16e2e24b60968..974ed2b3d611d 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -321,7 +321,7 @@ int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, mutex_lock(&qmi->txn_lock); ret = idr_alloc_cyclic(&qmi->txns, txn, 0, U16_MAX, GFP_KERNEL); if (ret < 0) - pr_err("failed to allocate transaction id\n"); + pr_err("failed to allocate transaction id: %d\n", ret); txn->id = ret; mutex_unlock(&qmi->txn_lock); @@ -413,7 +413,7 @@ static void qmi_invoke_handler(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, ret = qmi_decode_message(buf, len, handler->ei, dest); if (ret < 0) - pr_err("failed to decode incoming message\n"); + pr_err("failed to decode incoming message: %d\n", ret); else handler->fn(qmi, sq, txn, dest); @@ -502,7 +502,7 @@ static void qmi_handle_message(struct qmi_handle *qmi, if (txn->dest && txn->ei) { ret = qmi_decode_message(buf, len, txn->ei, txn->dest); if (ret < 0) - pr_err("failed to decode incoming message\n"); + pr_err("failed to decode incoming message: %d\n", ret); txn->result = ret; complete(&txn->completion); @@ -661,8 +661,8 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size, if (PTR_ERR(qmi->sock) == -EAFNOSUPPORT) { ret = -EPROBE_DEFER; } else { - pr_err("failed to create QMI socket\n"); ret = PTR_ERR(qmi->sock); + pr_err("failed to create QMI socket: %d\n", ret); } goto err_destroy_wq; } @@ -766,7 +766,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi, if (qmi->sock) { ret = kernel_sendmsg(qmi->sock, &msghdr, &iv, 1, len); if (ret < 0) - pr_err("failed to send QMI message\n"); + pr_err("failed to send QMI message: %d\n", ret); } else { ret = -EPIPE; } diff --git a/drivers/soc/qcom/qmi_tmd.c b/drivers/soc/qcom/qmi_tmd.c new file mode 100644 index 0000000000000..e09131e8ef0f6 --- /dev/null +++ b/drivers/soc/qcom/qmi_tmd.c @@ -0,0 +1,602 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QMI Thermal Mitigation Device (TMD) library. + * This library provides cooling device support for remote subsystems + * (modem and CDSP) running the TMD service via QMI. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QMI_TMD_INSTANCE_MODEM 0x0 +#define QMI_TMD_INSTANCE_CDSP 0x43 +#define QMI_TMD_INSTANCE_CDSP1 0x44 + +#define QMI_TMD_SERVICE_VERS_V01 0x01 + +#define QMI_TMD_SET_LEVEL_REQ 0x0021 +#define QMI_TMD_GET_DEV_LIST_REQ 0x0020 + +#define QMI_TMD_DEV_ID_LEN_MAX 32 +#define QMI_TMD_DEV_LIST_MAX 32 +#define QMI_TMD_RESP_TIMEOUT msecs_to_jiffies(100) +#define TMD_GET_LEVEL_REQ_MAX_LEN 36 +#define TMD_SET_LEVEL_REQ_MAX_LEN 40 + +#define TMD_GET_DEV_LIST_REQ_MAX_LEN 0 +#define TMD_GET_DEV_LIST_RESP_MAX_LEN 1099 + +struct tmd_dev_id { + char mitigation_dev_id[QMI_TMD_DEV_ID_LEN_MAX + 1]; +}; + +static const struct qmi_elem_info tmd_dev_id_ei[] = { + { + .data_type = QMI_STRING, + .elem_len = QMI_TMD_DEV_ID_LEN_MAX + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct tmd_dev_id, + mitigation_dev_id), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_dev_list { + struct tmd_dev_id mitigation_dev_id; + u8 max_mitigation_level; +}; + +static const struct qmi_elem_info tmd_dev_list_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct tmd_dev_id), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct tmd_dev_list, + mitigation_dev_id), + .ei_array = tmd_dev_id_ei, + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct tmd_dev_list, + max_mitigation_level), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_get_dev_list_req { + char placeholder; +}; + +static const struct qmi_elem_info tmd_get_dev_list_req_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_get_dev_list_resp { + struct qmi_response_type_v01 resp; + u8 mitigation_device_list_valid; + u32 mitigation_device_list_len; + struct tmd_dev_list + mitigation_device_list[QMI_TMD_DEV_LIST_MAX]; +}; + +static const struct qmi_elem_info tmd_get_dev_list_resp_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct tmd_get_dev_list_resp, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct tmd_get_dev_list_resp, + mitigation_device_list_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct tmd_get_dev_list_resp, + mitigation_device_list_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_TMD_DEV_LIST_MAX, + .elem_size = sizeof(struct tmd_dev_list), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct tmd_get_dev_list_resp, + mitigation_device_list), + .ei_array = tmd_dev_list_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_set_level_req { + struct tmd_dev_id mitigation_dev_id; + u8 mitigation_level; +}; + +static const struct qmi_elem_info tmd_set_level_req_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct tmd_dev_id), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct tmd_set_level_req, + mitigation_dev_id), + .ei_array = tmd_dev_id_ei, + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct tmd_set_level_req, + mitigation_level), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct tmd_set_level_resp { + struct qmi_response_type_v01 resp; +}; + +static const struct qmi_elem_info tmd_set_level_resp_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct tmd_set_level_resp, resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +/** + * struct qmi_tmd - A TMD cooling device + * @name: The name of this tmd shared by the remote subsystem + * @cdev: Thermal cooling device handle + * @cur_state: The current mitigation state + * @max_state: The maximum state + * @qmi_tmd_cli: Parent QMI TMD client + */ +struct qmi_tmd { + const char *name; + struct thermal_cooling_device *cdev; + unsigned int cur_state; + unsigned int max_state; + struct qmi_tmd_client *qmi_tmd_cli; +}; + +/** + * struct qmi_tmd_client - QMI TMD client state + * @dev: Device associated with this instance + * @handle: QMI connection handle + * @mutex: Lock to synchronise QMI communication + * @connection_active: Whether or not we're connected to the QMI TMD service + * @svc_arrive_work: Work item for initialising when the TMD service starts + * @num_tmds: Number of tmds described in the device tree + * @tmds: An array of tmd structures + */ +struct qmi_tmd_client { + struct device *dev; + struct qmi_handle handle; + /* protects QMI transactions and connection_active */ + struct mutex mutex; + bool connection_active; + struct work_struct svc_arrive_work; + int num_tmds; + struct qmi_tmd tmds[] __counted_by(num_tmds); +}; + +/* Notify the remote subsystem of the requested cooling state */ +static int qmi_tmd_send_state_request(struct qmi_tmd *tmd, int state) +{ + struct tmd_set_level_resp resp = { 0 }; + struct tmd_set_level_req req = { 0 }; + struct qmi_tmd_client *qmi_tmd_cli = tmd->qmi_tmd_cli; + struct qmi_txn txn; + int ret = 0; + + guard(mutex)(&qmi_tmd_cli->mutex); + + if (!qmi_tmd_cli->connection_active) + return 0; + + strscpy(req.mitigation_dev_id.mitigation_dev_id, tmd->name, + QMI_TMD_DEV_ID_LEN_MAX + 1); + req.mitigation_level = state; + + ret = qmi_txn_init(&qmi_tmd_cli->handle, &txn, + tmd_set_level_resp_ei, &resp); + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "qmi set state %d txn init failed for %s ret %d\n", + state, tmd->name, ret); + return ret; + } + + ret = qmi_send_request(&qmi_tmd_cli->handle, NULL, &txn, + QMI_TMD_SET_LEVEL_REQ, + TMD_SET_LEVEL_REQ_MAX_LEN, + tmd_set_level_req_ei, &req); + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "qmi set state %d txn send failed for %s ret %d\n", + state, tmd->name, ret); + qmi_txn_cancel(&txn); + return ret; + } + + ret = qmi_txn_wait(&txn, QMI_TMD_RESP_TIMEOUT); + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "qmi set state %d txn wait failed for %s ret %d\n", + state, tmd->name, ret); + return ret; + } + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + dev_err(qmi_tmd_cli->dev, + "qmi set state %d failed for %s result %#x error %#x\n", + state, tmd->name, + resp.resp.result, resp.resp.error); + return -EREMOTEIO; + } + + dev_dbg(qmi_tmd_cli->dev, "Requested state %d/%d for %s\n", state, + tmd->max_state, tmd->name); + + return 0; +} + +static int qmi_tmd_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct qmi_tmd *tmd = cdev->devdata; + + *state = tmd->max_state; + + return 0; +} + +static int qmi_tmd_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct qmi_tmd *tmd = cdev->devdata; + + *state = tmd->cur_state; + + return 0; +} + +static int qmi_tmd_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) +{ + struct qmi_tmd *tmd = cdev->devdata; + int ret; + + if (state > tmd->max_state) + return -EINVAL; + + if (tmd->cur_state == state) + return 0; + + ret = qmi_tmd_send_state_request(tmd, state); + if (!ret) + tmd->cur_state = state; + + return ret; +} + +static const struct thermal_cooling_device_ops qmi_tmd_cooling_ops = { + .get_max_state = qmi_tmd_get_max_state, + .get_cur_state = qmi_tmd_get_cur_state, + .set_cur_state = qmi_tmd_set_cur_state, +}; + +static int qmi_tmd_register(struct qmi_tmd_client *qmi_tmd_cli, + const char *label, u8 max_state) +{ + struct device *dev = qmi_tmd_cli->dev; + struct qmi_tmd *tmd; + int index; + + for (index = 0; index < qmi_tmd_cli->num_tmds; index++) { + tmd = &qmi_tmd_cli->tmds[index]; + + if (!strncasecmp(tmd->name, label, + QMI_TMD_DEV_ID_LEN_MAX + 1)) + goto found; + } + + dev_dbg(qmi_tmd_cli->dev, + "TMD '%s' available in firmware but not specified in DT\n", + label); + return 0; + +found: + tmd->max_state = max_state; + + /* + * If the cooling device already exists then the QMI service went away and + * came back. So just make sure the current cooling device state is + * reflected on the remote side and then return. + */ + if (tmd->cdev) + return qmi_tmd_send_state_request(tmd, tmd->cur_state); + + tmd->cdev = thermal_of_cooling_device_register(dev->of_node, index, + label, tmd, &qmi_tmd_cooling_ops); + if (IS_ERR(tmd->cdev)) + return PTR_ERR(tmd->cdev); + + return 0; +} + +static void qmi_tmd_unregister(struct qmi_tmd_client *qmi_tmd_cli) +{ + struct qmi_tmd *tmd; + int index; + + for (index = 0; index < qmi_tmd_cli->num_tmds; index++) { + tmd = &qmi_tmd_cli->tmds[index]; + + if (!tmd->cdev) + continue; + + thermal_cooling_device_unregister(tmd->cdev); + tmd->cdev = NULL; + } +} + +static void qmi_tmd_svc_arrive(struct work_struct *work) +{ + struct qmi_tmd_client *qmi_tmd_cli = + container_of(work, struct qmi_tmd_client, svc_arrive_work); + + struct tmd_get_dev_list_req req = { 0 }; + struct tmd_get_dev_list_resp *resp __free(kfree) = NULL; + int ret, i; + struct qmi_txn txn; + + resp = kzalloc_obj(*resp, GFP_KERNEL); + if (!resp) { + ret = -ENOMEM; + goto out; + } + + scoped_guard(mutex, &qmi_tmd_cli->mutex) { + ret = qmi_txn_init(&qmi_tmd_cli->handle, &txn, + tmd_get_dev_list_resp_ei, resp); + if (ret < 0) + goto out; + + ret = qmi_send_request(&qmi_tmd_cli->handle, NULL, &txn, + QMI_TMD_GET_DEV_LIST_REQ, + TMD_GET_DEV_LIST_REQ_MAX_LEN, + tmd_get_dev_list_req_ei, &req); + if (ret < 0) { + qmi_txn_cancel(&txn); + goto out; + } + + ret = qmi_txn_wait(&txn, QMI_TMD_RESP_TIMEOUT); + if (ret < 0) + goto out; + + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + ret = -EPROTO; + goto out; + } + + qmi_tmd_cli->connection_active = true; + } + + for (i = 0; i < resp->mitigation_device_list_len; i++) { + struct tmd_dev_list *device = + &resp->mitigation_device_list[i]; + + ret = qmi_tmd_register(qmi_tmd_cli, + device->mitigation_dev_id.mitigation_dev_id, + device->max_mitigation_level); + if (ret) + break; + } + +out: + if (ret) + dev_err(qmi_tmd_cli->dev, "Failed to initialize TMD service: %d\n", ret); +} + +static void qmi_tmd_del_server(struct qmi_handle *qmi, struct qmi_service *service) +{ + struct qmi_tmd_client *qmi_tmd_cli = + container_of(qmi, struct qmi_tmd_client, handle); + + scoped_guard(mutex, &qmi_tmd_cli->mutex) + qmi_tmd_cli->connection_active = false; +} + +static int qmi_tmd_new_server(struct qmi_handle *qmi, struct qmi_service *service) +{ + struct sockaddr_qrtr sq = { AF_QIPCRTR, service->node, service->port }; + struct qmi_tmd_client *qmi_tmd_cli; + int ret; + + qmi_tmd_cli = container_of(qmi, struct qmi_tmd_client, handle); + + scoped_guard(mutex, &qmi_tmd_cli->mutex) { + ret = kernel_connect(qmi->sock, (struct sockaddr_unsized *)&sq, + sizeof(sq), 0); + } + + if (ret < 0) { + dev_err(qmi_tmd_cli->dev, "QMI connect failed for node %u port %u: %d\n", + service->node, service->port, ret); + return ret; + } + + queue_work(system_highpri_wq, &qmi_tmd_cli->svc_arrive_work); + + return 0; +} + +static const struct qmi_ops qmi_tmd_ops = { + .new_server = qmi_tmd_new_server, + .del_server = qmi_tmd_del_server, +}; + +static int qmi_tmd_get_instance_id(const char *remoteproc_name) +{ + if (!strcmp(remoteproc_name, "modem")) + return QMI_TMD_INSTANCE_MODEM; + + if (!strcmp(remoteproc_name, "cdsp")) + return QMI_TMD_INSTANCE_CDSP; + + if (!strcmp(remoteproc_name, "cdsp1")) + return QMI_TMD_INSTANCE_CDSP1; + + return -ENODEV; +} + +/** + * qmi_tmd_init() - Initialize QMI TMD instance + * @dev: Device pointer + * @remoteproc_name: Remoteproc name (for example modem, cdsp) + * @tmd_names: Array of TMD names + * @num_tmds: Number of TMD names + * + * Return: Pointer to qmi_tmd_client on success, ERR_PTR on failure + */ +struct qmi_tmd_client *qmi_tmd_init(struct device *dev, + const char *remoteproc_name, + const char * const *tmd_names, + int num_tmds) +{ + struct qmi_tmd_client *qmi_tmd_cli; + int ret, i, instance_id; + + if (!dev || !remoteproc_name || !tmd_names || num_tmds <= 0) + return ERR_PTR(-EINVAL); + + instance_id = qmi_tmd_get_instance_id(remoteproc_name); + if (instance_id < 0) { + dev_err(dev, "Unsupported remoteproc name '%s' for TMD lookup\n", + remoteproc_name); + return ERR_PTR(instance_id); + } + + qmi_tmd_cli = devm_kzalloc(dev, struct_size(qmi_tmd_cli, tmds, num_tmds), GFP_KERNEL); + if (!qmi_tmd_cli) + return ERR_PTR(-ENOMEM); + + qmi_tmd_cli->dev = dev; + qmi_tmd_cli->num_tmds = num_tmds; + mutex_init(&qmi_tmd_cli->mutex); + INIT_WORK(&qmi_tmd_cli->svc_arrive_work, qmi_tmd_svc_arrive); + + /* Initialize TMD structures */ + for (i = 0; i < num_tmds; i++) { + qmi_tmd_cli->tmds[i].name = tmd_names[i]; + qmi_tmd_cli->tmds[i].qmi_tmd_cli = qmi_tmd_cli; + } + + ret = qmi_handle_init(&qmi_tmd_cli->handle, + TMD_GET_DEV_LIST_RESP_MAX_LEN, + &qmi_tmd_ops, NULL); + if (ret < 0) { + dev_err(dev, "QMI handle init failed: %d\n", ret); + return ERR_PTR(ret); + } + + ret = qmi_add_lookup(&qmi_tmd_cli->handle, QMI_SERVICE_ID_TMD, + QMI_TMD_SERVICE_VERS_V01, instance_id); + if (ret < 0) { + dev_err(dev, "QMI add lookup failed: %d\n", ret); + goto err_release_handle; + } + + return qmi_tmd_cli; + +err_release_handle: + qmi_handle_release(&qmi_tmd_cli->handle); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(qmi_tmd_init); + +/** + * qmi_tmd_exit() - Deinitialize QMI TMD instance + * @qmi_tmd_cli: QMI TMD client to deinitialize + */ +void qmi_tmd_exit(struct qmi_tmd_client *qmi_tmd_cli) +{ + if (!qmi_tmd_cli) + return; + + cancel_work_sync(&qmi_tmd_cli->svc_arrive_work); + qmi_handle_release(&qmi_tmd_cli->handle); + qmi_tmd_unregister(qmi_tmd_cli); + + scoped_guard(mutex, &qmi_tmd_cli->mutex) + qmi_tmd_cli->connection_active = false; +} +EXPORT_SYMBOL_GPL(qmi_tmd_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm QMI Thermal Mitigation library"); diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index afb21a778fe7b..4315512d3a1d4 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -4,6 +4,7 @@ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -16,6 +17,8 @@ #include #include +#include "smem.h" + /* * The Qualcomm shared memory system is a allocate only heap structure that * consists of one of more memory areas that can be accessed by the processors @@ -281,6 +284,8 @@ struct qcom_smem { struct smem_partition global_partition; struct xarray partitions; + struct dentry *debugfs_dir; + unsigned num_regions; struct smem_region regions[] __counted_by(num_regions); }; @@ -1239,17 +1244,24 @@ static int qcom_smem_probe(struct platform_device *pdev) __smem = smem; + smem->debugfs_dir = smem_dram_parse(smem->dev); + smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(smem->socinfo)) + if (IS_ERR(smem->socinfo)) { + debugfs_remove_recursive(smem->debugfs_dir); + dev_dbg(&pdev->dev, "failed to register socinfo device\n"); + } return 0; } static void qcom_smem_remove(struct platform_device *pdev) { + debugfs_remove_recursive(__smem->debugfs_dir); + platform_device_unregister(__smem->socinfo); xa_destroy(&__smem->partitions); diff --git a/drivers/soc/qcom/smem.h b/drivers/soc/qcom/smem.h new file mode 100644 index 0000000000000..8bf3f606e1ae8 --- /dev/null +++ b/drivers/soc/qcom/smem.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __QCOM_SMEM_INTERNAL__ +#define __QCOM_SMEM_INTERNAL__ + +#include + +struct dentry *smem_dram_parse(struct device *dev); + +#endif diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c new file mode 100644 index 0000000000000..dc2cd7e13b88e --- /dev/null +++ b/drivers/soc/qcom/smem_dramc.c @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smem.h" + +#define SMEM_DDR_INFO_ID 603 + +#define MAX_DDR_FREQ_NUM_V3 13 +#define MAX_DDR_FREQ_NUM_V5 14 + +#define MAX_CHAN_NUM 8 +#define MAX_RANK_NUM 2 + +#define DDR_HBB_MIN 13 +#define DDR_HBB_MAX 19 + +#define MAX_SHUB_ENTRIES 8 + +static struct smem_dram *__dram; + +enum ddr_info_version { + INFO_UNKNOWN, + INFO_V3, + INFO_V3_WITH_14_FREQS, + INFO_V4, + INFO_V5, + INFO_V5_WITH_6_REGIONS, + INFO_V6, /* INFO_V6 seems to only have shipped with 6 DDR regions, unlike V7 */ + INFO_V7, + INFO_V7_WITH_6_REGIONS, +}; + +struct smem_dram { + unsigned long frequencies[MAX_DDR_FREQ_NUM_V5]; + u32 num_frequencies; + u8 hbb; +}; + +enum ddr_type { + DDR_TYPE_NODDR = 0, + DDR_TYPE_LPDDR1 = 1, + DDR_TYPE_LPDDR2 = 2, + DDR_TYPE_PCDDR2 = 3, + DDR_TYPE_PCDDR3 = 4, + DDR_TYPE_LPDDR3 = 5, + DDR_TYPE_LPDDR4 = 6, + DDR_TYPE_LPDDR4X = 7, + DDR_TYPE_LPDDR5 = 8, + DDR_TYPE_LPDDR5X = 9, +}; + +/* The data structures below are NOT __packed on purpose! */ + +/* Structs used across multiple versions */ +struct ddr_part_details { + __le16 revision_id1; + __le16 revision_id2; + __le16 width; + __le16 density; +}; + +struct ddr_freq_table { + u32 freq_khz; + u8 enabled; +}; + +/* V3 */ +struct ddr_freq_plan_v3 { + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3]; + u8 num_ddr_freqs; + phys_addr_t clk_period_address; +}; + +struct ddr_details_v3 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v3 ddr_freq_tbl; + u8 num_channels; +}; + +/* Some V3 structs have an additional frequency level */ +struct ddr_freq_plan_v3_14freqs { + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3 + 1]; + u8 num_ddr_freqs; + phys_addr_t clk_period_address; +}; + +struct ddr_details_v3_14freqs { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v3_14freqs ddr_freq_tbl; + u8 num_channels; +}; + +/* V4 */ +struct ddr_details_v4 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v3 ddr_freq_tbl; + u8 num_channels; + u8 num_ranks[MAX_CHAN_NUM]; + u8 highest_bank_addr_bit[MAX_CHAN_NUM][MAX_RANK_NUM]; +}; + +/* V5 */ +struct shub_freq_table { + u8 enable; + u32 freq_khz; +}; + +struct shub_freq_plan_entry { + u8 num_shub_freqs; + struct shub_freq_table shub_freq[MAX_SHUB_ENTRIES]; +}; + +struct ddr_xbl2quantum_smem_data { + phys_addr_t ssr_cookie_addr; + u32 reserved[10]; +}; + +struct ddr_freq_plan_v5 { + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V5]; + u8 num_ddr_freqs; + phys_addr_t clk_period_address; + u32 max_nom_ddr_freq; +}; + +struct ddr_region_v5 { + u64 start_address; + u64 size; + u64 mem_controller_address; + u32 granule_size; /* MiB */ + u8 ddr_rank; +#define DDR_RANK_0 BIT(0) +#define DDR_RANK_1 BIT(1) + u8 segments_start_index; + u64 segments_start_offset; +}; + +struct ddr_regions_v5 { + u32 ddr_region_num; /* We expect this to always be 4 or 6 */ + u64 ddr_rank0_size; + u64 ddr_rank1_size; + u64 ddr_cs0_start_addr; + u64 ddr_cs1_start_addr; + u32 highest_bank_addr_bit; + struct ddr_region_v5 ddr_region[] __counted_by(ddr_region_num); +}; + +struct ddr_details_v5 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v5 ddr_freq_tbl; + u8 num_channels; + u8 _padding; + struct ddr_regions_v5 ddr_regions; +}; + +/* V6 */ +struct ddr_misc_info_v6 { + u32 dsf_version; + u32 reserved[10]; +}; + +/* V7 */ +struct ddr_details_v7 { + u8 manufacturer_id; + u8 device_type; + struct ddr_part_details ddr_params[MAX_CHAN_NUM]; + struct ddr_freq_plan_v5 ddr_freq_tbl; + u8 num_channels; + u8 sct_config; + struct ddr_regions_v5 ddr_regions; +}; + +/** + * qcom_smem_dram_get_hbb(): Get the Highest bank address bit + * + * Context: Check qcom_smem_is_available() before calling this function. + * Because __dram * is initialized by smem_dram_parse(), which is in turn + * called from * qcom_smem_probe(), __dram will only be NULL if the data + * couldn't have been found/interpreted correctly. + * + * Return: 0 on success, -ENODATA on failure. + */ +int qcom_smem_dram_get_hbb(void) +{ + int hbb; + + if (!__dram) + return -ENODATA; + + hbb = __dram->hbb; + if (hbb == 0) + return -ENODATA; + else if (hbb < DDR_HBB_MIN || hbb > DDR_HBB_MAX) + return -EINVAL; + + return hbb; +} +EXPORT_SYMBOL_GPL(qcom_smem_dram_get_hbb); + +static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v3 *details = data; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V3; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +static void smem_dram_parse_v3_14freqs_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v3_14freqs *details = data; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V3 + 1; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +static void smem_dram_parse_v4_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v4 *details = data; + + /* Rank 0 channel 0 entry holds the correct value */ + dram->hbb = details->highest_bank_addr_bit[0][0]; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V3; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +static void smem_dram_parse_v5_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v5 *details = data; + struct ddr_regions_v5 *region = &details->ddr_regions; + + dram->hbb = region[0].highest_bank_addr_bit; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +static void smem_dram_parse_v7_data(struct smem_dram *dram, void *data) +{ + struct ddr_details_v7 *details = data; + struct ddr_regions_v5 *region = &details->ddr_regions; + + dram->hbb = region[0].highest_bank_addr_bit; + + for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) { + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i]; + + if (freq_entry->freq_khz && freq_entry->enabled) + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz; + } +} + +/* The structure contains no version field, so we have to perform some guesswork.. */ +static int smem_dram_infer_struct_version(size_t size) +{ + /* Some early versions provided less bytes of less useful data */ + if (size < sizeof(struct ddr_details_v3)) + return -EINVAL; + + if (size == sizeof(struct ddr_details_v3)) + return INFO_V3; + + if (size == sizeof(struct ddr_details_v3_14freqs)) + return INFO_V3_WITH_14_FREQS; + + if (size == sizeof(struct ddr_details_v4)) + return INFO_V4; + + if (size == sizeof(struct ddr_details_v5) + + 4 * sizeof(struct ddr_region_v5)) + return INFO_V5; + + if (size == sizeof(struct ddr_details_v5) + + 4 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_xbl2quantum_smem_data) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V5; + + if (size == sizeof(struct ddr_details_v5) + + 6 * sizeof(struct ddr_region_v5)) + return INFO_V5_WITH_6_REGIONS; + + if (size == sizeof(struct ddr_details_v5) + + 6 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_xbl2quantum_smem_data) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V5_WITH_6_REGIONS; + + if (size == sizeof(struct ddr_details_v5) + + 6 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_misc_info_v6) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V6; + + if (size == sizeof(struct ddr_details_v7) + + 4 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_misc_info_v6) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V7; + + if (size == sizeof(struct ddr_details_v7) + + 6 * sizeof(struct ddr_region_v5) + + sizeof(struct ddr_misc_info_v6) + + sizeof(struct shub_freq_plan_entry)) + return INFO_V7_WITH_6_REGIONS; + + return INFO_UNKNOWN; +} + +static int smem_dram_frequencies_show(struct seq_file *s, void *unused) +{ + struct smem_dram *dram = s->private; + + for (int i = 0; i < dram->num_frequencies; i++) + seq_printf(s, "%lu\n", dram->frequencies[i]); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(smem_dram_frequencies); + +static int smem_hbb_show(struct seq_file *s, void *unused) +{ + struct smem_dram *dram = s->private; + + if (!dram->hbb) + return -EINVAL; + + seq_printf(s, "%d\n", dram->hbb); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(smem_hbb); + +struct dentry *smem_dram_parse(struct device *dev) +{ + struct dentry *debugfs_dir; + enum ddr_info_version ver; + struct smem_dram *dram; + size_t actual_size; + void *data = NULL; + + /* No need to check qcom_smem_is_available(), this func is called by the SMEM driver */ + data = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_DDR_INFO_ID, &actual_size); + if (IS_ERR_OR_NULL(data)) + return ERR_PTR(-ENODATA); + + ver = smem_dram_infer_struct_version(actual_size); + if (ver < 0) { + /* Some SoCs don't provide data that's useful for us */ + return ERR_PTR(-ENODATA); + } else if (ver == INFO_UNKNOWN) { + /* In other cases, we may not have added support for a newer struct revision */ + pr_err("Found an unknown type of DRAM info struct (size = %zu)\n", actual_size); + return ERR_PTR(-EINVAL); + } + + dram = devm_kzalloc(dev, sizeof(*dram), GFP_KERNEL); + if (!dram) + return ERR_PTR(-ENOMEM); + + switch (ver) { + case INFO_V3: + smem_dram_parse_v3_data(dram, data); + break; + case INFO_V3_WITH_14_FREQS: + smem_dram_parse_v3_14freqs_data(dram, data); + break; + case INFO_V4: + smem_dram_parse_v4_data(dram, data); + break; + case INFO_V5: + case INFO_V5_WITH_6_REGIONS: + case INFO_V6: + smem_dram_parse_v5_data(dram, data); + break; + case INFO_V7: + case INFO_V7_WITH_6_REGIONS: + smem_dram_parse_v7_data(dram, data); + break; + default: + return ERR_PTR(-EINVAL); + } + + /* Both the entry and its parent dir will be cleaned up by debugfs_remove_recursive */ + debugfs_dir = debugfs_create_dir("qcom_smem", NULL); + debugfs_create_file("dram_frequencies", 0444, debugfs_dir, dram, + &smem_dram_frequencies_fops); + debugfs_create_file("hbb", 0444, debugfs_dir, dram, &smem_hbb_fops); + + /* If there was no failure so far, assign the global variable */ + __dram = dram; + + return debugfs_dir; +} diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index 021e9d1f61dc5..5d62076024567 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -15,6 +15,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "trace-smsm.h" + /* * This driver implements the Qualcomm Shared Memory State Machine, a mechanism * for communicating single bit state information to remote processors. @@ -54,7 +57,7 @@ * Default sizes, in case SMEM_SMSM_SIZE_INFO is not found. */ #define SMSM_DEFAULT_NUM_ENTRIES 8 -#define SMSM_DEFAULT_NUM_HOSTS 3 +#define SMSM_DEFAULT_NUM_HOSTS 5 struct smsm_entry; struct smsm_host; @@ -162,6 +165,9 @@ static int smsm_update_bits(void *data, u32 mask, u32 value) /* Don't signal if we didn't change the value */ changes = val ^ orig; + + trace_smsm_update_bits(smsm->dev, mask, value, orig, val, changes); + if (!changes) { spin_unlock_irqrestore(&smsm->lock, flags); goto done; @@ -182,6 +188,8 @@ static int smsm_update_bits(void *data, u32 mask, u32 value) if (!(val & changes)) continue; + trace_smsm_ipc_kick(smsm->dev, host, val); + if (hostp->mbox_chan) { mbox_send_message(hostp->mbox_chan, NULL); mbox_client_txdone(hostp->mbox_chan, 0); @@ -214,10 +222,14 @@ static irqreturn_t smsm_intr(int irq, void *data) unsigned i; int irq_pin; u32 changed; + u32 old; u32 val; val = readl(entry->remote_state); - changed = val ^ xchg(&entry->last_value, val); + old = xchg(&entry->last_value, val); + changed = val ^ old; + + trace_smsm_intr(irq, old, val, changed); for_each_set_bit(i, entry->irq_enabled, 32) { if (!(changed & BIT(i))) @@ -226,11 +238,13 @@ static irqreturn_t smsm_intr(int irq, void *data) if (val & BIT(i)) { if (test_bit(i, entry->irq_rising)) { irq_pin = irq_find_mapping(entry->domain, i); + trace_smsm_irq_cascade(irq_pin, i, true); handle_nested_irq(irq_pin); } } else { if (test_bit(i, entry->irq_falling)) { irq_pin = irq_find_mapping(entry->domain, i); + trace_smsm_irq_cascade(irq_pin, i, false); handle_nested_irq(irq_pin); } } @@ -257,6 +271,7 @@ static void smsm_mask_irq(struct irq_data *irqd) val = readl(entry->subscription + smsm->local_host); val &= ~BIT(irq); writel(val, entry->subscription + smsm->local_host); + trace_smsm_irq_mask(irq, true, val); } clear_bit(irq, entry->irq_enabled); @@ -288,6 +303,7 @@ static void smsm_unmask_irq(struct irq_data *irqd) val = readl(entry->subscription + smsm->local_host); val |= BIT(irq); writel(val, entry->subscription + smsm->local_host); + trace_smsm_irq_mask(irq, false, val); } } diff --git a/drivers/soc/qcom/trace-smsm.h b/drivers/soc/qcom/trace-smsm.h new file mode 100644 index 0000000000000..8b8c79972130f --- /dev/null +++ b/drivers/soc/qcom/trace-smsm.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM qcom_smsm + +#if !defined(__QCOM_SMSM_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) +#define __QCOM_SMSM_TRACE_H__ + +#include +#include + +/* + * Fired on every call to smsm_update_bits(), whether or not the state + * actually changed. changes == 0 indicates the write was a no-op because + * the bits were already in the requested state. + */ +TRACE_EVENT(smsm_update_bits, + TP_PROTO(const struct device *dev, u32 mask, u32 value, + u32 orig, u32 val, u32 changes), + TP_ARGS(dev, mask, value, orig, val, changes), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u32, mask) + __field(u32, value) + __field(u32, orig) + __field(u32, val) + __field(u32, changes) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->mask = mask; + __entry->value = value; + __entry->orig = orig; + __entry->val = val; + __entry->changes = changes; + ), + TP_printk("%s: mask:0x%08x value:0x%08x 0x%08x->0x%08x changed:0x%08x", + __get_str(dev_name), + __entry->mask, __entry->value, + __entry->orig, __entry->val, + __entry->changes) +); + +/* + * Fired for each remote host that is subscribed to the changed bits and + * is about to receive an IPC kick. + */ +TRACE_EVENT(smsm_ipc_kick, + TP_PROTO(const struct device *dev, u32 host, u32 subscription), + TP_ARGS(dev, host, subscription), + TP_STRUCT__entry( + __string(dev_name, dev_name(dev)) + __field(u32, host) + __field(u32, subscription) + ), + TP_fast_assign( + __assign_str(dev_name); + __entry->host = host; + __entry->subscription = subscription; + ), + TP_printk("%s: kick host %u subscription:0x%08x", + __get_str(dev_name), __entry->host, __entry->subscription) +); + +/* + * Fired at the top of smsm_intr() after reading the remote state and + * computing the changed bits. + */ +TRACE_EVENT(smsm_intr, + TP_PROTO(int irq, u32 old_state, u32 new_state, u32 changed), + TP_ARGS(irq, old_state, new_state, changed), + TP_STRUCT__entry( + __field(int, irq) + __field(u32, old_state) + __field(u32, new_state) + __field(u32, changed) + ), + TP_fast_assign( + __entry->irq = irq; + __entry->old_state = old_state; + __entry->new_state = new_state; + __entry->changed = changed; + ), + TP_printk("IRQ %d: 0x%08x->0x%08x changed:0x%08x", + __entry->irq, + __entry->old_state, __entry->new_state, + __entry->changed) +); + +/* + * Fired for each cascaded (per-bit) IRQ that is about to be dispatched + * to a downstream consumer (e.g. the BAM DMUX pc/pc-ack handler). + */ +TRACE_EVENT(smsm_irq_cascade, + TP_PROTO(int irq_pin, unsigned int bit, bool rising), + TP_ARGS(irq_pin, bit, rising), + TP_STRUCT__entry( + __field(int, irq_pin) + __field(unsigned int, bit) + __field(bool, rising) + ), + TP_fast_assign( + __entry->irq_pin = irq_pin; + __entry->bit = bit; + __entry->rising = rising; + ), + TP_printk("IRQ %d bit %u %s", + __entry->irq_pin, __entry->bit, + __entry->rising ? "rising" : "falling") +); + +/* + * Fired when a cascaded per-bit IRQ is masked or unmasked, recording the + * resulting subscription bitmap written to shared memory. + */ +TRACE_EVENT(smsm_irq_mask, + TP_PROTO(unsigned long irq, bool mask, u32 subscription), + TP_ARGS(irq, mask, subscription), + TP_STRUCT__entry( + __field(unsigned long, irq) + __field(bool, mask) + __field(u32, subscription) + ), + TP_fast_assign( + __entry->irq = irq; + __entry->mask = mask; + __entry->subscription = subscription; + ), + TP_printk("IRQ %lu %s subscription:0x%08x", + __entry->irq, + __entry->mask ? "masked" : "unmasked", + __entry->subscription) +); + +#endif /* __QCOM_SMSM_TRACE_H__ */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace-smsm + +#include diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c index 3fe47d8f0f638..01dca97e26714 100644 --- a/drivers/soc/qcom/ubwc_config.c +++ b/drivers/soc/qcom/ubwc_config.c @@ -278,6 +278,7 @@ static const struct of_device_id qcom_ubwc_configs[] __maybe_unused = { { .compatible = "qcom,sdm660", .data = &msm8937_data }, { .compatible = "qcom,sdm670", .data = &sdm670_data, }, { .compatible = "qcom,sdm845", .data = &sdm845_data, }, + { .compatible = "qcom,shikra", .data = &no_ubwc_data, }, { .compatible = "qcom,sm4250", .data = &sm6115_data, }, { .compatible = "qcom,sm6115", .data = &sm6115_data, }, { .compatible = "qcom,sm6125", .data = &sm6125_data, }, diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 3d8f5a81eff19..b5750b42e25cc 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -26,6 +26,7 @@ #define SWRM_COMP_STATUS 0x014 #define SWRM_LINK_MANAGER_EE 0x018 #define SWRM_EE_CPU 1 +#define SWRM_MAX_EE 1 #define SWRM_FRM_GEN_ENABLED BIT(0) #define SWRM_VERSION_1_3_0 0x01030000 #define SWRM_VERSION_1_5_1 0x01050001 @@ -118,6 +119,7 @@ #define SWRM_V2_0_CLK_CTRL 0x5060 #define SWRM_V2_0_CLK_CTRL_CLK_START BIT(0) #define SWRM_V2_0_LINK_STATUS 0x5064 +#define SWRM_V2_REG_EE_STRIDE 0x1000 #define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18 #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 @@ -160,6 +162,10 @@ struct qcom_swrm_port_config { u8 word_length; u8 blk_group_count; u8 lane_control; + u8 tx_ch_mask; + u8 rx_ch_mask; + bool tx_ch_map_valid; + bool rx_ch_map_valid; }; /* @@ -202,6 +208,7 @@ struct qcom_swrm_ctrl { struct mutex port_lock; struct clk *hclk; int irq; + u32 ee; unsigned int version; int wake_irq; int num_din_ports; @@ -222,6 +229,7 @@ struct qcom_swrm_ctrl { u32 slave_status; u32 wr_fifo_depth; bool clock_stop_not_supported; + unsigned int reg_layout_local[SWRM_OFFSET_DP_SAMPLECTRL2_BANK + 1]; }; struct qcom_swrm_data { @@ -328,6 +336,36 @@ static const struct qcom_swrm_data swrm_v3_0_data = { }; #define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus) +static void qcom_swrm_set_ee_register_layout(struct qcom_swrm_ctrl *ctrl, + const struct qcom_swrm_data *data) +{ + int ee_offset; + + memcpy(ctrl->reg_layout_local, data->reg_layout, + sizeof(ctrl->reg_layout_local)); + ctrl->reg_layout = ctrl->reg_layout_local; + + if (ctrl->version < SWRM_VERSION_2_0_0) + return; + + /* + * Current register constants map EE1. For EE0, use the EE register + * window stride to access status/IRQ/FIFO registers. + */ + ee_offset = ((int)ctrl->ee - SWRM_EE_CPU) * SWRM_V2_REG_EE_STRIDE; + if (!ee_offset) + return; + + ctrl->reg_layout_local[SWRM_REG_FRAME_GEN_ENABLED] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_INTERRUPT_STATUS] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_INTERRUPT_CLEAR] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_INTERRUPT_CPU_EN] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_WR_CMD] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_RD_CMD] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_STATUS] += ee_offset; + ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] += ee_offset; +} + static int qcom_swrm_ahb_reg_read(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val) { @@ -904,12 +942,13 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val); if (ctrl->version == SWRM_VERSION_1_7_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, - SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU); + SWRM_MCP_BUS_CLK_START << ctrl->ee); } else if (ctrl->version >= SWRM_VERSION_2_0_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); - ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL, + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); + ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL + + ((int)ctrl->ee - SWRM_EE_CPU) * SWRM_V2_REG_EE_STRIDE, SWRM_V2_0_CLK_CTRL_CLK_START); } else { ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); @@ -935,11 +974,9 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR], 0xFFFFFFFF); - /* enable CPU IRQs */ - if (ctrl->mmio) { - ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], - SWRM_INTERRUPT_STATUS_RMSK); - } + /* enable CPU IRQs for the selected EE window */ + ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN], + SWRM_INTERRUPT_STATUS_RMSK); /* Set IRQ to PULSE */ ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR, @@ -1109,12 +1146,28 @@ static int qcom_swrm_port_enable(struct sdw_bus *bus, { u32 reg; struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + struct qcom_swrm_port_config *pcfg; u32 val; u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK]; reg = SWRM_DPn_PORT_CTRL_BANK(offset, enable_ch->port_num, bank); ctrl->reg_read(ctrl, reg, &val); + pcfg = &ctrl->pconfig[enable_ch->port_num]; + + mutex_lock(&ctrl->port_lock); + if (enable_ch->port_num <= ctrl->num_dout_ports) { + if (pcfg->rx_ch_map_valid) + enable_ch->ch_mask = pcfg->rx_ch_mask; + else if (pcfg->tx_ch_map_valid) + enable_ch->ch_mask = pcfg->tx_ch_mask; + } else { + if (pcfg->tx_ch_map_valid) + enable_ch->ch_mask = pcfg->tx_ch_mask; + else if (pcfg->rx_ch_map_valid) + enable_ch->ch_mask = pcfg->rx_ch_mask; + } + mutex_unlock(&ctrl->port_lock); if (enable_ch->enable) val |= (enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); @@ -1334,6 +1387,39 @@ static void *qcom_swrm_get_sdw_stream(struct snd_soc_dai *dai, int direction) return ctrl->sruntime[dai->id]; } +static int qcom_swrm_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, const unsigned int *tx_slot, + unsigned int rx_num, const unsigned int *rx_slot) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + unsigned int max_ports = ctrl->nports; + unsigned int i; + + if ((tx_num && !tx_slot) || (rx_num && !rx_slot)) + return -EINVAL; + + mutex_lock(&ctrl->port_lock); + for (i = 1; i <= max_ports; i++) { + ctrl->pconfig[i].tx_ch_map_valid = false; + ctrl->pconfig[i].rx_ch_map_valid = false; + + /* TX setup */ + if (tx_slot && i < tx_num) { + ctrl->pconfig[i].tx_ch_mask = tx_slot[i]; + ctrl->pconfig[i].tx_ch_map_valid = true; + } + + /* RX setup */ + if (rx_slot && i < rx_num) { + ctrl->pconfig[i].rx_ch_mask = rx_slot[i]; + ctrl->pconfig[i].rx_ch_map_valid = true; + } + } + mutex_unlock(&ctrl->port_lock); + + return 0; +} + static int qcom_swrm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -1370,6 +1456,7 @@ static const struct snd_soc_dai_ops qcom_swrm_pdm_dai_ops = { .shutdown = qcom_swrm_shutdown, .set_stream = qcom_swrm_set_sdw_stream, .get_stream = qcom_swrm_get_sdw_stream, + .set_channel_map = qcom_swrm_set_channel_map, }; static const struct snd_soc_component_driver qcom_swrm_dai_component = { @@ -1545,7 +1632,22 @@ static int qcom_swrm_probe(struct platform_device *pdev) return -ENOMEM; data = of_device_get_match_data(dev); + ctrl->ee = SWRM_EE_CPU; + ret = of_property_read_u32(dev->of_node, "qcom,swr-master-ee-val", &ctrl->ee); + if (ret) + ret = of_property_read_u32(dev->of_node, "qcom,ee", &ctrl->ee); + if (ret) + ctrl->ee = SWRM_EE_CPU; + if (ctrl->ee > SWRM_MAX_EE) { + dev_warn(dev, "invalid SoundWire EE %u, using EE%u\n", + ctrl->ee, SWRM_EE_CPU); + ctrl->ee = SWRM_EE_CPU; + } ctrl->max_reg = data->max_reg; + /* + * Defer EE register window selection until HW version is known. + * For v2.0+ the IRQ/FIFO window is EE-banked. + */ ctrl->reg_layout = data->reg_layout; ctrl->rows_index = sdw_find_row_index(data->default_rows); ctrl->cols_index = sdw_find_col_index(data->default_cols); @@ -1623,6 +1725,7 @@ static int qcom_swrm_probe(struct platform_device *pdev) prop->default_row = data->default_rows; ctrl->reg_read(ctrl, SWRM_COMP_HW_VERSION, &ctrl->version); + qcom_swrm_set_ee_register_layout(ctrl, data); ret = devm_request_threaded_irq(dev, ctrl->irq, NULL, qcom_swrm_irq_handler, @@ -1724,24 +1827,26 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev) if (!swrm_wait_for_frame_gen_enabled(ctrl)) dev_err(ctrl->dev, "link failed to connect\n"); - /* wait for hw enumeration to complete */ - wait_for_completion_timeout(&ctrl->enumeration, - msecs_to_jiffies(TIMEOUT_MS)); - qcom_swrm_get_device_status(ctrl); - sdw_handle_slave_status(&ctrl->bus, ctrl->status); - } else { - reset_control_reset(ctrl->audio_cgcr); - - if (ctrl->version == SWRM_VERSION_1_7_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); - ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, - SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU); - } else if (ctrl->version >= SWRM_VERSION_2_0_0) { - ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU); - ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL, - SWRM_V2_0_CLK_CTRL_CLK_START); + /* wait for hw enumeration to complete */ + wait_for_completion_timeout(&ctrl->enumeration, + msecs_to_jiffies(TIMEOUT_MS)); + qcom_swrm_get_device_status(ctrl); + sdw_handle_slave_status(&ctrl->bus, ctrl->status); } else { - ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); + reset_control_reset(ctrl->audio_cgcr); + + if (ctrl->version == SWRM_VERSION_1_7_0) { + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); + ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, + SWRM_MCP_BUS_CLK_START << ctrl->ee); + } else if (ctrl->version >= SWRM_VERSION_2_0_0) { + ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); + ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL + + ((int)ctrl->ee - SWRM_EE_CPU) * + SWRM_V2_REG_EE_STRIDE, + SWRM_V2_0_CLK_CTRL_CLK_START); + } else { + ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); } ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR], SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET); diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig index a6bb01082ec69..2d6df24e676ba 100644 --- a/drivers/thermal/qcom/Kconfig +++ b/drivers/thermal/qcom/Kconfig @@ -21,6 +21,26 @@ config QCOM_SPMI_ADC_TM5 Thermal client sets threshold temperature for both warm and cool and gets updated when a threshold is reached. +config QCOM_SPMI_ADC_TM5_GEN3 + tristate "Qualcomm SPMI PMIC Thermal Monitor ADC5 Gen3" + depends on QCOM_SPMI_ADC5_GEN3 + help + This enables the auxiliary thermal driver for the ADC5 Gen3 thermal + monitoring device. It shows up as a thermal zone with multiple trip points. + Thermal client sets threshold temperature for both warm and cool and + gets updated when a threshold is reached. + +config QCOM_SPMI_MBG_TM + tristate "Qualcomm SPMI PMIC MBG Temperature monitor" + depends on QCOM_SPMI_ADC5_GEN3 + select REGMAP_SPMI + help + This enables a thermal driver for the MBG thermal monitoring device. + It shows up in sysfs as a thermal sensor with single trip point. + It notifies the thermal framework when this trip is violated. The + temperature reported by the thermal sensor reflects the real + time die temperature through ADC channel. + config QCOM_SPMI_TEMP_ALARM tristate "Qualcomm SPMI PMIC Temperature Alarm" depends on OF && SPMI && IIO diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile index 0fa2512042e78..937ba0fe28013 100644 --- a/drivers/thermal/qcom/Makefile +++ b/drivers/thermal/qcom/Makefile @@ -4,5 +4,7 @@ obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o qcom_tsens-y += tsens.o tsens-v2.o tsens-v1.o tsens-v0_1.o \ tsens-8960.o obj-$(CONFIG_QCOM_SPMI_ADC_TM5) += qcom-spmi-adc-tm5.o +obj-$(CONFIG_QCOM_SPMI_ADC_TM5_GEN3) += qcom-spmi-adc-tm5-gen3.o +obj-$(CONFIG_QCOM_SPMI_MBG_TM) += qcom-spmi-mbg-tm.o obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o obj-$(CONFIG_QCOM_LMH) += lmh.o diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c new file mode 100644 index 0000000000000..633008f173a8a --- /dev/null +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../thermal_hwmon.h" + +#define ADC_TM5_GEN3_CONFIG_REGS 12 + +struct device; +struct adc_tm5_gen3_chip; + +/** + * struct adc_tm5_gen3_channel_props - ADC_TM channel structure + * @timer: time period of recurring TM measurement. + * @tm_chan_index: TM channel number used (ranging from 1-7). + * @sdam_index: SDAM on which this TM channel lies. + * @common_props: structure with common ADC channel properties. + * @high_thr_en: TM high threshold crossing detection enabled. + * @low_thr_en: TM low threshold crossing detection enabled. + * @chip: ADC TM device. + * @tzd: pointer to thermal device corresponding to TM channel. + */ +struct adc_tm5_gen3_channel_props { + unsigned int timer; + unsigned int tm_chan_index; + unsigned int sdam_index; + struct adc5_channel_common_prop common_props; + bool high_thr_en; + bool low_thr_en; + struct adc_tm5_gen3_chip *chip; + struct thermal_zone_device *tzd; +}; + +/** + * struct adc_tm5_gen3_chip - ADC Thermal Monitoring device structure + * @dev_data: Top-level ADC device data. + * @chan_props: Array of ADC_TM channel structures. + * @nchannels: number of TM channels allocated + * @dev: SPMI ADC5 Gen3 device. + */ +struct adc_tm5_gen3_chip { + struct adc5_device_data *dev_data; + struct adc_tm5_gen3_channel_props *chan_props; + unsigned int nchannels; + struct device *dev; +}; + +DEFINE_GUARD(adc5_gen3, struct adc_tm5_gen3_chip *, adc5_gen3_mutex_lock(_T->dev), + adc5_gen3_mutex_unlock(_T->dev)) + +static int get_sdam_from_irq(struct adc_tm5_gen3_chip *adc_tm5, int irq) +{ + for (int i = 0; i < adc_tm5->dev_data->num_sdams; i++) { + if (adc_tm5->dev_data->base[i].irq == irq) + return i; + } + return -ENOENT; +} + +static irqreturn_t adctm5_gen3_isr(int irq, void *dev_id) +{ + struct adc_tm5_gen3_chip *adc_tm5 = dev_id; + int ret, sdam_num; + u8 tm_status[2]; + u8 status, val; + + sdam_num = get_sdam_from_irq(adc_tm5, irq); + if (sdam_num < 0) + return IRQ_NONE; + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_num, ADC5_GEN3_STATUS1, + &status, sizeof(status)); + if (ret) + return IRQ_NONE; + + if (status & ADC5_GEN3_STATUS1_CONV_FAULT) { + val = ADC5_GEN3_CONV_ERR_CLR_REQ; + adc5_gen3_status_clear(adc_tm5->dev_data, sdam_num, + ADC5_GEN3_CONV_ERR_CLR, &val, 1); + return IRQ_HANDLED; + } + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_num, ADC5_GEN3_TM_HIGH_STS, + tm_status, sizeof(tm_status)); + if (ret) + return IRQ_NONE; + + if (tm_status[0] || tm_status[1]) + return IRQ_WAKE_THREAD; + + return IRQ_NONE; +} + +static int adc5_gen3_tm_status_check(struct adc_tm5_gen3_chip *adc_tm5, + int sdam_index, u8 *tm_status, u8 *buf) +{ + int ret; + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_index, ADC5_GEN3_TM_HIGH_STS, + tm_status, 2); + if (ret) + return ret; + + ret = adc5_gen3_status_clear(adc_tm5->dev_data, sdam_index, ADC5_GEN3_TM_HIGH_STS_CLR, + tm_status, 2); + if (ret) + return ret; + + ret = adc5_gen3_read(adc_tm5->dev_data, sdam_index, ADC5_GEN3_CH_DATA0(0), + buf, 16); + return ret; +} + +static irqreturn_t adctm5_gen3_isr_thread(int irq, void *dev_id) +{ + struct adc_tm5_gen3_chip *adc_tm5 = dev_id; + int sdam_index = -1; + u8 tm_status[2] = { }; + u8 buf[16] = { }; + + for (int i = 0; i < adc_tm5->nchannels; i++) { + struct adc_tm5_gen3_channel_props *chan_prop = &adc_tm5->chan_props[i]; + int offset = chan_prop->tm_chan_index; + bool upper_set, lower_set; + int ret; + + scoped_guard(adc5_gen3, adc_tm5) { + if (chan_prop->sdam_index != sdam_index) { + sdam_index = chan_prop->sdam_index; + ret = adc5_gen3_tm_status_check(adc_tm5, sdam_index, + tm_status, buf); + if (ret) + return IRQ_NONE; + } + + upper_set = ((tm_status[0] & BIT(offset)) && chan_prop->high_thr_en); + lower_set = ((tm_status[1] & BIT(offset)) && chan_prop->low_thr_en); + } + + if (!(upper_set || lower_set)) + continue; + + thermal_zone_device_update(chan_prop->tzd, THERMAL_TRIP_VIOLATED); + } + + return IRQ_HANDLED; +} + +static int adc_tm5_gen3_get_temp(struct thermal_zone_device *tz, int *temp) +{ + struct adc_tm5_gen3_channel_props *prop = thermal_zone_device_priv(tz); + struct adc_tm5_gen3_chip *adc_tm5; + + if (!prop || !prop->chip) + return -EINVAL; + + adc_tm5 = prop->chip; + + return adc5_gen3_get_scaled_reading(adc_tm5->dev, &prop->common_props, + temp); +} + +static int adc_tm5_gen3_disable_channel(struct adc_tm5_gen3_channel_props *prop) +{ + struct adc_tm5_gen3_chip *adc_tm5 = prop->chip; + int ret; + u8 val; + + prop->high_thr_en = false; + prop->low_thr_en = false; + + ret = adc5_gen3_poll_wait_hs(adc_tm5->dev_data, prop->sdam_index); + if (ret) + return ret; + + val = BIT(prop->tm_chan_index); + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_TM_HIGH_STS_CLR, &val, sizeof(val)); + if (ret) + return ret; + + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_TM_LOW_STS_CLR, &val, sizeof(val)); + if (ret) + return ret; + + val = MEAS_INT_DISABLE; + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_TIMER_SEL, &val, sizeof(val)); + if (ret) + return ret; + + /* To indicate there is an actual conversion request */ + val = ADC5_GEN3_CHAN_CONV_REQ | prop->tm_chan_index; + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_PERPH_CH, &val, sizeof(val)); + if (ret) + return ret; + + val = ADC5_GEN3_CONV_REQ_REQ; + return adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_CONV_REQ, &val, sizeof(val)); +} + +static int adc_tm5_gen3_configure(struct adc_tm5_gen3_channel_props *prop, + int low_temp, int high_temp) +{ + struct adc_tm5_gen3_chip *adc_tm5 = prop->chip; + u8 buf[ADC_TM5_GEN3_CONFIG_REGS]; + u8 conv_req; + u16 adc_code; + int ret; + + ret = adc5_gen3_poll_wait_hs(adc_tm5->dev_data, prop->sdam_index); + if (ret < 0) + return ret; + + ret = adc5_gen3_read(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_SID, buf, sizeof(buf)); + if (ret < 0) + return ret; + + /* Write SID */ + buf[0] = FIELD_PREP(ADC5_GEN3_SID_MASK, prop->common_props.sid); + + /* Select TM channel and indicate there is an actual conversion request */ + buf[1] = ADC5_GEN3_CHAN_CONV_REQ | prop->tm_chan_index; + + buf[2] = prop->timer; + + /* Digital param selection */ + adc5_gen3_update_dig_param(&prop->common_props, &buf[3]); + + /* Update fast average sample value */ + buf[4] &= ~ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK; + buf[4] |= prop->common_props.avg_samples | ADC5_GEN3_FAST_AVG_CTL_EN; + + /* Select ADC channel */ + buf[5] = prop->common_props.channel; + + /* Select HW settle delay for channel */ + buf[6] = FIELD_PREP(ADC5_GEN3_HW_SETTLE_DELAY_MASK, + prop->common_props.hw_settle_time_us); + + /* High temperature corresponds to low voltage threshold */ + prop->low_thr_en = (high_temp != INT_MAX); + if (prop->low_thr_en) { + adc_code = qcom_adc_tm5_gen2_temp_res_scale(high_temp); + put_unaligned_le16(adc_code, &buf[8]); + } + + /* Low temperature corresponds to high voltage threshold */ + prop->high_thr_en = (low_temp != -INT_MAX); + if (prop->high_thr_en) { + adc_code = qcom_adc_tm5_gen2_temp_res_scale(low_temp); + put_unaligned_le16(adc_code, &buf[10]); + } + + buf[7] = 0; + if (prop->high_thr_en) + buf[7] |= ADC5_GEN3_HIGH_THR_INT_EN; + if (prop->low_thr_en) + buf[7] |= ADC5_GEN3_LOW_THR_INT_EN; + + ret = adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, ADC5_GEN3_SID, + buf, sizeof(buf)); + if (ret < 0) + return ret; + + conv_req = ADC5_GEN3_CONV_REQ_REQ; + return adc5_gen3_write(adc_tm5->dev_data, prop->sdam_index, + ADC5_GEN3_CONV_REQ, &conv_req, sizeof(conv_req)); +} + +static int adc_tm5_gen3_set_trip_temp(struct thermal_zone_device *tz, + int low_temp, int high_temp) +{ + struct adc_tm5_gen3_channel_props *prop = thermal_zone_device_priv(tz); + struct adc_tm5_gen3_chip *adc_tm5; + + if (!prop || !prop->chip) + return -EINVAL; + + adc_tm5 = prop->chip; + + dev_dbg(adc_tm5->dev, "channel:%s, low_temp(mdegC):%d, high_temp(mdegC):%d\n", + prop->common_props.label, low_temp, high_temp); + + guard(adc5_gen3)(adc_tm5); + + return adc_tm5_gen3_configure(prop, low_temp, high_temp); +} + +static const struct thermal_zone_device_ops adc_tm_ops = { + .get_temp = adc_tm5_gen3_get_temp, + .set_trips = adc_tm5_gen3_set_trip_temp, +}; + +static int adc_tm5_register_tzd(struct adc_tm5_gen3_chip *adc_tm5) +{ + struct thermal_zone_device *tzd; + unsigned int channel; + int ret; + + for (int i = 0; i < adc_tm5->nchannels; i++) { + channel = ADC5_GEN3_V_CHAN(adc_tm5->chan_props[i].common_props); + tzd = devm_thermal_of_zone_register(adc_tm5->dev, channel, + &adc_tm5->chan_props[i], + &adc_tm_ops); + if (IS_ERR(tzd)) { + if (PTR_ERR(tzd) == -ENODEV) { + dev_info(adc_tm5->dev, + "thermal sensor on channel %d is not used\n", + channel); + continue; + } + return dev_err_probe(adc_tm5->dev, PTR_ERR(tzd), + "Error registering TZ zone:%ld for channel:%d\n", + PTR_ERR(tzd), channel); + } + adc_tm5->chan_props[i].tzd = tzd; + ret = devm_thermal_add_hwmon_sysfs(adc_tm5->dev, tzd); + if (ret) + return ret; + } + return 0; +} + +static void adc5_gen3_disable(void *data) +{ + struct adc_tm5_gen3_chip *adc_tm5 = data; + + guard(adc5_gen3)(adc_tm5); + /* Disable all available TM channels */ + for (int i = 0; i < adc_tm5->nchannels; i++) + adc_tm5_gen3_disable_channel(&adc_tm5->chan_props[i]); +} + +static int adc_tm5_probe(struct auxiliary_device *aux_dev, + const struct auxiliary_device_id *id) +{ + struct adc_tm5_gen3_chip *adc_tm5; + struct tm5_aux_dev_wrapper *aux_dev_wrapper; + struct device *dev = &aux_dev->dev; + int ret; + + adc_tm5 = devm_kzalloc(dev, sizeof(*adc_tm5), GFP_KERNEL); + if (!adc_tm5) + return -ENOMEM; + + aux_dev_wrapper = container_of(aux_dev, struct tm5_aux_dev_wrapper, + aux_dev); + + adc_tm5->dev = dev; + adc_tm5->dev_data = aux_dev_wrapper->dev_data; + adc_tm5->nchannels = aux_dev_wrapper->n_tm_channels; + adc_tm5->chan_props = devm_kcalloc(dev, aux_dev_wrapper->n_tm_channels, + sizeof(*adc_tm5->chan_props), GFP_KERNEL); + if (!adc_tm5->chan_props) + return -ENOMEM; + + for (int i = 0; i < adc_tm5->nchannels; i++) { + adc_tm5->chan_props[i].common_props = aux_dev_wrapper->tm_props[i]; + adc_tm5->chan_props[i].timer = MEAS_INT_1S; + adc_tm5->chan_props[i].sdam_index = (i + 1) / 8; + adc_tm5->chan_props[i].tm_chan_index = (i + 1) % 8; + adc_tm5->chan_props[i].chip = adc_tm5; + } + + /* This is to disable all ADC_TM channels in case of probe failure. */ + ret = devm_add_action(dev, adc5_gen3_disable, adc_tm5); + if (ret) + return ret; + + /* + * First SDAM's interrupt is shared between main ADC driver + * and auxiliary TM driver, so its flags must include + * IRQF_SHARED. This is not needed for other SDAMs as they + * will be used only for TM functionality. + */ + + ret = devm_request_threaded_irq(dev, + adc_tm5->dev_data->base[0].irq, + adctm5_gen3_isr, adctm5_gen3_isr_thread, + IRQF_ONESHOT | IRQF_SHARED, + adc_tm5->dev_data->base[0].irq_name, + adc_tm5); + if (ret < 0) + return ret; + + for (int i = 1; i < adc_tm5->dev_data->num_sdams; i++) { + ret = devm_request_threaded_irq(dev, + adc_tm5->dev_data->base[i].irq, + adctm5_gen3_isr, adctm5_gen3_isr_thread, + IRQF_ONESHOT, adc_tm5->dev_data->base[i].irq_name, + adc_tm5); + if (ret < 0) + return ret; + } + + return adc_tm5_register_tzd(adc_tm5); +} + +static const struct auxiliary_device_id adctm5_auxiliary_id_table[] = { + { .name = "qcom_spmi_adc5_gen3.adc5_tm_gen3", }, + { } +}; + +MODULE_DEVICE_TABLE(auxiliary, adctm5_auxiliary_id_table); + +static struct auxiliary_driver adctm5gen3_auxiliary_driver = { + .id_table = adctm5_auxiliary_id_table, + .probe = adc_tm5_probe, +}; + +module_auxiliary_driver(adctm5gen3_auxiliary_driver); + +MODULE_DESCRIPTION("SPMI PMIC Thermal Monitor ADC driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("QCOM_SPMI_ADC5_GEN3"); diff --git a/drivers/thermal/qcom/qcom-spmi-mbg-tm.c b/drivers/thermal/qcom/qcom-spmi-mbg-tm.c new file mode 100644 index 0000000000000..60190b341fc7c --- /dev/null +++ b/drivers/thermal/qcom/qcom-spmi-mbg-tm.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MBG_TEMP_MON2_FAULT_STATUS 0x50 + +#define MON_FAULT_STATUS_MASK GENMASK(7, 4) +#define MON_FAULT_LVL1_UPR 0x5 + +#define MON2_LVL1_UP_THRESH 0x59 + +#define MBG_TEMP_MON2_MISC_CFG 0x5f +#define MON2_UP_THRESH_EN BIT(1) + +#define MBG_TEMP_STEP_MV 8 +#define MBG_TEMP_DEFAULT_TEMP_MV 600 +#define MBG_TEMP_CONSTANT 1000 +#define MBG_MIN_TRIP_TEMP 25000 +#define MBG_MAX_SUPPORTED_TEMP 160000 + +/** + * struct mbg_tm_chip - MBG thermal monitor device data. + * @map: regmap for accessing MBG thermal registers. + * @dev: mbg_tm_chip device. + * @tz_dev: thermal zone device registered with the thermal framework. + * @lock: mbg_tm_chip lock for set trip temperature. + * @base: base register offset for this MBG instance + * @irq: interrupt line used to signal threshold events + * @last_temp: last measured temperature. + * @last_thres_crossed: indicates whether the last interrupt crossed a threshold + * @adc: IIO ADC channel used for temperature sensing + */ +struct mbg_tm_chip { + struct regmap *map; + struct device *dev; + struct thermal_zone_device *tz_dev; + struct mutex lock; + unsigned int base; + int irq; + int last_temp; + bool last_thres_crossed; + struct iio_channel *adc; +}; + +/** + * struct mbg_map_table - temperature to voltage mapping entry + * @min_temp: minimum temperature supported by this mapping entry + * @vtemp0: reference voltage or ADC code corresponding to the temperature + * @tc: temperature coefficient used for conversion calculations + */ +struct mbg_map_table { + int min_temp; + int vtemp0; + int tc; +}; + +static const struct mbg_map_table map_table[] = { + /* minT vtemp0 tc */ + { -60000, 4337, 1967 }, + { -40000, 4731, 1964 }, + { -20000, 5124, 1957 }, + { 0, 5515, 1949 }, + { 20000, 5905, 1940 }, + { 40000, 6293, 1930 }, + { 60000, 6679, 1921 }, + { 80000, 7064, 1910 }, + { 100000, 7446, 1896 }, + { 120000, 7825, 1878 }, + { 140000, 8201, 1859 }, +}; + +static int mbg_tm_get_temp(struct thermal_zone_device *tz, int *temp) +{ + struct mbg_tm_chip *chip = thermal_zone_device_priv(tz); + int ret, milli_celsius; + + if (chip->last_thres_crossed) { + dev_dbg(chip->dev, "last_temp: %d\n", chip->last_temp); + chip->last_thres_crossed = false; + *temp = chip->last_temp; + return 0; + } + + ret = iio_read_channel_processed(chip->adc, &milli_celsius); + if (ret < 0) { + dev_err(chip->dev, "Failed to read iio channel with %d\n", ret); + return ret; + } + + *temp = milli_celsius; + + return 0; +} + +static int temp_to_vtemp_mv(int temp) +{ + int idx, vtemp, tc = 0, t0 = 0, vtemp0 = 0; + + for (idx = 0; idx < ARRAY_SIZE(map_table); idx++) + if (temp >= map_table[idx].min_temp && + temp < (map_table[idx].min_temp + 20000)) { + tc = map_table[idx].tc; + t0 = map_table[idx].min_temp; + vtemp0 = map_table[idx].vtemp0; + break; + } + + /* + * Formula to calculate vtemp(mV) from a given temp + * vtemp = (temp - minT) * tc + vtemp0 + * tc, t0 and vtemp0 values are mentioned in the map_table array. + */ + vtemp = ((temp - t0) * tc + vtemp0 * 100000) / 1000000; + + /* step size is 8mV */ + return abs(vtemp - MBG_TEMP_DEFAULT_TEMP_MV) / MBG_TEMP_STEP_MV; +} + +static int mbg_tm_set_trip_temp(struct thermal_zone_device *tz, int low_temp, + int temp) +{ + struct mbg_tm_chip *chip = thermal_zone_device_priv(tz); + int ret = 0; + + guard(mutex)(&chip->lock); + + /* The HW has a limitation that the trip set must be above 25C */ + if (temp > MBG_MIN_TRIP_TEMP && temp < MBG_MAX_SUPPORTED_TEMP) { + ret = regmap_set_bits(chip->map, chip->base + MBG_TEMP_MON2_MISC_CFG, + MON2_UP_THRESH_EN); + if (ret < 0) + return ret; + + ret = regmap_write(chip->map, chip->base + MON2_LVL1_UP_THRESH, + temp_to_vtemp_mv(temp)); + if (ret < 0) + return ret; + } else { + dev_dbg(chip->dev, "Set trip b/w 25C and 160C\n"); + ret = regmap_clear_bits(chip->map, chip->base + MBG_TEMP_MON2_MISC_CFG, + MON2_UP_THRESH_EN); + return ret; + } + + /* + * Configure the last_temp one degree higher, to ensure the + * violated temp is returned to thermal framework when it reads + * temperature for the first time after the violation happens. + * This is needed to account for the inaccuracy in the conversion + * formula used which leads to the thermal framework setting back + * the same thresholds in case the temperature it reads does not + * show violation. + */ + chip->last_temp = temp + MBG_TEMP_CONSTANT; + + return ret; +} + +static const struct thermal_zone_device_ops mbg_tm_ops = { + .get_temp = mbg_tm_get_temp, + .set_trips = mbg_tm_set_trip_temp, +}; + +static irqreturn_t mbg_tm_isr(int irq, void *data) +{ + struct mbg_tm_chip *chip = data; + int ret, val; + + scoped_guard(mutex, &chip->lock) { + ret = regmap_read(chip->map, chip->base + MBG_TEMP_MON2_FAULT_STATUS, &val); + if (ret < 0) + return IRQ_HANDLED; + } + + if (FIELD_GET(MON_FAULT_STATUS_MASK, val) & MON_FAULT_LVL1_UPR) { + chip->last_thres_crossed = true; + dev_dbg(chip->dev, "Notifying Thermal, fault status=%d\n", val); + thermal_zone_device_update(chip->tz_dev, THERMAL_TRIP_VIOLATED); + } else { + dev_dbg(chip->dev, "Lvl1 upper threshold not violated, ignoring interrupt\n"); + } + + return IRQ_HANDLED; +} + +static int mbg_tm_probe(struct platform_device *pdev) +{ + struct mbg_tm_chip *chip; + struct device_node *node = pdev->dev.of_node; + u32 res; + int ret; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = &pdev->dev; + + mutex_init(&chip->lock); + + chip->map = dev_get_regmap(pdev->dev.parent, NULL); + if (!chip->map) + return -ENXIO; + + ret = device_property_read_u32(chip->dev, "reg", &res); + if (ret < 0) + return dev_err_probe(chip->dev, ret, "Couldn't read reg property\n"); + + chip->base = res; + + chip->irq = platform_get_irq(pdev, 0); + if (chip->irq < 0) + return dev_err_probe(chip->dev, chip->irq, "Failed to get irq\n"); + + chip->adc = devm_iio_channel_get(&pdev->dev, "thermal"); + if (IS_ERR(chip->adc)) + return dev_err_probe(chip->dev, PTR_ERR(chip->adc), "Failed to get adc channel\n"); + + chip->tz_dev = devm_thermal_of_zone_register(chip->dev, 0, chip, &mbg_tm_ops); + if (IS_ERR(chip->tz_dev)) + return dev_err_probe(chip->dev, PTR_ERR(chip->tz_dev), + "Failed to register sensor\n"); + + return devm_request_threaded_irq(&pdev->dev, chip->irq, NULL, mbg_tm_isr, IRQF_ONESHOT, + node->name, chip); +} + +static const struct of_device_id mbg_tm_match_table[] = { + { .compatible = "qcom,pm8775-mbg-tm" }, + { } +}; +MODULE_DEVICE_TABLE(of, mbg_tm_match_table); + +static struct platform_driver mbg_tm_driver = { + .driver = { + .name = "qcom-spmi-mbg-tm", + .of_match_table = mbg_tm_match_table, + }, + .probe = mbg_tm_probe, +}; +module_platform_driver(mbg_tm_driver); + +MODULE_DESCRIPTION("PMIC MBG Temperature monitor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 7ead87b4eb65b..ad69976555b86 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1974,6 +1974,7 @@ static int qcom_geni_serial_suspend(struct device *dev) struct qcom_geni_serial_port *port = dev_get_drvdata(dev); struct uart_port *uport = &port->uport; struct qcom_geni_private_data *private_data = uport->private_data; + int ret; /* * This is done so we can hit the lowest possible state in suspend @@ -1983,7 +1984,19 @@ static int qcom_geni_serial_suspend(struct device *dev) geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ACTIVE_ONLY); geni_icc_set_bw(&port->se); } - return uart_suspend_port(private_data->drv, uport); + + ret = uart_suspend_port(private_data->drv, uport); + if (ret) + return ret; + + /* + * When no_console_suspend is set the console must remain active + * across system sleep, so skip the force suspend path. + */ + if (uart_console(uport) && !uport->suspended) + return 0; + + return pm_runtime_force_suspend(dev); } static int qcom_geni_serial_resume(struct device *dev) @@ -1993,6 +2006,10 @@ static int qcom_geni_serial_resume(struct device *dev) struct uart_port *uport = &port->uport; struct qcom_geni_private_data *private_data = uport->private_data; + ret = pm_runtime_force_resume(dev); + if (ret) + return ret; + ret = uart_resume_port(private_data->drv, uport); if (uart_console(uport)) { geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ALWAYS); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index d3044a3089b53..f9fbd4cee367a 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -120,7 +120,7 @@ static bool is_mcq_supported(struct ufs_hba *hba) module_param(use_mcq_mode, bool, 0644); MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default"); -static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_DEFAULT; +static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_MAX; static int uic_cmd_timeout_set(const char *val, const struct kernel_param *kp) { diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 291c434487648..f605b3c73114b 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -770,9 +770,17 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, if (!ufs_qcom_is_link_active(hba)) ufs_qcom_disable_lane_clks(host); - - /* reset the connected UFS device during power down */ - if (ufs_qcom_is_link_off(hba) && host->device_reset) { + /* + * For some UFS vendors, skip asserting device reset here. + * These vendor parts keep drawing larger current after reset + * is asserted until it is deasserted, and the 10ms delay is + * not sufficient to prevent OCP (Over Current Protection) + * on the regulator. This is for the powerdown case, so + * the device reset can be asserted later as part of the + * platform shutdown sequence. + */ + if (ufs_qcom_is_link_off(hba) && host->device_reset && + !(hba->quirks & UFSHCD_QUIRK_SKIP_DEVICE_RESET)) { ufs_qcom_device_reset_ctrl(hba, true); /* * After sending the SSU command, asserting the rst_n @@ -1288,6 +1296,19 @@ static struct ufs_dev_quirk ufs_qcom_dev_fixups[] = { static void ufs_qcom_fixup_dev_quirks(struct ufs_hba *hba) { ufshcd_fixup_dev_quirks(hba, ufs_qcom_dev_fixups); + + /* + * Some UFS parts keep drawing larger current after reset is asserted + * until it is deasserted. The 10ms delay added after asserting HWRST + * (as done for other vendors) is not sufficient for these parts. + * + * Skip asserting device reset during UFS power down for these parts + * to prevent OCP (Over Current Protection) fault on the regulator. + * This is handled only in shutdown; the device reset will be asserted + * as part of the platform shutdown sequence. + */ + if (hba->dev_info.wmanufacturerid == UFS_VENDOR_MICRON) + hba->quirks |= UFSHCD_QUIRK_SKIP_DEVICE_RESET; } static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) @@ -2282,7 +2303,7 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, p->polling_ms = 60; p->timer = DEVFREQ_TIMER_DELAYED; d->upthreshold = 70; - d->downdifferential = 5; + d->downdifferential = 65; hba->clk_scaling.suspend_on_no_request = true; } diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 18169727a413e..ae03ae45e50e4 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -132,6 +132,7 @@ config USB_DWC3_QCOM depends on ARCH_QCOM || COMPILE_TEST depends on EXTCON || !EXTCON depends on OF + depends on USB_QCOM_EUD || !USB_QCOM_EUD default USB_DWC3 help Some Qualcomm SoCs use DesignWare Core IP for USB2/3 diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index f43f73ac36ff1..dc830f5aa25bc 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,7 +19,9 @@ #include #include #include +#include #include +#include #include "core.h" #include "glue.h" @@ -60,6 +63,10 @@ static const u32 pwr_evnt_irq_stat_reg[DWC3_QCOM_MAX_PORTS] = { 0x238, }; +struct dwc3_qcom_platform_data { + bool uses_eusb2_phy; +}; + struct dwc3_qcom_port { int qusb2_phy_irq; int dp_hs_phy_irq; @@ -85,6 +92,7 @@ struct dwc3_qcom { struct icc_path *icc_path_apps; enum usb_role current_role; + bool uses_eusb2_phy; }; #define to_dwc3_qcom(d) container_of((d), struct dwc3_qcom, dwc) @@ -272,15 +280,23 @@ static void dwc3_qcom_disable_wakeup_irq(int irq) disable_irq_nosync(irq); } -static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_disable_wakeup_irq(port->qusb2_phy_irq); if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + if (qcom->uses_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + if (qcom->uses_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); } else { dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); @@ -289,8 +305,10 @@ static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) dwc3_qcom_disable_wakeup_irq(port->ss_phy_irq); } -static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_enable_wakeup_irq(port->qusb2_phy_irq, 0); /* @@ -303,12 +321,20 @@ static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) */ if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->uses_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->uses_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else { dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, IRQ_TYPE_EDGE_RISING); @@ -324,7 +350,7 @@ static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_disable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_disable_port_interrupts(qcom, i); } static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) @@ -332,7 +358,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_enable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_enable_port_interrupts(qcom, i); } static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) @@ -362,6 +388,8 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) for (i = 0; i < qcom->num_ports; i++) qcom->ports[i].usb2_speed = dwc3_qcom_read_usb2_speed(qcom, i); dwc3_qcom_enable_interrupts(qcom); + } else { + dev_pm_genpd_synced_poweroff(qcom->dev); } qcom->is_suspended = true; @@ -561,6 +589,7 @@ static int dwc3_qcom_setup_irq(struct dwc3_qcom *qcom, struct platform_device *p static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_role) { struct dwc3_qcom *qcom = to_dwc3_qcom(dwc); + struct device_node *eud_node; if (qcom->current_role == next_role) return; @@ -570,6 +599,13 @@ static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_rol return; } + /* Notify EUD of role change */ + eud_node = of_graph_get_remote_node(qcom->dev->of_node, 0, -1); + if (eud_node) { + qcom_eud_usb_role_notify(eud_node, dwc->usb2_generic_phy[0], next_role); + of_node_put(eud_node); + } + if (qcom->current_role == USB_ROLE_DEVICE) dwc3_qcom_vbus_override_enable(qcom, false); else if (qcom->current_role != USB_ROLE_DEVICE) @@ -609,6 +645,7 @@ struct dwc3_glue_ops dwc3_qcom_glue_ops = { static int dwc3_qcom_probe(struct platform_device *pdev) { + const struct dwc3_qcom_platform_data *pdata; struct dwc3_probe_data probe_data = {}; struct device *dev = &pdev->dev; struct dwc3_qcom *qcom; @@ -624,6 +661,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) qcom->dev = &pdev->dev; + pdata = device_get_match_data(dev); + if (pdata) + qcom->uses_eusb2_phy = pdata->uses_eusb2_phy; + qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); if (IS_ERR(qcom->resets)) { return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets), @@ -838,8 +879,52 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { .prepare = pm_sleep_ptr(dwc3_qcom_prepare), }; +static const struct dwc3_qcom_platform_data dwc3_qcom_glymur_pdata = { + .uses_eusb2_phy = true, +}; + static const struct of_device_id dwc3_qcom_of_match[] = { - { .compatible = "qcom,snps-dwc3" }, + { .compatible = "qcom,snps-dwc3", }, + { + .compatible = "qcom,eliza-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,glymur-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,glymur-dwc3-mp", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,kaanapali-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,milos-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8550-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8650-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8750-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,x1e80100-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,x1e80100-dwc3-mp", + .data = &dwc3_qcom_glymur_pdata, + }, { } }; MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match); diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 91b62acb537b3..4c0aa718ef267 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -147,6 +147,7 @@ config USB_APPLEDISPLAY config USB_QCOM_EUD tristate "Qualcomm Embedded USB Debugger(EUD) Driver" depends on ARCH_QCOM || COMPILE_TEST + depends on OF select QCOM_SCM select USB_ROLE_SWITCH help diff --git a/drivers/usb/misc/onboard_usb_dev.h b/drivers/usb/misc/onboard_usb_dev.h index 3523f8f8a1496..62d93c9720ca7 100644 --- a/drivers/usb/misc/onboard_usb_dev.h +++ b/drivers/usb/misc/onboard_usb_dev.h @@ -153,7 +153,7 @@ static const struct of_device_id onboard_dev_match[] = { { .compatible = "usb5e3,608", .data = &genesys_gl850g_data, }, { .compatible = "usb5e3,610", .data = &genesys_gl852g_data, }, { .compatible = "usb5e3,620", .data = &genesys_gl852g_data, }, - { .compatible = "usb5e3,625", .data = &genesys_gl3590_data, }, + { .compatible = "usb5e3,625", .data = &genesys_gl852g_data, }, { .compatible = "usb5e3,626", .data = &genesys_gl852g_data, }, { .compatible = "usbbda,179", .data = &realtek_rtl8188etv_data, }, { .compatible = "usbbda,411", .data = &realtek_rts5411_data, }, diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 926419ca560fc..5b5cf11d6f526 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -11,10 +11,14 @@ #include #include #include +#include +#include +#include #include #include #include #include +#include #include #define EUD_REG_INT1_EN_MASK 0x0024 @@ -23,8 +27,11 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 +#define EUD_REG_PORT_SEL 0x1028 #define EUD_REG_EUD_EN2 0x0000 +#define EUD_MAX_PORTS 2 + #define EUD_ENABLE BIT(0) #define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) @@ -33,28 +40,84 @@ struct eud_chip { struct device *dev; - struct usb_role_switch *role_sw; + struct usb_role_switch *role_sw[EUD_MAX_PORTS]; + struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; phys_addr_t mode_mgr; + /* serializes EUD control operations */ + struct mutex state_lock; unsigned int int_status; int irq; bool enabled; bool usb_attached; + bool phy_enabled; + bool eud_disabled_for_host; + u8 port_idx; }; +static int eud_phy_enable(struct eud_chip *chip) +{ + struct phy *phy; + int ret; + + if (chip->phy_enabled) + return 0; + + phy = chip->phy[chip->port_idx]; + + ret = phy_init(phy); + if (ret) { + dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + return ret; + } + + ret = phy_power_on(phy); + if (ret) { + dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + phy_exit(phy); + return ret; + } + + chip->phy_enabled = true; + + return 0; +} + +static void eud_phy_disable(struct eud_chip *chip) +{ + struct phy *phy; + + if (!chip->phy_enabled) + return; + + phy = chip->phy[chip->port_idx]; + + phy_power_off(phy); + phy_exit(phy); + chip->phy_enabled = false; +} + static int enable_eud(struct eud_chip *priv) { int ret; - ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + ret = eud_phy_enable(priv); if (ret) return ret; + ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + if (ret) { + eud_phy_disable(priv); + return ret; + } + writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); - return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); + return 0; } static int disable_eud(struct eud_chip *priv) @@ -66,6 +129,8 @@ static int disable_eud(struct eud_chip *priv) return ret; writel(0, priv->base + EUD_REG_CSR_EUD_EN); + eud_phy_disable(priv); + return 0; } @@ -82,30 +147,107 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); + enum usb_role role; bool enable; int ret; if (kstrtobool(buf, &enable)) return -EINVAL; + guard(mutex)(&chip->state_lock); + + /* Skip operation if already in desired state */ + if (chip->enabled == enable) + return count; + + /* + * Handle double-disable scenario: User is disabling EUD that was already + * disabled due to host mode. Since the hardware is already disabled, we + * only need to clear the host-disabled flag to prevent unwanted re-enabling + * when exiting host mode. This respects the user's explicit disable request. + */ + if (!enable && chip->eud_disabled_for_host) { + chip->eud_disabled_for_host = false; + chip->enabled = false; + return count; + } + if (enable) { - ret = enable_eud(chip); - if (!ret) - chip->enabled = enable; - else - disable_eud(chip); + /* + * EUD functions by presenting itself as a USB device to the host PC for + * debugging, making it incompatible with USB host mode configuration. + * Prevent enabling EUD in this configuration to avoid hardware conflicts. + */ + role = usb_role_switch_get_role(chip->role_sw[chip->port_idx]); + if (role == USB_ROLE_HOST) { + dev_err(chip->dev, "Cannot enable EUD: USB port is in host mode\n"); + return -EBUSY; + } + ret = enable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to enable eud\n"); + return ret; + } } else { ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to disable eud\n"); + return ret; + } } - return ret < 0 ? ret : count; + chip->enabled = enable; + + return count; } static DEVICE_ATTR_RW(enable); +static ssize_t port_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", chip->port_idx); +} + +static ssize_t port_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + u8 port; + int ret; + + ret = kstrtou8(buf, 0, &port); + if (ret) + return ret; + + /* Only port 0 and port 1 are valid */ + if (port >= EUD_MAX_PORTS) + return -EINVAL; + + if (!chip->phy[port]) { + dev_err(chip->dev, "EUD not supported on selected port\n"); + return -EOPNOTSUPP; + } + + /* Port selection must be done before enabling EUD */ + if (chip->enabled) { + dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); + return -EBUSY; + } + + writel(port, chip->base + EUD_REG_PORT_SEL); + chip->port_idx = port; + + return count; +} + +static DEVICE_ATTR_RW(port); + static struct attribute *eud_attrs[] = { &dev_attr_enable.attr, + &dev_attr_port.attr, NULL, }; ATTRIBUTE_GROUPS(eud); @@ -167,10 +309,26 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) struct eud_chip *chip = data; int ret; + /* + * EUD virtual attach/detach event handling for low power debugging: + * + * When EUD is enabled in debug mode, the device remains physically + * connected to the PC throughout the debug session, keeping the USB + * controller active. This prevents testing of low power scenarios that + * require USB disconnection. + * + * EUD solves this by providing virtual USB attach/detach events while + * maintaining the physical connection. These events are triggered from + * the Host PC via the enumerated EUD control interface and delivered + * to the EUD driver as interrupts. + * + * These notifications are forwarded to the USB controller through role + * switch framework. + */ if (chip->usb_attached) - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_NONE); if (ret) dev_err(chip->dev, "failed to set role switch\n"); @@ -181,11 +339,125 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } +static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) +{ + struct device_node *controller_node; + struct phy *phy; + struct usb_role_switch *role_sw; + + /* + * Multiply port_id by 2 to get controller port number: + * port_id 0 -> port@0 (primary USB controller) + * port_id 1 -> port@2 (secondary USB controller) + */ + controller_node = of_graph_get_remote_node(chip->dev->of_node, + port_id * 2, -1); + if (!controller_node) + return dev_err_probe(chip->dev, -ENODEV, + "failed to get controller node for port %u\n", port_id); + + phy = devm_of_phy_get_by_index(chip->dev, controller_node, 0); + if (IS_ERR(phy)) { + of_node_put(controller_node); + return dev_err_probe(chip->dev, PTR_ERR(phy), + "failed to get HS PHY for port %u\n", port_id); + } + chip->phy[port_id] = phy; + + /* Only fetch role switch if usb-role-switch property exists */ + if (!of_property_read_bool(controller_node, "usb-role-switch")) { + of_node_put(controller_node); + return 0; + } + + role_sw = usb_role_switch_find_by_fwnode(of_fwnode_handle(controller_node)); + of_node_put(controller_node); + + if (!role_sw) + return dev_err_probe(chip->dev, -EPROBE_DEFER, + "failed to get role switch for port %u\n", port_id); + + chip->role_sw[port_id] = role_sw; + + return 0; +} + +/** + * qcom_eud_usb_role_notify - Notify EUD of USB role change + * @eud_node: Device node of the EUD device + * @phy: HSUSB PHY of the port changing role + * @role: New role being set + * + * Notifies EUD that a USB port is changing roles. EUD will disable itself + * if the port is switching to HOST mode, as EUD is incompatible with host + * mode operation. This API should be called by the USB controller driver + * when it switches the USB role. + * + * The PHY parameter is used to identify which physical USB port is changing + * roles. This is important in multi-port systems where EUD may be active on + * one port while another port changes roles. + * + * This is a best-effort notification - failures are logged but do not affect + * the role change operation. + */ +void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role) +{ + struct platform_device *pdev; + struct eud_chip *chip; + int ret; + + if (!of_device_is_compatible(eud_node, "qcom,eud")) + return; + + pdev = of_find_device_by_node(eud_node); + if (!pdev) + return; + + chip = platform_get_drvdata(pdev); + if (!chip) + goto put_dev; + + mutex_lock(&chip->state_lock); + + /* Only act if this notification is for the currently active EUD port */ + if (!chip->enabled || chip->phy[chip->port_idx] != phy) { + mutex_unlock(&chip->state_lock); + goto put_dev; + } + + /* + * chip->enabled preserves user's sysfs configuration and is not modified + * during host mode transitions to preserve user intent. + */ + if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { + ret = disable_eud(chip); + if (ret) + dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", ret); + else + chip->eud_disabled_for_host = true; + } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { + ret = enable_eud(chip); + if (ret) + dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", ret); + else + chip->eud_disabled_for_host = false; + } + + mutex_unlock(&chip->state_lock); + +put_dev: + platform_device_put(pdev); +} +EXPORT_SYMBOL_GPL(qcom_eud_usb_role_notify); + static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; + int i; - usb_role_switch_put(chip->role_sw); + for (i = 0; i < EUD_MAX_PORTS; i++) + usb_role_switch_put(chip->role_sw[i]); } static int eud_probe(struct platform_device *pdev) @@ -200,10 +472,18 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; - chip->role_sw = usb_role_switch_get(&pdev->dev); - if (IS_ERR(chip->role_sw)) - return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), - "failed to get role switch\n"); + mutex_init(&chip->state_lock); + + /* + * Parse the DT resources for primary port. + * This is the default EUD port and is mandatory. + */ + ret = eud_parse_dt_port(chip, 0); + if (ret) + return ret; + + /* Secondary port is optional */ + eud_parse_dt_port(chip, 1); ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) @@ -238,8 +518,14 @@ static void eud_remove(struct platform_device *pdev) { struct eud_chip *chip = platform_get_drvdata(pdev); - if (chip->enabled) + platform_set_drvdata(pdev, NULL); + + mutex_lock(&chip->state_lock); + if (chip->enabled) { disable_eud(chip); + chip->enabled = false; + } + mutex_unlock(&chip->state_lock); device_init_wakeup(&pdev->dev, false); disable_irq_wake(chip->irq); diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 263a89c5f3243..ff3659b8f5a2c 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -187,9 +187,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp) dp->pending_irq_hpd = true; } } else { - drm_connector_oob_hotplug_event(dp->connector_fwnode, + drm_connector_dp_oob_status(dp->connector_fwnode, hpd ? connector_status_connected : - connector_status_disconnected); + connector_status_disconnected, + (hpd && irq_hpd) ? DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); dp->hpd = hpd; sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); if (hpd && irq_hpd) { @@ -211,8 +213,11 @@ static int dp_altmode_configured(struct dp_altmode *dp) * configuration is complete to signal HPD. */ if (dp->pending_hpd) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_connected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_connected, + dp->pending_irq_hpd ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); dp->pending_hpd = false; if (dp->pending_irq_hpd) { @@ -396,8 +401,9 @@ static int dp_altmode_vdm(struct typec_altmode *alt, dp->data.status = 0; dp->data.conf = 0; if (dp->hpd) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_disconnected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_disconnected, + DRM_CONNECTOR_NO_EXTRA_STATUS); dp->hpd = false; sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); } @@ -828,8 +834,9 @@ void dp_altmode_remove(struct typec_altmode *alt) typec_altmode_put_plug(dp->plug_prime); if (dp->connector_fwnode) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_disconnected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_disconnected, + DRM_CONNECTOR_NO_EXTRA_STATUS); fwnode_handle_put(dp->connector_fwnode); } diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c index 3e39b800e6b5f..b56df9349f89b 100644 --- a/drivers/usb/typec/hd3ss3220.c +++ b/drivers/usb/typec/hd3ss3220.c @@ -501,6 +501,11 @@ static int hd3ss3220_probe(struct i2c_client *client) if (hd3ss3220->poll) schedule_delayed_work(&hd3ss3220->output_poll_work, HZ); + if (client->irq && device_property_read_bool(hd3ss3220->dev, "wakeup-source")) { + device_init_wakeup(&client->dev, true); + enable_irq_wake(client->irq); + } + dev_info(&client->dev, "probed revision=0x%x\n", ret); return 0; @@ -525,6 +530,35 @@ static void hd3ss3220_remove(struct i2c_client *client) usb_role_switch_put(hd3ss3220->role_sw); } +static int __maybe_unused hd3ss3220_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(client->irq); + else + disable_irq(client->irq); + + return 0; +} + +static int __maybe_unused hd3ss3220_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(client->irq); + else + enable_irq(client->irq); + + return 0; +} + +static const struct dev_pm_ops hd3ss3220_pm_ops = { + .suspend = hd3ss3220_suspend, + .resume = hd3ss3220_resume, +}; + static const struct of_device_id dev_ids[] = { { .compatible = "ti,hd3ss3220"}, {} @@ -535,6 +569,7 @@ static struct i2c_driver hd3ss3220_driver = { .driver = { .name = "hd3ss3220", .of_match_table = dev_ids, + .pm = &hd3ss3220_pm_ops, }, .probe = hd3ss3220_probe, .remove = hd3ss3220_remove, diff --git a/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c b/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c index ad669d2f8b9ce..2e3e00d577d4c 100644 --- a/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c +++ b/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c @@ -315,10 +315,13 @@ static void gaokun_ucsi_handle_usb_mode(struct gaokun_ucsi_port *port) /* UCSI callback .connector_status() have set orientation */ if (port->bridge && port->svid == USB_TYPEC_DP_SID) - drm_aux_hpd_bridge_notify(&port->bridge->dev, - port->hpd_state ? - connector_status_connected : - connector_status_disconnected); + drm_aux_hpd_bridge_notify_extra(&port->bridge->dev, + port->hpd_state ? + connector_status_connected : + connector_status_disconnected, + port->hpd_irq ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); gaokun_ec_ucsi_pan_ack(uec->ec, port->idx); } diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h index c2f5a855512f3..f9a86886b0dfa 100644 --- a/include/drm/bridge/aux-bridge.h +++ b/include/drm/bridge/aux-bridge.h @@ -25,7 +25,9 @@ struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, str int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev); struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_node *np); -void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status); +void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); #else static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np) @@ -44,9 +46,16 @@ static inline struct device *drm_dp_hpd_bridge_register(struct device *parent, return NULL; } -static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +static inline void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { } #endif +static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +{ + drm_aux_hpd_bridge_notify_extra(dev, status, DRM_CONNECTOR_NO_EXTRA_STATUS); +} + #endif diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 4ba3a5deef9a6..e6de665ce8f65 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -615,7 +615,9 @@ struct drm_bridge_funcs { */ void (*hpd_notify)(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status, + bool *send_hotplug); /** * @hpd_enable: @@ -1260,7 +1262,8 @@ struct drm_bridge { * @hpd_cb: Hot plug detection callback, registered with * drm_bridge_hpd_enable(). */ - void (*hpd_cb)(void *data, enum drm_connector_status status); + void (*hpd_cb)(void *data, enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @hpd_data: Private data passed to the Hot plug detection callback * @hpd_cb. @@ -1578,11 +1581,30 @@ const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge, struct drm_connector *connector); void drm_bridge_hpd_enable(struct drm_bridge *bridge, void (*cb)(void *data, - enum drm_connector_status status), + enum drm_connector_status status, + enum drm_connector_status_extra extra_status), void *data); void drm_bridge_hpd_disable(struct drm_bridge *bridge); -void drm_bridge_hpd_notify(struct drm_bridge *bridge, - enum drm_connector_status status); +void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); + +/** + * drm_bridge_hpd_notify - notify hot plug detection events + * @bridge: bridge control structure + * @status: output connection status + * + * Bridge drivers shall call this function to report hot plug events when they + * detect a change in the output status, when hot plug detection has been + * enabled by drm_bridge_hpd_enable(). + * + * This function shall be called in a context that can sleep. + */ +static inline void drm_bridge_hpd_notify(struct drm_bridge *bridge, + enum drm_connector_status status) +{ + drm_bridge_hpd_notify_extra(bridge, status, DRM_CONNECTOR_NO_EXTRA_STATUS); +} #ifdef CONFIG_DRM_PANEL_BRIDGE bool drm_bridge_is_panel(const struct drm_bridge *bridge); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 5f5ca023cd654..a4133a28b461a 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -91,6 +91,22 @@ enum drm_connector_status { connector_status_unknown = 3, }; +/** + * enum drm_connector_status_extra - additional events sent by the sink / + * display together or in replacement of the HPD status changes. + */ +enum drm_connector_status_extra { + /** + * @DRM_CONNECTOR_NO_EXTRA_STATUS: No additional status reported. + */ + DRM_CONNECTOR_NO_EXTRA_STATUS, + /** + * @DRM_CONNECTOR_DP_IRQ_HPD: DisplayPort Sink has sent the + * IRQ_HPD (either by the HPD short pulse or via the AltMode event). + */ + DRM_CONNECTOR_DP_IRQ_HPD, +}; + /** * enum drm_connector_registration_state - userspace registration status for * a &drm_connector @@ -1704,7 +1720,8 @@ struct drm_connector_funcs { * has been received from a source outside the display driver / device. */ void (*oob_hotplug_event)(struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @debugfs_init: @@ -2520,8 +2537,9 @@ drm_connector_is_unregistered(struct drm_connector *connector) DRM_CONNECTOR_UNREGISTERED; } -void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, - enum drm_connector_status status); +void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); diff --git a/include/dt-bindings/arm/aest.h b/include/dt-bindings/arm/aest.h new file mode 100644 index 0000000000000..43679314e98e8 --- /dev/null +++ b/include/dt-bindings/arm/aest.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * This header provides constants for the Arm Error Source Table (AEST) + * DT binding (Documentation/devicetree/bindings/arm/arm,aest.yaml). + */ + +#ifndef _DT_BINDINGS_ARM_AEST_H +#define _DT_BINDINGS_ARM_AEST_H + +/* arm,interface-flags - AEST node interface flags field */ +#define AEST_XFACE_SHARED 1 +#define AEST_XFACE_CLEAR_MISC 2 +#define AEST_XFACE_ERROR_DEVICE 4 +#define AEST_XFACE_AFFINITY 8 +#define AEST_XFACE_ERROR_GROUP 16 +#define AEST_XFACE_FAULT_INJECT 32 +#define AEST_XFACE_INT_CONFIG 64 + +/* arm,fhi-flags / arm,eri-flags - AEST node interrupt flags field */ +#define AEST_IRQ_MODE_LEVEL 0 +#define AEST_IRQ_MODE_EDGE 1 + +/* arm,processor-flags - AEST processor node flags field */ +#define AEST_PROC_GLOBAL 1 +#define AEST_PROC_SHARED 2 + +/* arm,group-format - error record group register window page size */ +#define AEST_GROUP_FORMAT_4K 0 +#define AEST_GROUP_FORMAT_16K 1 +#define AEST_GROUP_FORMAT_64K 2 + +/* arm,resource-type - processor resource type */ +#define AEST_RESOURCE_CACHE 0 +#define AEST_RESOURCE_TLB 1 +#define AEST_RESOURCE_GENERIC 2 + +/* arm,gic-type - GIC component type */ +#define AEST_GIC_CPU 0 +#define AEST_GIC_DISTRIBUTOR 1 +#define AEST_GIC_REDISTRIBUTOR 2 +#define AEST_GIC_ITS 3 + +#endif /* _DT_BINDINGS_ARM_AEST_H */ diff --git a/include/dt-bindings/camera/msm-camera.h b/include/dt-bindings/camera/msm-camera.h new file mode 100644 index 0000000000000..97228c26e7040 --- /dev/null +++ b/include/dt-bindings/camera/msm-camera.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __MSM_CAMERA_H +#define __MSM_CAMERA_H + +/* CPAS path data types */ +#define CAM_CPAS_PATH_DATA_IFE_START_OFFSET 0 +#define CAM_CPAS_PATH_DATA_IFE_LINEAR (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_IFE_VID (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IFE_DISP (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IFE_STATS (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IFE_RDI0 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IFE_RDI1 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IFE_RDI2 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_IFE_RDI3 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_IFE_PDAF (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_IFE_PIXEL_RAW (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 9) +#define CAM_CPAS_PATH_DATA_IFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_IPE_START_OFFSET 32 +#define CAM_CPAS_PATH_DATA_IPE_RD_IN (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_IPE_RD_REF (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IPE_WR_VID (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IPE_WR_DISP (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IPE_WR_REF (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IPE_WR_APP (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IPE_MAX_OFFSET (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_OPE_START_OFFSET 64 +#define CAM_CPAS_PATH_DATA_OPE_RD_IN (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_OPE_RD_REF (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OPE_WR_VID (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_OPE_WR_DISP (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_OPE_WR_REF (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_OPE_MAX_OFFSET (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_SFE_START_OFFSET 96 +#define CAM_CPAS_PATH_DATA_SFE_NRDI (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_SFE_RDI0 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_SFE_RDI1 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_SFE_RDI2 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_SFE_RDI3 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_SFE_RDI4 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_SFE_STATS (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_SFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_CRE_START_OFFSET (CAM_CPAS_PATH_DATA_SFE_MAX_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_CRE_RD_IN (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_CRE_WR_OUT (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_CRE_MAX_OFFSET (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_OFE_START_OFFSET (CAM_CPAS_PATH_DATA_CRE_MAX_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OFE_RD_EXT (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_OFE_RD_INT_PDI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OFE_RD_INT_HDR (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_OFE_WR_VID (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_OFE_WR_DISP (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_OFE_WR_IR (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_OFE_WR_HDR_LTM (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_OFE_WR_DC4 (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_OFE_WR_AI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_OFE_WR_PDI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 9) +#define CAM_CPAS_PATH_DATA_OFE_WR_IDEALRAW (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 10) +#define CAM_CPAS_PATH_DATA_OFE_WR_STATS (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 11) +#define CAM_CPAS_PATH_DATA_OFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_CONSO_OFFSET 256 +#define CAM_CPAS_PATH_DATA_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 0) + +/* IFE consolidated paths */ +#define CAM_CPAS_PATH_DATA_IFE_LINEAR_PDAF (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IFE_UBWC_STATS (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IFE_PIXEL_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IFE_RDI_PIXEL_RAW (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IFE_RDI_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IFE_UBWC (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_IFE_LINEAR_STATS (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_IFE_UBWC_LINEAR (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_IFE_PDAF_LINEAR (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 9) + +/* IPE Consolidated paths */ +#define CAM_CPAS_PATH_DATA_IPE_WR_VID_DISP (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 1) + +/* CPAS transaction types */ +#define CAM_CPAS_TRANSACTION_READ 0 +#define CAM_CPAS_TRANSACTION_WRITE 1 + +/* CPAS traffic merge types */ +#define CAM_CPAS_TRAFFIC_MERGE_SUM 0 +#define CAM_CPAS_TRAFFIC_MERGE_SUM_INTERLEAVE 1 + +/* Feature bit type */ +#define CAM_CPAS_FEATURE_TYPE_DISABLE 0 +#define CAM_CPAS_FEATURE_TYPE_ENABLE 1 +#define CAM_CPAS_FEATURE_TYPE_VALUE 2 + +/* Feature support bit positions in feature fuse register*/ +#define CAM_CPAS_QCFA_BINNING_ENABLE 0 +#define CAM_CPAS_SECURE_CAMERA_ENABLE 1 +#define CAM_CPAS_MF_HDR_ENABLE 2 +#define CAM_CPAS_MP_LIMIT_FUSE 3 +#define CAM_CPAS_ISP_FUSE 4 +#define CAM_CPAS_ISP_PIX_FUSE 5 +#define CAM_CPAS_ISP_LITE_FUSE 6 +#define CAM_CPAS_CSIPHY_FUSE 7 +#define CAM_CPAS_IPE_VID_OUT_8BPP_LIMIT_ENABLE 8 +#define CAM_CPAS_SFE_FUSE 9 +#define CAM_CPAS_CUSTOM_FUSE 10 +#define CAM_CPAS_CAM_FUSE 11 +#define CAM_CPAS_SHDR_FUSE 12 +#define CAM_CPAS_RT_OT_FUSE 13 +#define CAM_CPAS_FUSE_FEATURE_MAX 14 + +/* Flash type*/ +#define CAM_FLASH_TYPE_PMIC 0 +#define CAM_FLASH_TYPE_I2C 1 +#define CAM_FLASH_TYPE_GPIO 2 + +/* CCI master */ +#define CCI_MASTER_0 0 +#define CCI_MASTER_1 1 +#define CCI_MASTER_MAX 2 + +/* AON Camera IDs*/ +#define AON_CAM1 0 +#define AON_CAM2 1 +#define MAX_AON_CAM 2 +#define NOT_AON_CAM 255 + +/* Camera DRV enable masks */ +#define CAM_DDR_DRV 0x1 +#define CAM_CLK_DRV 0x2 + +/* Port index for BW voting */ +#define CAM_CPAS_PORT_HLOS_DRV 0 +#define CAM_CPAS_PORT_DRV_0 1 +#define CAM_CPAS_PORT_DRV_1 2 +#define CAM_CPAS_PORT_DRV_2 3 +#define CAM_CPAS_PORT_DRV_DYN 32 + +/* Domain ID types */ +#define CAM_CPAS_NON_SECURE_DOMAIN 0 +#define CAM_CPAS_SECURE_DOMAIN 1 + +/* Debug bypass driver */ +#define CAM_BYPASS_RGLTR 0x1 +#define CAM_BYPASS_RGLTR_MODE 0x2 +#define CAM_BYPASS_CLKS 0x4 +#define CAM_BYPASS_CESTA 0x8 +#define CAM_BYPASS_ICC 0x10 + +#endif diff --git a/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h b/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h new file mode 100644 index 0000000000000..7b8b285f18d27 --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_BIST_MCLK_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_CAM_BIST_MCLK_CC_ELIZA_H + +/* CAM_BIST_MCLK_CC clocks */ +#define CAM_BIST_MCLK_CC_MCLK0_CLK 0 +#define CAM_BIST_MCLK_CC_MCLK0_CLK_SRC 1 +#define CAM_BIST_MCLK_CC_MCLK1_CLK 2 +#define CAM_BIST_MCLK_CC_MCLK1_CLK_SRC 3 +#define CAM_BIST_MCLK_CC_MCLK2_CLK 4 +#define CAM_BIST_MCLK_CC_MCLK2_CLK_SRC 5 +#define CAM_BIST_MCLK_CC_MCLK3_CLK 6 +#define CAM_BIST_MCLK_CC_MCLK3_CLK_SRC 7 +#define CAM_BIST_MCLK_CC_MCLK4_CLK 8 +#define CAM_BIST_MCLK_CC_MCLK4_CLK_SRC 9 +#define CAM_BIST_MCLK_CC_MCLK5_CLK 10 +#define CAM_BIST_MCLK_CC_MCLK5_CLK_SRC 11 +#define CAM_BIST_MCLK_CC_MCLK6_CLK 12 +#define CAM_BIST_MCLK_CC_MCLK6_CLK_SRC 13 +#define CAM_BIST_MCLK_CC_MCLK7_CLK 14 +#define CAM_BIST_MCLK_CC_MCLK7_CLK_SRC 15 +#define CAM_BIST_MCLK_CC_PLL0 16 +#define CAM_BIST_MCLK_CC_PLL_TEST_CLK 17 +#define CAM_BIST_MCLK_CC_PLL_TEST_DIV_CLK_SRC 18 +#define CAM_BIST_MCLK_CC_SLEEP_CLK 19 +#define CAM_BIST_MCLK_CC_SLEEP_CLK_SRC 20 + +#endif diff --git a/include/dt-bindings/clock/qcom,eliza-camcc.h b/include/dt-bindings/clock/qcom,eliza-camcc.h new file mode 100644 index 0000000000000..d85ef9777d08d --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-camcc.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_CAM_CC_ELIZA_H + +/* CAM_CC clocks */ +#define CAM_CC_CAM_TOP_AHB_CLK 0 +#define CAM_CC_CAM_TOP_FAST_AHB_CLK 1 +#define CAM_CC_CAMNOC_DCD_XO_CLK 2 +#define CAM_CC_CAMNOC_NRT_AXI_CLK 3 +#define CAM_CC_CAMNOC_NRT_CRE_CLK 4 +#define CAM_CC_CAMNOC_NRT_IPE_NPS_CLK 5 +#define CAM_CC_CAMNOC_NRT_OFE_ANCHOR_CLK 6 +#define CAM_CC_CAMNOC_NRT_OFE_HDR_CLK 7 +#define CAM_CC_CAMNOC_NRT_OFE_MAIN_CLK 8 +#define CAM_CC_CAMNOC_RT_AXI_CLK 9 +#define CAM_CC_CAMNOC_RT_AXI_CLK_SRC 10 +#define CAM_CC_CAMNOC_RT_IFE_LITE_CLK 11 +#define CAM_CC_CAMNOC_RT_TFE_0_BAYER_CLK 12 +#define CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK 13 +#define CAM_CC_CAMNOC_RT_TFE_1_BAYER_CLK 14 +#define CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK 15 +#define CAM_CC_CAMNOC_RT_TFE_2_BAYER_CLK 16 +#define CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK 17 +#define CAM_CC_CAMNOC_XO_CLK 18 +#define CAM_CC_CCI_0_CLK 19 +#define CAM_CC_CCI_0_CLK_SRC 20 +#define CAM_CC_CCI_1_CLK 21 +#define CAM_CC_CCI_1_CLK_SRC 22 +#define CAM_CC_CCI_2_CLK 23 +#define CAM_CC_CCI_2_CLK_SRC 24 +#define CAM_CC_CORE_AHB_CLK 25 +#define CAM_CC_CPHY_RX_CLK_SRC 26 +#define CAM_CC_CRE_AHB_CLK 27 +#define CAM_CC_CRE_CLK 28 +#define CAM_CC_CRE_CLK_SRC 29 +#define CAM_CC_CSI0PHYTIMER_CLK 30 +#define CAM_CC_CSI0PHYTIMER_CLK_SRC 31 +#define CAM_CC_CSI1PHYTIMER_CLK 32 +#define CAM_CC_CSI1PHYTIMER_CLK_SRC 33 +#define CAM_CC_CSI2PHYTIMER_CLK 34 +#define CAM_CC_CSI2PHYTIMER_CLK_SRC 35 +#define CAM_CC_CSI3PHYTIMER_CLK 36 +#define CAM_CC_CSI3PHYTIMER_CLK_SRC 37 +#define CAM_CC_CSI4PHYTIMER_CLK 38 +#define CAM_CC_CSI4PHYTIMER_CLK_SRC 39 +#define CAM_CC_CSI5PHYTIMER_CLK 40 +#define CAM_CC_CSI5PHYTIMER_CLK_SRC 41 +#define CAM_CC_CSID_CLK 42 +#define CAM_CC_CSID_CLK_SRC 43 +#define CAM_CC_CSID_CSIPHY_RX_CLK 44 +#define CAM_CC_CSIPHY0_CLK 45 +#define CAM_CC_CSIPHY1_CLK 46 +#define CAM_CC_CSIPHY2_CLK 47 +#define CAM_CC_CSIPHY3_CLK 48 +#define CAM_CC_CSIPHY4_CLK 49 +#define CAM_CC_CSIPHY5_CLK 50 +#define CAM_CC_DRV_AHB_CLK 51 +#define CAM_CC_DRV_XO_CLK 52 +#define CAM_CC_FAST_AHB_CLK_SRC 53 +#define CAM_CC_GDSC_CLK 54 +#define CAM_CC_ICP_0_AHB_CLK 55 +#define CAM_CC_ICP_0_CLK 56 +#define CAM_CC_ICP_0_CLK_SRC 57 +#define CAM_CC_ICP_1_AHB_CLK 58 +#define CAM_CC_ICP_1_CLK 59 +#define CAM_CC_ICP_1_CLK_SRC 60 +#define CAM_CC_IFE_LITE_AHB_CLK 61 +#define CAM_CC_IFE_LITE_CLK 62 +#define CAM_CC_IFE_LITE_CLK_SRC 63 +#define CAM_CC_IFE_LITE_CPHY_RX_CLK 64 +#define CAM_CC_IFE_LITE_CSID_CLK 65 +#define CAM_CC_IFE_LITE_CSID_CLK_SRC 66 +#define CAM_CC_IPE_NPS_AHB_CLK 67 +#define CAM_CC_IPE_NPS_CLK 68 +#define CAM_CC_IPE_NPS_CLK_SRC 69 +#define CAM_CC_IPE_NPS_FAST_AHB_CLK 70 +#define CAM_CC_IPE_PPS_CLK 71 +#define CAM_CC_IPE_PPS_FAST_AHB_CLK 72 +#define CAM_CC_JPEG_0_CLK 73 +#define CAM_CC_JPEG_1_CLK 74 +#define CAM_CC_JPEG_CLK_SRC 75 +#define CAM_CC_OFE_AHB_CLK 76 +#define CAM_CC_OFE_ANCHOR_CLK 77 +#define CAM_CC_OFE_ANCHOR_FAST_AHB_CLK 78 +#define CAM_CC_OFE_CLK_SRC 79 +#define CAM_CC_OFE_HDR_CLK 80 +#define CAM_CC_OFE_HDR_FAST_AHB_CLK 81 +#define CAM_CC_OFE_MAIN_CLK 82 +#define CAM_CC_OFE_MAIN_FAST_AHB_CLK 83 +#define CAM_CC_PLL0 84 +#define CAM_CC_PLL0_OUT_EVEN 85 +#define CAM_CC_PLL0_OUT_ODD 86 +#define CAM_CC_PLL1 87 +#define CAM_CC_PLL1_OUT_EVEN 88 +#define CAM_CC_PLL2 89 +#define CAM_CC_PLL2_OUT_EVEN 90 +#define CAM_CC_PLL3 91 +#define CAM_CC_PLL3_OUT_EVEN 92 +#define CAM_CC_PLL4 93 +#define CAM_CC_PLL4_OUT_EVEN 94 +#define CAM_CC_PLL5 95 +#define CAM_CC_PLL5_OUT_EVEN 96 +#define CAM_CC_PLL6 97 +#define CAM_CC_PLL6_OUT_EVEN 98 +#define CAM_CC_PLL6_OUT_ODD 99 +#define CAM_CC_QDSS_DEBUG_CLK 100 +#define CAM_CC_QDSS_DEBUG_CLK_SRC 101 +#define CAM_CC_QDSS_DEBUG_XO_CLK 102 +#define CAM_CC_SLEEP_CLK 103 +#define CAM_CC_SLEEP_CLK_SRC 104 +#define CAM_CC_SLOW_AHB_CLK_SRC 105 +#define CAM_CC_TFE_0_BAYER_CLK 106 +#define CAM_CC_TFE_0_BAYER_FAST_AHB_CLK 107 +#define CAM_CC_TFE_0_CLK_SRC 108 +#define CAM_CC_TFE_0_MAIN_CLK 109 +#define CAM_CC_TFE_0_MAIN_FAST_AHB_CLK 110 +#define CAM_CC_TFE_1_BAYER_CLK 111 +#define CAM_CC_TFE_1_BAYER_FAST_AHB_CLK 112 +#define CAM_CC_TFE_1_CLK_SRC 113 +#define CAM_CC_TFE_1_MAIN_CLK 114 +#define CAM_CC_TFE_1_MAIN_FAST_AHB_CLK 115 +#define CAM_CC_TFE_2_BAYER_CLK 116 +#define CAM_CC_TFE_2_BAYER_FAST_AHB_CLK 117 +#define CAM_CC_TFE_2_CLK_SRC 118 +#define CAM_CC_TFE_2_MAIN_CLK 119 +#define CAM_CC_TFE_2_MAIN_FAST_AHB_CLK 120 +#define CAM_CC_XO_CLK_SRC 121 + +/* CAM_CC power domains */ +#define CAM_CC_IPE_0_GDSC 0 +#define CAM_CC_OFE_GDSC 1 +#define CAM_CC_TFE_0_GDSC 2 +#define CAM_CC_TFE_1_GDSC 3 +#define CAM_CC_TFE_2_GDSC 4 +#define CAM_CC_TITAN_TOP_GDSC 5 + +/* CAM_CC resets */ +#define CAM_CC_DRV_BCR 0 +#define CAM_CC_ICP_BCR 1 +#define CAM_CC_IPE_0_BCR 2 +#define CAM_CC_OFE_BCR 3 +#define CAM_CC_QDSS_DEBUG_BCR 4 +#define CAM_CC_TFE_0_BCR 5 +#define CAM_CC_TFE_1_BCR 6 +#define CAM_CC_TFE_2_BCR 7 + +#endif diff --git a/include/dt-bindings/clock/qcom,eliza-gpucc.h b/include/dt-bindings/clock/qcom,eliza-gpucc.h new file mode 100644 index 0000000000000..c3d9b7827325c --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-gpucc.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_GPU_CC_ELIZA_H + +/* GPU_CC clocks */ +#define GPU_CC_AHB_CLK 0 +#define GPU_CC_CRC_AHB_CLK 1 +#define GPU_CC_CX_ACCU_SHIFT_CLK 2 +#define GPU_CC_CX_FF_CLK 3 +#define GPU_CC_CX_GMU_CLK 4 +#define GPU_CC_CXO_AON_CLK 5 +#define GPU_CC_CXO_CLK 6 +#define GPU_CC_DEMET_CLK 7 +#define GPU_CC_DEMET_DIV_CLK_SRC 8 +#define GPU_CC_FF_CLK_SRC 9 +#define GPU_CC_FREQ_MEASURE_CLK 10 +#define GPU_CC_GMU_CLK_SRC 11 +#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK 12 +#define GPU_CC_HUB_AON_CLK 13 +#define GPU_CC_HUB_CLK_SRC 14 +#define GPU_CC_HUB_CX_INT_CLK 15 +#define GPU_CC_MEMNOC_GFX_CLK 16 +#define GPU_CC_MND1X_0_GFX3D_CLK 17 +#define GPU_CC_MND1X_1_GFX3D_CLK 18 +#define GPU_CC_PLL0 19 +#define GPU_CC_PLL1 20 +#define GPU_CC_SLEEP_CLK 21 +#define GPU_CC_XO_CLK_SRC 22 +#define GPU_CC_XO_DIV_CLK_SRC 23 + +/* GPU_CC power domains */ +#define GPU_CC_CX_GDSC 0 +#define GPU_CC_GX_GDSC 1 + +/* GPU_CC resets */ +#define GPU_CC_ACD_BCR 0 +#define GPU_CC_CB_BCR 1 +#define GPU_CC_CX_BCR 2 +#define GPU_CC_FAST_HUB_BCR 3 +#define GPU_CC_FF_BCR 4 +#define GPU_CC_GFX3D_AON_BCR 5 +#define GPU_CC_GMU_BCR 6 +#define GPU_CC_GX_BCR 7 +#define GPU_CC_RBCPR_BCR 8 +#define GPU_CC_XO_BCR 9 + +#endif diff --git a/include/dt-bindings/clock/qcom,eliza-videocc.h b/include/dt-bindings/clock/qcom,eliza-videocc.h new file mode 100644 index 0000000000000..1e922250a7fae --- /dev/null +++ b/include/dt-bindings/clock/qcom,eliza-videocc.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_ELIZA_H +#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_ELIZA_H + +/* VIDEO_CC clocks */ +#define VIDEO_CC_AHB_CLK 0 +#define VIDEO_CC_AHB_CLK_SRC 1 +#define VIDEO_CC_MVS0_CLK 2 +#define VIDEO_CC_MVS0_CLK_SRC 3 +#define VIDEO_CC_MVS0_DIV_CLK_SRC 4 +#define VIDEO_CC_MVS0_SHIFT_CLK 5 +#define VIDEO_CC_MVS0C_CLK 6 +#define VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC 7 +#define VIDEO_CC_MVS0C_SHIFT_CLK 8 +#define VIDEO_CC_PLL0 9 +#define VIDEO_CC_SLEEP_CLK 10 +#define VIDEO_CC_SLEEP_CLK_SRC 11 +#define VIDEO_CC_XO_CLK 12 +#define VIDEO_CC_XO_CLK_SRC 13 + +/* VIDEO_CC power domains */ +#define VIDEO_CC_MVS0_GDSC 0 +#define VIDEO_CC_MVS0C_GDSC 1 + +/* VIDEO_CC resets */ +#define VIDEO_CC_INTERFACE_BCR 0 +#define VIDEO_CC_MVS0_CLK_ARES 1 +#define VIDEO_CC_MVS0_BCR 2 +#define VIDEO_CC_MVS0C_CLK_ARES 3 +#define VIDEO_CC_MVS0C_BCR 4 +#define VIDEO_CC_XO_CLK_ARES 5 + +#endif diff --git a/include/dt-bindings/clock/qcom,glymur-camcc.h b/include/dt-bindings/clock/qcom,glymur-camcc.h new file mode 100644 index 0000000000000..0c93fc77ef268 --- /dev/null +++ b/include/dt-bindings/clock/qcom,glymur-camcc.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_GLYMUR_H +#define _DT_BINDINGS_CLK_QCOM_CAM_CC_GLYMUR_H + +/* CAM_CC clocks */ +#define CAM_CC_BPS_AHB_CLK 0 +#define CAM_CC_BPS_CLK 1 +#define CAM_CC_BPS_CLK_SRC 2 +#define CAM_CC_BPS_FAST_AHB_CLK 3 +#define CAM_CC_CAMNOC_AXI_NRT_CLK 4 +#define CAM_CC_CAMNOC_AXI_RT_CLK 5 +#define CAM_CC_CAMNOC_AXI_RT_CLK_SRC 6 +#define CAM_CC_CAMNOC_DCD_XO_CLK 7 +#define CAM_CC_CAMNOC_XO_CLK 8 +#define CAM_CC_CCI_0_CLK 9 +#define CAM_CC_CCI_0_CLK_SRC 10 +#define CAM_CC_CCI_1_CLK 11 +#define CAM_CC_CCI_1_CLK_SRC 12 +#define CAM_CC_CORE_AHB_CLK 13 +#define CAM_CC_CPAS_AHB_CLK 14 +#define CAM_CC_CPAS_BPS_CLK 15 +#define CAM_CC_CPAS_FAST_AHB_CLK 16 +#define CAM_CC_CPAS_IFE_0_CLK 17 +#define CAM_CC_CPAS_IFE_1_CLK 18 +#define CAM_CC_CPAS_IFE_LITE_CLK 19 +#define CAM_CC_CPAS_IPE_NPS_CLK 20 +#define CAM_CC_CPHY_RX_CLK_SRC 21 +#define CAM_CC_CSI0PHYTIMER_CLK 22 +#define CAM_CC_CSI0PHYTIMER_CLK_SRC 23 +#define CAM_CC_CSI1PHYTIMER_CLK 24 +#define CAM_CC_CSI1PHYTIMER_CLK_SRC 25 +#define CAM_CC_CSI4PHYTIMER_CLK 26 +#define CAM_CC_CSI4PHYTIMER_CLK_SRC 27 +#define CAM_CC_CSID_CLK 28 +#define CAM_CC_CSID_CLK_SRC 29 +#define CAM_CC_CSID_CSIPHY_RX_CLK 30 +#define CAM_CC_CSIPHY0_CLK 31 +#define CAM_CC_CSIPHY1_CLK 32 +#define CAM_CC_CSIPHY4_CLK 33 +#define CAM_CC_FAST_AHB_CLK_SRC 34 +#define CAM_CC_GDSC_CLK 35 +#define CAM_CC_ICP_AHB_CLK 36 +#define CAM_CC_ICP_CLK 37 +#define CAM_CC_ICP_CLK_SRC 38 +#define CAM_CC_IFE_0_CLK 39 +#define CAM_CC_IFE_0_CLK_SRC 40 +#define CAM_CC_IFE_0_DSP_CLK 41 +#define CAM_CC_IFE_0_FAST_AHB_CLK 42 +#define CAM_CC_IFE_1_CLK 43 +#define CAM_CC_IFE_1_CLK_SRC 44 +#define CAM_CC_IFE_1_DSP_CLK 45 +#define CAM_CC_IFE_1_FAST_AHB_CLK 46 +#define CAM_CC_IFE_LITE_AHB_CLK 47 +#define CAM_CC_IFE_LITE_CLK 48 +#define CAM_CC_IFE_LITE_CLK_SRC 49 +#define CAM_CC_IFE_LITE_CPHY_RX_CLK 50 +#define CAM_CC_IFE_LITE_CSID_CLK 51 +#define CAM_CC_IFE_LITE_CSID_CLK_SRC 52 +#define CAM_CC_IPE_NPS_AHB_CLK 53 +#define CAM_CC_IPE_NPS_CLK 54 +#define CAM_CC_IPE_NPS_CLK_SRC 55 +#define CAM_CC_IPE_NPS_FAST_AHB_CLK 56 +#define CAM_CC_IPE_PPS_CLK 57 +#define CAM_CC_IPE_PPS_FAST_AHB_CLK 58 +#define CAM_CC_JPEG_CLK 59 +#define CAM_CC_JPEG_CLK_SRC 60 +#define CAM_CC_MCLK0_CLK 61 +#define CAM_CC_MCLK0_CLK_SRC 62 +#define CAM_CC_MCLK1_CLK 63 +#define CAM_CC_MCLK1_CLK_SRC 64 +#define CAM_CC_MCLK2_CLK 65 +#define CAM_CC_MCLK2_CLK_SRC 66 +#define CAM_CC_MCLK3_CLK 67 +#define CAM_CC_MCLK3_CLK_SRC 68 +#define CAM_CC_MCLK4_CLK 69 +#define CAM_CC_MCLK4_CLK_SRC 70 +#define CAM_CC_MCLK5_CLK 71 +#define CAM_CC_MCLK5_CLK_SRC 72 +#define CAM_CC_MCLK6_CLK 73 +#define CAM_CC_MCLK6_CLK_SRC 74 +#define CAM_CC_MCLK7_CLK 75 +#define CAM_CC_MCLK7_CLK_SRC 76 +#define CAM_CC_PLL0 77 +#define CAM_CC_PLL0_OUT_EVEN 78 +#define CAM_CC_PLL0_OUT_ODD 79 +#define CAM_CC_PLL1 80 +#define CAM_CC_PLL1_OUT_EVEN 81 +#define CAM_CC_PLL2 82 +#define CAM_CC_PLL3 83 +#define CAM_CC_PLL3_OUT_EVEN 84 +#define CAM_CC_PLL4 85 +#define CAM_CC_PLL4_OUT_EVEN 86 +#define CAM_CC_PLL5 87 +#define CAM_CC_PLL5_OUT_EVEN 88 +#define CAM_CC_QDSS_DEBUG_CLK 89 +#define CAM_CC_QDSS_DEBUG_CLK_SRC 90 +#define CAM_CC_QDSS_DEBUG_XO_CLK 91 +#define CAM_CC_SLEEP_CLK 92 +#define CAM_CC_SLEEP_CLK_SRC 93 +#define CAM_CC_SLOW_AHB_CLK_SRC 94 +#define CAM_CC_XO_CLK_SRC 95 + +/* CAM_CC power domains */ +#define CAM_CC_BPS_GDSC 0 +#define CAM_CC_IFE_0_GDSC 1 +#define CAM_CC_IFE_1_GDSC 2 +#define CAM_CC_IPE_0_GDSC 3 +#define CAM_CC_TITAN_TOP_GDSC 4 + +/* CAM_CC resets */ +#define CAM_CC_BPS_BCR 0 +#define CAM_CC_ICP_BCR 1 +#define CAM_CC_IFE_0_BCR 2 +#define CAM_CC_IFE_1_BCR 3 +#define CAM_CC_IPE_0_BCR 4 +#define CAM_CC_QDSS_DEBUG_BCR 5 + +#endif diff --git a/include/dt-bindings/clock/qcom,glymur-evacc.h b/include/dt-bindings/clock/qcom,glymur-evacc.h new file mode 100644 index 0000000000000..35a7b45503516 --- /dev/null +++ b/include/dt-bindings/clock/qcom,glymur-evacc.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_EVACC_GLYMUR_H +#define _DT_BINDINGS_CLK_QCOM_EVACC_GLYMUR_H + +/* EVA_CC clocks */ +#define EVA_CC_AHB_CLK 0 +#define EVA_CC_AHB_CLK_SRC 1 +#define EVA_CC_MVS0_CLK 2 +#define EVA_CC_MVS0_CLK_SRC 3 +#define EVA_CC_MVS0_DIV_CLK_SRC 4 +#define EVA_CC_MVS0_FREERUN_CLK 5 +#define EVA_CC_MVS0_SHIFT_CLK 6 +#define EVA_CC_MVS0C_CLK 7 +#define EVA_CC_MVS0C_DIV2_DIV_CLK_SRC 8 +#define EVA_CC_MVS0C_FREERUN_CLK 9 +#define EVA_CC_MVS0C_SHIFT_CLK 10 +#define EVA_CC_PLL0 11 +#define EVA_CC_SLEEP_CLK 12 +#define EVA_CC_SLEEP_CLK_SRC 13 +#define EVA_CC_XO_CLK 14 +#define EVA_CC_XO_CLK_SRC 15 + +/* EVA_CC power domains */ +#define EVA_CC_MVS0_GDSC 0 +#define EVA_CC_MVS0C_GDSC 1 + +/* EVA_CC resets */ +#define EVA_CC_INTERFACE_BCR 0 +#define EVA_CC_MVS0_BCR 1 +#define EVA_CC_MVS0C_CLK_ARES 2 +#define EVA_CC_MVS0C_BCR 3 +#define EVA_CC_MVS0C_FREERUN_CLK_ARES 4 + +#endif /* _DT_BINDINGS_CLK_QCOM_EVACC_GLYMUR_H */ diff --git a/include/dt-bindings/clock/qcom,shikra-audiocorecc.h b/include/dt-bindings/clock/qcom,shikra-audiocorecc.h new file mode 100644 index 0000000000000..bc77d7a3946ea --- /dev/null +++ b/include/dt-bindings/clock/qcom,shikra-audiocorecc.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_AUDIO_CORE_CC_SHIKRA_H +#define _DT_BINDINGS_CLK_QCOM_AUDIO_CORE_CC_SHIKRA_H + +/* AUDIO_CORE_CC clocks */ +#define AUDIO_CORE_CC_DIG_PLL 0 +#define AUDIO_CORE_CC_DIG_PLL_OUT_AUX 1 +#define AUDIO_CORE_CC_DIG_PLL_OUT_AUX2 2 +#define AUDIO_CORE_CC_AIF_IF0_CLK_SRC 3 +#define AUDIO_CORE_CC_AIF_IF0_EBIT_CLK 4 +#define AUDIO_CORE_CC_AIF_IF0_IBIT_CLK 5 +#define AUDIO_CORE_CC_AIF_IF1_CLK_SRC 6 +#define AUDIO_CORE_CC_AIF_IF1_EBIT_CLK 7 +#define AUDIO_CORE_CC_AIF_IF1_IBIT_CLK 8 +#define AUDIO_CORE_CC_AIF_IF2_CLK_SRC 9 +#define AUDIO_CORE_CC_AIF_IF2_EBIT_CLK 10 +#define AUDIO_CORE_CC_AIF_IF2_IBIT_CLK 11 +#define AUDIO_CORE_CC_AIF_IF3_CLK_SRC 12 +#define AUDIO_CORE_CC_AIF_IF3_EBIT_CLK 13 +#define AUDIO_CORE_CC_AIF_IF3_IBIT_CLK 14 +#define AUDIO_CORE_CC_AUD_DMA_CLK 15 +#define AUDIO_CORE_CC_AUD_DMA_CLK_SRC 16 +#define AUDIO_CORE_CC_AUD_DMA_MEM_CLK 17 +#define AUDIO_CORE_CC_BUS_CLK 18 +#define AUDIO_CORE_CC_BUS_CLK_SRC 19 +#define AUDIO_CORE_CC_CDIV_TX_MCLK_DIV_CLK_SRC 20 +#define AUDIO_CORE_CC_EXT_MCLKA_CLK_SRC 21 +#define AUDIO_CORE_CC_EXT_MCLKA_OUT_CLK 22 +#define AUDIO_CORE_CC_EXT_MCLKB_CLK_SRC 23 +#define AUDIO_CORE_CC_EXT_MCLKB_OUT_CLK 24 +#define AUDIO_CORE_CC_IM_SLEEP_CLK 25 +#define AUDIO_CORE_CC_LPAIF_PCMOE_CLK 26 +#define AUDIO_CORE_CC_LPAIF_PCMOE_CLK_SRC 27 +#define AUDIO_CORE_CC_RX_MCLK_2X_CLK 28 +#define AUDIO_CORE_CC_RX_MCLK_CLK 29 +#define AUDIO_CORE_CC_SAMPLING_CLK 30 +#define AUDIO_CORE_CC_TX_MCLK_2X_CLK 31 +#define AUDIO_CORE_CC_TX_MCLK_CLK 32 +#define AUDIO_CORE_CC_TX_MCLK_RCG_CLK_SRC 33 + +/* AUDIO_CORE_CC resets */ +#define AUDIO_CORE_CSR_RX_SWR_CGCR 0 +#define AUDIO_CORE_CSR_TX_SWR_CGCR 1 + +#endif diff --git a/include/dt-bindings/clock/qcom,shikra-gcc.h b/include/dt-bindings/clock/qcom,shikra-gcc.h new file mode 100644 index 0000000000000..dc55e5652caae --- /dev/null +++ b/include/dt-bindings/clock/qcom,shikra-gcc.h @@ -0,0 +1,262 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SHIKRA_H +#define _DT_BINDINGS_CLK_QCOM_GCC_SHIKRA_H + +/* GCC clocks */ +#define GPLL0 0 +#define GPLL0_OUT_AUX2 1 +#define GPLL1 2 +#define GPLL10 3 +#define GPLL11 4 +#define GPLL12 5 +#define GPLL12_OUT_AUX2 6 +#define GPLL3 7 +#define GPLL3_OUT_MAIN 8 +#define GPLL4 9 +#define GPLL5 10 +#define GPLL6 11 +#define GPLL6_OUT_MAIN 12 +#define GPLL7 13 +#define GPLL8 14 +#define GPLL8_OUT_MAIN 15 +#define GPLL9 16 +#define GPLL9_OUT_MAIN 17 +#define GCC_AHB2PHY_CSI_CLK 18 +#define GCC_AHB2PHY_USB_CLK 19 +#define GCC_BOOT_ROM_AHB_CLK 20 +#define GCC_CAM_THROTTLE_NRT_CLK 21 +#define GCC_CAM_THROTTLE_RT_CLK 22 +#define GCC_CAMERA_AHB_CLK 23 +#define GCC_CAMERA_XO_CLK 24 +#define GCC_CAMSS_AXI_CLK 25 +#define GCC_CAMSS_AXI_CLK_SRC 26 +#define GCC_CAMSS_CAMNOC_ATB_CLK 27 +#define GCC_CAMSS_CAMNOC_DRAGONLINK_ATB_CLK 28 +#define GCC_CAMSS_CAMNOC_NTS_XO_CLK 29 +#define GCC_CAMSS_CCI_0_CLK 30 +#define GCC_CAMSS_CCI_CLK_SRC 31 +#define GCC_CAMSS_CPHY_0_CLK 32 +#define GCC_CAMSS_CPHY_1_CLK 33 +#define GCC_CAMSS_CSI0PHYTIMER_CLK 34 +#define GCC_CAMSS_CSI0PHYTIMER_CLK_SRC 35 +#define GCC_CAMSS_CSI1PHYTIMER_CLK 36 +#define GCC_CAMSS_CSI1PHYTIMER_CLK_SRC 37 +#define GCC_CAMSS_MCLK0_CLK 38 +#define GCC_CAMSS_MCLK0_CLK_SRC 39 +#define GCC_CAMSS_MCLK1_CLK 40 +#define GCC_CAMSS_MCLK1_CLK_SRC 41 +#define GCC_CAMSS_MCLK2_CLK 42 +#define GCC_CAMSS_MCLK2_CLK_SRC 43 +#define GCC_CAMSS_MCLK3_CLK 44 +#define GCC_CAMSS_MCLK3_CLK_SRC 45 +#define GCC_CAMSS_NRT_AXI_CLK 46 +#define GCC_CAMSS_OPE_AHB_CLK 47 +#define GCC_CAMSS_OPE_AHB_CLK_SRC 48 +#define GCC_CAMSS_OPE_CLK 49 +#define GCC_CAMSS_OPE_CLK_SRC 50 +#define GCC_CAMSS_RT_AXI_CLK 51 +#define GCC_CAMSS_TFE_0_CLK 52 +#define GCC_CAMSS_TFE_0_CLK_SRC 53 +#define GCC_CAMSS_TFE_0_CPHY_RX_CLK 54 +#define GCC_CAMSS_TFE_0_CSID_CLK 55 +#define GCC_CAMSS_TFE_0_CSID_CLK_SRC 56 +#define GCC_CAMSS_TFE_1_CLK 57 +#define GCC_CAMSS_TFE_1_CLK_SRC 58 +#define GCC_CAMSS_TFE_1_CPHY_RX_CLK 59 +#define GCC_CAMSS_TFE_1_CSID_CLK 60 +#define GCC_CAMSS_TFE_1_CSID_CLK_SRC 61 +#define GCC_CAMSS_TFE_CPHY_RX_CLK_SRC 62 +#define GCC_CAMSS_TOP_AHB_CLK 63 +#define GCC_CAMSS_TOP_AHB_CLK_SRC 64 +#define GCC_CFG_NOC_USB2_PRIM_AXI_CLK 65 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 66 +#define GCC_DDRSS_GPU_AXI_CLK 67 +#define GCC_DDRSS_MEMNOC_PCIE_SF_CLK 68 +#define GCC_DISP_AHB_CLK 69 +#define GCC_DISP_GPLL0_CLK_SRC 70 +#define GCC_DISP_GPLL0_DIV_CLK_SRC 71 +#define GCC_DISP_HF_AXI_CLK 72 +#define GCC_DISP_THROTTLE_CORE_CLK 73 +#define GCC_DISP_XO_CLK 74 +#define GCC_EMAC0_AHB_CLK 75 +#define GCC_EMAC0_AXI_CLK 76 +#define GCC_EMAC0_AXI_CLK_SRC 77 +#define GCC_EMAC0_AXI_SYS_NOC_CLK 78 +#define GCC_EMAC0_CC_SGMIIPHY_RX_CLK 79 +#define GCC_EMAC0_CC_SGMIIPHY_RX_CLK_SRC 80 +#define GCC_EMAC0_CC_SGMIIPHY_TX_CLK 81 +#define GCC_EMAC0_CC_SGMIIPHY_TX_CLK_SRC 82 +#define GCC_EMAC0_PHY_AUX_CLK 83 +#define GCC_EMAC0_PHY_AUX_CLK_SRC 84 +#define GCC_EMAC0_PTP_CLK 85 +#define GCC_EMAC0_PTP_CLK_SRC 86 +#define GCC_EMAC0_RGMII_CLK 87 +#define GCC_EMAC0_RGMII_CLK_SRC 88 +#define GCC_EMAC1_AHB_CLK 89 +#define GCC_EMAC1_AXI_CLK 90 +#define GCC_EMAC1_AXI_CLK_SRC 91 +#define GCC_EMAC1_AXI_SYS_NOC_CLK 92 +#define GCC_EMAC1_CC_SGMIIPHY_RX_CLK 93 +#define GCC_EMAC1_CC_SGMIIPHY_RX_CLK_SRC 94 +#define GCC_EMAC1_CC_SGMIIPHY_TX_CLK 95 +#define GCC_EMAC1_CC_SGMIIPHY_TX_CLK_SRC 96 +#define GCC_EMAC1_PHY_AUX_CLK 97 +#define GCC_EMAC1_PHY_AUX_CLK_SRC 98 +#define GCC_EMAC1_PTP_CLK 99 +#define GCC_EMAC1_PTP_CLK_SRC 100 +#define GCC_EMAC1_RGMII_CLK 101 +#define GCC_EMAC1_RGMII_CLK_SRC 102 +#define GCC_GP1_CLK 103 +#define GCC_GP1_CLK_SRC 104 +#define GCC_GP2_CLK 105 +#define GCC_GP2_CLK_SRC 106 +#define GCC_GP3_CLK 107 +#define GCC_GP3_CLK_SRC 108 +#define GCC_GPU_CFG_AHB_CLK 109 +#define GCC_GPU_GPLL0_CLK_SRC 110 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 111 +#define GCC_GPU_IREF_CLK 112 +#define GCC_GPU_MEMNOC_GFX_CLK 113 +#define GCC_GPU_SMMU_VOTE_CLK 114 +#define GCC_GPU_SNOC_DVM_GFX_CLK 115 +#define GCC_GPU_THROTTLE_CORE_CLK 116 +#define GCC_LPASS_CONFIG_CLK 117 +#define GCC_LPASS_CORE_AXIM_CLK 118 +#define GCC_MMU_TCU_VOTE_CLK 119 +#define GCC_PCIE_AUX_CLK 120 +#define GCC_PCIE_AUX_CLK_SRC 121 +#define GCC_PCIE_AUX_PHY_CLK_SRC 122 +#define GCC_PCIE_CFG_AHB_CLK 123 +#define GCC_PCIE_CLKREF_EN 124 +#define GCC_PCIE_MSTR_AXI_CLK 125 +#define GCC_PCIE_PIPE_CLK 126 +#define GCC_PCIE_PIPE_CLK_SRC 127 +#define GCC_PCIE_RCHNG_PHY_CLK 128 +#define GCC_PCIE_RCHNG_PHY_CLK_SRC 129 +#define GCC_PCIE_SLEEP_CLK 130 +#define GCC_PCIE_SLV_AXI_CLK 131 +#define GCC_PCIE_SLV_Q2A_AXI_CLK 132 +#define GCC_PCIE_TBU_CLK 133 +#define GCC_PCIE_THROTTLE_CORE_CLK 134 +#define GCC_PCIE_THROTTLE_XO_CLK 135 +#define GCC_PCIE_TILE_AXI_SYS_NOC_CLK 136 +#define GCC_PDM2_CLK 137 +#define GCC_PDM2_CLK_SRC 138 +#define GCC_PDM_AHB_CLK 139 +#define GCC_PDM_XO4_CLK 140 +#define GCC_PWM0_XO512_CLK 141 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 142 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 143 +#define GCC_QMIP_DISP_AHB_CLK 144 +#define GCC_QMIP_GPU_CFG_AHB_CLK 145 +#define GCC_QMIP_PCIE_CFG_AHB_CLK 146 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 147 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 148 +#define GCC_QUPV3_WRAP0_CORE_CLK 149 +#define GCC_QUPV3_WRAP0_S0_CLK 150 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 151 +#define GCC_QUPV3_WRAP0_S1_CLK 152 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 153 +#define GCC_QUPV3_WRAP0_S2_CLK 154 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 155 +#define GCC_QUPV3_WRAP0_S3_CLK 156 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 157 +#define GCC_QUPV3_WRAP0_S4_CLK 158 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 159 +#define GCC_QUPV3_WRAP0_S5_CLK 160 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 161 +#define GCC_QUPV3_WRAP0_S6_CLK 162 +#define GCC_QUPV3_WRAP0_S6_CLK_SRC 163 +#define GCC_QUPV3_WRAP0_S7_CLK 164 +#define GCC_QUPV3_WRAP0_S7_CLK_SRC 165 +#define GCC_QUPV3_WRAP0_S8_CLK 166 +#define GCC_QUPV3_WRAP0_S8_CLK_SRC 167 +#define GCC_QUPV3_WRAP0_S9_CLK 168 +#define GCC_QUPV3_WRAP0_S9_CLK_SRC 169 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 170 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 171 +#define GCC_SDCC1_AHB_CLK 172 +#define GCC_SDCC1_APPS_CLK 173 +#define GCC_SDCC1_APPS_CLK_SRC 174 +#define GCC_SDCC1_ICE_CORE_CLK 175 +#define GCC_SDCC1_ICE_CORE_CLK_SRC 176 +#define GCC_SDCC2_AHB_CLK 177 +#define GCC_SDCC2_APPS_CLK 178 +#define GCC_SDCC2_APPS_CLK_SRC 179 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 180 +#define GCC_SYS_NOC_USB2_PRIM_AXI_CLK 181 +#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK 182 +#define GCC_TSCSS_AHB_CLK 183 +#define GCC_TSCSS_CLK_SRC 184 +#define GCC_TSCSS_CNTR_CLK 185 +#define GCC_TSCSS_ETU_CLK 186 +#define GCC_UFS_CLKREF_EN 187 +#define GCC_USB20_MASTER_CLK 188 +#define GCC_USB20_MASTER_CLK_SRC 189 +#define GCC_USB20_MOCK_UTMI_CLK 190 +#define GCC_USB20_MOCK_UTMI_CLK_SRC 191 +#define GCC_USB20_MOCK_UTMI_POSTDIV_CLK_SRC 192 +#define GCC_USB20_SLEEP_CLK 193 +#define GCC_USB30_PRIM_MASTER_CLK 194 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 195 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 196 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 197 +#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 198 +#define GCC_USB30_PRIM_SLEEP_CLK 199 +#define GCC_USB3_PRIM_CLKREF_EN 200 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 201 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 202 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 203 +#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 204 +#define GCC_VCODEC0_AXI_CLK 205 +#define GCC_VENUS_AHB_CLK 206 +#define GCC_VENUS_CTL_AXI_CLK 207 +#define GCC_VIDEO_AHB_CLK 208 +#define GCC_VIDEO_AXI0_CLK 209 +#define GCC_VIDEO_THROTTLE_CORE_CLK 210 +#define GCC_VIDEO_VCODEC0_SYS_CLK 211 +#define GCC_VIDEO_VENUS_CLK_SRC 212 +#define GCC_VIDEO_VENUS_CTL_CLK 213 +#define GCC_VIDEO_XO_CLK 214 + +/* GCC power domains */ +#define GCC_CAMSS_TOP_GDSC 0 +#define GCC_EMAC0_GDSC 1 +#define GCC_EMAC1_GDSC 2 +#define GCC_PCIE_GDSC 3 +#define GCC_USB20_GDSC 4 +#define GCC_USB30_PRIM_GDSC 5 +#define GCC_VCODEC0_GDSC 6 +#define GCC_VENUS_GDSC 7 + +/* GCC resets */ +#define GCC_CAMSS_OPE_BCR 0 +#define GCC_CAMSS_TFE_BCR 1 +#define GCC_CAMSS_TOP_BCR 2 +#define GCC_EMAC0_BCR 3 +#define GCC_EMAC1_BCR 4 +#define GCC_GPU_BCR 5 +#define GCC_MMSS_BCR 6 +#define GCC_PCIE_BCR 7 +#define GCC_PCIE_PHY_BCR 8 +#define GCC_PDM_BCR 9 +#define GCC_QUPV3_WRAPPER_0_BCR 10 +#define GCC_QUSB2PHY_PRIM_BCR 11 +#define GCC_QUSB2PHY_SEC_BCR 12 +#define GCC_SDCC1_BCR 13 +#define GCC_SDCC2_BCR 14 +#define GCC_TSCSS_BCR 15 +#define GCC_USB20_BCR 16 +#define GCC_USB30_PRIM_BCR 17 +#define GCC_USB3PHY_PHY_PRIM_SP0_BCR 18 +#define GCC_USB3_PHY_PRIM_SP0_BCR 19 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 20 +#define GCC_VCODEC0_BCR 21 +#define GCC_VENUS_BCR 22 +#define GCC_VIDEO_INTERFACE_BCR 23 + +#endif diff --git a/include/dt-bindings/mailbox/qcom-ipcc.h b/include/dt-bindings/mailbox/qcom-ipcc.h index fd85a79381b31..b9f358a9b7aee 100644 --- a/include/dt-bindings/mailbox/qcom-ipcc.h +++ b/include/dt-bindings/mailbox/qcom-ipcc.h @@ -33,6 +33,10 @@ #define IPCC_CLIENT_NSP1 18 #define IPCC_CLIENT_TME 23 #define IPCC_CLIENT_WPSS 24 +#define IPCC_CLIENT_RTSS0 27 +#define IPCC_CLIENT_RTSS1 28 +#define IPCC_CLIENT_RTSS2 29 +#define IPCC_CLIENT_RTSS3 30 #define IPCC_CLIENT_GPDSP0 31 #define IPCC_CLIENT_GPDSP1 32 diff --git a/include/dt-bindings/media/qcom,glymur-iris.h b/include/dt-bindings/media/qcom,glymur-iris.h new file mode 100644 index 0000000000000..dcaa2bc21db56 --- /dev/null +++ b/include/dt-bindings/media/qcom,glymur-iris.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_GLYMUR_IRIS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_GLYMUR_IRIS_H_ + +#define IOMMU_FID_IRIS_FIRMWARE 0 + +#endif diff --git a/include/dt-bindings/media/qcom,qcs615-venus.h b/include/dt-bindings/media/qcom,qcs615-venus.h new file mode 100644 index 0000000000000..ca755f2f6aa40 --- /dev/null +++ b/include/dt-bindings/media/qcom,qcs615-venus.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_QCS615_VENUS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_QCS615_VENUS_H_ + +#define VENUS_FIRMWARE 0 + +#endif diff --git a/include/dt-bindings/media/qcom,sm8550-iris.h b/include/dt-bindings/media/qcom,sm8550-iris.h new file mode 100644 index 0000000000000..5165ef817f8bb --- /dev/null +++ b/include/dt-bindings/media/qcom,sm8550-iris.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_SM8550_IRIS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_SM8550_IRIS_H_ + +/* Function identifiers for iommu-map to attach for the context bank devices */ +#define IRIS_NON_PIXEL_VCODEC 0 +#define IRIS_PIXEL 1 + +#endif diff --git a/include/dt-bindings/phy/phy-qcom-mipi-csi2.h b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..fa48fd75c58d8 --- /dev/null +++ b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Qualcomm MIPI CSI2 PHY constants + * + * Copyright (C) 2026 Linaro Limited + */ + +#ifndef __DT_BINDINGS_PHY_MIPI_CSI2__ +#define __DT_BINDINGS_PHY_MIPI_CSI2__ + +#define PHY_QCOM_CSI2_MODE_DPHY 0 +#define PHY_QCOM_CSI2_MODE_CPHY 1 +#define PHY_QCOM_CSI2_MODE_SPLIT_DPHY 2 + +#endif /* __DT_BINDINGS_PHY_MIPI_CSI2__ */ diff --git a/include/dt-bindings/sound/qcom,lpass.h b/include/dt-bindings/sound/qcom,lpass.h index a9404c3b8884c..e2c29416e2b98 100644 --- a/include/dt-bindings/sound/qcom,lpass.h +++ b/include/dt-bindings/sound/qcom,lpass.h @@ -41,6 +41,8 @@ #define LPASS_CDC_DMA_VA_TX7 32 #define LPASS_CDC_DMA_VA_TX8 33 +#define MI2S_SENARY 34 + #define LPASS_MCLK0 0 #endif /* __DT_QCOM_LPASS_H */ diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h index 45850f2d43425..bc860fcbf0f51 100644 --- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h +++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h @@ -233,6 +233,63 @@ /* Clock ID for RX CORE MCLK2 2X MCLK */ #define LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK 70 +/** Clock ID of the Audio Intf 0 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF0_IBIT 71 +/** Clock ID of the Audio Intf 0 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF0_EBIT 72 +/** Clock ID of the Audio Intf 1 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF1_IBIT 73 +/** Clock ID of the Audio Intf 1 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF1_EBIT 74 +/** Clock ID of the Audio Intf 2 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF2_IBIT 75 +/** Clock ID of the Audio Intf 2 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF2_EBIT 76 +/** Clock ID of the Audio Intf 3 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF3_IBIT 77 +/** Clock ID of the Audio Intf 3 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF3_EBIT 78 +/** Clock ID of the Audio Intf 4 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF4_IBIT 79 +/** Clock ID of the Audio Intf 4 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF4_EBIT 80 +/** Clock ID of the Audio Intf 5 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF5_IBIT 81 +/** Clock ID of the Audio Intf 5 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF5_EBIT 82 +/** Clock ID of the Audio Intf 6 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF6_IBIT 83 +/** Clock ID of the Audio Intf 6 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF6_EBIT 84 +/** Clock ID of the Audio Intf 7 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF7_IBIT 85 +/** Clock ID of the Audio Intf 7 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF7_EBIT 86 +/** Clock ID of the Audio Intf 8 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF8_IBIT 87 +/** Clock ID of the Audio Intf 8 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF8_EBIT 88 +/** Clock ID of the Audio Intf 9 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF9_IBIT 89 +/** Clock ID of the Audio Intf 9 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF9_EBIT 90 +/** Clock ID of the Audio Intf 10 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF10_IBIT 91 +/** Clock ID of the Audio Intf 10 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF10_EBIT 92 +/** Clock ID of the Audio Intf 11 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF11_IBIT 93 +/** Clock ID of the Audio Intf 11 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF11_EBIT 94 +/** Clock ID of the Audio Intf 12 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_INTF12_IBIT 95 +/** Clock ID of the Audio Intf 12 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_INTF12_EBIT 96 +/** Clock ID of the Audio VA Intf 0 internal bit clock (IBIT). */ +#define LPASS_CLK_ID_AUD_VA_INTF0_IBIT 97 +/** Clock ID of the Audio VA Intf 0 external bit clock (EBIT). */ +#define LPASS_CLK_ID_AUD_VA_INTF0_EBIT 98 + #define LPASS_HW_AVTIMER_VOTE 101 #define LPASS_HW_MACRO_VOTE 102 #define LPASS_HW_DCODEC_VOTE 103 diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h new file mode 100644 index 0000000000000..3a899f57f92fb --- /dev/null +++ b/include/linux/acpi_aest.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ACPI_AEST_H__ +#define __ACPI_AEST_H__ + +#include +#include + +/* AEST resource name */ +#define AEST_NODE_NAME "AEST:NODE" +#define AEST_FHI_NAME "AEST:FHI" +#define AEST_ERI_NAME "AEST:ERI" + +/* AEST component */ +#define ACPI_AEST_PROC_FLAG_GLOBAL (1<<0) +#define ACPI_AEST_PROC_FLAG_SHARED (1<<1) + +#define AEST_ADDREESS_SPA 0 +#define AEST_ADDREESS_LA 1 + +/* AEST interrupt */ +#define AEST_INTERRUPT_MODE BIT(0) + +#define AEST_INTERRUPT_FHI_UE_SUPPORT BIT(0) +#define AEST_INTERRUPT_FHI_UE_NO_SUPPORT BIT(1) + +#define AEST_MAX_INTERRUPT_PER_NODE 2 + +/* AEST interface */ +#define AEST_XFACE_FLAG_SHARED (1 << 0) +#define AEST_XFACE_FLAG_CLEAR_MISC (1 << 1) +#define AEST_XFACE_FLAG_ERROR_DEVICE (1 << 2) +#define AEST_XFACE_FLAG_AFFINITY (1 << 3) +#define AEST_XFACE_FLAG_ERROR_GROUP (1 << 4) +#define AEST_XFACE_FLAG_FAULT_INJECT (1 << 5) +#define AEST_XFACE_FLAG_INT_CONFIG (1 << 6) + +#define KB 1024 +#define MB (1024 * KB) +#define GB (1024 * MB) + +struct aest_hnode { + struct list_head list; + int count; + u32 id; + int type; +}; + +struct acpi_aest_node { + struct list_head list; + int type; + struct acpi_aest_node_interface_header *interface_hdr; + unsigned long *record_implemented; + unsigned long *status_reporting; + unsigned long *addressing_mode; + struct acpi_aest_node_interface_common *common; + union { + struct acpi_aest_processor *processor; + struct acpi_aest_memory *memory; + struct acpi_aest_smmu *smmu; + struct acpi_aest_vendor_v2 *vendor; + struct acpi_aest_gic *gic; + struct acpi_aest_pcie *pcie; + struct acpi_aest_proxy *proxy; + void *spec_pointer; + }; + union { + struct acpi_aest_processor_cache *cache; + struct acpi_aest_processor_tlb *tlb; + struct acpi_aest_processor_generic *generic; + void *processor_spec_pointer; + }; + struct acpi_aest_node_interrupt_v2 *interrupt; + int interrupt_count; +}; +#endif /* __ACPI_AEST_H__ */ diff --git a/include/linux/coresight.h b/include/linux/coresight.h index ddf18c970e343..7beb70f9990a3 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -388,7 +388,8 @@ struct coresight_ops_sink { struct coresight_ops_link { int (*enable)(struct coresight_device *csdev, struct coresight_connection *in, - struct coresight_connection *out); + struct coresight_connection *out, + enum cs_mode mode); void (*disable)(struct coresight_device *csdev, struct coresight_connection *in, struct coresight_connection *out); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 0fb3a2a62eb00..7f20b820bad11 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -178,6 +178,7 @@ enum cpuhp_state { CPUHP_AP_HYPERV_TIMER_STARTING, /* Must be the last timer callback */ CPUHP_AP_DUMMY_TIMER_STARTING, + CPUHP_AP_ARM_AEST_STARTING, CPUHP_AP_ARM_XEN_STARTING, CPUHP_AP_ARM_XEN_RUNSTATE_STARTING, CPUHP_AP_ARM_CORESIGHT_CTI_STARTING, diff --git a/include/linux/dma/qcom-gpi-dma.h b/include/linux/dma/qcom-gpi-dma.h index 332be28427e47..f10fa93713f96 100644 --- a/include/linux/dma/qcom-gpi-dma.h +++ b/include/linux/dma/qcom-gpi-dma.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2020, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef QCOM_GPI_DMA_H @@ -54,6 +55,21 @@ enum i2c_op { I2C_READ, }; +/** + * enum gpi_lock_action - request lock/unlock TRE sequencing + * @GPI_LOCK_NONE: No lock/unlock TRE requested for this transfer + * @GPI_LOCK_ACQUIRE: Emit a lock TRE before the transfer + * @GPI_LOCK_RELEASE: Emit an unlock TRE after the transfer + * + * Used by protocol drivers for multi-owner controller setups (e.g. when + * DeviceTree indicates the controller is shared via qcom,qup-multi-owner). + */ +enum gpi_lock_action { + GPI_LOCK_NONE = 0, + GPI_LOCK_ACQUIRE, + GPI_LOCK_RELEASE, +}; + /** * struct gpi_i2c_config - i2c config for peripheral * @@ -67,7 +83,8 @@ enum i2c_op { * @set_config: set peripheral config * @rx_len: receive length for buffer * @op: i2c cmd - * @multi_msg: is part of multi i2c r-w msgs + * @muli-msg: is part of multi i2c r-w msgs + * @lock_action: request lock/unlock TRE sequencing for this transfer */ struct gpi_i2c_config { u8 set_config; @@ -81,6 +98,7 @@ struct gpi_i2c_config { u32 rx_len; enum i2c_op op; bool multi_msg; + enum gpi_lock_action lock_action; }; #endif /* QCOM_GPI_DMA_H */ diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h index 68fc0e643b1b9..a2594264b0f58 100644 --- a/include/linux/dma/qcom_bam_dma.h +++ b/include/linux/dma/qcom_bam_dma.h @@ -6,6 +6,8 @@ #ifndef _QCOM_BAM_DMA_H #define _QCOM_BAM_DMA_H +#include + #include /* @@ -34,6 +36,18 @@ enum bam_command_type { BAM_READ_COMMAND, }; +/** + * struct bam_desc_metadata - DMA descriptor metadata specific to the BAM driver. + * + * @scratchpad_addr: Physical address to use for dummy write operations when + * queuing command descriptors with LOCK/UNLOCK bits set. + * @direction: Transfer direction of this channel. + */ +struct bam_desc_metadata { + phys_addr_t scratchpad_addr; + enum dma_transfer_direction direction; +}; + /* * prep_bam_ce_le32 - Wrapper function to prepare a single BAM command * element with the data already in le32 format. diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index b3d251c9734e9..5244edb90e7e7 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -623,7 +623,7 @@ struct dma_async_tx_descriptor { void *callback_param; struct dmaengine_unmap_data *unmap; enum dma_desc_metadata_mode desc_metadata_mode; - struct dma_descriptor_metadata_ops *metadata_ops; + const struct dma_descriptor_metadata_ops *metadata_ops; #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH struct dma_async_tx_descriptor *next; struct dma_async_tx_descriptor *parent; diff --git a/include/linux/firmware/qcom/memory_dump.h b/include/linux/firmware/qcom/memory_dump.h new file mode 100644 index 0000000000000..ead7add4265c5 --- /dev/null +++ b/include/linux/firmware/qcom/memory_dump.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012, 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __MSM_MEMORY_DUMP_H +#define __MSM_MEMORY_DUMP_H + +#include +#include + +enum dump_client_type { + MSM_CPU_CTXT = 0, + MSM_L1_CACHE, + MSM_L2_CACHE, + MSM_OCMEM, + MSM_TMC_ETFETB, + MSM_ETM0_REG, + MSM_ETM1_REG, + MSM_ETM2_REG, + MSM_ETM3_REG, + MSM_TMC0_REG, /* TMC_ETR */ + MSM_TMC1_REG, /* TMC_ETF */ + MSM_LOG_BUF, + MSM_LOG_BUF_FIRST_IDX, + MAX_NUM_CLIENTS, +}; + +struct msm_client_dump { + enum dump_client_type id; + unsigned long start_addr; + unsigned long end_addr; +}; + +void __init reserve_memdump_cma(void); +extern struct cma *memdump_cma; + +#ifdef CONFIG_QCOM_MEMORY_DUMP +extern int msm_dump_tbl_register(struct msm_client_dump *client_entry); +#else +static inline int msm_dump_tbl_register(struct msm_client_dump *entry) +{ + return -EIO; +} +#endif + +#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) +extern uint32_t msm_dump_table_version(void); +#else +static inline uint32_t msm_dump_table_version(void) +{ + return 0; +} +#endif + +#define MSM_DUMP_MAKE_VERSION(ma, mi) ((ma << 20) | mi) +#define MSM_DUMP_MAJOR(val) (val >> 20) +#define MSM_DUMP_MINOR(val) (val & 0xFFFFF) + + +#define MAX_NUM_ENTRIES 0x150 + +enum msm_dump_data_ids { + MSM_DUMP_DATA_CPU_CTX = 0x00, + MSM_DUMP_DATA_L1_INST_CACHE = 0x60, + MSM_DUMP_DATA_L1_DATA_CACHE = 0x80, + MSM_DUMP_DATA_ETM_REG = 0xA0, + MSM_DUMP_DATA_L2_CACHE = 0xC0, + MSM_DUMP_DATA_L3_CACHE = 0xD0, + MSM_DUMP_DATA_OCMEM = 0xE0, + MSM_DUMP_DATA_CNSS_WLAN = 0xE1, + MSM_DUMP_DATA_WIGIG = 0xE2, + MSM_DUMP_DATA_PMIC = 0xE4, + MSM_DUMP_DATA_DBGUI_REG = 0xE5, + MSM_DUMP_DATA_DCC_REG = 0xE6, + MSM_DUMP_DATA_DCC_SRAM = 0xE7, + MSM_DUMP_DATA_MISC = 0xE8, + MSM_DUMP_DATA_VSENSE = 0xE9, + MSM_DUMP_DATA_RPM = 0xEA, + MSM_DUMP_DATA_SCANDUMP = 0xEB, + MSM_DUMP_DATA_RPMH = 0xEC, + MSM_DUMP_DATA_TMC_ETF = 0xF0, + MSM_DUMP_DATA_TMC_ETF_SWAO = 0xF1, + MSM_DUMP_DATA_TMC_REG = 0x100, + MSM_DUMP_DATA_TMC_ETF_SWAO_REG = 0x102, + MSM_DUMP_DATA_LOG_BUF = 0x110, + MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111, + MSM_DUMP_DATA_SCANDUMP_PER_CPU = 0x130, + MSM_DUMP_DATA_LLCC_PER_INSTANCE = 0x140, + MSM_DUMP_DATA_MAX = MAX_NUM_ENTRIES, +}; + +enum msm_dump_table_ids { + MSM_DUMP_TABLE_APPS, + MSM_DUMP_TABLE_MAX = MAX_NUM_ENTRIES, +}; + +enum msm_dump_type { + MSM_DUMP_TYPE_DATA, + MSM_DUMP_TYPE_TABLE, +}; + +struct msm_dump_data { + uint32_t version; + uint32_t magic; + char name[32]; + uint64_t addr; + uint64_t len; + uint32_t reserved; +}; + +struct msm_dump_entry { + uint32_t id; + char name[32]; + uint32_t type; + uint64_t addr; +}; + +struct dump_item { + u32 dump_id; + size_t size; + const char *name; +}; + +struct dump_table { + const struct dump_item *items; + u32 num_of_items; + phys_addr_t imem_base; + resource_size_t imem_size; +}; + +#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) +extern int msm_dump_data_register(enum msm_dump_table_ids id, + struct msm_dump_entry *entry); +extern int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry); +#else +static inline int msm_dump_data_register(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return -EINVAL; +} +static inline int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return -EINVAL; +} +#endif + +#endif diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h index 5747bd191bf15..d84b5eb6870c6 100644 --- a/include/linux/firmware/qcom/qcom_scm.h +++ b/include/linux/firmware/qcom/qcom_scm.h @@ -10,10 +10,12 @@ #include #include +#include #define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) #define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0 #define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1 +#define QCOM_SCM_CAMERA_MAX_QOS_CNT 2 #define QCOM_SCM_HDCP_MAX_REQ_CNT 5 struct qcom_scm_hdcp_req { @@ -77,6 +79,14 @@ struct qcom_scm_pas_context { bool use_tzmem; }; +struct qcom_scm_camera_qos { + u32 offset; + u32 val; +}; + +int qcom_scm_camera_update_camnoc_qos(uint32_t use_case_id, + uint32_t qos_cnt, struct qcom_scm_camera_qos *scm_buf); + struct qcom_scm_pas_context *devm_qcom_scm_pas_context_alloc(struct device *dev, u32 pas_id, phys_addr_t mem_phys, diff --git a/include/linux/iio/adc/qcom-adc5-gen3-common.h b/include/linux/iio/adc/qcom-adc5-gen3-common.h index 6303eaa6640be..39cbfcbdb101c 100644 --- a/include/linux/iio/adc/qcom-adc5-gen3-common.h +++ b/include/linux/iio/adc/qcom-adc5-gen3-common.h @@ -205,7 +205,5 @@ int adc5_gen3_get_scaled_reading(struct device *dev, int adc5_gen3_therm_code_to_temp(struct device *dev, struct adc5_channel_common_prop *common_props, u16 code, int *val); -void adc5_gen3_register_tm_event_notifier(struct device *dev, - void (*handler)(struct auxiliary_device *)); #endif /* QCOM_ADC5_GEN3_COMMON_H */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ba84f02c2a101..83d92fb64417f 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -457,12 +457,9 @@ struct mmc_host { #define MMC_CAP2_CQE_DCMD (1 << 24) /* CQE can issue a direct command */ #define MMC_CAP2_AVOID_3_3V (1 << 25) /* Host must negotiate down from 3.3V */ #define MMC_CAP2_MERGE_CAPABLE (1 << 26) /* Host can merge a segment over the segment size */ -#ifdef CONFIG_MMC_CRYPTO #define MMC_CAP2_CRYPTO (1 << 27) /* Host supports inline encryption */ -#else -#define MMC_CAP2_CRYPTO 0 -#endif #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */ +#define MMC_CAP2_CRYPTO_NO_REPROG (1 << 29) /* Host handles inline crypto key reprogramming */ bool uhs2_sd_tran; /* UHS-II flag for SD_TRAN state */ bool uhs2_app_cmd; /* UHS-II flag for APP command */ diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index 1ac128d78dfeb..f7b4ad29e6f83 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -6,6 +6,8 @@ #ifndef __PHY_MIPI_DPHY_H_ #define __PHY_MIPI_DPHY_H_ +#define PHY_MIPI_DPHY_MAX_DATA_LANES 4 + /** * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set * @@ -269,10 +271,41 @@ struct phy_configure_opts_mipi_dphy { /** * @lanes: * - * Number of active, consecutive, data lanes, starting from - * lane 0, used for the transmissions. + * Number of active data lanes used for the transmission. + * When @lane_positions is not populated, lanes are consecutive + * starting from lane 0. */ unsigned char lanes; + + /** + * @lane_positions: + * + * Array representing the physical positions of the data-lanes. + * Indexed by logical lane number. + */ + unsigned char lane_positions[PHY_MIPI_DPHY_MAX_DATA_LANES]; + + /** + * @lane_polarities: + * + * Array representing data-lane polarities. True means inverted. + * Indexed by logical lane number. + */ + bool lane_polarities[PHY_MIPI_DPHY_MAX_DATA_LANES]; + + /** + * @clock_lane_position: + * + * Physical lane number used as the clock lane. + */ + unsigned char clock_lane_position; + + /** + * @clock_lane_polarity: + * + * Clock lane polarity. True means inverted. + */ + bool clock_lane_polarity; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, diff --git a/include/linux/ras.h b/include/linux/ras.h index 468941bfe855f..05096f049dacb 100644 --- a/include/linux/ras.h +++ b/include/linux/ras.h @@ -63,4 +63,12 @@ amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) { return -EINVAL; } #define GET_LOGICAL_INDEX(mpidr) -EINVAL #endif /* CONFIG_ARM || CONFIG_ARM64 */ +#if IS_ENABLED(CONFIG_AEST) +void aest_register_decode_chain(struct notifier_block *nb); +void aest_unregister_decode_chain(struct notifier_block *nb); +#else +static inline void aest_register_decode_chain(struct notifier_block *nb) {} +static inline void aest_unregister_decode_chain(struct notifier_block *nb) {} +#endif /* CONFIG_AEST */ + #endif /* __RAS_H__ */ diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 4a2abb38d1d61..56581199af234 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -2,14 +2,18 @@ #ifndef __REBOOT_MODE_H__ #define __REBOOT_MODE_H__ +#include +#include + struct reboot_mode_driver { struct device *dev; + const char *name; struct list_head head; - int (*write)(struct reboot_mode_driver *reboot, unsigned int magic); + int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; }; -int reboot_mode_register(struct reboot_mode_driver *reboot); +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode); int reboot_mode_unregister(struct reboot_mode_driver *reboot); int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver *reboot); diff --git a/include/linux/soc/qcom/geni-se.h b/include/linux/soc/qcom/geni-se.h index c5e6ab85df099..6a8f67a5f1c83 100644 --- a/include/linux/soc/qcom/geni-se.h +++ b/include/linux/soc/qcom/geni-se.h @@ -66,6 +66,7 @@ struct geni_icc_path { * @icc_paths: Array of ICC paths for SE * @pd_list: Power domain list for managing power domains * @has_opp: Indicates if OPP is supported + * @multi_owner: True if SE is shared between multiprocessors. */ struct geni_se { void __iomem *base; @@ -78,6 +79,7 @@ struct geni_se { struct geni_icc_path icc_paths[3]; struct dev_pm_domain_list *pd_list; bool has_opp; + bool multi_owner; }; /* Common SE registers */ diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h index 82372e0db0a18..7c551b98e1822 100644 --- a/include/linux/soc/qcom/mdt_loader.h +++ b/include/linux/soc/qcom/mdt_loader.h @@ -21,7 +21,7 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw, phys_addr_t *reloc_base); int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, - const char *firmware, void *mem_region, phys_addr_t *reloc_base); + const char *firmware, phys_addr_t *reloc_base); int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, const char *fw_name, void *mem_region, @@ -47,7 +47,7 @@ static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw, static inline int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, const char *firmware, - void *mem_region, phys_addr_t *reloc_base) + phys_addr_t *reloc_base) { return -ENODEV; } diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h index b9dcb437a0be5..683d27cee4132 100644 --- a/include/linux/soc/qcom/qmi.h +++ b/include/linux/soc/qcom/qmi.h @@ -96,6 +96,7 @@ struct qmi_elem_info { * Enumerate the IDs of the QMI services */ #define QMI_SERVICE_ID_TEST 0x0f /* 15 */ +#define QMI_SERVICE_ID_TMD 0x18 /* 24 */ #define QMI_SERVICE_ID_SSCTL 0x2b /* 43 */ #define QMI_SERVICE_ID_IPA 0x31 /* 49 */ #define QMI_SERVICE_ID_SERVREG_LOC 0x40 /* 64 */ diff --git a/include/linux/soc/qcom/qmi_tmd.h b/include/linux/soc/qcom/qmi_tmd.h new file mode 100644 index 0000000000000..75373eb09d618 --- /dev/null +++ b/include/linux/soc/qcom/qmi_tmd.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QMI Thermal Mitigation Device (TMD) library header. + */ + +#ifndef __QMI_TMD_H__ +#define __QMI_TMD_H__ + +struct device; +struct qmi_tmd_client; + +struct qmi_tmd_client *qmi_tmd_init(struct device *dev, + const char *remoteproc_name, + const char * const *tmd_names, + int num_tmds); + +void qmi_tmd_exit(struct qmi_tmd_client *tmd_cli); + +#endif /* __QMI_TMD_H__ */ + diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h index f946e3beca215..223cd5090a2a8 100644 --- a/include/linux/soc/qcom/smem.h +++ b/include/linux/soc/qcom/smem.h @@ -2,6 +2,8 @@ #ifndef __QCOM_SMEM_H__ #define __QCOM_SMEM_H__ +#include + #define QCOM_SMEM_HOST_ANY -1 bool qcom_smem_is_available(void); @@ -17,4 +19,6 @@ int qcom_smem_get_feature_code(u32 *code); int qcom_smem_bust_hwspin_lock_by_host(unsigned int host); +int qcom_smem_dram_get_hbb(void); + #endif diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 3dae0f592063e..1665a9ce8f941 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -32,8 +32,12 @@ struct scatterlist; #define IO_TLB_SHIFT 11 #define IO_TLB_SIZE (1 << IO_TLB_SHIFT) -/* default to 64MB */ -#define IO_TLB_DEFAULT_SIZE (64UL<<20) +/* compile-time default; overridable via CONFIG_SWIOTLB_DEFAULT_SIZE_MB */ +#ifdef CONFIG_SWIOTLB +#define IO_TLB_DEFAULT_SIZE ((unsigned long)CONFIG_SWIOTLB_DEFAULT_SIZE_MB << 20) +#else +#define IO_TLB_DEFAULT_SIZE (64UL << 20) +#endif unsigned long swiotlb_size_or_default(void); void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags, diff --git a/include/linux/usb/qcom_eud.h b/include/linux/usb/qcom_eud.h new file mode 100644 index 0000000000000..fe560426b78f3 --- /dev/null +++ b/include/linux/usb/qcom_eud.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __LINUX_USB_QCOM_EUD_H +#define __LINUX_USB_QCOM_EUD_H + +#include + +#if IS_ENABLED(CONFIG_USB_QCOM_EUD) +void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role); +#else +static inline void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role) +{ +} +#endif + +#endif /* __LINUX_USB_QCOM_EUD_H */ diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h index fdb785fa4613a..c4063f7ad7342 100644 --- a/include/ras/ras_event.h +++ b/include/ras/ras_event.h @@ -381,6 +381,77 @@ TRACE_EVENT(aer_event, "Not available") ); #endif /* CONFIG_PCIEAER */ + +/* + * ARM RAS Extension Events Report + * + * This event is generated when an error reported by the ARM RAS extension + * hardware is detected. + */ + +#ifdef CONFIG_ARM64_RAS_EXTN +#include +TRACE_EVENT(arm_ras_ext_event, + + TP_PROTO(const u8 type, + const u32 id0, + const u32 id1, + const u32 index, + char *hid, + struct ras_ext_regs *regs, + const u8 *data, + const u32 len), + + TP_ARGS(type, id0, id1, index, hid, regs, data, len), + + TP_STRUCT__entry( + __field(u8, type) + __field(u32, id0) + __field(u32, id1) + __field(u32, index) + __field(char *, hid) + __field(u64, err_fr) + __field(u64, err_ctlr) + __field(u64, err_status) + __field(u64, err_addr) + __field(u64, err_misc0) + __field(u64, err_misc1) + __field(u64, err_misc2) + __field(u64, err_misc3) + __field(u32, len) + __dynamic_array(u8, buf, len) + ), + + TP_fast_assign( + __entry->type = type; + __entry->id0 = id0; + __entry->id1 = id1; + __entry->index = index; + __entry->hid = hid; + __entry->err_fr = regs->err_fr; + __entry->err_ctlr = regs->err_ctlr; + __entry->err_status = regs->err_status; + __entry->err_addr = regs->err_addr; + __entry->err_misc0 = regs->err_misc[0]; + __entry->err_misc1 = regs->err_misc[1]; + __entry->err_misc2 = regs->err_misc[2]; + __entry->err_misc3 = regs->err_misc[3]; + __entry->len = len; + memcpy(__get_dynamic_array(buf), data, len); + ), + + TP_printk("type: %d; id0: %d; id1: %d; index: %d; hid: %s; " + "ERR_FR: %llx; ERR_CTLR: %llx; ERR_STATUS: %llx; " + "ERR_ADDR: %llx; ERR_MISC0: %llx; ERR_MISC1: %llx; " + "ERR_MISC2: %llx; ERR_MISC3: %llx; data len:%d; raw data:%s", + __entry->type, __entry->id0, __entry->id1, __entry->index, + __entry->hid, __entry->err_fr, __entry->err_ctlr, + __entry->err_status, __entry->err_addr, __entry->err_misc0, + __entry->err_misc1, __entry->err_misc2, __entry->err_misc3, + __entry->len, + __print_hex(__get_dynamic_array(buf), __entry->len)) +); +#endif /* CONFIG_ARM64_RAS_EXTN */ #endif /* _TRACE_HW_EVENT_MC_H */ /* This part must be outside protection */ diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h index c6e2925f47e69..ba1ea5ed426c4 100644 --- a/include/uapi/misc/fastrpc.h +++ b/include/uapi/misc/fastrpc.h @@ -16,6 +16,7 @@ #define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static) #define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map) #define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap) +#define FASTRPC_IOCTL_SET_OPTION _IOWR('R', 12, struct fastrpc_ioctl_set_option) #define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability) /** @@ -67,6 +68,28 @@ enum fastrpc_proc_attr { /* Fastrpc attribute for memory protection of buffers */ #define FASTRPC_ATTR_SECUREMAP (1) +/** + * FASTRPC_POLL_MODE - Enable/disable poll mode for FastRPC invocations + * + * Poll mode is an optimization that allows the CPU to poll shared memory + * for completion instead of waiting for an interrupt-based response. + * This reduces latency for fast-completing operations. + * + * Restrictions: + * - Only supported for USER_PD (User Protection Domain) + * - Only applies to dynamic modules (handle > 20) + * - Static modules always use interrupt-based completion + * + * Values: + * - 0: Disable poll mode (use interrupt-based completion) + * - 1: Enable poll mode (poll shared memory for completion) + */ +#define FASTRPC_POLL_MODE (1) + +/* Values for FASTRPC_POLL_MODE request */ +#define FASTRPC_POLL_MODE_DISABLE 0 +#define FASTRPC_POLL_MODE_ENABLE 1 + struct fastrpc_invoke_args { __u64 ptr; __u64 length; @@ -133,6 +156,12 @@ struct fastrpc_mem_unmap { __s32 reserved[5]; }; +struct fastrpc_ioctl_set_option { + __u32 request_id; /* Request type (e.g., FASTRPC_POLL_MODE) */ + __u32 value; /* Request-specific value */ + __s32 reserved[6]; +}; + struct fastrpc_ioctl_capability { __u32 unused; /* deprecated, ignored by the kernel */ __u32 attribute_id; diff --git a/include/uapi/sound/snd_ar_tokens.h b/include/uapi/sound/snd_ar_tokens.h index 6b8102eaa121f..dd14d2a88d863 100644 --- a/include/uapi/sound/snd_ar_tokens.h +++ b/include/uapi/sound/snd_ar_tokens.h @@ -168,6 +168,47 @@ enum ar_event_types { * LOG_WAIT = 0, * LOG_IMMEDIATELY = 1 * + * %AR_TKN_U32_MODULE_SYNC_SRC: Frame sync source + * 0 = external, 1 = internal + * + * %AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE: Enable data-out tri-state control + * 0 = disable, 1 = enable + * + * %AR_TKN_U32_MODULE_SLOT_MASK: Active TDM slot bitmask + * + * %AR_TKN_U32_MODULE_NSLOTS_PER_FRAME: Number of slots per TDM frame + * + * %AR_TKN_U32_MODULE_SLOT_WIDTH: Slot width in bits (16 or 32) + * + * %AR_TKN_U32_MODULE_SYNC_MODE: Frame sync mode + * 0 = short pulse, 1 = long pulse + * + * %AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE: Invert frame sync pulse polarity + * 0 = normal, 1 = inverted + * + * %AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY: Data delay relative to frame sync + * 0 = no delay, 1 = one cycle delay + * + * %AR_TKN_U32_MODULE_INTF_MODE: Audio IF interface mode + * AUDIO_IF_INTF_MODE_TDM = 0, + * AUDIO_IF_INTF_MODE_PCM = 1, + * AUDIO_IF_INTF_MODE_I2S = 2 + * + * %AR_TKN_U32_MODULE_QAIF_TYPE: QAIF hardware port type index + * + * %AR_TKN_U32_MODULE_ACTIVE_LANE_MASK: Active lane bitmask for multi-lane + * + * %AR_TKN_U32_MODULE_FRAME_SYNC_RATE: Frame sync rate in Hz + * + * %AR_TKN_U32_MODULE_BIT_CLK_TYPE: Bit clock type + * 0 = internal, 1 = external + * + * %AR_TKN_U32_MODULE_INV_INT_BIT_CLK: Invert internal bit clock + * 0 = normal, 1 = inverted + * + * %AR_TKN_U32_MODULE_INV_EXT_BIT_CLK: Invert external bit clock + * 0 = normal, 1 = inverted + * * %AR_TKN_DAI_INDEX: dai index * */ @@ -240,6 +281,22 @@ enum ar_event_types { #define AR_TKN_U32_MODULE_LOG_TAP_POINT_ID 260 #define AR_TKN_U32_MODULE_LOG_MODE 261 +#define AR_TKN_U32_MODULE_SYNC_SRC 262 +#define AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE 263 +#define AR_TKN_U32_MODULE_SLOT_MASK 264 +#define AR_TKN_U32_MODULE_NSLOTS_PER_FRAME 265 +#define AR_TKN_U32_MODULE_SLOT_WIDTH 266 +#define AR_TKN_U32_MODULE_SYNC_MODE 267 +#define AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE 268 +#define AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY 269 +#define AR_TKN_U32_MODULE_INTF_MODE 270 +#define AR_TKN_U32_MODULE_QAIF_TYPE 271 +#define AR_TKN_U32_MODULE_ACTIVE_LANE_MASK 272 +#define AR_TKN_U32_MODULE_FRAME_SYNC_RATE 273 +#define AR_TKN_U32_MODULE_BIT_CLK_TYPE 274 +#define AR_TKN_U32_MODULE_INV_INT_BIT_CLK 275 +#define AR_TKN_U32_MODULE_INV_EXT_BIT_CLK 276 + #define SND_SOC_AR_TPLG_MODULE_CFG_TYPE 0x01001006 struct audioreach_module_priv_data { __le32 size; /* size in bytes of the array, including all elements */ diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 248d0a5bef407..98ea715c03051 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -812,7 +812,22 @@ enum ufshcd_quirks { * (EQTR) using Adapt L0L1L2L3 length which is larger than what is * allowed by M-PHY spec ver 6.0. */ + UFSHCD_QUIRK_EXTENDED_TX_EQTR_ADAPT_LENGTH_L0L1L2L3 = 1 << 28, + /* + * Some UFS devices keep drawing larger current after reset is + * asserted until it is deasserted. Asserting device reset + * during UFS power down causes the device firmware to wake up and + * execute its reset routine, drawing current beyond the permissible + * limit for low-power mode (LPM). This may trigger an OCP fault on + * the regulator supplying power to UFS. + * + * Enable this quirk to skip asserting device reset during UFS power + * down. This is handled only in shutdown; the device reset will be + * asserted as part of the platform shutdown sequence. + */ + + UFSHCD_QUIRK_SKIP_DEVICE_RESET = 1 << 29, }; enum ufshcd_caps { diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 307c97ac5fa9c..f6ca58cf61e04 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -32,12 +32,12 @@ CONFIG_SECTION_MISMATCH_WARN_ONLY=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS_ALLOW_ALL=y CONFIG_DEBUG_IRQFLAGS=y -CONFIG_UBSAN=y -CONFIG_UBSAN_BOOL=y -CONFIG_UBSAN_BOUNDS=y -CONFIG_UBSAN_ENUM=y -CONFIG_UBSAN_SHIFT=y -CONFIG_UBSAN_UNREACHABLE=y +# CONFIG_UBSAN is not set +# CONFIG_UBSAN_BOOL is not set +# CONFIG_UBSAN_BOUNDS is not set +# CONFIG_UBSAN_ENUM is not set +# CONFIG_UBSAN_SHIFT is not set +# CONFIG_UBSAN_UNREACHABLE is not set # # Networking Debugging # @@ -56,8 +56,8 @@ CONFIG_DEBUG_NET=y # CONFIG_SLUB_STATS is not set CONFIG_PAGE_EXTENSION=y CONFIG_PAGE_OWNER=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN is not set CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 CONFIG_DEBUG_OBJECTS_FREE=y @@ -72,10 +72,10 @@ CONFIG_DEBUG_VM=y CONFIG_DEBUG_VM_PGFLAGS=y CONFIG_DEBUG_VM_RB=y CONFIG_DEBUG_VM_VMACACHE=y -CONFIG_KASAN=y -CONFIG_KASAN_GENERIC=y -CONFIG_KASAN_INLINE=y -CONFIG_KASAN_VMALLOC=y +# CONFIG_KASAN is not set +# CONFIG_KASAN_GENERIC is not set +# CONFIG_KASAN_INLINE is not set +# CONFIG_KASAN_VMALLOC is not set CONFIG_PTDUMP_DEBUGFS=y CONFIG_SCHED_STACK_END_CHECK=y CONFIG_SLUB_DEBUG_ON=y @@ -93,7 +93,7 @@ CONFIG_SOFTLOCKUP_DETECTOR=y # Lock Debugging (spinlocks, mutexes, etc...) # # CONFIG_PROVE_RAW_LOCK_NESTING is not set -CONFIG_PROVE_LOCKING=y +# CONFIG_PROVE_LOCKING is not set # # Debug kernel data structures # @@ -101,18 +101,97 @@ CONFIG_BUG_ON_DATA_CORRUPTION=y # # RCU Debugging # -CONFIG_RCU_EXPERT=y -CONFIG_PROVE_RCU=y -CONFIG_PROVE_RCU_LIST=y +# CONFIG_RCU_EXPERT is not set +# CONFIG_PROVE_RCU is not set +# CONFIG_PROVE_RCU_LIST is not set # # Tracers # CONFIG_BRANCH_PROFILE_NONE=y CONFIG_DYNAMIC_FTRACE=y CONFIG_FTRACE=y -CONFIG_FUNCTION_TRACER=y +# CONFIG_FUNCTION_TRACER is not set # # Preemption # CONFIG_DEBUG_PREEMPT=y CONFIG_PREEMPT=y + +# +# Qualcomm Debug Configs +# +CONFIG_ATH11K_CFR=y +CONFIG_ATH11K_COREDUMP=y +CONFIG_ATH11K_DEBUG=y +CONFIG_ATH11K_DEBUGFS=y +CONFIG_ATH11K_TRACING=y +CONFIG_ATH12K_COREDUMP=y +CONFIG_ATH12K_DEBUG=y +CONFIG_ATH12K_DEBUGFS=y +CONFIG_ATH12K_TRACING=y +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CMA_DEBUG=y +CONFIG_CMA_DEBUGFS=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000 +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DEBUG_RWSEMS=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_DMABUF_SYSFS_STATS=y +CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y +CONFIG_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_EFI_VARS_PSTORE=y +CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y +CONFIG_FTRACE_MCOUNT_RECORD=y +CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_FUNCTION_ALIGNMENT=8 +CONFIG_FUNCTION_ALIGNMENT_8B=y +CONFIG_FUNCTION_GRAPH_TRACER=y +# CONFIG_FW_LOADER_DEBUG is not set +CONFIG_GENERIC_TRACER=y +CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y +CONFIG_HWLAT_TRACER=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_KPROBE_EVENTS=y +CONFIG_LOCALVERSION="" +CONFIG_LOCKUP_DETECTOR=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_NL80211_TESTMODE=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y +CONFIG_PCIEAER_INJECT=y +CONFIG_PID_IN_CONTEXTIDR=y +CONFIG_PM_ADVANCED_DEBUG=y +CONFIG_PM_DEBUG=y +CONFIG_PM_SLEEP_DEBUG=y +CONFIG_PREEMPT_TRACER=y +CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_BLK=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 +CONFIG_PSTORE_PMSG=y +CONFIG_RCU_CPU_STALL_CPUTIME=y +CONFIG_REED_SOLOMON=y +CONFIG_RELAY=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_TEST_DYNAMIC_DEBUG=y +CONFIG_TIMERLAT_TRACER=y +CONFIG_TRACE_IRQFLAGS=y +CONFIG_TRACE_IRQFLAGS_NMI=y +CONFIG_TRACER_MAX_TRACE=y +CONFIG_TRACER_SNAPSHOT=y +CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y +CONFIG_TRACEPOINTS=y +CONFIG_TRACING=y +CONFIG_UPROBE_EVENTS=y +CONFIG_WQ_CPU_INTENSIVE_REPORT=y +CONFIG_WQ_WATCHDOG=y diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig index 0a4ba21a57a7c..3830a63ae032d 100644 --- a/kernel/dma/Kconfig +++ b/kernel/dma/Kconfig @@ -86,6 +86,28 @@ config SWIOTLB bool select NEED_DMA_MAP_STATE +config SWIOTLB_DEFAULT_SIZE_MB + int "Default SWIOTLB bounce buffer size in MB" + depends on SWIOTLB + range 1 64 + default 64 + help + Sets the default size of the software IO TLB (SWIOTLB) bounce buffer + pool allocated at boot time. The default is 64 MB. + + On memory-constrained embedded or mobile platforms (e.g., those with + a hardware IOMMU such as ARM SMMU covering most DMA-capable devices), + a smaller value such as 4 or 8 MB may be sufficient. The SWIOTLB is + then only needed for devices that bypass the IOMMU or have restricted + DMA address ranges. + + The minimum allowed value is 1 MB. This compile-time default can be + overridden at runtime using the "swiotlb=" kernel command line + parameter. Refer to Documentation/admin-guide/kernel-parameters.txt + for details. + + If unsure, leave at the default value of 64. + config SWIOTLB_DYNAMIC bool "Dynamic allocation of DMA bounce buffers" default n diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 7eb07e3bdb4c2..f73fda08417ab 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -171,6 +171,7 @@ int irq_can_set_affinity(unsigned int irq) { return __irq_can_set_affinity(irq_to_desc(irq)); } +EXPORT_SYMBOL_GPL(irq_can_set_affinity); /** * irq_can_set_affinity_usr - Check if affinity of a irq can be set from user space diff --git a/qcom-next/merge.log b/qcom-next/merge.log new file mode 100644 index 0000000000000..9e6791e753ee8 --- /dev/null +++ b/qcom-next/merge.log @@ -0,0 +1,485 @@ +Verified existence of local and remote repos: Success +/local/mnt/workspace/sgaud/Builds/Github/All_Runners/kernel-automation/actions-runner/_work/kernel-automation/kernel-automation/kernel-topics /local/mnt/workspace/sgaud/Builds/Github/All_Runners/kernel-automation/actions-runner/_work/kernel-automation/kernel-automation/kernel-topics +Reuse-Recorded-Resolution: Enabled +Downloaded shared rerere cache +Local tree is clean +Removing old remotes ... +The remote kernel https://github.com/qualcomm-linux/kernel.git is no longer tracked. +Delete it [Y/n]? The remote origin https://github.com/qualcomm-linux/kernel-topics.git is no longer tracked. +Delete it [Y/n]? The remote trovalds https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git is no longer tracked. +Delete it [Y/n]? Done, removed 3 old remote(s). +Adding new remotes... +Adding remote baseline https://github.com/qualcomm-linux/kernel.git qcom-next-staging +Updating baseline +Adding remote tech/bsp/clk https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/clk +Updating tech/bsp/clk +Adding remote tech/bsp/devfreq https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/devfreq +Updating tech/bsp/devfreq +Adding remote tech/bsp/ec https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/ec +Updating tech/bsp/ec +Adding remote tech/bsp/interconnect https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/interconnect +Updating tech/bsp/interconnect +Adding remote tech/mem/secure-buffer https://github.com/qualcomm-linux/kernel-topics.git tech/mem/secure-buffer +Updating tech/mem/secure-buffer +Adding remote tech/security/firmware-smc https://github.com/qualcomm-linux/kernel-topics.git tech/security/firmware-smc +Updating tech/security/firmware-smc +Adding remote tech/bsp/soc-infra https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/soc-infra +Updating tech/bsp/soc-infra +Adding remote tech/debug/soc https://github.com/qualcomm-linux/kernel-topics.git tech/debug/soc +Updating tech/debug/soc +Adding remote tech/bsp/pinctrl https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/pinctrl +Updating tech/bsp/pinctrl +Adding remote tech/bsp/remoteproc https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/remoteproc +Updating tech/bsp/remoteproc +Adding remote tech/bus/peripherals https://github.com/qualcomm-linux/kernel-topics.git tech/bus/peripherals +Updating tech/bus/peripherals +Adding remote tech/bus/pci/all https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/all +Updating tech/bus/pci/all +Adding remote tech/bus/pci/mhi https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/mhi +Updating tech/bus/pci/mhi +Adding remote tech/bus/pci/phy https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/phy +Updating tech/bus/pci/phy +Adding remote tech/bus/pci/pwrctl https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/pwrctl +Updating tech/bus/pci/pwrctl +Adding remote tech/bus/usb/dwc https://github.com/qualcomm-linux/kernel-topics.git tech/bus/usb/dwc +Updating tech/bus/usb/dwc +Adding remote tech/bus/usb/gadget https://github.com/qualcomm-linux/kernel-topics.git tech/bus/usb/gadget +Updating tech/bus/usb/gadget +Adding remote tech/bus/usb/phy https://github.com/qualcomm-linux/kernel-topics.git tech/bus/usb/phy +Updating tech/bus/usb/phy +Adding remote tech/debug/eud https://github.com/qualcomm-linux/kernel-topics.git tech/debug/eud +Updating tech/debug/eud +Adding remote tech/debug/hwtracing https://github.com/qualcomm-linux/kernel-topics.git tech/debug/hwtracing +Updating tech/debug/hwtracing +Adding remote tech/debug/rdbg https://github.com/qualcomm-linux/kernel-topics.git tech/debug/rdbg +Updating tech/debug/rdbg +Adding remote tech/pmic/backlight https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/backlight +Updating tech/pmic/backlight +Adding remote tech/pmic/mfd https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/mfd +Updating tech/pmic/mfd +Adding remote tech/pmic/misc https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/misc +Updating tech/pmic/misc +Adding remote tech/pmic/regulator https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/regulator +Updating tech/pmic/regulator +Adding remote tech/pmic/supply https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/supply +Updating tech/pmic/supply +Adding remote tech/mem/dma-buf https://github.com/qualcomm-linux/kernel-topics.git tech/mem/dma-buf +Updating tech/mem/dma-buf +Adding remote tech/mem/iommu https://github.com/qualcomm-linux/kernel-topics.git tech/mem/iommu +Updating tech/mem/iommu +Adding remote tech/mm/audio/all https://github.com/qualcomm-linux/kernel-topics.git tech/mm/audio/all +Updating tech/mm/audio/all +Adding remote tech/mm/audio/soundwire https://github.com/qualcomm-linux/kernel-topics.git tech/mm/audio/soundwire +Updating tech/mm/audio/soundwire +Adding remote tech/mm/camss https://github.com/qualcomm-linux/kernel-topics.git tech/mm/camss +Updating tech/mm/camss +Adding remote tech/mm/drm https://github.com/qualcomm-linux/kernel-topics.git tech/mm/drm +Updating tech/mm/drm +Adding remote tech/mm/fastrpc https://github.com/qualcomm-linux/kernel-topics.git tech/mm/fastrpc +Updating tech/mm/fastrpc +Adding remote tech/mm/phy https://github.com/qualcomm-linux/kernel-topics.git tech/mm/phy +Updating tech/mm/phy +Adding remote tech/mm/video https://github.com/qualcomm-linux/kernel-topics.git tech/mm/video +Updating tech/mm/video +Adding remote tech/mm/gpu https://github.com/qualcomm-linux/kernel-topics.git tech/mm/gpu +Updating tech/mm/gpu +Adding remote tech/mproc/rpmsg https://github.com/qualcomm-linux/kernel-topics.git tech/mproc/rpmsg +Updating tech/mproc/rpmsg +Adding remote tech/mproc/qmi https://github.com/qualcomm-linux/kernel-topics.git tech/mproc/qmi +Updating tech/mproc/qmi +Adding remote tech/net/ath https://github.com/qualcomm-linux/kernel-topics.git tech/net/ath +Updating tech/net/ath +Adding remote tech/net/eth https://github.com/qualcomm-linux/kernel-topics.git tech/net/eth +Updating tech/net/eth +Adding remote tech/net/rmnet https://github.com/qualcomm-linux/kernel-topics.git tech/net/rmnet +Updating tech/net/rmnet +Adding remote tech/net/qrtr https://github.com/qualcomm-linux/kernel-topics.git tech/net/qrtr +Updating tech/net/qrtr +Adding remote tech/net/phy https://github.com/qualcomm-linux/kernel-topics.git tech/net/phy +Updating tech/net/phy +Adding remote tech/net/bluetooth https://github.com/qualcomm-linux/kernel-topics.git tech/net/bluetooth +Updating tech/net/bluetooth +Adding remote tech/pm/opp https://github.com/qualcomm-linux/kernel-topics.git tech/pm/opp +Updating tech/pm/opp +Adding remote tech/pm/pmdomain https://github.com/qualcomm-linux/kernel-topics.git tech/pm/pmdomain +Updating tech/pm/pmdomain +Adding remote tech/pm/power https://github.com/qualcomm-linux/kernel-topics.git tech/pm/power +Updating tech/pm/power +Adding remote tech/pm/thermal https://github.com/qualcomm-linux/kernel-topics.git tech/pm/thermal +Updating tech/pm/thermal +Adding remote tech/security/crypto https://github.com/qualcomm-linux/kernel-topics.git tech/security/crypto +Updating tech/security/crypto +Adding remote tech/security/fscrypt https://github.com/qualcomm-linux/kernel-topics.git tech/security/fscrypt +Updating tech/security/fscrypt +Adding remote tech/security/ice https://github.com/qualcomm-linux/kernel-topics.git tech/security/ice +Updating tech/security/ice +Adding remote tech/storage/nvmem https://github.com/qualcomm-linux/kernel-topics.git tech/storage/nvmem +Updating tech/storage/nvmem +Adding remote tech/storage/phy https://github.com/qualcomm-linux/kernel-topics.git tech/storage/phy +Updating tech/storage/phy +Adding remote tech/storage/all https://github.com/qualcomm-linux/kernel-topics.git tech/storage/all +Updating tech/storage/all +Adding remote tech/virt/gunyah https://github.com/qualcomm-linux/kernel-topics.git tech/virt/gunyah +Updating tech/virt/gunyah +Adding remote tech/all/dt/qcs6490 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs6490 +Updating tech/all/dt/qcs6490 +Adding remote tech/all/dt/qcs9100 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs9100 +Updating tech/all/dt/qcs9100 +Adding remote tech/all/dt/qcs8300 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs8300 +Updating tech/all/dt/qcs8300 +Adding remote tech/all/dt/qcs615 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs615 +Updating tech/all/dt/qcs615 +Adding remote tech/all/dt/agatti https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/agatti +Updating tech/all/dt/agatti +Adding remote tech/all/dt/hamoa https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/hamoa +Updating tech/all/dt/hamoa +Adding remote tech/all/dt/glymur https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/glymur +Updating tech/all/dt/glymur +Adding remote tech/all/dt/kaanapali https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/kaanapali +Updating tech/all/dt/kaanapali +Adding remote tech/all/dt/pakala https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/pakala +Updating tech/all/dt/pakala +Adding remote tech/all/config https://github.com/qualcomm-linux/kernel-topics.git tech/all/config +Updating tech/all/config +Adding remote tech/overlay/dt https://github.com/qualcomm-linux/kernel-topics.git tech/overlay/dt +Updating tech/overlay/dt +Adding remote tech/all/workaround https://github.com/qualcomm-linux/kernel-topics.git tech/all/workaround +Updating tech/all/workaround +Adding remote tech/mproc/all https://github.com/qualcomm-linux/kernel-topics.git tech/mproc/all +Updating tech/mproc/all +Adding remote tech/noup/debug/all https://github.com/qualcomm-linux/kernel-topics.git tech/noup/debug/all +Updating tech/noup/debug/all +Adding remote tech/hwe/unoq https://github.com/qualcomm-linux/kernel-topics.git tech/hwe/unoq +Updating tech/hwe/unoq +Adding remote early/hwe/shikra/drivers https://github.com/qualcomm-linux/kernel-topics.git early/hwe/shikra/drivers +Updating early/hwe/shikra/drivers +Adding remote early/hwe/shikra/dt https://github.com/qualcomm-linux/kernel-topics.git early/hwe/shikra/dt +Updating early/hwe/shikra/dt +Done, added 73 new remote(s). +Updating the remotes ... +Updating tech/bsp/clk +Updating tech/bsp/devfreq +Updating tech/bsp/ec +Updating tech/bsp/interconnect +Updating tech/mem/secure-buffer +Updating tech/security/firmware-smc +Updating tech/bsp/soc-infra +Updating tech/debug/soc +Updating tech/bsp/pinctrl +Updating tech/bsp/remoteproc +Updating tech/bus/peripherals +Updating tech/bus/pci/all +Updating tech/bus/pci/mhi +Updating tech/bus/pci/phy +Updating tech/bus/pci/pwrctl +Updating tech/bus/usb/dwc +Updating tech/bus/usb/gadget +Updating tech/bus/usb/phy +Updating tech/debug/eud +Updating tech/debug/hwtracing +Updating tech/debug/rdbg +Updating tech/pmic/backlight +Updating tech/pmic/mfd +Updating tech/pmic/misc +Updating tech/pmic/regulator +Updating tech/pmic/supply +Updating tech/mem/dma-buf +Updating tech/mem/iommu +Updating tech/mm/audio/all +Updating tech/mm/audio/soundwire +Updating tech/mm/camss +Updating tech/mm/drm +Updating tech/mm/fastrpc +Updating tech/mm/phy +Updating tech/mm/video +Updating tech/mm/gpu +Updating tech/mproc/rpmsg +Updating tech/mproc/qmi +Updating tech/net/ath +Updating tech/net/eth +Updating tech/net/rmnet +Updating tech/net/qrtr +Updating tech/net/phy +Updating tech/net/bluetooth +Updating tech/pm/opp +Updating tech/pm/pmdomain +Updating tech/pm/power +Updating tech/pm/thermal +Updating tech/security/crypto +Updating tech/security/fscrypt +Updating tech/security/ice +Updating tech/storage/nvmem +Updating tech/storage/phy +Updating tech/storage/all +Updating tech/virt/gunyah +Updating tech/all/dt/qcs6490 +Updating tech/all/dt/qcs9100 +Updating tech/all/dt/qcs8300 +Updating tech/all/dt/qcs615 +Updating tech/all/dt/agatti +Updating tech/all/dt/hamoa +Updating tech/all/dt/glymur +Updating tech/all/dt/kaanapali +Updating tech/all/dt/pakala +Updating tech/all/config +Updating tech/overlay/dt +Updating tech/all/workaround +Updating tech/mproc/all +Updating tech/noup/debug/all +Updating tech/hwe/unoq +Updating early/hwe/shikra/drivers +Updating early/hwe/shikra/dt +Done, updated 0 remote(s). +Updating baseline ... +Fetching baseline +latest tag/id is dc59e4fea9d83f03bad6bddf3fa2e52491777482 +Done, updated baseline. +Latest tag is dc59e4fea9d83f03bad6bddf3fa2e52491777482 +Create a new integration branch based on dc59e4fea9d83f03bad6bddf3fa2e52491777482 +Merging topic branches... +------------------------------------------ + ** Merging topic branch: tech/bsp/clk/tech/bsp/clk +Merge successful : tech/bsp/clk : dcf6518b860209e2608f9cb22081f829ab7b43d4 : 22 +------------------------------------------ + ** Merging topic branch: tech/bsp/devfreq/tech/bsp/devfreq +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/ec/tech/bsp/ec +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/interconnect/tech/bsp/interconnect +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/secure-buffer/tech/mem/secure-buffer +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/firmware-smc/tech/security/firmware-smc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/soc-infra/tech/bsp/soc-infra +Merge successful : tech/bsp/soc-infra : 600ea9c656eedd9961e311ec6c0c252ed046221f : 24 +------------------------------------------ + ** Merging topic branch: tech/debug/soc/tech/debug/soc +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bsp/pinctrl/tech/bsp/pinctrl +Merge successful : tech/bsp/pinctrl : 79149ef6a826d6237346aa74eca65ccbe19d761f : 1 +------------------------------------------ + ** Merging topic branch: tech/bsp/remoteproc/tech/bsp/remoteproc +Merge successful : tech/bsp/remoteproc : ce284eea5fbde6dd880cb8e90df6b044a01d0256 : 9 +------------------------------------------ + ** Merging topic branch: tech/bus/peripherals/tech/bus/peripherals +Merge successful : tech/bus/peripherals : fedd8c628af7b28992224012386fec13483c514c : 6 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/all/tech/bus/pci/all +Merge successful : tech/bus/pci/all : ebd808fbc5fcd2b79e89bec0a311f7bb417b020c : 4 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/mhi/tech/bus/pci/mhi +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/pci/phy/tech/bus/pci/phy +Merge successful : tech/bus/pci/phy : ec405c892a7bede96799f42453a4e0281fad9447 : 4 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/pwrctl/tech/bus/pci/pwrctl +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/usb/dwc/tech/bus/usb/dwc +Merge successful : tech/bus/usb/dwc : 9dd47ad7e5c1dea9cfbcdd3f5e84af8d647af95f : 3 +------------------------------------------ + ** Merging topic branch: tech/bus/usb/gadget/tech/bus/usb/gadget +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/bus/usb/phy/tech/bus/usb/phy +Merge successful : tech/bus/usb/phy : c3aa7d5c9b171a9fb9ae9d1a9adf4dab251508f9 : 35 +------------------------------------------ + ** Merging topic branch: tech/debug/eud/tech/debug/eud +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/debug/hwtracing/tech/debug/hwtracing +Merge successful : tech/debug/hwtracing : ee4a490ad48a7236b3f417efda48cc1393d2e0d9 : 31 +------------------------------------------ + ** Merging topic branch: tech/debug/rdbg/tech/debug/rdbg +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/backlight/tech/pmic/backlight +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/mfd/tech/pmic/mfd +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/misc/tech/pmic/misc +Merge successful : tech/pmic/misc : 6fb618c321fd27ccf873f5b4bc6737baee8fd8bb : 8 +------------------------------------------ + ** Merging topic branch: tech/pmic/regulator/tech/pmic/regulator +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/supply/tech/pmic/supply +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/dma-buf/tech/mem/dma-buf +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mem/iommu/tech/mem/iommu +Merge successful : tech/mem/iommu : 44df12a52b9e962122cf7f6253ca1d6d3f2da862 : 8 +------------------------------------------ + ** Merging topic branch: tech/mm/audio/all/tech/mm/audio/all +Merge successful : tech/mm/audio/all : 88b8f29570c5211e654cec357e6a1282f92737b7 : 8 +------------------------------------------ + ** Merging topic branch: tech/mm/audio/soundwire/tech/mm/audio/soundwire +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/camss/tech/mm/camss +Merge successful : tech/mm/camss : c394dfb4b3768df4d41b9b32bf310c307451fa68 : 32 +------------------------------------------ + ** Merging topic branch: tech/mm/drm/tech/mm/drm +Merge successful : tech/mm/drm : b480a075f51d506402f8a081a271e5e05896986e : 65 +------------------------------------------ + ** Merging topic branch: tech/mm/fastrpc/tech/mm/fastrpc +Merge successful : tech/mm/fastrpc : e014e351825ea08a7a6ba61f4c005cf1aebcb147 : 11 +------------------------------------------ + ** Merging topic branch: tech/mm/phy/tech/mm/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mm/video/tech/mm/video +Merge successful : tech/mm/video : dc89f72844c066088e5d47e5efa9e32589b2959d : 32 +------------------------------------------ + ** Merging topic branch: tech/mm/gpu/tech/mm/gpu +Merge successful : tech/mm/gpu : 4433b066ef8096363c84ab1e9fc6f71e465ac95f : 6 +------------------------------------------ + ** Merging topic branch: tech/mproc/rpmsg/tech/mproc/rpmsg +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/mproc/qmi/tech/mproc/qmi +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/ath/tech/net/ath +Merge successful : tech/net/ath : a91544020bd06f83313c1544f2f94d7c19064843 : 14 +------------------------------------------ + ** Merging topic branch: tech/net/eth/tech/net/eth +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/rmnet/tech/net/rmnet +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/qrtr/tech/net/qrtr +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/phy/tech/net/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/bluetooth/tech/net/bluetooth +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/opp/tech/pm/opp +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/pmdomain/tech/pm/pmdomain +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pm/power/tech/pm/power +Merge successful : tech/pm/power : bb887016f3998f14184b38d1ae3ced78a6d80567 : 13 +------------------------------------------ + ** Merging topic branch: tech/pm/thermal/tech/pm/thermal +Merge failed, manual merge +No files need merging +[qcom-next fdc65996002d] Merge remote-tracking branch tech/pm/thermal into qcom-next +Merge successful : tech/pm/thermal : d36b3ee3b5ce84165d974c7141b15c3b6a283691 : 7 +------------------------------------------ + ** Merging topic branch: tech/security/crypto/tech/security/crypto +Merge successful : tech/security/crypto : c36112e9987659986a3171f206e4c4a05932fb8b : 14 +------------------------------------------ + ** Merging topic branch: tech/security/fscrypt/tech/security/fscrypt +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/security/ice/tech/security/ice +Merge successful : tech/security/ice : beabac03036a596434bb02c3f91b7c9672ea7c15 : 9 +------------------------------------------ + ** Merging topic branch: tech/storage/nvmem/tech/storage/nvmem +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/phy/tech/storage/phy +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/all/tech/storage/all +Merge successful : tech/storage/all : d86d915355ae0f4d79ec0223864f41cb1c30ab70 : 4 +------------------------------------------ + ** Merging topic branch: tech/virt/gunyah/tech/virt/gunyah +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs6490/tech/all/dt/qcs6490 +Merge successful : tech/all/dt/qcs6490 : d70580362b1b5c9d8db75e08b810c8a9c8358fc3 : 21 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs9100/tech/all/dt/qcs9100 +Merge successful : tech/all/dt/qcs9100 : 3853a4908bb4a047bb6d096a83ca28de504b56ac : 91 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs8300/tech/all/dt/qcs8300 +Merge failed, manual merge +No files need merging +[qcom-next 82d075244dbc] Merge remote-tracking branch tech/all/dt/qcs8300 into qcom-next +Merge successful : tech/all/dt/qcs8300 : e93aa15800b0cebedc8e0d79e5cf39fb32616e48 : 24 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs615/tech/all/dt/qcs615 +Merge successful : tech/all/dt/qcs615 : 1cc303d042350bbb1e4fc4494c33356769995308 : 8 +------------------------------------------ + ** Merging topic branch: tech/all/dt/agatti/tech/all/dt/agatti +Merge successful : tech/all/dt/agatti : c828f10cd2c53b7ff2cc061e73b239973ee17bc6 : 1 +------------------------------------------ + ** Merging topic branch: tech/all/dt/hamoa/tech/all/dt/hamoa +Merge successful : tech/all/dt/hamoa : 723e3ef44a909d5e2a4b270d6bccdbeec975b9d1 : 32 +------------------------------------------ + ** Merging topic branch: tech/all/dt/glymur/tech/all/dt/glymur +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/dt/kaanapali/tech/all/dt/kaanapali +Merge successful : tech/all/dt/kaanapali : f6ed56b503a15dc168700ec4f02e0365680c2cf4 : 20 +------------------------------------------ + ** Merging topic branch: tech/all/dt/pakala/tech/all/dt/pakala +Merge successful : tech/all/dt/pakala : b2e5e9630f3ff8f681ae77aaab3ef852c4896df4 : 12 +------------------------------------------ + ** Merging topic branch: tech/all/config/tech/all/config +Merge successful : tech/all/config : 2f8abb9a606bd9d9194983ee7ed3d0a4ee20bca2 : 69 +------------------------------------------ + ** Merging topic branch: tech/overlay/dt/tech/overlay/dt +Merge failed, manual merge +No files need merging +[qcom-next 158b9354ca96] Merge remote-tracking branch tech/overlay/dt into qcom-next +Merge successful : tech/overlay/dt : cb96f0691662ec18e92c2cbc483351e4ebdf11f5 : 68 +------------------------------------------ + ** Merging topic branch: tech/all/workaround/tech/all/workaround +Merge failed, manual merge +No files need merging +[qcom-next 355e6d4a5ebe] Merge remote-tracking branch tech/all/workaround into qcom-next +Merge successful : tech/all/workaround : ecc126013f9aac2681125eddbe60f7fa40beeaa3 : 26 +------------------------------------------ + ** Merging topic branch: tech/mproc/all/tech/mproc/all +Merge failed, manual merge +No files need merging +[qcom-next 2efc0ed28481] Merge remote-tracking branch tech/mproc/all into qcom-next +Merge successful : tech/mproc/all : 0aa90b7d45babe6116bcbb3006ae4636256b6e0f : 3 +------------------------------------------ + ** Merging topic branch: tech/noup/debug/all/tech/noup/debug/all +Merge successful : tech/noup/debug/all : cbdd4bbfa24a682d76769d4c1c66bb67b262ae4d : 26 +------------------------------------------ + ** Merging topic branch: tech/hwe/unoq/tech/hwe/unoq +Merge successful : tech/hwe/unoq : a2d85fe547167dbd8fc59618907c20a6f17d2e5a : 4 +------------------------------------------ + ** Merging topic branch: early/hwe/shikra/drivers/early/hwe/shikra/drivers +Merge failed, manual merge +No files need merging +[qcom-next 272c95718d75] Merge remote-tracking branch early/hwe/shikra/drivers into qcom-next +Merge successful : early/hwe/shikra/drivers : f5654fe87079b83cd2bfc1a4bf10a7bf331ad4dd : 160 +------------------------------------------ + ** Merging topic branch: early/hwe/shikra/dt/early/hwe/shikra/dt +Merge failed, manual merge +No files need merging +[qcom-next 4a8a9a0d0fba] Merge remote-tracking branch early/hwe/shikra/dt into qcom-next +Merge successful : early/hwe/shikra/dt : e6da759870c85255263830048e5567d47dab3978 : 122 +Done, merged 40 topic(s). +[main 76354b9] New rr-cache entries from ci-merge + 6 files changed, 5881 insertions(+) + create mode 100644 rr-cache/28bf2625415bd45915fcc4a076558f1eccd39540/thisimage.1 + create mode 100644 rr-cache/3d29194c00c402d7c6a76bd9cc81b2073a0ca7ca/thisimage + create mode 100644 rr-cache/4fb584f263e8b86ac32435d904fb9214c658e52d/thisimage + create mode 100644 rr-cache/9d75e91f6e0a77bd894803a54fa46add0b1f02bb/thisimage + create mode 100644 rr-cache/a1639217f5ed352a58fadd68737220f3dfe1a41e/thisimage + create mode 100644 rr-cache/f75781ed0106a815e457aedd5c00b62d10357272/thisimage diff --git a/qcom-next/topic_SHA1 b/qcom-next/topic_SHA1 new file mode 100644 index 0000000000000..335a1f094ec65 --- /dev/null +++ b/qcom-next/topic_SHA1 @@ -0,0 +1,42 @@ +Name SHA Commits +------------------------------------------------------------------------------------ +tech/bsp/clk dcf6518b860209e2608f9cb22081f829ab7b43d4 22 +tech/bsp/soc-infra 600ea9c656eedd9961e311ec6c0c252ed046221f 24 +tech/bsp/pinctrl 79149ef6a826d6237346aa74eca65ccbe19d761f 1 +tech/bsp/remoteproc ce284eea5fbde6dd880cb8e90df6b044a01d0256 9 +tech/bus/peripherals fedd8c628af7b28992224012386fec13483c514c 6 +tech/bus/pci/all ebd808fbc5fcd2b79e89bec0a311f7bb417b020c 4 +tech/bus/pci/phy ec405c892a7bede96799f42453a4e0281fad9447 4 +tech/bus/usb/dwc 9dd47ad7e5c1dea9cfbcdd3f5e84af8d647af95f 3 +tech/bus/usb/phy c3aa7d5c9b171a9fb9ae9d1a9adf4dab251508f9 35 +tech/debug/hwtracing ee4a490ad48a7236b3f417efda48cc1393d2e0d9 31 +tech/pmic/misc 6fb618c321fd27ccf873f5b4bc6737baee8fd8bb 8 +tech/mem/iommu 44df12a52b9e962122cf7f6253ca1d6d3f2da862 8 +tech/mm/audio/all 88b8f29570c5211e654cec357e6a1282f92737b7 8 +tech/mm/camss c394dfb4b3768df4d41b9b32bf310c307451fa68 32 +tech/mm/drm b480a075f51d506402f8a081a271e5e05896986e 65 +tech/mm/fastrpc e014e351825ea08a7a6ba61f4c005cf1aebcb147 11 +tech/mm/video dc89f72844c066088e5d47e5efa9e32589b2959d 32 +tech/mm/gpu 4433b066ef8096363c84ab1e9fc6f71e465ac95f 6 +tech/net/ath a91544020bd06f83313c1544f2f94d7c19064843 14 +tech/pm/power bb887016f3998f14184b38d1ae3ced78a6d80567 13 +tech/pm/thermal d36b3ee3b5ce84165d974c7141b15c3b6a283691 7 +tech/security/crypto c36112e9987659986a3171f206e4c4a05932fb8b 14 +tech/security/ice beabac03036a596434bb02c3f91b7c9672ea7c15 9 +tech/storage/all d86d915355ae0f4d79ec0223864f41cb1c30ab70 4 +tech/all/dt/qcs6490 d70580362b1b5c9d8db75e08b810c8a9c8358fc3 21 +tech/all/dt/qcs9100 3853a4908bb4a047bb6d096a83ca28de504b56ac 91 +tech/all/dt/qcs8300 e93aa15800b0cebedc8e0d79e5cf39fb32616e48 24 +tech/all/dt/qcs615 1cc303d042350bbb1e4fc4494c33356769995308 8 +tech/all/dt/agatti c828f10cd2c53b7ff2cc061e73b239973ee17bc6 1 +tech/all/dt/hamoa 723e3ef44a909d5e2a4b270d6bccdbeec975b9d1 32 +tech/all/dt/kaanapali f6ed56b503a15dc168700ec4f02e0365680c2cf4 20 +tech/all/dt/pakala b2e5e9630f3ff8f681ae77aaab3ef852c4896df4 12 +tech/all/config 2f8abb9a606bd9d9194983ee7ed3d0a4ee20bca2 69 +tech/overlay/dt cb96f0691662ec18e92c2cbc483351e4ebdf11f5 68 +tech/all/workaround ecc126013f9aac2681125eddbe60f7fa40beeaa3 26 +tech/mproc/all 0aa90b7d45babe6116bcbb3006ae4636256b6e0f 3 +tech/noup/debug/all cbdd4bbfa24a682d76769d4c1c66bb67b262ae4d 26 +tech/hwe/unoq a2d85fe547167dbd8fc59618907c20a6f17d2e5a 4 +early/hwe/shikra/drivers f5654fe87079b83cd2bfc1a4bf10a7bf331ad4dd 160 +early/hwe/shikra/dt e6da759870c85255263830048e5567d47dab3978 122 diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 252f683be3c18..9ceb474a18de9 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -367,6 +367,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_WSA881X imply SND_SOC_WSA883X imply SND_SOC_WSA884X + imply SND_SOC_WSA885X_I2C imply SND_SOC_ZL38060 help Normally ASoC codec drivers are only built if a machine driver which @@ -2770,6 +2771,14 @@ config SND_SOC_WSA884X This enables support for Qualcomm WSA8840/WSA8845/WSA8845H Class-D Smart Speaker Amplifier. +config SND_SOC_WSA885X_I2C + tristate "WSA885X I2C Codec" + depends on I2C + select REGMAP_I2C + help + This enables support for Qualcomm WSA885X Smart Speaker + Amplifier over I2C. + config SND_SOC_ZL38060 tristate "Microsemi ZL38060 Connected Home Audio Processor" depends on SPI_MASTER diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index aa0396e5b575b..18cfff959290c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -426,6 +426,7 @@ snd-soc-wm-hubs-y := wm_hubs.o snd-soc-wsa881x-y := wsa881x.o snd-soc-wsa883x-y := wsa883x.o snd-soc-wsa884x-y := wsa884x.o +snd-soc-wsa885x-i2c-y := wsa885x-i2c.o snd-soc-zl38060-y := zl38060.o # Amp snd-soc-max9877-y := max9877.o @@ -876,6 +877,7 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o obj-$(CONFIG_SND_SOC_WSA883X) += snd-soc-wsa883x.o obj-$(CONFIG_SND_SOC_WSA884X) += snd-soc-wsa884x.o +obj-$(CONFIG_SND_SOC_WSA885X_I2C) += snd-soc-wsa885x-i2c.o obj-$(CONFIG_SND_SOC_ZL38060) += snd-soc-zl38060.o # Amp diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index 10ad682019fa7..0afcb2dce5d91 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -10,6 +10,8 @@ #define LPASS_MACRO_FLAG_HAS_NPL_CLOCK BIT(0) /* The soundwire block should be internally reset at probe */ #define LPASS_MACRO_FLAG_RESET_SWR BIT(1) +/* FS counter control bit[7] must be toggled (Shikra / v4.0) */ +#define LPASS_MACRO_FLAG_BYPASS_FS_CONTROL BIT(2) enum lpass_version { LPASS_VER_9_0_0, @@ -30,6 +32,7 @@ enum lpass_codec_version { LPASS_CODEC_VERSION_2_7, LPASS_CODEC_VERSION_2_8, LPASS_CODEC_VERSION_2_9, + LPASS_CODEC_VERSION_4_0, }; struct lpass_macro { @@ -68,6 +71,8 @@ static inline const char *lpass_macro_get_codec_version_string(int version) return "v2.7"; case LPASS_CODEC_VERSION_2_8: return "v2.8"; + case LPASS_CODEC_VERSION_4_0: + return "v4.0"; default: break; } diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 6233aa9f5bc6d..3a3dec6b14cda 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -646,6 +646,7 @@ struct rx_macro { int clsh_users; int rx_mclk_cnt; enum lpass_codec_version codec_version; + bool bypass_fs_control; int rxn_reg_stride; int rxn_reg_stride2; bool is_ear_mode_on; @@ -1612,6 +1613,7 @@ static bool rx_is_rw_register(struct device *dev, unsigned int reg) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_4_0: return rx_2_5_is_rw_register(dev, reg); default: break; @@ -2043,6 +2045,11 @@ static void rx_macro_mclk_enable(struct rx_macro *rx, bool mclk_enable) CDC_RX_CLK_MCLK2_ENABLE); regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_RX_FS_MCLK_CNT_CLR_MASK, 0x00); + + if (rx->bypass_fs_control) + regmap_update_bits(regmap, + CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x80, 0x80); regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_RX_FS_MCLK_CNT_EN_MASK, CDC_RX_FS_MCLK_CNT_ENABLE); @@ -3648,6 +3655,7 @@ static int rx_macro_component_probe(struct snd_soc_component *component) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_4_0: controls = rx_macro_2_5_snd_controls; num_controls = ARRAY_SIZE(rx_macro_2_5_snd_controls); widgets = rx_macro_2_5_dapm_widgets; @@ -3809,6 +3817,7 @@ static int rx_macro_probe(struct platform_device *pdev) return PTR_ERR(base); rx->codec_version = lpass_macro_get_codec_version(); + rx->bypass_fs_control = !!(flags & LPASS_MACRO_FLAG_BYPASS_FS_CONTROL); struct reg_default *reg_defaults __free(kfree) = NULL; switch (rx->codec_version) { @@ -3831,6 +3840,7 @@ static int rx_macro_probe(struct platform_device *pdev) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_4_0: rx->rxn_reg_stride = 0xc0; rx->rxn_reg_stride2 = 0x0; def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); @@ -3961,6 +3971,10 @@ static const struct of_device_id rx_macro_dt_match[] = { }, { .compatible = "qcom,sc8280xp-lpass-rx-macro", .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,shikra-lpass-rx-macro", + .data = (void *)(LPASS_MACRO_FLAG_HAS_NPL_CLOCK | + LPASS_MACRO_FLAG_BYPASS_FS_CONTROL), }, { } }; diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 528d5b167ecff..53b6976c68c78 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +82,14 @@ #define CDC_VA_SWR_MIC_CLK_SEL_0_1_MASK (0xEE) #define CDC_VA_SWR_MIC_CLK_SEL_0_1_DIV1 (0xCC) #define CDC_VA_TOP_CSR_SWR_CTRL (0x00DC) + +#define CDC_VA_TOP_CSR_SWR_GPIN_CH0 (0x00E0) +#define CDC_VA_TOP_CSR_SWR_GPIN_CH1 (0x00E4) +#define CDC_VA_TOP_CSR_TOP_CFG2 (0x00EC) +#define CDC_VA_TOP_CSR_TOP_CFG3 (0x00F0) +#define CDC_VA_TOP_CSR_SWR_GPOUT_CH0 (0x00F8) +#define CDC_VA_TOP_CSR_SWR_GPOUT_CH1 (0x00FC) + #define CDC_VA_INP_MUX_ADC_MUX0_CFG0 (0x0100) #define CDC_VA_INP_MUX_ADC_MUX0_CFG1 (0x0104) #define CDC_VA_INP_MUX_ADC_MUX1_CFG0 (0x0108) @@ -89,6 +98,40 @@ #define CDC_VA_INP_MUX_ADC_MUX2_CFG1 (0x0114) #define CDC_VA_INP_MUX_ADC_MUX3_CFG0 (0x0118) #define CDC_VA_INP_MUX_ADC_MUX3_CFG1 (0x011C) + +/* ADC MUX4-7 CFG0/1 - Bolero V4 extended decimator mux (up to 8 DMICs) */ +#define CDC_VA_INP_MUX_ADC_MUX4_CFG0 (0x0120) +#define CDC_VA_INP_MUX_ADC_MUX4_CFG1 (0x0124) +#define CDC_VA_INP_MUX_ADC_MUX5_CFG0 (0x0128) +#define CDC_VA_INP_MUX_ADC_MUX5_CFG1 (0x012C) +#define CDC_VA_INP_MUX_ADC_MUX6_CFG0 (0x0130) +#define CDC_VA_INP_MUX_ADC_MUX6_CFG1 (0x0134) +#define CDC_VA_INP_MUX_ADC_MUX7_CFG0 (0x0138) +#define CDC_VA_INP_MUX_ADC_MUX7_CFG1 (0x013C) + +/* ADC MUXx CFG2 - Bolero V4 CFG2 extension for all 8 MUXes */ +#define CDC_VA_INP_MUX_ADC_MUX0_CFG2 (0x0140) +#define CDC_VA_INP_MUX_ADC_MUX1_CFG2 (0x0144) +#define CDC_VA_INP_MUX_ADC_MUX2_CFG2 (0x0148) +#define CDC_VA_INP_MUX_ADC_MUX3_CFG2 (0x014C) +#define CDC_VA_INP_MUX_ADC_MUX4_CFG2 (0x0150) +#define CDC_VA_INP_MUX_ADC_MUX5_CFG2 (0x0154) +#define CDC_VA_INP_MUX_ADC_MUX6_CFG2 (0x0158) +#define CDC_VA_INP_MUX_ADC_MUX7_CFG2 (0x015C) + +/* INTR_CTRL registers - SWR interrupt controller (VA macro owns SWR0 on QCM2290) */ +#define CDC_VA_MACRO_INTR_CTRL_CFG (0x0340) +#define CDC_VA_MACRO_INTR_CTRL_CLR_COMMIT (0x0344) +#define CDC_VA_MACRO_INTR_CTRL_PIN1_MASK0 (0x0360) +#define CDC_VA_MACRO_INTR_CTRL_PIN1_STATUS0 (0x0368) +#define CDC_VA_MACRO_INTR_CTRL_PIN1_CLEAR0 (0x0370) +#define CDC_VA_MACRO_INTR_CTRL_PIN2_MASK0 (0x0380) +#define CDC_VA_MACRO_INTR_CTRL_PIN2_STATUS0 (0x0388) +#define CDC_VA_MACRO_INTR_CTRL_PIN2_CLEAR0 (0x0390) +#define CDC_VA_MACRO_INTR_CTRL_LEVEL0 (0x03C0) +#define CDC_VA_MACRO_INTR_CTRL_BYPASS0 (0x03C8) +#define CDC_VA_MACRO_INTR_CTRL_SET0 (0x03D0) + #define CDC_VA_TX0_TX_PATH_CTL (0x0400) #define CDC_VA_TX_PATH_CLK_EN_MASK BIT(5) #define CDC_VA_TX_PATH_CLK_EN BIT(5) @@ -118,6 +161,9 @@ #define CDC_VA_TX0_TX_PATH_SEC5 (0x0424) #define CDC_VA_TX0_TX_PATH_SEC6 (0x0428) #define CDC_VA_TX0_TX_PATH_SEC7 (0x042C) + +#define CDC_VA_TX0_TX_PATH_CFG2 (0x0430) + #define CDC_VA_TX1_TX_PATH_CTL (0x0480) #define CDC_VA_TX1_TX_PATH_CFG0 (0x0484) #define CDC_VA_TX1_TX_PATH_CFG1 (0x0488) @@ -129,6 +175,9 @@ #define CDC_VA_TX1_TX_PATH_SEC4 (0x04A0) #define CDC_VA_TX1_TX_PATH_SEC5 (0x04A4) #define CDC_VA_TX1_TX_PATH_SEC6 (0x04A8) + +#define CDC_VA_TX1_TX_PATH_CFG2 (0x04B0) + #define CDC_VA_TX2_TX_PATH_CTL (0x0500) #define CDC_VA_TX2_TX_PATH_CFG0 (0x0504) #define CDC_VA_TX2_TX_PATH_CFG1 (0x0508) @@ -140,6 +189,9 @@ #define CDC_VA_TX2_TX_PATH_SEC4 (0x0520) #define CDC_VA_TX2_TX_PATH_SEC5 (0x0524) #define CDC_VA_TX2_TX_PATH_SEC6 (0x0528) + +#define CDC_VA_TX2_TX_PATH_CFG2 (0x0530) + #define CDC_VA_TX3_TX_PATH_CTL (0x0580) #define CDC_VA_TX3_TX_PATH_CFG0 (0x0584) #define CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK BIT(7) @@ -155,7 +207,66 @@ #define CDC_VA_TX3_TX_PATH_SEC5 (0x05A4) #define CDC_VA_TX3_TX_PATH_SEC6 (0x05A8) -#define VA_MAX_OFFSET (0x07A8) +#define CDC_VA_TX3_TX_PATH_CFG2 (0x05B0) + +#define CDC_VA_CDC_ADPT0_ADPT_CTRL (0x0800) +#define CDC_VA_CDC_ADPT0_ADPT_GAIN_0 (0x0804) +#define CDC_VA_CDC_ADPT0_ADPT_GAIN_1 (0x0808) +#define CDC_VA_CDC_ADPT0_DH_FSM_CTRL (0x080C) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_0 (0x0810) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_1 (0x0814) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_2 (0x0818) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_3 (0x081C) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_4 (0x0820) +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5 (0x0824) + +#define CDC_VA_CDC_ADPT1_ADPT_CTRL (0x0880) +#define CDC_VA_CDC_ADPT1_ADPT_GAIN_0 (0x0884) +#define CDC_VA_CDC_ADPT1_ADPT_GAIN_1 (0x0888) +#define CDC_VA_CDC_ADPT1_DH_FSM_CTRL (0x088C) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_0 (0x0890) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_1 (0x0894) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_2 (0x0898) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_3 (0x089C) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_4 (0x08A0) +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5 (0x08A4) +#define CDC_VA_CDC_ADPT1_DBG_CTRL (0x08B0) +#define CDC_VA_CDC_ADPT1_DBG_PDM_RATE_CTRL_0 (0x08B2) +#define CDC_VA_CDC_ADPT1_DBG_PDM_RATE_CTRL_1 (0x08B4) +#define CDC_VA_CDC_ADPT1_SPARE0 (0x08B8) + +#define CDC_VA_CDC_ADPT2_ADPT_CTRL (0x0900) +#define CDC_VA_CDC_ADPT2_ADPT_GAIN_0 (0x0904) +#define CDC_VA_CDC_ADPT2_ADPT_GAIN_1 (0x0908) +#define CDC_VA_CDC_ADPT2_DH_FSM_CTRL (0x090C) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_0 (0x0910) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_1 (0x0914) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_2 (0x0918) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_3 (0x091C) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_4 (0x0920) +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5 (0x0924) + +#define CDC_VA_CDC_ADPT3_ADPT_CTRL (0x0980) +#define CDC_VA_CDC_ADPT3_ADPT_GAIN_0 (0x0984) +#define CDC_VA_CDC_ADPT3_ADPT_GAIN_1 (0x0988) +#define CDC_VA_CDC_ADPT3_DH_FSM_CTRL (0x098C) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_0 (0x0990) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_1 (0x0994) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_2 (0x0998) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_3 (0x099C) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_4 (0x09A0) +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5 (0x09A4) + +/* VA ALT TOP registers - Bolero V4 alternate top config */ +#define CDC_VA_ALT_TOP_VA_CFG0 0x1000 +#define CDC_VA_ALT_TOP_RX_CFG0 0x1040 +#define CDC_VA_ALT_TOP_WSA1_CFG0 0x1080 +#define CDC_VA_ALT_TOP_WSA2_CFG0 0x10C0 +#define CDC_VA_ALT_TOP_WSA3_CFG0 0x1100 +#define CDC_VA_ALT_TOP_WSA4_CFG0 0x1140 + +#define VA_MAX_OFFSET (0x1240) +#define VA_MAX_OFFSET_PRE_4_0 (0x07A8) #define VA_MACRO_NUM_DECIMATORS 4 #define VA_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ @@ -200,6 +311,11 @@ enum { VA_MACRO_CLK_DIV_16, }; +enum { + MSM_DMIC, + SWR_MIC, +}; + #define VA_NUM_CLKS_MAX 3 struct va_macro { @@ -209,6 +325,8 @@ struct va_macro { u16 dmic_clk_div; bool has_swr_master; bool has_npl_clk; + bool bypass_fs_control; + enum lpass_codec_version codec_version; int dec_mode[VA_MACRO_NUM_DECIMATORS]; struct regmap *regmap; @@ -235,6 +353,7 @@ struct va_macro { struct va_macro_data { bool has_swr_master; bool has_npl_clk; + bool bypass_fs_control; int version; }; @@ -249,6 +368,13 @@ static const struct va_macro_data sm8450_va_data = { .has_npl_clk = true, }; +static const struct va_macro_data shikra_va_data = { + .has_swr_master = true, + .has_npl_clk = true, + .bypass_fs_control = true, + .version = LPASS_CODEC_VERSION_4_0, +}; + static const struct va_macro_data sm8550_va_data = { .has_swr_master = true, .has_npl_clk = false, @@ -266,7 +392,23 @@ static bool va_is_volatile_register(struct device *dev, unsigned int reg) case CDC_VA_TOP_CSR_DMIC2_CTL: case CDC_VA_TOP_CSR_DMIC3_CTL: return true; + default: + break; } + + if (lpass_macro_get_codec_version() == LPASS_CODEC_VERSION_4_0) { + switch (reg) { + case CDC_VA_MACRO_INTR_CTRL_PIN1_STATUS0: + case CDC_VA_MACRO_INTR_CTRL_PIN1_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_STATUS0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_CLR_COMMIT: + return true; + default: + break; + } + } + return false; } @@ -304,6 +446,7 @@ static const struct reg_default va_defaults[] = { { CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00}, { CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00}, { CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00}, + { CDC_VA_TX0_TX_PATH_CTL, 0x04}, { CDC_VA_TX0_TX_PATH_CFG0, 0x10}, { CDC_VA_TX0_TX_PATH_CFG1, 0x0B}, @@ -351,6 +494,101 @@ static const struct reg_default va_defaults[] = { { CDC_VA_TX3_TX_PATH_SEC6, 0x00}, }; +/* Register defaults specific to LPASS codec v4.0 (Shikra) */ +static const struct reg_default va_4_0_defaults[] = { + /* ADC MUX4-7 CFG0/1 - 8-DMIC support */ + { CDC_VA_INP_MUX_ADC_MUX4_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX4_CFG1, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX5_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX5_CFG1, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX6_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX6_CFG1, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX7_CFG0, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX7_CFG1, 0x00 }, + + /* ADC MUXx CFG2 extension */ + { CDC_VA_INP_MUX_ADC_MUX0_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX1_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX2_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX3_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX4_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX5_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX6_CFG2, 0x00 }, + { CDC_VA_INP_MUX_ADC_MUX7_CFG2, 0x00 }, + + /* INTR_CTRL: SWR interrupt masking registers */ + { CDC_VA_MACRO_INTR_CTRL_CFG, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_PIN1_MASK0, 0xFF }, + { CDC_VA_MACRO_INTR_CTRL_PIN1_STATUS0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_PIN2_MASK0, 0xFF }, + { CDC_VA_MACRO_INTR_CTRL_PIN2_STATUS0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_LEVEL0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_BYPASS0, 0x00 }, + { CDC_VA_MACRO_INTR_CTRL_SET0, 0x00 }, + + /* TX PATH CFG2 per decimator */ + { CDC_VA_TX0_TX_PATH_CFG2, 0x03 }, + { CDC_VA_TX1_TX_PATH_CFG2, 0x03 }, + { CDC_VA_TX2_TX_PATH_CFG2, 0x03 }, + { CDC_VA_TX3_TX_PATH_CFG2, 0x03 }, + + /* CDC ADPT0 - adaptive filter */ + { CDC_VA_CDC_ADPT0_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT0_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT0_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT0_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* CDC ADPT1 */ + { CDC_VA_CDC_ADPT1_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT1_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT1_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT1_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* CDC ADPT2 */ + { CDC_VA_CDC_ADPT2_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT2_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT2_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT2_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* CDC ADPT3 */ + { CDC_VA_CDC_ADPT3_ADPT_CTRL, 0x51 }, + { CDC_VA_CDC_ADPT3_ADPT_GAIN_0, 0x11 }, + { CDC_VA_CDC_ADPT3_ADPT_GAIN_1, 0x01 }, + { CDC_VA_CDC_ADPT3_DH_FSM_CTRL, 0x02 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_0, 0x77 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_1, 0x64 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_2, 0x00 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_3, 0x41 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_4, 0x04 }, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5, 0x01 }, + + /* VA ALT TOP */ + { CDC_VA_ALT_TOP_VA_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_RX_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA1_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA2_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA3_CFG0, 0x00 }, + { CDC_VA_ALT_TOP_WSA4_CFG0, 0x00 }, +}; + static bool va_is_rw_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -425,6 +663,41 @@ static bool va_is_rw_register(struct device *dev, unsigned int reg) case CDC_VA_TX3_TX_PATH_SEC5: case CDC_VA_TX3_TX_PATH_SEC6: return true; + default: + break; + } + + if (lpass_macro_get_codec_version() == LPASS_CODEC_VERSION_4_0) { + switch (reg) { + case CDC_VA_MACRO_INTR_CTRL_CFG: + case CDC_VA_MACRO_INTR_CTRL_CLR_COMMIT: + case CDC_VA_MACRO_INTR_CTRL_PIN1_MASK0: + case CDC_VA_MACRO_INTR_CTRL_PIN1_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_MASK0: + case CDC_VA_MACRO_INTR_CTRL_PIN2_CLEAR0: + case CDC_VA_MACRO_INTR_CTRL_LEVEL0: + case CDC_VA_MACRO_INTR_CTRL_BYPASS0: + case CDC_VA_MACRO_INTR_CTRL_SET0: + case CDC_VA_INP_MUX_ADC_MUX4_CFG0 ... CDC_VA_INP_MUX_ADC_MUX7_CFG1: + case CDC_VA_INP_MUX_ADC_MUX0_CFG2 ... CDC_VA_INP_MUX_ADC_MUX7_CFG2: + case CDC_VA_TX0_TX_PATH_CFG2: + case CDC_VA_TX1_TX_PATH_CFG2: + case CDC_VA_TX2_TX_PATH_CFG2: + case CDC_VA_TX3_TX_PATH_CFG2: + case CDC_VA_ALT_TOP_VA_CFG0: + case CDC_VA_ALT_TOP_RX_CFG0: + case CDC_VA_ALT_TOP_WSA1_CFG0: + case CDC_VA_ALT_TOP_WSA2_CFG0: + case CDC_VA_ALT_TOP_WSA3_CFG0: + case CDC_VA_ALT_TOP_WSA4_CFG0: + case CDC_VA_CDC_ADPT0_ADPT_CTRL ... CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT1_ADPT_CTRL ... CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT2_ADPT_CTRL ... CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT3_ADPT_CTRL ... CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5: + return true; + default: + break; + } } return false; @@ -449,9 +722,6 @@ static const struct regmap_config va_regmap_config = { .val_bits = 32, .reg_stride = 4, .cache_type = REGCACHE_FLAT, - .reg_defaults = va_defaults, - .num_reg_defaults = ARRAY_SIZE(va_defaults), - .max_register = VA_MAX_OFFSET, .volatile_reg = va_is_volatile_register, .readable_reg = va_is_readable_register, .writeable_reg = va_is_rw_register, @@ -469,6 +739,10 @@ static int va_clk_rsc_fs_gen_request(struct va_macro *va, bool enable) regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR); + + if (va->bypass_fs_control) + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, + 0x80, 0x80); regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, CDC_VA_FS_CONTROL_EN); @@ -552,14 +826,32 @@ static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, return -EINVAL; } - if (val != 0) - snd_soc_component_update_bits(component, mic_sel_reg, - CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, - CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); + if (val != 0) { + if (strnstr(widget->name, "SMIC", strlen(widget->name))) + snd_soc_component_update_bits(component, mic_sel_reg, + CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, 0); + else + snd_soc_component_update_bits(component, mic_sel_reg, + CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, + CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); + } return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); } +static bool is_amic_enabled(struct snd_soc_component *comp, int decimator) +{ + u16 adc_mux_reg = 0; + bool ret = false; + + adc_mux_reg = CDC_VA_INP_MUX_ADC_MUX0_CFG1 + + VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + if (snd_soc_component_read(comp, adc_mux_reg) & SWR_MIC) + return true; + + return ret; +} + static int va_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -744,6 +1036,8 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg; u16 tx_gain_ctl_reg; u8 hpf_cut_off_freq; + u16 adc_mux0_reg = 0; + u16 adapt_ctrl = 0; struct va_macro *va = snd_soc_component_get_drvdata(comp); @@ -757,6 +1051,10 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, VA_MACRO_TX_PATH_OFFSET * decimator; tx_gain_ctl_reg = CDC_VA_TX0_TX_VOL_CTL + VA_MACRO_TX_PATH_OFFSET * decimator; + adc_mux0_reg = CDC_VA_INP_MUX_ADC_MUX0_CFG0 + + VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + adapt_ctrl = CDC_VA_CDC_ADPT0_ADPT_CTRL + + VA_MACRO_TX_PATH_OFFSET *decimator; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -766,6 +1064,9 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, /* Enable TX PGA Mute */ break; case SND_SOC_DAPM_POST_PMU: + if (va->codec_version == LPASS_CODEC_VERSION_4_0) + snd_soc_component_update_bits(comp, adapt_ctrl, 0xFF, 0x00); + /* Enable TX CLK */ snd_soc_component_update_bits(comp, tx_vol_ctl_reg, CDC_VA_TX_PATH_CLK_EN_MASK, @@ -774,7 +1075,13 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, CDC_VA_TX_HPF_ZERO_GATE_MASK, CDC_VA_TX_HPF_ZERO_GATE); - usleep_range(1000, 1010); + if (!is_amic_enabled(comp, decimator)) { + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_ZERO_GATE_MASK, + CDC_VA_TX_HPF_ZERO_GATE); + usleep_range(1000, 1010); + } + hpf_cut_off_freq = (snd_soc_component_read(comp, dec_cfg_reg) & TX_HPF_CUT_OFF_FREQ_MASK) >> 5; @@ -782,23 +1089,25 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(comp, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK, CF_MIN_3DB_150HZ << 5); + } - snd_soc_component_update_bits(comp, hpf_gate_reg, - CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, - CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ); + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_REQ); - /* - * Minimum 1 clk cycle delay is required as per HW spec - */ - usleep_range(1000, 1010); + /* + * Minimum 1 clk cycle delay is required as per HW spec + */ + usleep_range(1000, 1010); + + if (!is_amic_enabled(comp, decimator)) { snd_soc_component_update_bits(comp, - hpf_gate_reg, - CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, - 0x0); + hpf_gate_reg, + CDC_VA_TX_HPF_CUTOFF_FREQ_CHANGE_MASK, + 0x0); } - usleep_range(1000, 1010); snd_soc_component_update_bits(comp, hpf_gate_reg, CDC_VA_TX_HPF_ZERO_GATE_MASK, @@ -1277,6 +1586,12 @@ static const struct snd_soc_dapm_route va_audio_map[] = { {"VA DMIC MUX3", "DMIC6", "VA DMIC6"}, {"VA DMIC MUX3", "DMIC7", "VA DMIC7"}, + /* SWR_MIC routes: connect each VA DECx MUX to its SWR_MIC input */ + {"VA DEC0 MUX", "SWR_MIC", "VA SWR_MIC0"}, + {"VA DEC1 MUX", "SWR_MIC", "VA SWR_MIC1"}, + {"VA DEC2 MUX", "SWR_MIC", "VA SWR_MIC2"}, + {"VA DEC3 MUX", "SWR_MIC", "VA SWR_MIC3"}, + { "VA DMIC0", NULL, "DMIC0 Pin" }, { "VA DMIC1", NULL, "DMIC1 Pin" }, { "VA DMIC2", NULL, "DMIC2 Pin" }, @@ -1348,18 +1663,22 @@ static int fsgen_gate_enable(struct clk_hw *hw) struct regmap *regmap = va->regmap; int ret; - if (va->has_swr_master) { - ret = clk_prepare_enable(va->mclk); - if (ret) - return ret; + ret = pm_runtime_get_sync(va->dev); + if (ret < 0) { + pm_runtime_put_noidle(va->dev); + return ret; } ret = va_macro_mclk_enable(va, true); + if (ret) { + pm_runtime_put_noidle(va->dev); + return ret; + } if (va->has_swr_master) regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_SWR_CONTROL, CDC_VA_SWR_CLK_EN_MASK, CDC_VA_SWR_CLK_ENABLE); - return ret; + return 0; } static void fsgen_gate_disable(struct clk_hw *hw) @@ -1372,8 +1691,24 @@ static void fsgen_gate_disable(struct clk_hw *hw) CDC_VA_SWR_CLK_EN_MASK, 0x0); va_macro_mclk_enable(va, false); - if (va->has_swr_master) - clk_disable_unprepare(va->mclk); + + pm_runtime_mark_last_busy(va->dev); + pm_runtime_put_autosuspend(va->dev); +} + +static int va_macro_setup_pm_clocks(struct device *dev, struct va_macro *va) +{ + int ret; + + ret = devm_pm_clk_create(dev); + if (ret) + return ret; + + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return ret; + + return 0; } static int fsgen_gate_is_enabled(struct clk_hw *hw) @@ -1386,12 +1721,25 @@ static int fsgen_gate_is_enabled(struct clk_hw *hw) return !!(val & CDC_VA_FS_BROADCAST_EN); } +static unsigned long fsgen_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate / 2; +} + static const struct clk_ops fsgen_gate_ops = { .prepare = fsgen_gate_enable, .unprepare = fsgen_gate_disable, .is_enabled = fsgen_gate_is_enabled, }; +static const struct clk_ops fsgen_gate_ops_4_0 = { + .prepare = fsgen_gate_enable, + .unprepare = fsgen_gate_disable, + .is_enabled = fsgen_gate_is_enabled, + .recalc_rate = fsgen_recalc_rate, +}; + static int va_macro_register_fsgen_output(struct va_macro *va) { struct clk *parent = va->mclk; @@ -1410,7 +1758,8 @@ static int va_macro_register_fsgen_output(struct va_macro *va) of_property_read_string(np, "clock-output-names", &clk_name); init.name = clk_name; - init.ops = &fsgen_gate_ops; + init.ops = (va->codec_version == LPASS_CODEC_VERSION_4_0) + ? &fsgen_gate_ops_4_0 : &fsgen_gate_ops; init.flags = 0; init.parent_names = &parent_clk_name; init.num_parents = 1; @@ -1511,6 +1860,14 @@ static int va_macro_set_lpass_codec_version(struct va_macro *va) default: break; } + } else if (maj == 4) { + switch (min) { + case 0: + version = LPASS_CODEC_VERSION_4_0; + break; + default: + break; + } } if (version == LPASS_CODEC_VERSION_UNKNOWN) { @@ -1520,6 +1877,7 @@ static int va_macro_set_lpass_codec_version(struct va_macro *va) } lpass_macro_set_codec_version(version); + va->codec_version = version; dev_dbg(va->dev, "LPASS Codec Version %s\n", lpass_macro_get_codec_version_string(version)); @@ -1534,6 +1892,7 @@ static int va_macro_probe(struct platform_device *pdev) void __iomem *base; u32 sample_rate = 0; int ret; + int rpm_ret; va = devm_kzalloc(dev, sizeof(*va), GFP_KERNEL); if (!va) @@ -1576,18 +1935,61 @@ static int va_macro_probe(struct platform_device *pdev) goto err; } - va->regmap = devm_regmap_init_mmio(dev, base, &va_regmap_config); + data = of_device_get_match_data(dev); + va->has_swr_master = data->has_swr_master; + va->has_npl_clk = data->has_npl_clk; + va->bypass_fs_control = data->bypass_fs_control; + + /* + * Use the version from match data if available; for platforms that + * detect version from registers, clocks must be enabled first, so + * the full detection is deferred to after clk_prepare_enable below. + */ + va->codec_version = data->version ? data->version : LPASS_CODEC_VERSION_UNKNOWN; + + int def_count; + struct reg_default *reg_defaults_buf __free(kfree) = NULL; + + if (va->codec_version == LPASS_CODEC_VERSION_4_0) { + def_count = ARRAY_SIZE(va_defaults) + ARRAY_SIZE(va_4_0_defaults); + reg_defaults_buf = kmalloc_objs(struct reg_default, def_count); + if (!reg_defaults_buf) { + ret = -ENOMEM; + goto err; + } + memcpy(®_defaults_buf[0], va_defaults, sizeof(va_defaults)); + memcpy(®_defaults_buf[ARRAY_SIZE(va_defaults)], + va_4_0_defaults, sizeof(va_4_0_defaults)); + } else { + def_count = ARRAY_SIZE(va_defaults); + reg_defaults_buf = kmalloc_objs(struct reg_default, def_count); + if (!reg_defaults_buf) { + ret = -ENOMEM; + goto err; + } + memcpy(reg_defaults_buf, va_defaults, sizeof(va_defaults)); + } + + struct regmap_config *reg_config __free(kfree) = + kmemdup(&va_regmap_config, sizeof(va_regmap_config), GFP_KERNEL); + if (!reg_config) { + ret = -ENOMEM; + goto err; + } + + reg_config->reg_defaults = reg_defaults_buf; + reg_config->num_reg_defaults = def_count; + reg_config->max_register = (va->codec_version == LPASS_CODEC_VERSION_4_0) + ? VA_MAX_OFFSET : VA_MAX_OFFSET_PRE_4_0; + + va->regmap = devm_regmap_init_mmio(dev, base, reg_config); if (IS_ERR(va->regmap)) { - ret = -EINVAL; + ret = PTR_ERR(va->regmap); goto err; } dev_set_drvdata(dev, va); - data = of_device_get_match_data(dev); - va->has_swr_master = data->has_swr_master; - va->has_npl_clk = data->has_npl_clk; - /* mclk rate */ clk_set_rate(va->mclk, 2 * VA_MACRO_MCLK_FREQ); @@ -1601,22 +2003,18 @@ static int va_macro_probe(struct platform_device *pdev) clk_set_rate(va->npl, 2 * VA_MACRO_MCLK_FREQ); } - ret = clk_prepare_enable(va->macro); + ret = va_macro_setup_pm_clocks(dev, va); if (ret) - goto err; + goto err_rpm_disable; - ret = clk_prepare_enable(va->dcodec); - if (ret) - goto err_dcodec; - - ret = clk_prepare_enable(va->mclk); - if (ret) - goto err_mclk; + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); - if (va->has_npl_clk) { - ret = clk_prepare_enable(va->npl); - if (ret) - goto err_npl; + rpm_ret = pm_runtime_resume_and_get(dev); + if (rpm_ret < 0) { + ret = rpm_ret; + goto err_rpm_disable; } /** @@ -1625,11 +2023,12 @@ static int va_macro_probe(struct platform_device *pdev) */ if (data->version) { lpass_macro_set_codec_version(data->version); + va->codec_version = data->version; } else { /* read version from register */ ret = va_macro_set_lpass_codec_version(va); if (ret) - goto err_clkout; + goto err_rpm_put; } if (va->has_swr_master) { @@ -1659,35 +2058,27 @@ static int va_macro_probe(struct platform_device *pdev) va_macro_dais, ARRAY_SIZE(va_macro_dais)); if (ret) - goto err_clkout; - - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); + goto err_rpm_put; ret = va_macro_register_fsgen_output(va); if (ret) - goto err_clkout; + goto err_rpm_put; va->fsgen = devm_clk_hw_get_clk(dev, &va->hw, "fsgen"); if (IS_ERR(va->fsgen)) { ret = PTR_ERR(va->fsgen); - goto err_clkout; + goto err_rpm_put; } + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return 0; -err_clkout: - if (va->has_npl_clk) - clk_disable_unprepare(va->npl); -err_npl: - clk_disable_unprepare(va->mclk); -err_mclk: - clk_disable_unprepare(va->dcodec); -err_dcodec: - clk_disable_unprepare(va->macro); +err_rpm_put: + pm_runtime_put_noidle(dev); +err_rpm_disable: + pm_runtime_disable(dev); err: lpass_macro_pds_exit(va->pds); @@ -1698,12 +2089,7 @@ static void va_macro_remove(struct platform_device *pdev) { struct va_macro *va = dev_get_drvdata(&pdev->dev); - if (va->has_npl_clk) - clk_disable_unprepare(va->npl); - - clk_disable_unprepare(va->mclk); - clk_disable_unprepare(va->dcodec); - clk_disable_unprepare(va->macro); + pm_runtime_disable(&pdev->dev); lpass_macro_pds_exit(va->pds); } @@ -1715,12 +2101,7 @@ static int va_macro_runtime_suspend(struct device *dev) regcache_cache_only(va->regmap, true); regcache_mark_dirty(va->regmap); - if (va->has_npl_clk) - clk_disable_unprepare(va->npl); - - clk_disable_unprepare(va->mclk); - - return 0; + return pm_clk_suspend(dev); } static int va_macro_runtime_resume(struct device *dev) @@ -1728,25 +2109,13 @@ static int va_macro_runtime_resume(struct device *dev) struct va_macro *va = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(va->mclk); - if (ret) { - dev_err(va->dev, "unable to prepare mclk\n"); + ret = pm_clk_resume(dev); + if (ret) return ret; - } - - if (va->has_npl_clk) { - ret = clk_prepare_enable(va->npl); - if (ret) { - clk_disable_unprepare(va->mclk); - dev_err(va->dev, "unable to prepare npl\n"); - return ret; - } - } regcache_cache_only(va->regmap, false); - regcache_sync(va->regmap); - return 0; + return regcache_sync(va->regmap); } @@ -1761,6 +2130,7 @@ static const struct of_device_id va_macro_dt_match[] = { { .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data }, { .compatible = "qcom,sm8550-lpass-va-macro", .data = &sm8550_va_data }, { .compatible = "qcom,sc8280xp-lpass-va-macro", .data = &sm8450_va_data }, + { .compatible = "qcom,shikra-lpass-va-macro", .data = &shikra_va_data }, {} }; MODULE_DEVICE_TABLE(of, va_macro_dt_match); diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 5ad0448af649d..8c8c50a63f4e2 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "lpass-macro-common.h" @@ -2529,15 +2530,15 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = { static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) { struct regmap *regmap = wsa->regmap; + int ret; - if (enable) { - int ret; + ret = pm_runtime_get_sync(wsa->dev); + if (ret < 0) { + pm_runtime_put_noidle(wsa->dev); + return ret; + } - ret = clk_prepare_enable(wsa->mclk); - if (ret) { - dev_err(wsa->dev, "failed to enable mclk\n"); - return ret; - } + if (enable) { wsa_macro_mclk_enable(wsa, true); regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, @@ -2548,9 +2549,10 @@ static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) regmap_update_bits(regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, CDC_WSA_SWR_CLK_EN_MASK, 0); wsa_macro_mclk_enable(wsa, false); - clk_disable_unprepare(wsa->mclk); } + pm_runtime_mark_last_busy(wsa->dev); + pm_runtime_put_autosuspend(wsa->dev); return 0; } @@ -2772,27 +2774,26 @@ static int wsa_macro_probe(struct platform_device *pdev) /* set MCLK and NPL rates */ clk_set_rate(wsa->mclk, WSA_MACRO_MCLK_FREQ); - clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); + if (wsa->npl) + clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); - ret = clk_prepare_enable(wsa->macro); + ret = devm_pm_clk_create(dev); if (ret) - goto err; + return ret; - ret = clk_prepare_enable(wsa->dcodec); - if (ret) - goto err_dcodec; + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return ret; - ret = clk_prepare_enable(wsa->mclk); - if (ret) - goto err_mclk; + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); - ret = clk_prepare_enable(wsa->npl); - if (ret) - goto err_npl; - ret = clk_prepare_enable(wsa->fsgen); - if (ret) - goto err_fsgen; + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) { + goto err_rpm_disable; + } /* reset swr ip */ regmap_update_bits(wsa->regmap, CDC_WSA_CLK_RST_CTRL_SWR_CONTROL, @@ -2809,44 +2810,26 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_macro_dai, ARRAY_SIZE(wsa_macro_dai)); if (ret) - goto err_clkout; - - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); + goto err_rpm_put; ret = wsa_macro_register_mclk_output(wsa); if (ret) - goto err_clkout; + goto err_rpm_put; - return 0; + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); -err_clkout: - clk_disable_unprepare(wsa->fsgen); -err_fsgen: - clk_disable_unprepare(wsa->npl); -err_npl: - clk_disable_unprepare(wsa->mclk); -err_mclk: - clk_disable_unprepare(wsa->dcodec); -err_dcodec: - clk_disable_unprepare(wsa->macro); -err: + return 0; +err_rpm_put: + pm_runtime_put_noidle(dev); +err_rpm_disable: + pm_runtime_disable(dev); return ret; - } static void wsa_macro_remove(struct platform_device *pdev) { - struct wsa_macro *wsa = dev_get_drvdata(&pdev->dev); - - clk_disable_unprepare(wsa->macro); - clk_disable_unprepare(wsa->dcodec); - clk_disable_unprepare(wsa->mclk); - clk_disable_unprepare(wsa->npl); - clk_disable_unprepare(wsa->fsgen); + pm_runtime_disable(&pdev->dev); } static int wsa_macro_runtime_suspend(struct device *dev) @@ -2856,11 +2839,7 @@ static int wsa_macro_runtime_suspend(struct device *dev) regcache_cache_only(wsa->regmap, true); regcache_mark_dirty(wsa->regmap); - clk_disable_unprepare(wsa->fsgen); - clk_disable_unprepare(wsa->npl); - clk_disable_unprepare(wsa->mclk); - - return 0; + return pm_clk_suspend(dev); } static int wsa_macro_runtime_resume(struct device *dev) @@ -2868,34 +2847,12 @@ static int wsa_macro_runtime_resume(struct device *dev) struct wsa_macro *wsa = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(wsa->mclk); - if (ret) { - dev_err(dev, "unable to prepare mclk\n"); - return ret; - } - - ret = clk_prepare_enable(wsa->npl); - if (ret) { - dev_err(dev, "unable to prepare mclkx2\n"); - goto err_npl; - } - - ret = clk_prepare_enable(wsa->fsgen); - if (ret) { - dev_err(dev, "unable to prepare fsgen\n"); - goto err_fsgen; - } - regcache_cache_only(wsa->regmap, false); - regcache_sync(wsa->regmap); - - return 0; -err_fsgen: - clk_disable_unprepare(wsa->npl); -err_npl: - clk_disable_unprepare(wsa->mclk); + ret = pm_clk_resume(dev); + if (ret) + return ret; - return ret; + return regcache_sync(wsa->regmap); } static const struct dev_pm_ops wsa_macro_pm_ops = { diff --git a/sound/soc/codecs/wsa885x-i2c.c b/sound/soc/codecs/wsa885x-i2c.c new file mode 100644 index 0000000000000..ac2d464b9742d --- /dev/null +++ b/sound/soc/codecs/wsa885x-i2c.c @@ -0,0 +1,1474 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* WSA885X I2C codec driver */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Driver Constants */ +#define CLK_RATE_FIXED 73728000 +#define SUPPLIES_NUM 2 +#define SLAVE_ADDR 0x00c +#define NUM_REGS 0x03 + +/* Interrupt Registers */ +#define WSA885X_INTR_STATUS0 0x8584 /* Base address of the status register */ +#define WSA885X_INTR_MASK0 0x8581 /* Base address of the mask register */ +#define WSA885X_INTR_CLEAR0 0x8587 /* Base address of the acknowledge register */ +#define WSA885X_INTR_LEVEL0 0x858A /* Base address of the acknowledge register */ + +/* Power and PA FSM Control Registers */ +#define WSA885X_POWER_FSM_CTL0 0x8423 +#define WSA885X_PA0_FSM_CTL0 0x842A +#define WSA885X_PA1_FSM_CTL0 0x8434 + +/* Digital Control GPIO and Interrupt Registers */ +#define DIG_CTRL1_PIN_CT 0x8510 +#define DIG_CTRL1_SPMI_PAD_GPIO2_CTL 0x8518 +#define DIG_CTRL1_INTR_MODE 0x8580 + +/* Control Registers - Audio Processing */ +#define SMP_AMP_CTRL_STEREO_STEREO_SMP_AMP_CTRL_I2S 0x0000 +#define SMP_AMP_CTRL_STEREO_CMT_GRP_MASK 0x0004 +#define SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX 0x0140 +#define SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID 0x0208 +#define SMP_AMP_CTRL_STEREO_CS21_SAMPLERATEINDEX 0x0240 +#define SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER 0x0340 +#define SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X0 0x4405 +#define SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X1 0x4406 +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB 0x4409 +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB 0x6409 +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB 0x440a +#define SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB 0x640a +#define SMP_AMP_CTRL_STEREO_PDE23_REQ_PS 0x0a04 +#define SMP_AMP_CTRL_STEREO_PDE23_ACT_PS 0x0a40 +#define SMP_AMP_CTRL_STEREO_OT23_USAGE 0x0b10 +#define SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX 0x0e40 + +/* Analog Top Registers - Power and Clock Control */ +#define ANA_TOP_PON_CKSK_CTL_0 0x800d +#define ANA_TOP_BG_TVP_UVLO1_PROG 0x8024 +#define ANA_TOP_BG_TVP_UVLO2_PROG 0x8025 +#define ANA_TOP_BG_TVP_OVRD_CTL 0x8034 + +/* Analog PLL Registers */ +#define ANA_PLL_DIV_CTL_0 0x8090 +#define ANA_PLL_DIV_CTL_1 0x8091 +#define ANA_TOP_PLL_VCO_CTL 0x8092 +#define ANA_TOP_PLL_LOOPFILT_0 0x8093 +#define ANA_TOP_PLL_OVRD_CTL 0x8098 +#define ANA_TOP_PLL_STATUS_0 0x809a +#define ANA_TOP_PLL_STATUS_1 0x809b + +/* Analog Boost Control Registers */ +#define ANA_TOP_BOOST_STB_CTRL2 0x805b +#define ANA_TOP_BOOST_STB_CTRL3 0x805c +#define ANA_TOP_BOOST_BYP_CTRL2 0x805e +#define ANA_TOP_BOOST_BYP_CTRL3 0x805f +#define ANA_TOP_BOOST_MISC 0x8063 +#define ANA_TOP_BOOST_PWRSTAGE_CTRL2 0x8065 +#define ANA_TOP_BOOST_PWRSTAGE_CTRL4 0x8067 + +/* Analog IV Sense ADC Registers */ +#define ANA_TOP_IVSENSE_ADC_MODE_CTL2 0x80ca +#define ANA_TOP_IVSENSE_ADC_MODE_CTL3 0x80cb +#define ANA_TOP_IVSENSE_ADC_REF_CTL 0x80cc +#define ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2 0x80d0 + +/* Analog Speaker Power Stage Registers */ +#define ANA_TOP_SPK_TOP_PWRSTG_CH1_CTRL3 0x8108 +#define ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3 0x810b +#define ANA_TOP_SPK_TOP_PWRSTG_CH2_CTRL3 0x810e +#define ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3 0x8111 +#define ANA_TOP_SPK_TOP_SPARE3 0x813c +#define SPK_TOP_LF_CH1_CTRL11 0x811c +#define SPK_TOP_LF_CH1_TUNE1 0x811d +#define SPK_TOP_LF_CH2_TUNE1 0x8129 +#define SPK_TOP_LF_CH1_CTRL9 0x811a +#define SPK_TOP_LF_CH2_CTRL9 0x8126 +#define SPK_TOP_LF_CH2_CTRL11 0x8128 +#define SPK_TOP_COMMON_CTRL2 0x8102 +#define SPK_TOP_COMMON_TUNE1 0x8103 +#define IVSENSE_VSNS_ISNS_CTL_CH1 0x80ba +#define DIG_CTRL0_CDC_CLK_CTL 0x841c +#define PON_CKSK_CTL_0 0x800d +#define DIG_CTRL0_TOP_CLK_CFG 0x8418 +#define DIG_CTRL0_SDCA_COMMIT 0x8419 +#define DIG_CTRL0_CLK_SOURCE_ENABLE 0x841a +#define DIG_CTRL0_SYS_CLK_SEL 0x841b +#define DIG_CTRL0_CDC_CLK_CTL 0x841c +#define DIG_CTRL0_PA_FSM_CTL 0x8420 +#define DIG_CTRL0_POWER_FSM_CTL0 0x8423 +#define DIG_CTRL0_POWER_FSM_CTL1 0x8424 +#define DIG_CTRL0_PA0_FSM_CTL1 0x842b +#define DIG_CTRL0_PA1_FSM_CTL1 0x8435 +#define DIG_CTRL0_VBAT_THRM_FLT_CTL 0x8458 +#define DIG_CTRL0_CDC_RXTX_FSCNT_CTL 0x8470 +#define DIG_CTRL0_GAIN_RAMP0_CTL1 0x84b4 +#define DIG_CTRL0_GAIN_RAMP1_CTL1 0x84b7 + +/* Digital Control 1 Registers - I2S/TDM Interface */ +#define DIG_CTRL1_I2S_CTL0 0x85A0 +#define DIG_CTRL1_I2S_CFG0_TDM_TX 0x85A2 +#define DIG_CTRL1_I2S_CFG1_TDM_TX 0x85A3 +#define DIG_CTRL1_I2S_TDM_CTL0 0x85A7 +#define DIG_CTRL1_I2S_TDM_CTL1 0x85A9 +#define DIG_CTRL1_I2S_TDM_CH_RX 0x85AA +#define DIG_CTRL1_I2S_TDM_CH_TX 0x85AB +#define DIG_CTRL1_I2S_RESET_CTL 0x85AE + +/* CDC RX Path Registers - Audio Data Path */ +#define CDC_RX0_RX_PATH_CFG0 0x8601 +#define CDC_RX0_RX_PATH_CFG1 0x8602 +#define CDC_RX0_RX_PATH_CTL 0x8606 +#define RX0_RX_PATH_DSMDEM_CTL 0x8613 +#define CDC_RX1_RX_PATH_CFG0 0x8621 +#define CDC_RX1_RX_PATH_CFG1 0x8622 +#define CDC_RX1_RX_PATH_CTL 0x8626 +#define RX1_RX_PATH_DSMDEM_CTL 0x8633 + +/* CDC Compander Registers - Dynamic Range Control */ +#define CDC_COMPANDER0_CTL0 0x8640 +#define CDC_COMPANDER0_CTL7 0x8647 +#define CDC_COMPANDER1_CTL0 0x8660 +#define CDC_COMPANDER1_CTL7 0x8667 + +/* CDC Speaker Protection Registers - IV Sense */ +#define CDC_VSENSE0_SPKR_PROT_PATH_CTL 0x86A1 +#define CDC_VSENSE1_SPKR_PROT_PATH_CTL 0x86B1 +#define CDC_ISENSE0_SPKR_PROT_PATH_CTL 0x86A9 +#define CDC_ISENSE1_SPKR_PROT_PATH_CTL 0x86B9 + +/* CDC Class-H Registers - Headroom Control */ +#define CDC_CLSH_V1P8_BP_CTL1 0x86CD +#define CDC_CLSH_V1P8_BP_CTL0 0x86CC +#define CDC_CLSH_CLSH_SIG_DP_CTL0 0x86C7 +#define CDC_CLSH_CLSH_V_HD_PA 0x86C3 +#define CDC_CLSH_V1P8_BP_CTL2 0x86CE + +/* RX Sample Rate Index Values - Audio Playback Path */ +#define WSA885X_RX_RATE_8000HZ 0x00 /* 8 kHz sample rate */ +#define WSA885X_RX_RATE_16000HZ 0x01 /* 16 kHz sample rate */ +#define WSA885X_RX_RATE_32000HZ 0x02 /* 32 kHz sample rate */ +#define WSA885X_RX_RATE_44100HZ 0x03 /* 44.1 kHz sample rate */ +#define WSA885X_RX_RATE_48000HZ 0x04 /* 48 kHz sample rate */ +#define WSA885X_RX_RATE_96000HZ 0x05 /* 96 kHz sample rate */ +#define WSA885X_RX_RATE_192000HZ 0x06 /* 192 kHz sample rate */ +#define WSA885X_RX_RATE_384000HZ 0x07 /* 384 kHz sample rate */ + +/* VI Sample Rate Index Values - Voltage/Current Sensing Path */ +#define WSA885X_VI_RATE_8000HZ 0x00 /* 8 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_16000HZ 0x01 /* 16 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_44100HZ 0x02 /* 44.1 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_48000HZ 0x03 /* 48 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_96000HZ 0x04 /* 96 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_22050HZ 0x05 /* 22.05 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_24000HZ 0x06 /* 24 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_192000HZ 0x07 /* 192 kHz sample rate for VI sensing */ +#define WSA885X_VI_RATE_384000HZ 0x08 /* 384 kHz sample rate for VI sensing */ + +/* Channel Configuration Masks */ +#define WSA885X_CHANNEL_STEREO 0x03 /* Both left and right channels (0b11) */ +#define WSA885X_CHANNEL_MONO_LEFT 0x01 /* Left channel only (0b01) */ +#define WSA885X_CHANNEL_MONO_RIGHT 0x02 /* Right channel only (0b10) */ + +/* PLL Status Register Bits */ +#define WSA885X_PLL_LOCK_BIT 0x01 /* PLL lock status bit (bit 0) */ + +/* FU21 volume support */ +#define FU21_VOL_STEPS 124 +static const DECLARE_TLV_DB_SCALE(fu21_digital_gain, -8400, 100, 0); + +/*TDM Slots*/ +#define WSA885X_TDM8 0X08 +#define WSA885X_TDM4 0X04 +#define WSA885X_TDM2 0X02 + +static const char *const supply_name[] = { + "vdd-io", + "vdd-1p8", +}; + +enum { + batt_1s = 1, + batt_2s, +}; + +enum { + WSA885X_IRQ_INT_SAF2WAR = 0, + WSA885X_IRQ_INT_WAR2SAF, + WSA885X_IRQ_INT_DISABLE, + WSA885X_IRQ_INT_PA0_OCP, + WSA885X_IRQ_INT_PA1_OCP, + WSA885X_IRQ_INT_CLIP0, + WSA885X_IRQ_INT_CLIP1, + WSA885X_IRQ_INT_CLK_WD, + WSA885X_IRQ_INT_INTR_GPIO1_PIN, + WSA885X_IRQ_INT_INTR_GPIO2_PIN, + WSA885X_IRQ_INT_UVLO, + WSA885X_IRQ_INT_BOP, + WSA885X_IRQ_INT_PA0_FSM_ERR, + WSA885X_IRQ_INT_PA1_FSM_ERR, + WSA885X_IRQ_INT_MAIN_FSM_ERR, + WSA885X_IRQ_INT_PCM_DATA0_WD, + WSA885X_IRQ_INT_PCM_DATA1_WD, + WSA885X_IRQ_INT_PCM_DATA0_DC, + WSA885X_IRQ_INT_PCM_DATA1_DC, + WSA885X_IRQ_INT_PLL_UNLOCKED, + WSA885X_IRQ_INT_PROT_MODE_CHANGE, + WSA885X_IRQ_INT_PB_CLOCK_VALID, + WSA885X_IRQ_INT_SENSE_CLOCK_VALID, + WSA885X_IRQ_MAX, +}; + +static const char *wsa885x_irq_names[WSA885X_IRQ_MAX] = { + "WSA885X_IRQ_INT_SAF2WAR", + "WSA885X_IRQ_INT_WAR2SAF", + "WSA885X_IRQ_INT_DISABLE", + "WSA885X_IRQ_INT_PA0_OCP", + "WSA885X_IRQ_INT_PA1_OCP", + "WSA885X_IRQ_INT_CLIP0", + "WSA885X_IRQ_INT_CLIP1", + "WSA885X_IRQ_INT_CLK_WD", + "WSA885X_IRQ_INT_INTR_GPIO1_PIN", + "WSA885X_IRQ_INT_INTR_GPIO2_PIN", + "WSA885X_IRQ_INT_UVLO", + "WSA885X_IRQ_INT_BOP", + "WSA885X_IRQ_INT_PA0_FSM_ERR", + "WSA885X_IRQ_INT_PA1_FSM_ERR", + "WSA885X_IRQ_INT_MAIN_FSM_ERR", + "WSA885X_IRQ_INT_PCM_DATA0_WD", + "WSA885X_IRQ_INT_PCM_DATA1_WD", + "WSA885X_IRQ_INT_PCM_DATA0_DC", + "WSA885X_IRQ_INT_PCM_DATA1_DC", + "WSA885X_IRQ_INT_PLL_UNLOCKED", + "WSA885X_IRQ_INT_PROT_MODE_CHANGE", + "WSA885X_IRQ_INT_PB_CLOCK_VALID", + "WSA885X_IRQ_INT_SENSE_CLOCK_VALID"}; + +struct wsa885x_i2c_priv { + struct i2c_client *client; + struct regmap *regmap; + struct device *dev; + struct snd_soc_component *component; + struct regulator_bulk_data supplies[SUPPLIES_NUM]; + struct gpio_desc *sd_n; + uint32_t sample_rate; + uint32_t *init_table; + uint32_t init_table_size; + uint32_t usage_mode; + uint32_t rx_slot_mask; + struct gpio_desc *intr_pin; + atomic_t open_count; + uint32_t batt_conf; + int stereo_voldB; /* in dB, -84..+40, encoded as signed 8-bit in MSB register */ +}; + +static const struct regmap_range_cfg regmap_ranges[] = { + { + .range_min = 0, + .range_max = 0x88ff, + .selector_reg = 0x0, + .selector_mask = 0xFF, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct reg_default codec_reg_defaults[] = { + {SMP_AMP_CTRL_STEREO_STEREO_SMP_AMP_CTRL_I2S, 0x00}, + {SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX, 0x01}, + {SMP_AMP_CTRL_STEREO_CMT_GRP_MASK, 0x00}, + {SMP_AMP_CTRL_STEREO_OT23_USAGE, 0x00}, + {SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID, 0x00}, + {SMP_AMP_CTRL_STEREO_CS21_SAMPLERATEINDEX, 0x04}, + {SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER, 0x01}, + {SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X0, 0x01}, + {SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X1, 0x01}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, 0xac}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, 0xac}, + {SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00}, + {SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x03}, + {SMP_AMP_CTRL_STEREO_PDE23_ACT_PS, 0x03}, + {SMP_AMP_CTRL_STEREO_OT23_USAGE, 0x00}, + {SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX, 0x03}, + {SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX, 0x03}, + {ANA_TOP_PON_CKSK_CTL_0, 0x00}, + {ANA_TOP_BG_TVP_UVLO1_PROG, 0x19}, + {ANA_TOP_BG_TVP_UVLO2_PROG, 0x22}, + {ANA_PLL_DIV_CTL_0, 0x0c}, + {ANA_PLL_DIV_CTL_1, 0x50}, + {ANA_TOP_PLL_VCO_CTL, 0x00}, + {ANA_TOP_PLL_LOOPFILT_0, 0xb4}, + {ANA_TOP_PLL_OVRD_CTL, 0x00}, + {ANA_TOP_BG_TVP_OVRD_CTL, 0x00}, + {ANA_TOP_BOOST_STB_CTRL2, 0x03}, + {ANA_TOP_BOOST_STB_CTRL3, 0x3c}, + {ANA_TOP_BOOST_BYP_CTRL2, 0xc5}, + {ANA_TOP_BOOST_BYP_CTRL3, 0x13}, + {ANA_TOP_BOOST_MISC, 0x79}, + {ANA_TOP_SPK_TOP_SPARE3, 0x00}, + {SPK_TOP_COMMON_CTRL2, 0x08}, + {SPK_TOP_LF_CH1_CTRL11, 0x09}, + {SPK_TOP_LF_CH1_TUNE1, 0x00}, + {SPK_TOP_LF_CH2_TUNE1, 0x00}, + {SPK_TOP_LF_CH1_CTRL9, 0x00}, + {SPK_TOP_LF_CH2_CTRL9, 0x00}, + {SPK_TOP_LF_CH2_CTRL11, 0x09}, + {SPK_TOP_COMMON_TUNE1, 0x08}, + {SPK_TOP_COMMON_TUNE1, 0x03}, + {IVSENSE_VSNS_ISNS_CTL_CH1, 0x00}, + {DIG_CTRL0_CDC_CLK_CTL, 0x0e}, + {PON_CKSK_CTL_0, 0x00}, + {ANA_TOP_BOOST_PWRSTAGE_CTRL2, 0x40}, + {ANA_TOP_BOOST_PWRSTAGE_CTRL4, 0xff}, + {ANA_TOP_PLL_STATUS_0, 0x00}, + {ANA_TOP_PLL_STATUS_1, 0x00}, + {ANA_TOP_IVSENSE_ADC_MODE_CTL2, 0x84}, + {ANA_TOP_IVSENSE_ADC_MODE_CTL3, 0x02}, + {ANA_TOP_IVSENSE_ADC_REF_CTL, 0x00}, + {ANA_TOP_IVSENSE_ADC_CDAC_CAL_CTL2, 0xe0}, + {ANA_TOP_SPK_TOP_PWRSTG_CH1_CTRL3, 0xa4}, + {ANA_TOP_SPK_TOP_PWRSTG_CH1_TUNE3, 0xc9}, + {ANA_TOP_SPK_TOP_PWRSTG_CH2_CTRL3, 0xa4}, + {ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3, 0xc5}, + {ANA_TOP_SPK_TOP_PWRSTG_CH2_TUNE3, 0xc9}, + {DIG_CTRL0_TOP_CLK_CFG, 0x00}, + {DIG_CTRL0_SDCA_COMMIT, 0x00}, + {DIG_CTRL0_CLK_SOURCE_ENABLE, 0x00}, + {DIG_CTRL0_SYS_CLK_SEL, 0x00}, + {DIG_CTRL0_CDC_CLK_CTL, 0x0e}, + {DIG_CTRL0_PA_FSM_CTL, 0x00}, + {DIG_CTRL0_POWER_FSM_CTL0, 0x05}, + {DIG_CTRL0_POWER_FSM_CTL1, 0x00}, + {DIG_CTRL0_PA0_FSM_CTL1, 0x45}, + {DIG_CTRL0_PA1_FSM_CTL1, 0x45}, + {DIG_CTRL0_VBAT_THRM_FLT_CTL, 0x7f}, + {DIG_CTRL0_CDC_RXTX_FSCNT_CTL, 0x00}, + {DIG_CTRL0_GAIN_RAMP0_CTL1, 0x01}, + {DIG_CTRL0_GAIN_RAMP1_CTL1, 0x01}, + {DIG_CTRL1_I2S_CTL0, 0x06}, + {DIG_CTRL1_I2S_CFG0_TDM_TX, 0x00}, + {DIG_CTRL1_I2S_CFG1_TDM_TX, 0x00}, + {DIG_CTRL1_I2S_TDM_CTL0, 0x00}, + {DIG_CTRL1_I2S_TDM_CTL1, 0x05}, + {DIG_CTRL1_I2S_TDM_CH_TX, 0x00}, + {DIG_CTRL1_I2S_RESET_CTL, 0x00}, + {DIG_CTRL1_I2S_TDM_CH_RX, 0x08}, + {CDC_RX0_RX_PATH_CFG0, 0x89}, + {CDC_RX0_RX_PATH_CFG1, 0x64}, + {CDC_RX0_RX_PATH_CTL, 0x24}, + {RX0_RX_PATH_DSMDEM_CTL, 0x01}, + {CDC_RX1_RX_PATH_CFG0, 0x89}, + {CDC_RX1_RX_PATH_CFG1, 0x64}, + {CDC_RX1_RX_PATH_CTL, 0x04}, + {RX1_RX_PATH_DSMDEM_CTL, 0x01}, + {CDC_COMPANDER0_CTL0, 0x01}, + {CDC_COMPANDER0_CTL7, 0x2a}, + {CDC_COMPANDER1_CTL0, 0x01}, + {CDC_COMPANDER1_CTL7, 0x2a}, + {CDC_VSENSE0_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_VSENSE1_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_ISENSE0_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_ISENSE1_SPKR_PROT_PATH_CTL, 0x14}, + {CDC_CLSH_V1P8_BP_CTL1, 0x50}, + {CDC_CLSH_V1P8_BP_CTL0, 0x6c}, + {CDC_CLSH_CLSH_SIG_DP_CTL0, 0x0d}, + {CDC_CLSH_CLSH_V_HD_PA, 0x03}, + {CDC_CLSH_V1P8_BP_CTL2, 0x05}, +}; + +static int wsa885x_gpio_set(struct wsa885x_i2c_priv *wsa885x, bool val) +{ + int ret = 0; + + if (val) + ret = gpiod_direction_output(wsa885x->sd_n, 1); + else + ret = gpiod_direction_output(wsa885x->sd_n, 0); + + if (ret < 0) { + dev_err_ratelimited(wsa885x->dev, "%s: failed to set GPIO: %d\n", __func__, + ret); + } + return ret; +} + +static void reg_update_sequence(struct regmap *regmap, int slots) +{ + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x15); + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x11); + + /* Configure TDM control register 0 */ + if (slots == WSA885X_TDM2) + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x0); + else if (slots == WSA885X_TDM4) + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x04); + else if (slots == WSA885X_TDM8) + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0xC); + else + pr_warn("Invalid TDM slot count: %d, expected 2, 4, or 8\n", slots); + + regmap_update_bits(regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x01, 0x01); + + /* Configure TDM transmit channel settings */ + regmap_write(regmap, DIG_CTRL1_I2S_TDM_CH_TX, 0x01); + regmap_update_bits(regmap, DIG_CTRL1_I2S_TDM_CH_TX, 0x02, 0x02); +} + +static int wait_for_pll_lock(struct wsa885x_i2c_priv *wsa885x) +{ + unsigned int status; + int cnt = 0; + int ret = 0; + + do { + usleep_range(1000, 1100); + ret = regmap_read(wsa885x->regmap, ANA_TOP_PLL_STATUS_0, &status); + + /* Check if PLL is locked (bit 0 set) */ + if (ret == 0 && (status & WSA885X_PLL_LOCK_BIT)) { + dev_dbg(wsa885x->component->dev, "PLL locked successfully after %d ms\n", + cnt + 1); + return 0; + } + } while (++cnt < 20); /* Maximum 20ms timeout */ + + /* PLL lock timeout */ + dev_warn(wsa885x->component->dev, "PLL lock timeout after 20ms, status=0x%x\n", status); + return -ETIMEDOUT; +} + +static void wsa885x_2s_conf(struct wsa885x_i2c_priv *wsa885x) +{ + regmap_write(wsa885x->regmap, SPK_TOP_COMMON_TUNE1, 0x03); + regmap_write(wsa885x->regmap, SPK_TOP_LF_CH1_CTRL11, 0x0d); + regmap_write(wsa885x->regmap, SPK_TOP_LF_CH2_CTRL11, 0x0d); + regmap_write(wsa885x->regmap, CDC_CLSH_V1P8_BP_CTL1, 0x71); + regmap_write(wsa885x->regmap, CDC_CLSH_V1P8_BP_CTL0, 0xAA); +} + +static int wait_for_pde_state(struct wsa885x_i2c_priv *wsa885x, + int ps, int reg) +{ + int act_ps, cnt = 0, clock_valid; + int rc = 0; + + /* Poll for power state transition with timeout */ + do { + usleep_range(1000, 1500); + + /* Read actual power state from PDE register */ + rc = regmap_read(wsa885x->regmap, + SMP_AMP_CTRL_STEREO_PDE23_ACT_PS, + &act_ps); + + /* Check if desired power state is reached */ + if (rc == 0 && act_ps == ps) + return 0; + } while (++cnt < 5); + + /* Read clock validity status for debugging */ + regmap_read(wsa885x->regmap, + SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID, + &clock_valid); + + dev_err(wsa885x->component->dev, + "PDE power state %d request failed, actual_ps %d, clock_valid:%d\n", + ps, act_ps, clock_valid); + + return -ETIMEDOUT; +} + +static int codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = snd_soc_component_get_drvdata(component); + uint8_t value, cs21_sample_rate_idx, cs24_sample_rate_idx; + int open_count = 0; + + dev_dbg(wsa885x->dev, "%s: HW Params called with sampling rate as %d\n", __func__, + params_rate(params)); + + /* Check if multiple streams are open - only configure on first stream */ + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 1) + return 0; + + /* Extract sample rate from ALSA parameters */ + wsa885x->sample_rate = params_rate(params); + + /* Map sample rate to codec-specific rate indices */ + switch (wsa885x->sample_rate) { + case 8000: + value = 0x00; + cs21_sample_rate_idx = WSA885X_RX_RATE_8000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_8000HZ; + break; + case 16000: + value = 0x01; + cs21_sample_rate_idx = WSA885X_RX_RATE_16000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_16000HZ; + break; + case 32000: + value = 0x02; + cs21_sample_rate_idx = WSA885X_RX_RATE_32000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_48000HZ; + break; + case 44100: + value = 0x03; + cs21_sample_rate_idx = WSA885X_RX_RATE_44100HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_44100HZ; + break; + case 48000: + value = 0x03; + cs21_sample_rate_idx = WSA885X_RX_RATE_48000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_48000HZ; + break; + case 88200: + case 96000: + value = 0x04; + cs21_sample_rate_idx = WSA885X_RX_RATE_96000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_96000HZ; + break; + case 176400: + case 192000: + value = 0x05; + cs21_sample_rate_idx = WSA885X_RX_RATE_192000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_192000HZ; + break; + case 352800: + case 384000: + value = 0x06; + cs21_sample_rate_idx = WSA885X_RX_RATE_384000HZ; + cs24_sample_rate_idx = WSA885X_VI_RATE_384000HZ; + break; + default: + dev_err(component->dev, "sampling rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* Configure I2S control register with sample rate (bits 1:4) and enable bit */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CTL0, 0x1f, + (value << 1) + 1); + + /* Reset I2S interface */ + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x00); + + /* Set RX (playback) sample rate index */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_CS21_SAMPLERATEINDEX, + cs21_sample_rate_idx); + + /* Set VI (voltage/current sensing) sample rate index */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_CS24_SAMPLERATEINDEX, + cs24_sample_rate_idx); + + /* Program FU21 volume with current dB value (MSB) and zero LSB, then commit */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + + return 0; +} + +static int codec_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_slot_mask, + unsigned int rx_slot_mask, int slots, + int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + + dev_dbg(wsa885x->dev, "%s: TDM num_slots configured as %d\n", __func__, slots); + + /* Increment open count atomically - only configure on first call */ + if (atomic_inc_return(&wsa885x->open_count) > 1) + return 0; + + /* Reset I2S interface before configuration */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x01, 0x01); + + /* Configure TDM slots based on channel mask */ + if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_STEREO) { + /* Stereo configuration - both channels active */ + /* Configure slot0 for I-sense channel 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x01, 0x01); + /* Configure slot1 for I-sense channel 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x20, 0x20); + /* Configure slot3 for current protection sense 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG1_TDM_TX, + 0x05, 0x05); + /* Configure slot4 for current protection sense 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG1_TDM_TX, + 0x60, 0x60); + /* Apply TDM control sequence */ + reg_update_sequence(wsa885x->regmap, slots); + /* Enable transmit channels */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_TX, + 0x04, 0x04); + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_TX, + 0x08, 0x08); + } else if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_MONO_LEFT) { + /* Mono left channel configuration */ + /* Configure slot0 for I-sense channel 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x01, 0x01); + /* Configure slot1 for current protection sense 0 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x50, 0x50); + reg_update_sequence(wsa885x->regmap, slots); + } else if (wsa885x->rx_slot_mask == WSA885X_CHANNEL_MONO_RIGHT) { + /* Mono right channel configuration */ + /* Configure slot0 for I-sense channel 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x02, 0x02); + /* Configure slot1 for current protection sense 1 */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, + 0x60, 0x60); + reg_update_sequence(wsa885x->regmap, slots); + } + + /* Enable I2S control */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_CTL0, 0x01, 0x01); + + /* Release I2S reset */ + regmap_update_bits(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x01, 0x00); + + return 0; +} + +static int codec_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + uint8_t pll_div; + int i, open_count = 0, ret = 0; + + dev_dbg(wsa885x->dev, "%s: Freq: %d\n", __func__, freq); + + /* Check if multiple streams are open - only configure on first stream */ + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 1) + return 0; + + /* Calculate PLL divider: Fixed rate / target frequency */ + pll_div = CLK_RATE_FIXED / freq; + + /* Configure analog bias and thermal/voltage protection override */ + regmap_write(wsa885x->regmap, ANA_TOP_BG_TVP_OVRD_CTL, 0x03); + + /* Select internal system clock source */ + regmap_write(wsa885x->regmap, DIG_CTRL0_SYS_CLK_SEL, 0x04); + + /* Configure PLL loop filter for stability */ + regmap_write(wsa885x->regmap, ANA_TOP_PLL_LOOPFILT_0, 0xB4); + + /* Configure VCO (Voltage Controlled Oscillator) */ + regmap_write(wsa885x->regmap, ANA_TOP_PLL_VCO_CTL, 0x00); + + /* Disable PLL override mode */ + regmap_write(wsa885x->regmap, ANA_TOP_PLL_OVRD_CTL, 0x00); + + /* Set calculated PLL divider */ + regmap_write(wsa885x->regmap, ANA_PLL_DIV_CTL_0, pll_div); + + /* Enable PLL clock source */ + regmap_write(wsa885x->regmap, DIG_CTRL0_CLK_SOURCE_ENABLE, 0x02); + + /* Wait for PLL to lock with intelligent polling */ + ret = wait_for_pll_lock(wsa885x); + if (ret) { + dev_err(wsa885x->component->dev, "PLL lock failed, aborting sysclk configuration\n"); + return ret; + } + + /* Switch to PLL as system clock source */ + regmap_write(wsa885x->regmap, DIG_CTRL0_SYS_CLK_SEL, 0x00); + + /* Enable power FSM control */ + regmap_write(wsa885x->regmap, DIG_CTRL0_POWER_FSM_CTL1, 0x01); + + /* Apply codec-specific initialization table from device tree */ + for (i = 0; i < wsa885x->init_table_size / 2; i++) { + if (wsa885x->batt_conf == batt_2s && wsa885x->init_table[2 * i] == + SPK_TOP_LF_CH1_CTRL11) + wsa885x_2s_conf(wsa885x); + else if (wsa885x->batt_conf == batt_2s && + wsa885x->init_table[2 * i] == SPK_TOP_COMMON_TUNE1) + regmap_write(wsa885x->regmap, SPK_TOP_COMMON_TUNE1, 0x26); + else + regmap_write(wsa885x->regmap, wsa885x->init_table[2 * i], + wsa885x->init_table[2 * i + 1]); + } + return 0; +} + +static int wsa885x_handle_ssr_reset(struct wsa885x_i2c_priv *wsa885x) +{ + int ret; + + /* + * Re-toggle shutdown GPIO to force codec out of a potential SSR/fault + * state, then keep PA FSM disabled until power-up reconfiguration. + */ + if (wsa885x->sd_n) { + dev_dbg(wsa885x->component->dev, "%s: asserting powerdown gpio\n", + __func__); + ret = wsa885x_gpio_set(wsa885x, true); + if (ret) { + dev_err(wsa885x->component->dev, + "%s: failed to assert powerdown gpio: %d\n", + __func__, ret); + return ret; + } + + usleep_range(1000, 1500); + + dev_dbg(wsa885x->component->dev, "%s: deasserting powerdown gpio\n", + __func__); + ret = wsa885x_gpio_set(wsa885x, false); + if (ret) { + dev_err(wsa885x->component->dev, + "%s: failed to deassert powerdown gpio: %d\n", + __func__, ret); + return ret; + } + + usleep_range(2000, 2500); + } else { + dev_dbg(wsa885x->component->dev, + "%s: no powerdown gpio, skip gpio reset sequence\n", __func__); + } + + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + dev_dbg(wsa885x->component->dev, "%s: PA FSM disabled\n", __func__); + return 0; +} + +static int reinit_wsa885x_powerup(struct wsa885x_i2c_priv *wsa885x) +{ + int ret = 0; + int ps = 0; + + ret = wsa885x_handle_ssr_reset(wsa885x); + if (ret) { + dev_err(wsa885x->component->dev, "SSR reset failed: %d\n", ret); + return ret; + } + + dev_dbg(wsa885x->component->dev, "%s: programming reinit sequence\n", + __func__); + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_OT23_USAGE, + wsa885x->usage_mode); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX, 0x01); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER, 0x01); + + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, + wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, + wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + dev_dbg(wsa885x->component->dev, + "%s: committed usage=%u vol_db=%d cluster=1 posture=1\n", + __func__, wsa885x->usage_mode, wsa885x->stereo_voldB); + + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x00); + dev_dbg(wsa885x->component->dev, "%s: requested PS%d\n", __func__, ps); + + ret = wait_for_pde_state(wsa885x, ps, SMP_AMP_CTRL_STEREO_PDE23_ACT_PS); + if (!ret) { + dev_dbg(wsa885x->component->dev, + "Successfully transitioned to power state %d\n", ps); + } else { + dev_err(wsa885x->component->dev, + "Failed transitioned to power state %d\n", ps); + } + + return ret; +} + +static int codec_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct wsa885x_i2c_priv *wsa885x = snd_soc_dai_get_drvdata(dai); + int ret = 0, ps0 = 0, ps3 = 3, open_count = 0; + + dev_dbg(wsa885x->dev, "%s: Stream is %s\n", __func__, mute ? "muted" : "unmuted"); + + if (mute) { + open_count = atomic_dec_return(&wsa885x->open_count); + if (open_count > 0) + return 0; + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + /* Request power state 3 (low power/standby mode) */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x03); + ret = wait_for_pde_state(wsa885x, ps3, SMP_AMP_CTRL_STEREO_PDE23_ACT_PS); + if (!ret) { + dev_dbg(wsa885x->component->dev, + "Successfully transitioned to power state %d\n", ps3); + } + } else { + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 1) + return 0; + /* Disable power amplifier FSM before configuration */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x00); + + /* Configure usage mode for thermal/speaker protection */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_OT23_USAGE, + wsa885x->usage_mode); + + /* Set cluster index for audio processing */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX, 0x01); + + /* Set posture number for speaker configuration */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER, 0x01); + + /* Apply requested volume */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB, wsa885x->stereo_voldB); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB, 0x00); + + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + + /* Request power state 0 (active mode) */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_PDE23_REQ_PS, 0x00); + ret = wait_for_pde_state(wsa885x, ps0, SMP_AMP_CTRL_STEREO_PDE23_ACT_PS); + if (!ret) { + dev_dbg(wsa885x->component->dev, + "Successfully transitioned to power state %d\n", ps0); + } else { + dev_err(wsa885x->component->dev, "PS0 request failed\n"); + ret = reinit_wsa885x_powerup(wsa885x); + if (ret) + goto exit; + } + + /* Configure power amplifier based on channel configuration */ + if (wsa885x->rx_slot_mask == 0b11) { + /* Stereo mode - enable both PA channels */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x03); + } else if (wsa885x->rx_slot_mask == 0b01) { + /* Mono left channel */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0x01); + } else if (wsa885x->rx_slot_mask == 0b10) { + /* Mono right channel */ + regmap_write(wsa885x->regmap, DIG_CTRL0_PA_FSM_CTL, 0b10); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_RX, 0b01); + } + + /* Unmute both channels */ + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X0, 0x00); + regmap_write(wsa885x->regmap, SMP_AMP_CTRL_STEREO_FU21_MUTE_CH2X1, 0x00); + + /* Commit all changes */ + regmap_write(wsa885x->regmap, DIG_CTRL0_SDCA_COMMIT, 0x01); + } +exit: + return ret; +} + +static int codec_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + int open_count = 0; + + dev_dbg(wsa885x->dev, "%s: HW Free, resetting I2S registers\n", __func__); + + open_count = atomic_read(&wsa885x->open_count); + if (open_count > 0) + return 0; + + /* Reset I2S register in any case */ + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_RESET_CTL, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_CFG0_TDM_TX, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_CFG1_TDM_TX, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CTL1, 0x05); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CTL0, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_TX, 0x00); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_CTL0, 0x06); + regmap_write(wsa885x->regmap, DIG_CTRL1_I2S_TDM_CH_RX, 0x08); + + /* Reset Clock */ + regmap_write(wsa885x->regmap, DIG_CTRL0_CLK_SOURCE_ENABLE, 0x00); + regmap_write(wsa885x->regmap, ANA_TOP_BG_TVP_OVRD_CTL, 0x00); + + return 0; +} + +static const struct snd_soc_dai_ops wsa885x_i2c_dai_ops = { + .hw_params = codec_hw_params, + .set_tdm_slot = codec_set_tdm_slot, + .set_sysclk = codec_set_sysclk, + .mute_stream = codec_mute_stream, + .hw_free = codec_hw_free, +}; + +static struct snd_soc_dai_driver wsa885x_i2c_dai[] = { + { + .name = "wsa885x_dai_drv", + .playback = { + .stream_name = "WSA885X I2C TDM Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &wsa885x_i2c_dai_ops, + }, +}; + +static void wsa885x_gpio_powerdown(void *data) +{ + gpiod_direction_output(data, 1); +} + +static bool wsa885x_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ANA_TOP_PLL_STATUS_0: + case ANA_TOP_PLL_STATUS_1: + case SMP_AMP_CTRL_STEREO_PDE23_ACT_PS: + case SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID: + case WSA885X_INTR_STATUS0: + case WSA885X_INTR_STATUS0 + 1: + case WSA885X_INTR_STATUS0 + 2: + case WSA885X_INTR_CLEAR0: + case WSA885X_INTR_CLEAR0 + 1: + case WSA885X_INTR_CLEAR0 + 2: + return true; + default: + return false; + } +} + +static bool wsa885x_readable_register(struct device *dev, unsigned int reg) +{ + if (reg >= 0 && reg <= 0x88ff) + return true; + return false; +} + +static bool wsa885x_writeable_register(struct device *dev, unsigned int reg) +{ + if (reg >= 0 && reg <= 0x88ff) { + /* Read-only status registers */ + if (reg == ANA_TOP_PLL_STATUS_0 || + reg == WSA885X_INTR_STATUS0 || + reg == WSA885X_INTR_STATUS0 + 1 || + reg == WSA885X_INTR_STATUS0 + 2 || + reg == SMP_AMP_CTRL_STEREO_PDE23_ACT_PS || + reg == SMP_AMP_CTRL_STEREO_CS21_CLOCK_VALID) + return false; + return true; + } + return false; +} + +static const struct regmap_config regmap_cfg = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x88FF, + .ranges = regmap_ranges, + .num_ranges = ARRAY_SIZE(regmap_ranges), + .reg_defaults = codec_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(codec_reg_defaults), + .volatile_reg = wsa885x_volatile_register, + .writeable_reg = wsa885x_writeable_register, + .readable_reg = wsa885x_readable_register, + .cache_type = REGCACHE_MAPLE, + .use_single_read = true, + .use_single_write = true, +}; + +static int wsa885x_component_probe(struct snd_soc_component *component) +{ + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + wsa885x->component = component; + snd_soc_component_init_regmap(component, wsa885x->regmap); + /* Enable interrupts */ + regmap_write(wsa885x->regmap, DIG_CTRL1_SPMI_PAD_GPIO2_CTL, 0x2e); + regmap_write(wsa885x->regmap, DIG_CTRL1_INTR_MODE, 0x01); + regmap_write(wsa885x->regmap, DIG_CTRL1_PIN_CT, 0x04); + regmap_write(wsa885x->regmap, WSA885X_INTR_MASK0, 0x00); + regmap_write(wsa885x->regmap, WSA885X_INTR_MASK0 + 1, 0x00); + regmap_write(wsa885x->regmap, WSA885X_INTR_MASK0 + 2, 0xf8); + + return 0; +} + +static void wsa885x_component_remove(struct snd_soc_component *component) +{ + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + + if (!wsa885x) + return; + + snd_soc_component_exit_regmap(component); +} + +static void wsa885x_regulator_disable(void *data) +{ + regulator_bulk_disable(SUPPLIES_NUM, data); +} + +static int wsa885x_stereo_gain_offset_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + + /* UI range 0..124 maps to dB = value - 84; return slider value */ + ucontrol->value.integer.value[0] = wsa885x->stereo_voldB + 84; + return 0; +} + +static int wsa885x_stereo_gain_offset_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x = + snd_soc_component_get_drvdata(component); + long val = ucontrol->value.integer.value[0]; + + if (val < 0 || val > FU21_VOL_STEPS) { + dev_err(component->dev, "%s: Invalid range, Val: %ld\n", __func__, val); + return -EINVAL; + } + wsa885x->stereo_voldB = (int)val - 84; + dev_dbg(component->dev, "%s: Volume dB: %d\n", __func__, wsa885x->stereo_voldB); + return 0; +} + +static int wsa885x_i2c_usage_modes_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + if (!wsa885x_i2c) + return -EINVAL; + + ucontrol->value.integer.value[0] = wsa885x_i2c->usage_mode; + + return 0; +} + +static int wsa885x_i2c_usage_modes_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + if (!wsa885x_i2c) + return -EINVAL; + + wsa885x_i2c->usage_mode = ucontrol->value.integer.value[0]; + + dev_dbg(component->dev, "%s: Usage mode:%d\n", __func__, + wsa885x_i2c->usage_mode); + + return 0; +} + +static int wsa885x_i2c_rx_slot_mask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + ucontrol->value.enumerated.item[0] = wsa885x_i2c->rx_slot_mask; + + return 0; +} + +static int wsa885x_i2c_rx_slot_mask_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct wsa885x_i2c_priv *wsa885x_i2c = + snd_soc_component_get_drvdata(component); + + wsa885x_i2c->rx_slot_mask = ucontrol->value.enumerated.item[0]; + + dev_dbg(component->dev, "%s: Rx channel:%d select\n", __func__, + wsa885x_i2c->rx_slot_mask); + return 0; +} + +static const struct snd_kcontrol_new wsa885x_snd_controls[] = { + SOC_SINGLE_EXT("OT23 Usage Mode", SND_SOC_NOPM, 0, 8, 0, + wsa885x_i2c_usage_modes_get, + wsa885x_i2c_usage_modes_put), + + SOC_SINGLE_EXT_TLV("SA1 FU21 Stereo Gain Offset dB", SND_SOC_NOPM, + 0, FU21_VOL_STEPS, 0, + wsa885x_stereo_gain_offset_get, + wsa885x_stereo_gain_offset_put, + fu21_digital_gain), + + SOC_SINGLE_EXT("Rx Slot Mask", SND_SOC_NOPM, 0, 3, 0, + wsa885x_i2c_rx_slot_mask_get, + wsa885x_i2c_rx_slot_mask_put), +}; + +static const struct snd_soc_component_driver wsa885x_i2c_component = { + .name = "wsa885x-i2c", + .probe = wsa885x_component_probe, + .remove = wsa885x_component_remove, + .controls = wsa885x_snd_controls, + .num_controls = ARRAY_SIZE(wsa885x_snd_controls), + .dapm_widgets = NULL, + .num_dapm_widgets = 0, + .dapm_routes = NULL, + .num_dapm_routes = 0, +}; + +static irqreturn_t handle_wsa885x_i2c_irq(int irq, void *data) +{ + struct wsa885x_i2c_priv *wsa885x = data; + + /* Handle the interrupt based on the IRQ number */ + switch (irq) { + case WSA885X_IRQ_INT_SAF2WAR: + case WSA885X_IRQ_INT_WAR2SAF: + case WSA885X_IRQ_INT_PA0_OCP: + case WSA885X_IRQ_INT_PA1_OCP: + case WSA885X_IRQ_INT_CLIP0: + case WSA885X_IRQ_INT_CLIP1: + case WSA885X_IRQ_INT_CLK_WD: + case WSA885X_IRQ_INT_BOP: + case WSA885X_IRQ_INT_UVLO: + case WSA885X_IRQ_INT_PCM_DATA0_DC: + case WSA885X_IRQ_INT_PCM_DATA1_DC: + case WSA885X_IRQ_INT_PLL_UNLOCKED: + case WSA885X_IRQ_INT_PROT_MODE_CHANGE: + case WSA885X_IRQ_INT_PB_CLOCK_VALID: + case WSA885X_IRQ_INT_SENSE_CLOCK_VALID: + break; + case WSA885X_IRQ_INT_PCM_DATA0_WD: + case WSA885X_IRQ_INT_PCM_DATA1_WD: + if (!wsa885x) + return IRQ_NONE; + if (irq == WSA885X_IRQ_INT_PCM_DATA0_WD) { + regmap_update_bits(wsa885x->regmap, 0x84A0, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, 0x84A0, + 0x04, 0x01); + } else { + regmap_update_bits(wsa885x->regmap, 0x84A4, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, 0x84A4, + 0x04, 0x01); + } + break; + case WSA885X_IRQ_INT_PA0_FSM_ERR: + case WSA885X_IRQ_INT_PA1_FSM_ERR: + case WSA885X_IRQ_INT_MAIN_FSM_ERR: + if (!wsa885x) + return IRQ_NONE; + + if (irq == WSA885X_IRQ_INT_MAIN_FSM_ERR) { + regmap_update_bits(wsa885x->regmap, WSA885X_POWER_FSM_CTL0, + 0x08, 0x00); + regmap_update_bits(wsa885x->regmap, WSA885X_POWER_FSM_CTL0, + 0x08, 0x08); + regmap_update_bits(wsa885x->regmap, WSA885X_POWER_FSM_CTL0, + 0x08, 0x00); + } else if (irq == WSA885X_IRQ_INT_PA0_FSM_ERR) { + regmap_update_bits(wsa885x->regmap, WSA885X_PA0_FSM_CTL0, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, WSA885X_PA0_FSM_CTL0, + 0x04, 0x04); + regmap_update_bits(wsa885x->regmap, WSA885X_PA0_FSM_CTL0, + 0x04, 0x00); + } else if (irq == WSA885X_IRQ_INT_PA1_FSM_ERR) { + regmap_update_bits(wsa885x->regmap, WSA885X_PA1_FSM_CTL0, + 0x04, 0x00); + regmap_update_bits(wsa885x->regmap, WSA885X_PA1_FSM_CTL0, + 0x04, 0x04); + regmap_update_bits(wsa885x->regmap, WSA885X_PA1_FSM_CTL0, + 0x04, 0x00); + } + break; + default: + dev_warn(wsa885x->dev, "Unhandled IRQ: %d\n", irq); + return IRQ_NONE; + } + + pr_err_ratelimited("%s: handled %s interrupt\n", __func__, + wsa885x_irq_names[irq]); + + return IRQ_HANDLED; +} + +static irqreturn_t wsa885x_interrupt_handler(int irq, void *data) +{ + unsigned int status[NUM_REGS]; + int i, bit, ret = IRQ_NONE; + int irq_num; + struct wsa885x_i2c_priv *wsa885x = data; + int status_reg[NUM_REGS] = { + WSA885X_INTR_STATUS0, + WSA885X_INTR_STATUS0 + 1, + WSA885X_INTR_STATUS0 + 2 + }; + int clear_reg[NUM_REGS] = { + WSA885X_INTR_CLEAR0, + WSA885X_INTR_CLEAR0 + 1, + WSA885X_INTR_CLEAR0 + 2 + }; + + pr_debug("%s: interrupt for irq = %d triggered\n", __func__, irq); + /* Read all status registers */ + for (i = 0; i < NUM_REGS; i++) { + ret = regmap_read(wsa885x->regmap, status_reg[i], &status[i]); + if (ret) { + dev_err(wsa885x->dev, "Failed to read status_reg[%d] (0x%x): %d\n", + i, status_reg[i], ret); + return IRQ_NONE; + } + } + + for (i = 0; i < NUM_REGS; i++) { + for (bit = 0; bit < 8; bit++) { + if (status[i] & (1 << bit)) { + irq_num = i * 8 + bit; + ret = handle_wsa885x_i2c_irq(irq_num, wsa885x); + /* Clear the interrupt by writing 1 to the bit */ + regmap_update_bits(wsa885x->regmap, + clear_reg[i], + (1 << bit), + (1 << bit)); + /* Optionally clear again to 0 if needed */ + regmap_update_bits(wsa885x->regmap, + clear_reg[i], + (1 << bit), 0); + } + } + } + return ret; +} + +static int wsa885x_register_irq(struct wsa885x_i2c_priv *wsa885x) +{ + int ret; + + /* Get the IRQ number for the GPIO */ + int irq_number = gpiod_to_irq(wsa885x->intr_pin); + + if (irq_number < 0) { + pr_err("Failed to get IRQ number\n"); + gpiod_put(wsa885x->intr_pin); + return irq_number; + } + + ret = devm_request_threaded_irq(wsa885x->dev, irq_number, NULL, + wsa885x_interrupt_handler, + IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_FALLING, "WSA885X I2C Interrupt", + wsa885x); + if (ret) { + dev_err(wsa885x->dev, "Failed to request IRQ for wsa885x i2c\n"); + gpiod_put(wsa885x->intr_pin); + return ret; + } + return ret; +} + +static int wsa885x_i2c_probe(struct i2c_client *client) +{ + struct wsa885x_i2c_priv *wsa885x; + const char *init_table_prop = "wsa885x-init-table"; + int ret, i, count; + struct device *dev = &client->dev; + + wsa885x = devm_kzalloc(&client->dev, sizeof(struct wsa885x_i2c_priv), + GFP_KERNEL); + if (!wsa885x) + return -ENOMEM; + + wsa885x->client = client; + wsa885x->dev = dev; + wsa885x->stereo_voldB = -84; + wsa885x->regmap = devm_regmap_init_i2c(client, ®map_cfg); + atomic_set(&wsa885x->open_count, 0); + + if (IS_ERR(wsa885x->regmap)) + return PTR_ERR(wsa885x->regmap); + + count = of_property_count_u32_elems(dev->of_node, + "qcom,wsa885x-init-table"); + if (count > 0) + init_table_prop = "qcom,wsa885x-init-table"; + else + count = of_property_count_u32_elems(dev->of_node, init_table_prop); + + if (count > 0) { + if (count % 2 != 0) { + dev_err(dev, "%s: Invalid number of elements in %s\n", + __func__, init_table_prop); + return -EINVAL; + } + + wsa885x->init_table_size = count; + wsa885x->init_table = devm_kcalloc(dev, wsa885x->init_table_size, + sizeof(*wsa885x->init_table), + GFP_KERNEL); + if (!wsa885x->init_table) + return -ENOMEM; + + if (of_property_read_u32_array(dev->of_node, init_table_prop, wsa885x->init_table, + wsa885x->init_table_size)) { + dev_err(dev, "%s: Failed to read %s\n", + __func__, init_table_prop); + return -EINVAL; + } + } else { + dev_dbg(dev, "%s: init table absent, relying on reg_defaults\n", + __func__); + } + + ret = of_property_read_u32(dev->of_node, "qcom,battery-config", + &wsa885x->batt_conf); + if (ret) + ret = of_property_read_u32(dev->of_node, "qcom,battery_config", + &wsa885x->batt_conf); + if (ret) { + dev_dbg(dev, "battery-config not specified, defaulting to 1S\n"); + wsa885x->batt_conf = batt_1s; + } else if (wsa885x->batt_conf != batt_1s && wsa885x->batt_conf != batt_2s) { + return dev_err_probe(dev, -EINVAL, + "Invalid battery-config value %u (expected 1 or 2)\n", + wsa885x->batt_conf); + } + + for (i = 0; i < SUPPLIES_NUM; i++) + wsa885x->supplies[i].supply = supply_name[i]; + + ret = devm_regulator_bulk_get(dev, SUPPLIES_NUM, wsa885x->supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to get regulators\n"); + + ret = regulator_bulk_enable(SUPPLIES_NUM, wsa885x->supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable regulators\n"); + + ret = devm_add_action_or_reset(dev, wsa885x_regulator_disable, + wsa885x->supplies); + if (ret) { + dev_err(dev, "failed to devm_add_action_or_reset, %d\n", ret); + return ret; + } + + wsa885x->sd_n = + devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); + if (IS_ERR(wsa885x->sd_n)) + return dev_err_probe(dev, PTR_ERR(wsa885x->sd_n), + "Shutdown Control GPIO not found\n"); + + ret = wsa885x_gpio_set(wsa885x, false); + if (ret != 0) + return ret; + + ret = devm_add_action_or_reset(dev, wsa885x_gpio_powerdown, + wsa885x->sd_n); + if (ret) { + dev_err(dev, "failed to devm_add_action_or_reset, %d\n", ret); + return ret; + } + + ret = devm_snd_soc_register_component(dev, &wsa885x_i2c_component, wsa885x_i2c_dai, + ARRAY_SIZE(wsa885x_i2c_dai)); + if (ret) { + dev_err(dev, "Codec component registration failed\n"); + } else { + dev_dbg(dev, "Codec component:dai %s registration success!\n", + wsa885x_i2c_dai[0].name); + } + + i2c_set_clientdata(client, wsa885x); + + wsa885x->intr_pin = devm_gpiod_get_optional(dev, "interrupt", GPIOD_IN); + if (IS_ERR(wsa885x->intr_pin)) { + ret = PTR_ERR(wsa885x->intr_pin); + dev_err(dev, "Failed to get interrupt pin, %d\n", ret); + return ret; + } + + ret = wsa885x_register_irq(wsa885x); + if (ret) + dev_err(dev, "wsa885x irq registration failed ret: %d\n", ret); + + return ret; +} + +static const struct of_device_id wsa885x_i2c_dt_match[] = { + { + .compatible = "qcom,wsa885x-i2c", + }, + {}}; + +MODULE_DEVICE_TABLE(of, wsa885x_i2c_dt_match); + +static const struct i2c_device_id wsa885x_id_i2c[] = { + {"wsa885x_i2c", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, wsa885x_id_i2c); + +static struct i2c_driver i2c_slave_driver = { + .driver = { + .name = "wsa885x_i2c", + .of_match_table = wsa885x_i2c_dt_match, + }, + .probe = wsa885x_i2c_probe, + .id_table = wsa885x_id_i2c, +}; + +module_i2c_driver(i2c_slave_driver); + +MODULE_DESCRIPTION("ASoC WSA8855-I2C Smart PA Codec Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index e6e24f3b99222..a43f3fa7f4b77 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -71,6 +71,16 @@ config SND_SOC_QCOM_COMMON config SND_SOC_QCOM_SDW tristate +config SND_SOC_QCOM_QAIF + tristate "Qualcomm QAIF audio interface support" + depends on COMMON_CLK + select REGMAP_MMIO + help + Say Y or M to enable Qualcomm Audio Interface (QAIF) support + used on Shikra audio platforms. QAIF provides DMA-based audio + data transfer between the application processor and the audio + hardware interfaces (AIF and CIF). + config SND_SOC_QDSP6_COMMON tristate @@ -101,6 +111,7 @@ config SND_SOC_QDSP6_ASM_DAI config SND_SOC_QDSP6_APM_DAI tristate + select QCOM_SCM select SND_SOC_COMPRESS config SND_SOC_QDSP6_APM_LPASS_DAI @@ -202,6 +213,7 @@ config SND_SOC_SC8280XP select SND_SOC_QDSP6 select SND_SOC_QCOM_COMMON select SND_SOC_QCOM_SDW + select SND_SOC_QCOM_QAIF help To add support for audio on Qualcomm Technologies Inc. SC8280XP SoC-based systems. diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 985ce2ae286ba..857bb2a032a2d 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -31,6 +31,7 @@ snd-soc-qcom-common-y := common.o snd-soc-qcom-sdw-y := sdw.o snd-soc-x1e80100-y := x1e80100.o snd-soc-qcom-offload-utils-objs := usb_offload_utils.o +snd-soc-qcom-qaif-y := qaif-cpu.o qaif-platform.o qaif-shikra.o obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o obj-$(CONFIG_SND_SOC_QCOM_SDW) += snd-soc-qcom-sdw.o obj-$(CONFIG_SND_SOC_X1E80100) += snd-soc-x1e80100.o obj-$(CONFIG_SND_SOC_QCOM_OFFLOAD_UTILS) += snd-soc-qcom-offload-utils.o +obj-$(CONFIG_SND_SOC_QCOM_QAIF) += snd-soc-qcom-qaif.o #DSP lib obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/ diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index edc4611691f73..767606ea3ab7b 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -2,6 +2,7 @@ // Copyright (c) 2018, Linaro Limited. // Copyright (c) 2018, The Linux Foundation. All rights reserved. +#include #include #include #include @@ -23,6 +24,160 @@ static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = { SND_SOC_DAPM_SPK("DP7 Jack", NULL), }; +static struct device_node *qcom_snd_get_link_node(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_card *card = rtd->card; + struct device_node *np; + struct device_node *cpu_np; + struct of_phandle_args args; + int ret; + + if (!card->dev || !card->dev->of_node) + return NULL; + + for_each_available_child_of_node(card->dev->of_node, np) { + cpu_np = of_get_child_by_name(np, "cpu"); + if (!cpu_np) + continue; + + ret = of_parse_phandle_with_args(cpu_np, "sound-dai", "#sound-dai-cells", 0, &args); + of_node_put(cpu_np); + if (ret) + continue; + + if (args.np == rtd->dai_link->cpus[0].of_node && + args.args_count == 1 && args.args[0] == cpu_dai->id) { + of_node_put(args.np); + return np; + } + + of_node_put(args.np); + } + + return NULL; +} + +static int qcom_snd_parse_tdm_slot(struct device_node *np, + struct qcom_snd_tdm_slot_cfg *cfg) +{ + memset(cfg, 0, sizeof(*cfg)); + + return snd_soc_of_parse_tdm_slot(np, &cfg->tx_mask, &cfg->rx_mask, + &cfg->slots, &cfg->slot_width); +} + +static int qcom_snd_normalize_tdm_slots(struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg) +{ + unsigned int slots; + unsigned int slot_width; + + if (cpu_cfg->slots && codec_cfg->slots && cpu_cfg->slots != codec_cfg->slots) + return -EINVAL; + + if (cpu_cfg->slot_width && codec_cfg->slot_width && + cpu_cfg->slot_width != codec_cfg->slot_width) + return -EINVAL; + + slots = cpu_cfg->slots ?: codec_cfg->slots; + if (!slots) + return 0; + + slot_width = cpu_cfg->slot_width ?: codec_cfg->slot_width; + if (!slot_width) + return -EINVAL; + + cpu_cfg->slots = slots; + codec_cfg->slots = slots; + cpu_cfg->slot_width = slot_width; + codec_cfg->slot_width = slot_width; + + return 0; +} + +static int qcom_snd_parse_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd, + struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg) +{ + struct device_node *link_np; + struct device_node *cpu_np = NULL; + struct device_node *codec_np = NULL; + int ret; + + link_np = qcom_snd_get_link_node(rtd); + if (!link_np) + return -EINVAL; + + cpu_np = of_get_child_by_name(link_np, "cpu"); + codec_np = of_get_child_by_name(link_np, "codec"); + if (!cpu_np || !codec_np) { + ret = -EINVAL; + goto out; + } + + ret = qcom_snd_parse_tdm_slot(cpu_np, cpu_cfg); + if (ret) + goto out; + + ret = qcom_snd_parse_tdm_slot(codec_np, codec_cfg); +out: + of_node_put(codec_np); + of_node_put(cpu_np); + of_node_put(link_np); + + return ret; +} + +int qcom_snd_get_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd, + struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg) +{ + int ret; + + ret = qcom_snd_parse_dai_tdm_slots(rtd, cpu_cfg, codec_cfg); + if (ret) + return ret; + + return qcom_snd_normalize_tdm_slots(cpu_cfg, codec_cfg); +} +EXPORT_SYMBOL_GPL(qcom_snd_get_dai_tdm_slots); + +int qcom_snd_apply_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + struct qcom_snd_tdm_slot_cfg cpu_cfg; + struct qcom_snd_tdm_slot_cfg codec_cfg; + int i; + int ret; + + ret = qcom_snd_get_dai_tdm_slots(rtd, &cpu_cfg, &codec_cfg); + if (ret) + return ret == -EINVAL ? 0 : ret; + + if (!cpu_cfg.slots) + return ret; + + ret = snd_soc_dai_set_tdm_slot(cpu_dai, cpu_cfg.tx_mask, cpu_cfg.rx_mask, + cpu_cfg.slots, cpu_cfg.slot_width); + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, + codec_cfg.tx_mask, + codec_cfg.rx_mask, + codec_cfg.slots, + codec_cfg.slot_width); + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_snd_apply_dai_tdm_slots); + int qcom_snd_parse_of(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -219,6 +374,7 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: + case LPASS_CDC_DMA_VA_TX1: for_each_rtd_codec_dais(rtd, i, codec_dai) { rval = snd_soc_component_set_jack(codec_dai->component, jack, NULL); diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h index ee6662885593c..b73c25045e672 100644 --- a/sound/soc/qcom/common.h +++ b/sound/soc/qcom/common.h @@ -9,7 +9,18 @@ #define LPASS_MAX_PORT (SENARY_MI2S_TX + 1) +struct qcom_snd_tdm_slot_cfg { + unsigned int tx_mask; + unsigned int rx_mask; + unsigned int slots; + unsigned int slot_width; +}; + int qcom_snd_parse_of(struct snd_soc_card *card); +int qcom_snd_get_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd, + struct qcom_snd_tdm_slot_cfg *cpu_cfg, + struct qcom_snd_tdm_slot_cfg *codec_cfg); +int qcom_snd_apply_dai_tdm_slots(struct snd_soc_pcm_runtime *rtd); int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, struct snd_soc_jack *jack, bool *jack_setup); int qcom_snd_dp_jack_setup(struct snd_soc_pcm_runtime *rtd, diff --git a/sound/soc/qcom/qaif-cpu.c b/sound/soc/qcom/qaif-cpu.c new file mode 100644 index 0000000000000..0a3bd9e5879a0 --- /dev/null +++ b/sound/soc/qcom/qaif-cpu.c @@ -0,0 +1,1585 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-cpu.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qaif-reg.h" +#include "qaif.h" + +#define QAIF_AIF_REG_READ 1 +#define QAIF_AIF_REG_WRITE 0 + +static int qaif_cif_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *rd_dmactl; + struct qaif_dmactl *wr_dmactl; + struct qaif_cdc_intfctl *rd_intfctl; + struct qaif_cdc_intfctl *wr_intfctl; + + /* Allocate RDDMA control structure */ + rd_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!rd_dmactl) + return -ENOMEM; + + /* Allocate WRDMA control structure */ + wr_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!wr_dmactl) + return -ENOMEM; + + /* Allocate RDDMA INTF control structure */ + rd_intfctl = devm_kzalloc(dev, sizeof(struct qaif_cdc_intfctl), GFP_KERNEL); + if (!rd_intfctl) + return -ENOMEM; + + /* Allocate WRDMA INTF control structure */ + wr_intfctl = devm_kzalloc(dev, sizeof(struct qaif_cdc_intfctl), GFP_KERNEL); + if (!wr_intfctl) + return -ENOMEM; + + /* =================================================================== + * Allocate RDDMA (RX/Playback) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + rd_dmactl->enable = devm_regmap_field_alloc(dev, map, v->cif_rddma_enable); + rd_dmactl->reset = devm_regmap_field_alloc(dev, map, v->cif_rddma_reset); + + /* CFG register fields */ + rd_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->cif_rddma_shram_wm); + rd_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst1); + rd_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst2); + rd_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst4); + rd_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst8); + rd_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->cif_rddma_burst16); + rd_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_rddma_dma_dyncclk); + rd_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->cif_rddma_num_ot); + + /* INTF_CFG register fields */ + rd_intfctl->en_16bit_unpack = + devm_regmap_field_alloc(dev, map, v->cif_rddma_en_16bit_unpack); + rd_intfctl->intf_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_rddma_intf_dyncclk); + rd_intfctl->fs_out_gate = devm_regmap_field_alloc(dev, map, v->cif_rddma_fs_out_gate); + rd_intfctl->fs_sel = devm_regmap_field_alloc(dev, map, v->cif_rddma_fs_sel); + rd_intfctl->fs_delay = devm_regmap_field_alloc(dev, map, v->cif_rddma_fs_delay); + rd_intfctl->active_ch_en = devm_regmap_field_alloc(dev, map, v->cif_rddma_active_ch_en); + + /* =================================================================== + * Allocate WRDMA (TX/Capture) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + wr_dmactl->enable = devm_regmap_field_alloc(dev, map, v->cif_wrdma_enable); + wr_dmactl->reset = devm_regmap_field_alloc(dev, map, v->cif_wrdma_reset); + + /* CFG register fields */ + wr_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->cif_wrdma_shram_wm); + wr_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst1); + wr_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst2); + wr_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst4); + wr_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst8); + wr_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->cif_wrdma_burst16); + wr_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_wrdma_dma_dyncclk); + wr_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->cif_wrdma_num_ot); + + /* INTF_CFG register fields */ + wr_intfctl->en_16bit_unpack = + devm_regmap_field_alloc(dev, map, v->cif_wrdma_en_16bit_unpack); + wr_intfctl->intf_dyncclk = devm_regmap_field_alloc(dev, map, v->cif_wrdma_intf_dyncclk); + wr_intfctl->fs_out_gate = devm_regmap_field_alloc(dev, map, v->cif_wrdma_fs_out_gate); + wr_intfctl->fs_sel = devm_regmap_field_alloc(dev, map, v->cif_wrdma_fs_sel); + wr_intfctl->fs_delay = devm_regmap_field_alloc(dev, map, v->cif_wrdma_fs_delay); + wr_intfctl->active_ch_en = devm_regmap_field_alloc(dev, map, v->cif_wrdma_active_ch_en); + + /* =================================================================== + * Check for allocation errors + * =================================================================== + */ + if (IS_ERR(rd_dmactl->enable) || IS_ERR(wr_dmactl->enable) || + IS_ERR(rd_dmactl->reset) || IS_ERR(wr_dmactl->reset) || + IS_ERR(rd_dmactl->num_ot) || IS_ERR(wr_dmactl->num_ot) || + IS_ERR(rd_dmactl->dma_dyncclk) || IS_ERR(wr_dmactl->dma_dyncclk) || + IS_ERR(rd_dmactl->burst16) || IS_ERR(wr_dmactl->burst16) || + IS_ERR(rd_dmactl->burst8) || IS_ERR(wr_dmactl->burst8) || + IS_ERR(rd_dmactl->burst4) || IS_ERR(wr_dmactl->burst4) || + IS_ERR(rd_dmactl->burst2) || IS_ERR(wr_dmactl->burst2) || + IS_ERR(rd_dmactl->burst1) || IS_ERR(wr_dmactl->burst1) || + IS_ERR(rd_dmactl->shram_wm) || IS_ERR(wr_dmactl->shram_wm) || + IS_ERR(rd_intfctl->active_ch_en) || IS_ERR(wr_intfctl->active_ch_en) || + IS_ERR(rd_intfctl->fs_sel) || IS_ERR(wr_intfctl->fs_sel) || + IS_ERR(rd_intfctl->fs_delay) || IS_ERR(wr_intfctl->fs_delay) || + IS_ERR(rd_intfctl->fs_out_gate) || IS_ERR(wr_intfctl->fs_out_gate) || + IS_ERR(rd_intfctl->intf_dyncclk) || IS_ERR(wr_intfctl->intf_dyncclk) || + IS_ERR(rd_intfctl->en_16bit_unpack) || IS_ERR(wr_intfctl->en_16bit_unpack)) { + dev_err(dev, "error allocating codec dma regmap fields\n"); + return -EINVAL; + } + + /* Store in variant data */ + v->cif_rd_dmactl = rd_dmactl; + v->cif_wr_dmactl = wr_dmactl; + v->cif_rddma_intfctl = rd_intfctl; + v->cif_wrdma_intfctl = wr_intfctl; + + return 0; +} + +static struct qaif_cdc_intfctl * +qaif_get_cif_intfctl_handle(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct qaif_variant *v = drvdata->variant; + unsigned int dai_id = cpu_dai->driver->id; + struct qaif_cdc_intfctl *intfctl = NULL; + + if (!v) { + dev_err(soc_runtime->dev, "No variant data\n"); + return intfctl; + } + + switch (dai_id) { + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + intfctl = v->cif_rddma_intfctl; + break; + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + intfctl = v->cif_wrdma_intfctl; + break; + default: + dev_err(soc_runtime->dev, "invalid dai id for dma ctl: %d\n", dai_id); + break; + } + return intfctl; +} + +static int qaif_cif_daiops_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct qaif_variant *v = drvdata->variant; + struct qaif_cdc_intfctl *intfctl = NULL; + unsigned int dai_id = cpu_dai->driver->id; + unsigned int ret, regval; + unsigned int channels = params_channels(params); + int idx; + + pr_err("%s:%d: dai_id=%u stream=%d channels=%u rate=%u\n", + __func__, __LINE__, dai_id, substream->stream, channels, + params_rate(params)); + + switch (channels) { + case 1: + regval = QAIF_CIF_DMA_INTF_ONE_CHANNEL; + break; + case 2: + regval = QAIF_CIF_DMA_INTF_TWO_CHANNEL; + break; + case 4: + regval = QAIF_CIF_DMA_INTF_FOUR_CHANNEL; + break; + case 6: + regval = QAIF_CIF_DMA_INTF_SIX_CHANNEL; + break; + case 8: + regval = QAIF_CIF_DMA_INTF_EIGHT_CHANNEL; + break; + default: + dev_err(soc_runtime->dev, "invalid PCM config\n"); + return -EINVAL; + } + + intfctl = qaif_get_cif_intfctl_handle(substream, dai); + if (!intfctl) { + dev_err(soc_runtime->dev, "Invalid intfctl: %d\n", dai_id); + return -EINVAL; + } + idx = v->get_dma_idx(dai_id); + if (idx < 0) { + dev_err(soc_runtime->dev, "Invalid DMA index: %d\n", idx); + return -EINVAL; + } + //active channel mask + ret = regmap_fields_write(intfctl->active_ch_en, idx, regval); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to intfctl active_ch_en reg field: %d\n", ret); + return ret; + } + pr_err("%s:%d: configured active_ch_en idx=%d val=0x%x\n", + __func__, __LINE__, idx, regval); + + return 0; +} + +static int qaif_cif_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct qaif_variant *v = drvdata->variant; + unsigned int dai_id = cpu_dai->driver->id; + struct qaif_cdc_intfctl *intfctl = NULL; + int ret = 0, idx; + + pr_err("%s:%d: dai_id=%u stream=%d cmd=%d\n", + __func__, __LINE__, dai_id, substream->stream, cmd); + + intfctl = qaif_get_cif_intfctl_handle(substream, dai); + if (!intfctl) { + dev_err(soc_runtime->dev, "Invalid intfctl: %d\n", dai_id); + return -EINVAL; + } + idx = v->get_dma_idx(dai_id); + if (idx < 0) { + dev_err(soc_runtime->dev, "Invalid DMA index: %d\n", idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = regmap_fields_write(intfctl->intf_dyncclk, idx, 1); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl intf_dyncclk reg field: %d\n", + ret); + return ret; + } + /* ToDo: Hardcoded for now, Later to modify dynamically */ + ret = regmap_fields_write(intfctl->fs_sel, idx, 0x0); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl codec_fs_sel reg field: %d\n", + ret); + return ret; + } + + ret = regmap_fields_write(intfctl->en_16bit_unpack, idx, 0x1); + /* ToDo: based on bw and packing enable flag */ + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl en_16bit_unpack reg field: %d\n", + ret); + return ret; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = regmap_fields_write(intfctl->intf_dyncclk, idx, 0); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl intf_dyncclk reg field: %d\n", + ret); + return ret; + } + ret = regmap_fields_write(intfctl->en_16bit_unpack, idx, 0); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dmactl en_16bit_unpack reg field: %d\n", + ret); + return ret; + } + break; + default: + ret = -EINVAL; + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, cmd); + break; + } + pr_err("%s:%d: cmd=%d ret=%d idx=%d\n", + __func__, __LINE__, cmd, ret, idx); + return ret; +} + +const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops = { + .hw_params = qaif_cif_daiops_hw_params, + .trigger = qaif_cif_daiops_trigger, +}; +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cif_dai_ops); + +static int qaif_aif_cfg_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + struct qaif_aud_intfctl *aif_intfctl; + + /* Allocate AIF interface control structure */ + aif_intfctl = devm_kzalloc(dev, sizeof(struct qaif_aud_intfctl), GFP_KERNEL); + if (!aif_intfctl) + return -ENOMEM; + + /* =================================================================== + * Allocate regmap fields for AUD_INTF SYNC_CFG register + * =================================================================== + */ + aif_intfctl->inv_sync = devm_regmap_field_alloc(dev, map, v->aif_inv_sync); + aif_intfctl->sync_delay = devm_regmap_field_alloc(dev, map, v->aif_sync_delay); + aif_intfctl->sync_mode = devm_regmap_field_alloc(dev, map, v->aif_sync_mode); + aif_intfctl->sync_src = devm_regmap_field_alloc(dev, map, v->aif_sync_src); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF BIT_WIDTH_CFG register + * =================================================================== + */ + aif_intfctl->slot_width_rx = devm_regmap_field_alloc(dev, map, v->aif_slot_width_rx); + aif_intfctl->slot_width_tx = devm_regmap_field_alloc(dev, map, v->aif_slot_width_tx); + aif_intfctl->sample_width_rx = devm_regmap_field_alloc(dev, map, v->aif_sample_width_rx); + aif_intfctl->sample_width_tx = devm_regmap_field_alloc(dev, map, v->aif_sample_width_tx); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF MI2S_CFG register + * =================================================================== + */ + aif_intfctl->mono_mode_rx = devm_regmap_field_alloc(dev, map, v->aif_mono_mode_rx); + aif_intfctl->mono_mode_tx = devm_regmap_field_alloc(dev, map, v->aif_mono_mode_tx); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF LANE_CFG register + * =================================================================== + */ + aif_intfctl->lane_en = devm_regmap_field_alloc(dev, map, v->aif_lane_en); + aif_intfctl->lane_dir = devm_regmap_field_alloc(dev, map, v->aif_lane_dir); + aif_intfctl->loopback_en = devm_regmap_field_alloc(dev, map, v->aif_loopback_en); + aif_intfctl->ctrl_data_oe = devm_regmap_field_alloc(dev, map, v->aif_ctrl_data_oe); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF SLOT_EN registers + * =================================================================== + */ + aif_intfctl->slot_en_rx_mask = devm_regmap_field_alloc(dev, map, v->aif_slot_en_rx_mask); + aif_intfctl->slot_en_tx_mask = devm_regmap_field_alloc(dev, map, v->aif_slot_en_tx_mask); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF FRAME_CFG register + * =================================================================== + */ + aif_intfctl->bits_per_lane = devm_regmap_field_alloc(dev, map, v->aif_bits_per_lane); + + /* =================================================================== + * Allocate regmap fields for AUD_INTF CFG register + * =================================================================== + */ + aif_intfctl->full_cycle_en = devm_regmap_field_alloc(dev, map, v->aif_full_cycle_en); + + /* =================================================================== + * Check for allocation errors + * =================================================================== + */ + if (IS_ERR(aif_intfctl->inv_sync) || IS_ERR(aif_intfctl->sync_delay) || + IS_ERR(aif_intfctl->sync_mode) || IS_ERR(aif_intfctl->sync_src) || + IS_ERR(aif_intfctl->slot_width_rx) || IS_ERR(aif_intfctl->slot_width_tx) || + IS_ERR(aif_intfctl->sample_width_rx) || IS_ERR(aif_intfctl->sample_width_tx) || + IS_ERR(aif_intfctl->mono_mode_rx) || IS_ERR(aif_intfctl->mono_mode_tx) || + IS_ERR(aif_intfctl->lane_en) || IS_ERR(aif_intfctl->lane_dir) || + IS_ERR(aif_intfctl->loopback_en) || IS_ERR(aif_intfctl->ctrl_data_oe) || + IS_ERR(aif_intfctl->slot_en_rx_mask) || IS_ERR(aif_intfctl->slot_en_tx_mask) || + IS_ERR(aif_intfctl->bits_per_lane) || IS_ERR(aif_intfctl->full_cycle_en)) { + dev_err(dev, "error allocating AIF interface regmap fields\n"); + return -EINVAL; + } + + /* Store in variant data */ + v->aif_intfctl = aif_intfctl; + + dev_info(dev, "Successfully initialized AIF interface control bitfields\n"); + return 0; +} + +static int qaif_aif_cpu_init_bitfields(struct device *dev, + struct regmap *map) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *rd_dmactl; + struct qaif_dmactl *wr_dmactl; + + /* Allocate RDDMA control structure */ + rd_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!rd_dmactl) + return -ENOMEM; + + /* Allocate WRDMA control structure */ + wr_dmactl = devm_kzalloc(dev, sizeof(struct qaif_dmactl), GFP_KERNEL); + if (!wr_dmactl) + return -ENOMEM; + + /* =================================================================== + * Allocate RDDMA (RX/Playback) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + rd_dmactl->enable = devm_regmap_field_alloc(dev, map, v->rddma_enable); + rd_dmactl->reset = devm_regmap_field_alloc(dev, map, v->rddma_reset); + + /* CFG register fields */ + rd_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->rddma_shram_wm); + rd_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->rddma_burst1); + rd_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->rddma_burst2); + rd_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->rddma_burst4); + rd_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->rddma_burst8); + rd_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->rddma_burst16); + rd_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->rddma_dma_dyncclk); + rd_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->rddma_num_ot); + + /* =================================================================== + * Allocate WRDMA (TX/Capture) regmap fields for all 4 channels + * =================================================================== + */ + + /* CTL register fields */ + wr_dmactl->enable = devm_regmap_field_alloc(dev, map, v->wrdma_enable); + wr_dmactl->reset = devm_regmap_field_alloc(dev, map, v->wrdma_reset); + + /* CFG register fields */ + wr_dmactl->shram_wm = devm_regmap_field_alloc(dev, map, v->wrdma_shram_wm); + wr_dmactl->burst1 = devm_regmap_field_alloc(dev, map, v->wrdma_burst1); + wr_dmactl->burst2 = devm_regmap_field_alloc(dev, map, v->wrdma_burst2); + wr_dmactl->burst4 = devm_regmap_field_alloc(dev, map, v->wrdma_burst4); + wr_dmactl->burst8 = devm_regmap_field_alloc(dev, map, v->wrdma_burst8); + wr_dmactl->burst16 = devm_regmap_field_alloc(dev, map, v->wrdma_burst16); + wr_dmactl->dma_dyncclk = devm_regmap_field_alloc(dev, map, v->wrdma_dma_dyncclk); + wr_dmactl->num_ot = devm_regmap_field_alloc(dev, map, v->wrdma_num_ot); + + /* =================================================================== + * Check for allocation errors + * =================================================================== + */ + if (IS_ERR(rd_dmactl->enable) || IS_ERR(wr_dmactl->enable) || + IS_ERR(rd_dmactl->reset) || IS_ERR(wr_dmactl->reset) || + IS_ERR(rd_dmactl->num_ot) || IS_ERR(wr_dmactl->num_ot) || + IS_ERR(rd_dmactl->dma_dyncclk) || IS_ERR(wr_dmactl->dma_dyncclk) || + IS_ERR(rd_dmactl->burst16) || IS_ERR(wr_dmactl->burst16) || + IS_ERR(rd_dmactl->burst8) || IS_ERR(wr_dmactl->burst8) || + IS_ERR(rd_dmactl->burst4) || IS_ERR(wr_dmactl->burst4) || + IS_ERR(rd_dmactl->burst2) || IS_ERR(wr_dmactl->burst2) || + IS_ERR(rd_dmactl->burst1) || IS_ERR(wr_dmactl->burst1) || + IS_ERR(rd_dmactl->shram_wm) || IS_ERR(wr_dmactl->shram_wm)) { + dev_err(dev, "error allocating AIF dma regmap fields\n"); + return -EINVAL; + } + + /* Store in variant data */ + v->aif_rd_dmactl = rd_dmactl; + v->aif_wr_dmactl = wr_dmactl; + + return 0; +} + +static int qaif_aif_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + return 0; +} + +static int qaif_aif_cpu_daiops_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v = drvdata->variant; + int idx, ret = 0; + + pr_err("%s:%d: dai_id=%d stream=%d\n", + __func__, __LINE__, dai->driver->id, substream->stream); + + idx = v->get_dma_idx(dai->driver->id); + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = clk_prepare(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + pr_err("%s:%d: prepared bit_clk idx=%d\n", + __func__, __LINE__, idx); + return 0; +} + +static void qaif_aif_cpu_daiops_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v = drvdata->variant; + int idx = v->get_dma_idx(dai->driver->id); + + pr_err("%s:%d: dai_id=%d stream=%d\n", + __func__, __LINE__, dai->driver->id, substream->stream); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + else + regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + + if (drvdata->mi2s_was_prepared[idx]) { + drvdata->mi2s_was_prepared[idx] = false; + clk_disable(drvdata->mi2s_bit_clk[idx]); + } + + clk_unprepare(drvdata->mi2s_bit_clk[idx]); +} + +static int qaif_aif_cpu_daiops_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + const struct qaif_variant *v = drvdata->variant; + int idx, ret = -EINVAL; + + idx = v->get_dma_idx(dai->driver->id); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), QAIF_AUD_INTF_CTL_ENABLE_TX); + } else { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), QAIF_AUD_INTF_CTL_ENABLE_RX); + } + if (ret) + dev_err(dai->dev, "error writing to AIF CTL reg: %d\n", ret); + + ret = clk_enable(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + } else { + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CTL_REG(idx), 0); + } + if (ret) + dev_err(dai->dev, "error writing to AIF CTL reg: %d\n", ret); + + clk_disable(drvdata->mi2s_bit_clk[idx]); + + break; + } + + return ret; +} + +static int qaif_aif_cpu_daiops_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static int qaif_aif_cpu_daiops_probe(struct snd_soc_dai *dai) +{ + return 0; +} + +static int qaif_aif_cpu_daiops_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct qaif_drv_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + struct qaif_variant *v = drvdata->variant; + unsigned int idx; + struct qaif_aif_config *aif_intf_cfg = NULL; + snd_pcm_format_t format = params_format(params); + unsigned int channels = params_channels(params); + unsigned int rate = params_rate(params); + unsigned int slot_width = 32; + int bitwidth, ret; + u32 sync_cfg_val, lane_cfg_val, mi2s_cfg_val, frame_cfg_val; + u32 tx_bw_fields, rx_bw_fields, bit_width_cfg_val; + + idx = v->get_dma_idx(dai->driver->id); + + if (idx < 0) { + dev_err(dai->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + aif_intf_cfg = &v->aif_intf_cfg[idx]; + + if (!aif_intf_cfg) { + dev_err(dai->dev, "AIF interface config not found\n"); + return -EINVAL; + } + bitwidth = snd_pcm_format_width(format); + if (bitwidth < 0) { + dev_err(dai->dev, "invalid bit width given: %d\n", bitwidth); + return bitwidth; + } + + /* Combine all fields into single value */ + sync_cfg_val = ((aif_intf_cfg->invert_sync << QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_MASK) | + ((aif_intf_cfg->sync_delay << + QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_MASK) | + ((aif_intf_cfg->sync_mode << + QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_MASK) | + ((aif_intf_cfg->sync_src << QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_SHFT) & + QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_MASK); + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_SYNC_CFG_REG(idx), sync_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_SYNC_CFG_REG: %d\n", ret); + return ret; + } + + lane_cfg_val = ((aif_intf_cfg->loopback_en << QAIF_AUD_INTF_LANE_CFG_LOOPBACK_SHFT) & + QAIF_AUD_INTF_LANE_CFG_LOOPBACK_MASK) | + ((aif_intf_cfg->ctrl_data_oe << + QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_SHFT) & + QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_MASK) | + ((aif_intf_cfg->lane_en_mask << + QAIF_AUD_INTF_LANE_CFG_LANE_EN_SHFT) & + QAIF_AUD_INTF_LANE_CFG_LANE_EN_MASK) | + ((aif_intf_cfg->lane_dir_mask << + QAIF_AUD_INTF_LANE_CFG_LANE_DIR_SHFT) & + QAIF_AUD_INTF_LANE_CFG_LANE_DIR_MASK); + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_LANE_CFG_REG(idx), lane_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_LANE_CFG_REG: %d\n", ret); + return ret; + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_CFG_REG(idx), aif_intf_cfg->full_cycle_en); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_CFG_REG: %d\n", ret); + return ret; + } + dev_dbg(dai->dev, "%s: sync_cfg_val: %x, lane_cfg_val: %x, full_cycle_en: %x\n", + __func__, sync_cfg_val, lane_cfg_val, aif_intf_cfg->full_cycle_en); + + ret = regmap_read(drvdata->audio_qaif_map, + QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx), + &bit_width_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to read QAIF_AUD_INTF_BIT_WIDTH_CFG_REG: %d\n", ret); + return ret; + } + + ret = regmap_read(drvdata->audio_qaif_map, + QAIF_AUD_INTF_MI2S_CFG_REG(idx), &mi2s_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to read QAIF_AUD_INTF_MI2S_CFG_REG: %d\n", ret); + return ret; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slot_width = aif_intf_cfg->slot_width_tx; + /* Prepare TX field values */ + tx_bw_fields = + ((QAIF_AIF_SAMPLE_WIDTH(bitwidth) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_MASK) | + ((QAIF_AIF_SLOT_WIDTH(slot_width) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_MASK); + + /* Clear TX fields, preserve RX fields, write new TX values */ + bit_width_cfg_val = + (bit_width_cfg_val & + ~QAIF_AUD_INTF_BIT_WIDTH_CFG_TX_FIELDS_MASK) | + tx_bw_fields; + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx), bit_width_cfg_val); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_BIT_WIDTH_CFG_REG: %d\n", + ret); + return ret; + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(idx), + aif_intf_cfg->slot_en_tx_mask); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG: %d\n", + ret); + return ret; + } + + frame_cfg_val = (slot_width * aif_intf_cfg->bits_per_lane) - 1; + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_FRAME_CFG_REG(idx), frame_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_FRAME_CFG_REG: %d\n", ret); + return ret; + } + + /* Clear TX field, preserve RX field */ + mi2s_cfg_val &= ~QAIF_AUD_INTF_MI2S_CFG_TX_FIELDS_MASK; + if (channels >= 2) { + /* Set new TX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_STEREO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK); + } else { + /* Set new TX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_MONO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK); + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_MI2S_CFG_REG(idx), + mi2s_cfg_val); + if (ret) { + dev_err(dai->dev, "Write to read QAIF_AUD_INTF_MI2S_CFG_REG: %d\n", ret); + return ret; + } + dev_err(dai->dev, "%s: TX bw_cfg=%x slot_en=%x frame=%x mi2s=%x\n", + __func__, bit_width_cfg_val, + aif_intf_cfg->slot_en_tx_mask, + frame_cfg_val, mi2s_cfg_val); + } else { + slot_width = aif_intf_cfg->slot_width_tx; + /* Prepare RX field values */ + rx_bw_fields = + ((QAIF_AIF_SAMPLE_WIDTH(bitwidth) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_MASK) | + ((QAIF_AIF_SLOT_WIDTH(slot_width) << + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_SHFT) & + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_MASK); + + /* Clear RX fields, preserve TX fields, write new RX values */ + bit_width_cfg_val = + (bit_width_cfg_val & + ~QAIF_AUD_INTF_BIT_WIDTH_CFG_RX_FIELDS_MASK) | + rx_bw_fields; + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(idx), bit_width_cfg_val); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_BIT_WIDTH_CFG_REG: %d\n", + ret); + return ret; + } + + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(idx), + aif_intf_cfg->slot_en_rx_mask); + if (ret) { + dev_err(dai->dev, + "Write to read QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG: %d\n", + ret); + return ret; + } + + frame_cfg_val = (slot_width * aif_intf_cfg->bits_per_lane) - 1; + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_FRAME_CFG_REG(idx), frame_cfg_val); + if (ret) { + dev_err(dai->dev, "Failed to write QAIF_AUD_INTF_FRAME_CFG_REG: %d\n", ret); + return ret; + } + + /* Clear RX field, preserve TX field */ + mi2s_cfg_val &= ~QAIF_AUD_INTF_MI2S_CFG_RX_FIELDS_MASK; + if (channels >= 2) { + /* Set new RX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_STEREO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK); + } else { + /* Set new RX mono mode value */ + mi2s_cfg_val |= + ((QAIF_AUD_INTF_CTL_MONO << + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_SHFT) & + QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK); + } + ret = regmap_write(drvdata->audio_qaif_map, + QAIF_AUD_INTF_MI2S_CFG_REG(idx), + mi2s_cfg_val); + if (ret) { + dev_err(dai->dev, "Write to read QAIF_AUD_INTF_MI2S_CFG_REG: %d\n", ret); + return ret; + } + dev_err(dai->dev, "%s: RX bw_cfg=%x slot_en=%x frame=%x mi2s=%x\n", + __func__, bit_width_cfg_val, + aif_intf_cfg->slot_en_rx_mask, + frame_cfg_val, mi2s_cfg_val); + } + + if (ret) { + dev_err(dai->dev, "error writing to aif_intfctl channels mode: %d\n", + ret); + return ret; + } + + ret = clk_set_rate(drvdata->mi2s_bit_clk[idx], + rate * slot_width * aif_intf_cfg->bits_per_lane); + if (ret) { + dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n", + rate * slot_width * aif_intf_cfg->bits_per_lane, ret); + return ret; + } + dev_dbg(dai->dev, "setting IBIT clock to %u\n", + rate * slot_width * aif_intf_cfg->bits_per_lane); + + if (!drvdata->mi2s_was_prepared[idx]) { + ret = clk_enable(drvdata->mi2s_bit_clk[idx]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + return ret; + } + drvdata->mi2s_was_prepared[idx] = true; + + dev_dbg(rtd->card->dev, "%s: substream = %s stream = %d\n", + __func__, substream->name, substream->stream); + snd_soc_dai_set_tdm_slot(codec_dai, 0x0f, 0b11, + aif_intf_cfg->bits_per_lane, slot_width); + snd_soc_dai_set_sysclk(codec_dai, 0, + rate * aif_intf_cfg->bits_per_lane * slot_width, + 0); + } + + return 0; +} + +const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops = { + .probe = qaif_aif_cpu_daiops_probe, + .set_sysclk = qaif_aif_cpu_daiops_set_sysclk, + .startup = qaif_aif_cpu_daiops_startup, + .shutdown = qaif_aif_cpu_daiops_shutdown, + .hw_params = qaif_aif_cpu_daiops_hw_params, + .trigger = qaif_aif_cpu_daiops_trigger, + .prepare = qaif_aif_cpu_daiops_prepare, +}; +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_aif_cpu_dai_ops); + +static int asoc_qcom_of_xlate_dai_name(struct snd_soc_component *component, + const struct of_phandle_args *args, + const char **dai_name) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct qaif_variant *v = drvdata->variant; + int id = args->args[0]; + int ret = -EINVAL; + int i; + + for (i = 0; i < v->num_dai; i++) { + if (v->dai_driver[i].id == id) { + *dai_name = v->dai_driver[i].name; + ret = 0; + break; + } + } + + return ret; +} + +static const struct snd_soc_component_driver qaif_cpu_comp_driver = { + .name = "qaif-cpu", + .of_xlate_dai_name = asoc_qcom_of_xlate_dai_name, + .legacy_dai_naming = 1, +}; + +static bool __audio_qaif_regmap_accessible(struct device *dev, unsigned int reg, bool rw) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + int i; + + if (reg == QAIF_EE_OVERLAP_IRQ_EN_REG) + return true; + if (reg == QAIF_EE_OVERLAP_IRQ_RAW_STATUS_REG) + return true; + if (reg == QAIF_EE_OVERLAP_IRQ_CLEAR_REG) + return true; + if (reg == QAIF_EE_OVERLAP_IRQ_FORCE_REG) + return true; + + for (i = 0; i < DMA_TYPE_MAX; i++) { + //RDDMA IRQ + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_FORCE_REG(v, i)) + return true; + + //WRDMA IRQ + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_FORCE_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_FORCE_REG(v, i)) + return true; + } + + for (i = 0; i < v->num_rddma; i++) { + if (reg == QAIF_RDDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_RDDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_RDDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + + for (i = 0; i < v->num_wrdma; i++) { + if (reg == QAIF_WRDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_WRDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_WRDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + + for (i = 0; i < v->num_codec_rddma; i++) { + if (reg == QAIF_CODEC_RDDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_RDDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + + for (i = 0; i < v->num_codec_wrdma; i++) { + if (reg == QAIF_CODEC_WRDMA_CTL_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_CFG_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, i)) + return true; + if (rw == QAIF_AIF_REG_READ) { + if (reg == QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i)) + return true; + if (reg == QAIF_CODEC_WRDMA_PERIOD_CNT_REG(v, i)) + return true; + } + } + return true; +} + +static bool audio_qaif_regmap_writeable(struct device *dev, unsigned int reg) +{ + return __audio_qaif_regmap_accessible(dev, reg, QAIF_AIF_REG_WRITE); +} + +static bool audio_qaif_regmap_readable(struct device *dev, unsigned int reg) +{ + return __audio_qaif_regmap_accessible(dev, reg, QAIF_AIF_REG_READ); +} + +static bool audio_qaif_regmap_volatile(struct device *dev, unsigned int reg) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + struct qaif_variant *v = drvdata->variant; + int i; + + for (i = 0; i < DMA_TYPE_MAX; i++) { + //RDDMA IRQ + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + + //WRDMA IRQ + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i)) + return true; + if (reg == QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i)) + return true; + } + + for (i = 0; i < v->num_rddma; i++) + if (reg == QAIF_RDDMA_CURR_ADDR_REG(v, i)) + return true; + + for (i = 0; i < v->num_wrdma; i++) + if (reg == QAIF_WRDMA_CURR_ADDR_REG(v, i)) + return true; + + for (i = 0; i < v->num_codec_rddma; i++) + if (reg == QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, i)) + return true; + + for (i = 0; i < v->num_codec_wrdma; i++) + if (reg == QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, i)) + return true; + + return true; +} + +static struct regmap_config audio_qaif_regmap_config = { + .name = "audio_qaif_cpu", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .writeable_reg = audio_qaif_regmap_writeable, + .readable_reg = audio_qaif_regmap_readable, + .volatile_reg = audio_qaif_regmap_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static int of_qaif_parse_aif_intf_cfg(struct device *dev, + struct qaif_drv_data *data) +{ + struct qaif_variant *v = data->variant; + struct device_node *np = dev->of_node; + struct device_node *intf_np; + struct qaif_aif_config *cfg; + const __be32 *lane_cfg_prop; + int num_interfaces, ret, i, j; + int lane_cfg_len; + int dai_id, intf_idx; + + if (!v) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + /* Get count of interface phandles from aif-interface property */ + num_interfaces = of_count_phandle_with_args(np, "aif-interface", NULL); + if (num_interfaces <= 0) { + dev_err(dev, "No aif-interface property found or invalid: %d\n", num_interfaces); + return -EINVAL; + } + + if (num_interfaces > QAIF_MAX_AIF_CFG_CNT) { + dev_warn(dev, "Too many interfaces (%d), limiting to %d\n", + num_interfaces, QAIF_MAX_AIF_CFG_CNT); + num_interfaces = QAIF_MAX_AIF_CFG_CNT; + } + + dev_info(dev, "Found %d AIF interfaces to parse\n", num_interfaces); + + /* Parse each interface node */ + for (i = 0; i < num_interfaces; i++) { + intf_np = of_parse_phandle(np, "aif-interface", i); + if (!intf_np) { + dev_err(dev, "Failed to get interface node %d\n", i); + continue; + } + + dev_dbg(dev, "Parsing interface %d: %s\n", i, intf_np->name); + + ret = of_property_read_u32(intf_np, "qcom,qaif-intf-dai-id", &dai_id); + if (ret) { + dev_err(dev, "Missing dai-id for interface %d: %s ===\n", i, intf_np->name); + continue; + } + + if (v->get_dma_idx) { + intf_idx = v->get_dma_idx(dai_id); + if (intf_idx < 0) { + dev_err(dev, + "invalid intf idx for : %d: %s ===\n", + i, intf_np->name); + continue; + } + } else { + dev_err(dev, "can not get intf idx for : %d: %s ===\n", i, intf_np->name); + return -EINVAL; + } + cfg = &v->aif_intf_cfg[intf_idx]; + + /* Parse sync configuration */ + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-mode", &cfg->sync_mode); + if (ret) { + dev_warn(dev, "Missing sync-mode for interface %d\n", i); + cfg->sync_mode = 0; + } + + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-src", &cfg->sync_src); + if (ret) { + dev_warn(dev, "Missing sync-src for interface %d\n", i); + cfg->sync_src = 0; + } + + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-invert-sync", &cfg->invert_sync); + if (ret) { + dev_warn(dev, "Missing invert-sync for interface %d\n", i); + cfg->invert_sync = 0; + } + + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-sync-delay", &cfg->sync_delay); + if (ret) { + dev_warn(dev, "Missing sync-delay for interface %d\n", i); + cfg->sync_delay = 0; + } + + /* Parse slot and sample width configuration */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-width-rx", + &cfg->slot_width_rx); + if (ret) { + dev_warn(dev, "Missing slot-width-rx for interface %d\n", i); + cfg->slot_width_rx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-width-tx", + &cfg->slot_width_tx); + if (ret) { + dev_warn(dev, "Missing slot-width-tx for interface %d\n", i); + cfg->slot_width_tx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-sample-width-rx", + &cfg->sample_width_rx); + if (ret) { + dev_warn(dev, "Missing sample-width-rx for interface %d\n", i); + cfg->sample_width_rx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-sample-width-tx", + &cfg->sample_width_tx); + if (ret) { + dev_warn(dev, "Missing sample-width-tx for interface %d\n", i); + cfg->sample_width_tx = 0; + } + + /* Parse slot enable masks */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-en-rx-mask", + &cfg->slot_en_rx_mask); + if (ret) { + dev_warn(dev, "Missing slot-en-rx-mask for interface %d\n", i); + cfg->slot_en_rx_mask = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-slot-en-tx-mask", + &cfg->slot_en_tx_mask); + if (ret) { + dev_warn(dev, "Missing slot-en-tx-mask for interface %d\n", i); + cfg->slot_en_tx_mask = 0; + } + + /* Parse control configuration */ + ret = of_property_read_u32(intf_np, "qcom,qaif-aif-loopback-en", &cfg->loopback_en); + if (ret) { + dev_warn(dev, "Missing loopback-en for interface %d\n", i); + cfg->loopback_en = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-ctrl-data-oe", + &cfg->ctrl_data_oe); + if (ret) { + dev_warn(dev, "Missing ctrl-data-oe for interface %d\n", i); + cfg->ctrl_data_oe = 0; + } + + /* Parse lane configuration */ + lane_cfg_prop = of_get_property(intf_np, + "qcom,qaif-aif-lane-config", + &lane_cfg_len); + if (lane_cfg_prop) { + /* Each lane config has 2 u32 values: enable and direction */ + cfg->num_lanes = lane_cfg_len / (2 * sizeof(u32)); + if (cfg->num_lanes > QAIF_MAX_LANES) { + dev_warn(dev, "Too many lanes (%d), limiting to %d\n", + cfg->num_lanes, QAIF_MAX_LANES); + cfg->num_lanes = QAIF_MAX_LANES; + } + + for (j = 0; j < cfg->num_lanes; j++) { + cfg->lane_cfg[j].enable = + be32_to_cpup(lane_cfg_prop + (j * 2)); + if (cfg->lane_cfg[j].enable) + cfg->lane_en_mask |= BIT(j); + /* Set bit j for lane enable */ + + cfg->lane_cfg[j].direction = + be32_to_cpup(lane_cfg_prop + (j * 2 + 1)); + if (cfg->lane_cfg[j].direction) + cfg->lane_dir_mask |= BIT(j); + /* Set bit j for RX direction */ + } + + } else { + dev_warn(dev, "Missing lane-config for interface %d\n", i); + cfg->num_lanes = 0; + } + + /* Parse mono/stereo mode */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-mono-mode-tx", + &cfg->mono_mode_tx); + if (ret) { + dev_warn(dev, "Missing mono-mode-tx for interface %d\n", i); + cfg->mono_mode_tx = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-mono-mode-rx", + &cfg->mono_mode_rx); + if (ret) { + dev_warn(dev, "Missing mono-mode-rx for interface %d\n", i); + cfg->mono_mode_rx = 0; + } + + /* Parse frame configuration */ + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-full-cycle-en", + &cfg->full_cycle_en); + if (ret) { + dev_warn(dev, "Missing full-cycle-en for interface %d\n", i); + cfg->full_cycle_en = 0; + } + + ret = of_property_read_u32(intf_np, + "qcom,qaif-aif-bits-per-lane", + &cfg->bits_per_lane); + if (ret) { + dev_warn(dev, "Missing bits-per-lane for interface %d\n", i); + cfg->bits_per_lane = 0; + } + + /* Debug dump of parsed properties. */ + dev_dbg(dev, "Interface %d configuration:\n", i); + dev_dbg(dev, " Node name: %s\n", intf_np->name); + + /* Sync configuration */ + dev_dbg(dev, " Sync Configuration:\n"); + dev_dbg(dev, " sync_mode = %u\n", cfg->sync_mode); + dev_dbg(dev, " sync_src = %u\n", cfg->sync_src); + dev_dbg(dev, " invert_sync = %u\n", cfg->invert_sync); + dev_dbg(dev, " sync_delay = %u\n", cfg->sync_delay); + + /* Slot and sample width */ + dev_dbg(dev, " Width Configuration:\n"); + dev_dbg(dev, " slot_width_rx = %u\n", cfg->slot_width_rx); + dev_dbg(dev, " slot_width_tx = %u\n", cfg->slot_width_tx); + dev_dbg(dev, " sample_width_rx= %u\n", cfg->sample_width_rx); + dev_dbg(dev, " sample_width_tx= %u\n", cfg->sample_width_tx); + + /* Slot enable masks */ + dev_dbg(dev, " Slot Enable Masks:\n"); + dev_dbg(dev, " slot_en_rx_mask= 0x%08X\n", cfg->slot_en_rx_mask); + dev_dbg(dev, " slot_en_tx_mask= 0x%08X\n", cfg->slot_en_tx_mask); + + /* Control configuration */ + dev_dbg(dev, " Control Configuration:\n"); + dev_dbg(dev, " loopback_en = %u\n", cfg->loopback_en); + dev_dbg(dev, " ctrl_data_oe = %u\n", cfg->ctrl_data_oe); + + /* Lane configuration */ + dev_dbg(dev, " Lane Configuration (num_lanes=%u):\n", cfg->num_lanes); + for (j = 0; j < cfg->num_lanes; j++) { + dev_dbg(dev, " Lane %d: enable=%u, direction=%u (%s)\n", + j, cfg->lane_cfg[j].enable, cfg->lane_cfg[j].direction, + cfg->lane_cfg[j].direction ? "RX_MIC" : "TX_SPKR"); + } + dev_dbg(dev, " Lane Configuration (lane_en_mask=0x%x):\n", cfg->lane_en_mask); + dev_dbg(dev, " Lane Configuration (lane_dir_mask=0x%x):\n", cfg->lane_dir_mask); + + /* Mono/Stereo mode */ + dev_dbg(dev, " Mono/Stereo Mode:\n"); + dev_dbg(dev, " mono_mode_tx = %u (%s)\n", + cfg->mono_mode_tx, cfg->mono_mode_tx ? "MONO" : "STEREO"); + dev_dbg(dev, " mono_mode_rx = %u (%s)\n", + cfg->mono_mode_rx, cfg->mono_mode_rx ? "MONO" : "STEREO"); + + /* Frame configuration */ + dev_dbg(dev, " Frame Configuration:\n"); + dev_dbg(dev, " full_cycle_en = %u\n", cfg->full_cycle_en); + dev_dbg(dev, " bits_per_lane = %u\n", cfg->bits_per_lane); + + dev_dbg(dev, "End interface %d\n", i); + + of_node_put(intf_np); + } + + dev_info(dev, "Successfully parsed %d AIF interfaces\n", num_interfaces); + return 0; +} + +static int of_qaif_cdc_dma_clks_parse(struct device *dev, + struct qaif_drv_data *data) +{ + data->aud_dma_clk = devm_clk_get(dev, "audio_core_cc_aud_dma_clk"); + if (IS_ERR(data->aud_dma_clk)) + return PTR_ERR(data->aud_dma_clk); + + data->aud_dma_mem_clk = devm_clk_get(dev, "audio_core_cc_aud_dma_mem_clk"); + if (IS_ERR(data->aud_dma_mem_clk)) + return PTR_ERR(data->aud_dma_mem_clk); + + return 0; +} + +int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata; + struct resource *res; + struct qaif_variant *variant; + struct device *dev = &pdev->dev; + const struct of_device_id *match; + int ret, i, dai_id, idx; + bool variant_init_done = false; + + drvdata = devm_kzalloc(dev, sizeof(struct qaif_drv_data), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + platform_set_drvdata(pdev, drvdata); + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) + return -EINVAL; + + drvdata->variant = (struct qaif_variant *)match->data; + variant = drvdata->variant; + if (!variant) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + + ret = of_qaif_parse_aif_intf_cfg(dev, drvdata); + if (ret) { + dev_err(dev, "Failed to parse aif interfaces: %d\n", ret); + return -EINVAL; + } + + drvdata->audio_qaif = + devm_platform_ioremap_resource_byname(pdev, "audio-qaif-core"); + if (IS_ERR(drvdata->audio_qaif)) + return PTR_ERR(drvdata->audio_qaif); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audio-qaif-core"); + if (!res) + return -EINVAL; + + audio_qaif_regmap_config.max_register = resource_size(res); + + drvdata->audio_qaif_map = devm_regmap_init_mmio(dev, drvdata->audio_qaif, + &audio_qaif_regmap_config); + if (IS_ERR(drvdata->audio_qaif_map)) + return PTR_ERR(drvdata->audio_qaif_map); + + ret = of_qaif_cdc_dma_clks_parse(dev, drvdata); + if (ret) { + dev_err(dev, "failed to get cdc dma clocks %d\n", ret); + return ret; + } + + if (variant->init) { + ret = variant->init(pdev); + if (ret) { + dev_err(dev, "error initializing variant: %d\n", ret); + return ret; + } + variant_init_done = true; + } + + for (i = 0; i < variant->num_dai; i++) { + dai_id = variant->dai_driver[i].id; + if (is_cif_dma_port(dai_id)) + continue; + idx = variant->get_dma_idx(dai_id); + if (idx < 0) + continue; + + drvdata->mi2s_bit_clk[idx] = devm_clk_get(dev, + variant->dai_bit_clk_names[idx]); + if (IS_ERR(drvdata->mi2s_bit_clk[idx])) { + dev_err(dev, + "error getting %s: %ld\n", + variant->dai_bit_clk_names[idx], + PTR_ERR(drvdata->mi2s_bit_clk[idx])); + ret = PTR_ERR(drvdata->mi2s_bit_clk[idx]); + goto err; + } + } + + ret = qaif_aif_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init cif bitfield: %d\n", ret); + goto err; + } + + /* Initialize bitfields for dai AIF CFG register */ + ret = qaif_aif_cfg_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init aif_intfctl field: %d\n", ret); + goto err; + } + + ret = qaif_cif_cpu_init_bitfields(dev, drvdata->audio_qaif_map); + if (ret) { + dev_err(dev, "error init cif bitfield: %d\n", ret); + goto err; + } + + ret = devm_snd_soc_register_component(dev, &qaif_cpu_comp_driver, + variant->dai_driver, + variant->num_dai); + if (ret) { + dev_err(dev, "error registering cpu driver: %d\n", ret); + goto err; + } + + ret = asoc_qcom_qaif_platform_register(pdev); + if (ret) { + dev_err(dev, "error registering platform driver: %d\n", ret); + goto err; + } + dev_info(&pdev->dev, "%s: QAIF CPU-Platform Driver Registered Successfully\n", __func__); +err: + if (ret && variant_init_done && variant->exit) + variant->exit(pdev); + return ret; +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_probe); + +void asoc_qcom_qaif_cpu_platform_remove(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + + if (drvdata->variant->exit) + drvdata->variant->exit(pdev); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_remove); + +void asoc_qcom_qaif_cpu_platform_shutdown(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + + if (drvdata->variant->exit) + drvdata->variant->exit(pdev); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_cpu_platform_shutdown); + +MODULE_DESCRIPTION("QTi QAIF CPU Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c new file mode 100644 index 0000000000000..545c2fd857d20 --- /dev/null +++ b/sound/soc/qcom/qaif-platform.c @@ -0,0 +1,1219 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-platform.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qaif-reg.h" +#include "qaif.h" + +#define DRV_NAME "qaif-platform" + +/* 20 ms @ 48kHz S16 stereo = 3840 bytes */ +#define QAIF_PLATFORM_BUFFER_MIN_SIZE (960 * 2 * 2) +/* min period = 960 frames @ S16 stereo = 3840 bytes */ +#define QAIF_PLATFORM_PERIOD_BYTES_MIN (960 * 2 * 2) +/* 80 ms = 15360 bytes */ +#define QAIF_PLATFORM_BUFFER_SIZE (4 * QAIF_PLATFORM_BUFFER_MIN_SIZE) +#define QAIF_PLATFORM_PERIODS_MIN 2 +#define QAIF_PLATFORM_PERIODS_MAX 4 // 4 × 3840 = 15360 = buffer_bytes_max + +#define QAIF_SMMU_SID_OFFSET 32 + +static irqreturn_t qaif_aif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status); +static irqreturn_t qaif_cif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status); +//static irqreturn_t qaif_aud_inf_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status); + +static int qaif_init(struct snd_soc_component *component); + +static const struct snd_pcm_hardware qaif_platform_aif_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = QAIF_PLATFORM_BUFFER_SIZE, + .period_bytes_min = QAIF_PLATFORM_PERIOD_BYTES_MIN, + .period_bytes_max = QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_MIN, + .periods_min = QAIF_PLATFORM_PERIODS_MIN, + .periods_max = QAIF_PLATFORM_PERIODS_MAX, + .fifo_size = 0, +}; + +static const struct snd_pcm_hardware qaif_platform_cif_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = QAIF_PLATFORM_BUFFER_SIZE, + .period_bytes_min = QAIF_PLATFORM_PERIOD_BYTES_MIN, + .period_bytes_max = QAIF_PLATFORM_BUFFER_SIZE / QAIF_PLATFORM_PERIODS_MIN, + .periods_min = QAIF_PLATFORM_PERIODS_MIN, + .periods_max = QAIF_PLATFORM_PERIODS_MAX, + .fifo_size = 0, +}; + +static const struct qaif_irq_map qaif_irq_clients[] = { + { QAIF_CLIENT_ID_AIF_DMA, QAIF_BITMASK_AIF_RDDMA_WRDMA, qaif_aif_irq_handler}, + { QAIF_CLIENT_ID_CIF_DMA, QAIF_BITMASK_CIF_RDDMA_WRDMA, qaif_cif_irq_handler}, + { QAIF_CLIENT_ID_AUD_INF, QAIF_BITMASK_AUD_INF, NULL}, +}; + +static const u32 QAIF_ALL_CLIENTS_MASK = + QAIF_BITMASK_AIF_RDDMA_WRDMA | + QAIF_BITMASK_CIF_RDDMA_WRDMA | + QAIF_BITMASK_AUD_INF; + +static struct qaif_dma_mem_info *qaif_mem_alloc_attach(struct snd_soc_component *component, + size_t alloc_size) +{ + struct device *dev = component->dev; + struct qaif_dma_mem_info *dma_mem_info; + + dma_mem_info = kzalloc_obj(*dma_mem_info, GFP_KERNEL); + if (!dma_mem_info) + return NULL; + + dma_mem_info->alloc_size = alloc_size; + + /* + * dma_alloc_coherent: allocates cache-coherent memory, returns + * CPU virtual address and fills dma_addr with the DMA/IOVA address. + */ + dma_mem_info->vaddr = dma_alloc_coherent(dev, alloc_size, + &dma_mem_info->dma_addr, + GFP_KERNEL); + if (!dma_mem_info->vaddr) { + dev_err(dev, "dma_alloc_coherent failed for %zu bytes\n", alloc_size); + kfree(dma_mem_info); + return NULL; + } + + dev_dbg(dev, "%s: dma_addr=%llx vaddr=%p\n", __func__, + dma_mem_info->dma_addr, dma_mem_info->vaddr); + return dma_mem_info; +} + +static void qaif_mem_dealloc_detach(struct device *dev, + struct qaif_dma_mem_info *dma_info) +{ + if (!dma_info) + return; + + if (dma_info->vaddr) + dma_free_coherent(dev, dma_info->alloc_size, + dma_info->vaddr, dma_info->dma_addr); + + kfree(dma_info); +} + +static struct qaif_dmactl *qaif_get_dmactl_handle(const struct snd_pcm_substream *substream, + struct snd_soc_component *component) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct qaif_dmactl *dmactl = NULL; + struct qaif_variant *v = drvdata->variant; + + switch (cpu_dai->driver->id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dmactl = v->aif_rd_dmactl; + else + dmactl = v->aif_wr_dmactl; + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + dmactl = v->cif_rd_dmactl; + break; + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + dmactl = v->cif_wr_dmactl; + break; + } + + return dmactl; +} + +static int qaif_platform_pcmops_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct snd_dma_buffer *buf; + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + int ret, stream_dma_idx, dir = substream->stream; + struct qaif_pcm_data *data; + struct qaif_dmactl *dmactl; + struct qaif_dma_mem_info *dma_mem_info; + struct regmap *map; + unsigned int dai_id = cpu_dai->driver->id; + + pr_err("%s:%d: dai_id=%u stream=%d\n", + __func__, __LINE__, dai_id, dir); + + if (v->alloc_stream_dma_idx) + stream_dma_idx = v->alloc_stream_dma_idx(drvdata, dir, dai_id); + else + return -EINVAL; + + if (stream_dma_idx < 0) + return stream_dma_idx; + data = kzalloc_obj(*data, GFP_KERNEL); + if (!data) + return -ENOMEM; + + //data->i2s_port = cpu_dai->driver->id; + data->stream_dma_idx = stream_dma_idx; + + runtime->private_data = data; + map = drvdata->audio_qaif_map; + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) { + kfree(data); + return -EINVAL; + } + buf = &substream->dma_buffer; + buf->dev.dev = component->dev; + buf->private_data = NULL; + /* Assign DMA buffer pointers */ + buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS; + + dma_mem_info = qaif_mem_alloc_attach(component, + qaif_platform_aif_hardware.buffer_bytes_max); + if (!dma_mem_info) + return -ENOMEM; + + clk_prepare_enable(drvdata->aud_dma_clk); + clk_prepare_enable(drvdata->aud_dma_mem_clk); + + ret = qaif_init(component); + if (ret) { + dev_err(soc_runtime->dev, "qaif_init failed: %d\n", ret); + return -EINVAL; + } + drvdata->qaif_init_ref_cnt++; + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + drvdata->aif_substream[stream_dma_idx] = substream; + drvdata->aif_dma_heap[stream_dma_idx] = dma_mem_info; + buf->bytes = qaif_platform_aif_hardware.buffer_bytes_max; + buf->addr = drvdata->aif_dma_heap[stream_dma_idx]->dma_addr; + buf->area = (unsigned char *)drvdata->aif_dma_heap[stream_dma_idx]->vaddr; + + snd_soc_set_runtime_hwparams(substream, &qaif_platform_aif_hardware); + runtime->dma_bytes = qaif_platform_aif_hardware.buffer_bytes_max; + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + drvdata->cif_substream[stream_dma_idx] = substream; + drvdata->cif_dma_heap[stream_dma_idx] = dma_mem_info; + buf->bytes = qaif_platform_cif_hardware.buffer_bytes_max; + buf->addr = drvdata->cif_dma_heap[stream_dma_idx]->dma_addr; + buf->area = (unsigned char *)drvdata->cif_dma_heap[stream_dma_idx]->vaddr; + + snd_soc_set_runtime_hwparams(substream, &qaif_platform_cif_hardware); + runtime->dma_bytes = qaif_platform_cif_hardware.buffer_bytes_max; + break; + default: + break; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + kfree(data); + dev_err(soc_runtime->dev, "setting constraints failed: %d\n", + ret); + return -EINVAL; + } + dev_dbg(soc_runtime->dev, + "%s: runtime info - dma_area=%p, dma_addr=0x%llx, dma_bytes=%zu\n", + __func__, + runtime->dma_area, + (unsigned long long)runtime->dma_addr, + runtime->dma_bytes); + pr_err("%s:%d: stream_dma_idx=%d qaif_init_ref_cnt=%d\n", + __func__, __LINE__, stream_dma_idx, drvdata->qaif_init_ref_cnt); + + return 0; +} + +static int qaif_platform_pcmops_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_pcm_data *data; + unsigned int dai_id = cpu_dai->driver->id; + + data = runtime->private_data; + pr_err("%s:%d: dai_id=%u stream=%d stream_dma_idx=%d\n", + __func__, __LINE__, dai_id, substream->stream, + data ? data->stream_dma_idx : -1); + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + drvdata->aif_substream[data->stream_dma_idx] = NULL; + qaif_mem_dealloc_detach(component->dev, + drvdata->aif_dma_heap[data->stream_dma_idx]); + drvdata->aif_dma_heap[data->stream_dma_idx] = NULL; + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + drvdata->cif_substream[data->stream_dma_idx] = NULL; + qaif_mem_dealloc_detach(component->dev, + drvdata->cif_dma_heap[data->stream_dma_idx]); + drvdata->cif_dma_heap[data->stream_dma_idx] = NULL; + break; + default: + break; + } + + if (drvdata->qaif_init_ref_cnt > 0) + drvdata->qaif_init_ref_cnt--; + else + dev_dbg(component->dev, "%s: QAIF init ref cnt: %d, skipping decrement\n", + __func__, drvdata->qaif_init_ref_cnt); + + if (v->free_stream_dma_idx) + v->free_stream_dma_idx(drvdata, data->stream_dma_idx, dai_id); + clk_disable_unprepare(drvdata->aud_dma_clk); + clk_disable_unprepare(drvdata->aud_dma_mem_clk); + kfree(data); + pr_err("%s:%d: done qaif_init_ref_cnt=%d\n", + __func__, __LINE__, drvdata->qaif_init_ref_cnt); + return 0; +} + +static int qaif_platform_pcmops_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *dmactl; + unsigned int dai_id = cpu_dai->driver->id; + int idx; + int ret; + + pr_err("%s:%d: dai_id=%u stream=%d channels=%u rate=%u\n", + __func__, __LINE__, dai_id, substream->stream, + params_channels(params), params_rate(params)); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = regmap_fields_write(dmactl->burst4, idx, QAIF_DMACTL_BURSTEN); + if (ret) { + dev_err(soc_runtime->dev, "error updating burst4 field: %d\n", ret); + return ret; + } + + ret = regmap_fields_write(dmactl->shram_wm, idx, QAIF_DMACTL_WM_5); + if (ret) { + dev_err(soc_runtime->dev, "error updating shram_wm field: %d\n", ret); + return ret; + } + + pr_err("%s:%d: configured idx=%d\n", __func__, __LINE__, idx); + return 0; +} + +static int qaif_platform_pcmops_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + unsigned int reg; + int ret, idx; + unsigned int dai_id = cpu_dai->driver->id; + struct regmap *map = drvdata->audio_qaif_map; + struct qaif_dmactl *dmactl; + + pr_err("%s:%d: dai_id=%u stream=%d\n", + __func__, __LINE__, dai_id, substream->stream); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_OFF); + if (ret) + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); + + reg = QAIF_DMACFG_REG(v, idx, substream->stream, dai_id); + ret = regmap_write(map, reg, 0); + if (ret) + dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); + + pr_err("%s:%d: idx=%d ret=%d\n", __func__, __LINE__, idx, ret); + return ret; +} + +static int qaif_platform_pcmops_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *dmactl; + struct regmap *map; + int bitwidth = 32;//snd_pcm_format_width(runtime->format); + unsigned int channels = runtime->channels; + unsigned int rate = runtime->rate; + int ret, idx, dir = substream->stream; + unsigned int dai_id = cpu_dai->driver->id; + + pr_err("%s:%d: dai_id=%u stream=%d rate=%u channels=%u\n", + __func__, __LINE__, dai_id, dir, rate, channels); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + map = drvdata->audio_qaif_map; + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + clk_set_rate(drvdata->aud_dma_clk, rate * bitwidth * channels * 100); + clk_set_rate(drvdata->aud_dma_mem_clk, rate * bitwidth * channels * 100); + dev_dbg(soc_runtime->dev, "setting aud_dma_clk & aud_dma_mem_clk to %u\n", + rate * bitwidth * channels * 100); + + ret = regmap_write(map, QAIF_SID_MAP_REG(dir, dai_id), + drvdata->smmu_csid_bits); + if (ret) { + dev_err(soc_runtime->dev, "error writing to SID MAP reg: %d\n", + ret); + return ret; + } + + ret = regmap_write(map, QAIF_DMABASE_REG(v, idx, dir, dai_id), + runtime->dma_addr); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n", + ret); + return ret; + } + + ret = regmap_write(map, QAIF_DMABUFF_REG(v, idx, dir, dai_id), + (snd_pcm_lib_buffer_bytes(substream) >> 3) - 1); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n", + ret); + return ret; + } + + ret = regmap_write(map, QAIF_DMAPER_LEN_REG(v, idx, dir, dai_id), + (snd_pcm_lib_period_bytes(substream) >> 3) - 1); + if (ret) { + dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n", + ret); + return ret; + } + + pr_err("%s:%d: idx=%d dma_addr=0x%llx buf_bytes=%zu period_bytes=%zu\n", + __func__, __LINE__, idx, (unsigned long long)runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream)); + return 0; +} + +static int qaif_platform_irq_clear(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type_t irq_type, int idx) +{ + int ret = 0; + const struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + unsigned int val_irqclr = BIT(idx); + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + ret |= regmap_write(map, QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, irq_type), val_irqclr); + ret |= regmap_write(map, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, irq_type), + val_irqclr); + ret |= regmap_write(map, + QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type), + val_irqclr); + } else { + ret |= regmap_write(map, QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, irq_type), val_irqclr); + ret |= regmap_write(map, + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, irq_type), + val_irqclr); + ret |= regmap_write(map, + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, irq_type), + val_irqclr); + } + return ret; +} + +static int qaif_platform_irq_enable(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type_t irq_type, int idx) +{ + int ret = 0; + const struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + unsigned int val_irqen = BIT(idx); + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + } else { + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irqen, val_irqen); + } + return ret; +} + +static int qaif_platform_irq_disable(struct qaif_drv_data *drvdata, + int dir, enum qaif_irq_type_t irq_type, int idx) +{ + int ret = 0; + const struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + unsigned int val_irq_disable = BIT(idx); + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + } else { + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + ret |= regmap_write_bits(map, + QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, irq_type), + val_irq_disable, 0); + } + return ret; +} + +static int qaif_platform_pcmops_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + int cmd) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + struct qaif_dmactl *dmactl; + struct regmap *map; + int ret, idx; + unsigned int dai_id = cpu_dai->driver->id; + + //pr_err("%s:%d: dai_id=%u stream=%d cmd=%d\n", + // __func__, __LINE__, dai_id, substream->stream, cmd); + + dmactl = qaif_get_dmactl_handle(substream, component); + if (!dmactl) + return -EINVAL; + idx = v->get_dma_idx(dai_id); + map = drvdata->audio_qaif_map; + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = regmap_fields_write(dmactl->dma_dyncclk, idx, QAIF_DMACTL_DYNCLK_ON); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma_dyncclk reg field: %d\n", ret); + return ret; + } + ret = regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_ON); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma enable reg: %d\n", ret); + return ret; + } + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + ret = qaif_platform_irq_clear(drvdata, + substream->stream, QAIF_AIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to clear irq reg: %d\n", ret); + return ret; + } + ret = qaif_platform_irq_enable(drvdata, + substream->stream, QAIF_AIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + ret = qaif_platform_irq_clear(drvdata, + substream->stream, QAIF_CIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to clear irq reg: %d\n", ret); + return ret; + } + ret = qaif_platform_irq_enable(drvdata, + substream->stream, QAIF_CIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + default: + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); + return -EINVAL; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = regmap_fields_write(dmactl->dma_dyncclk, idx, QAIF_DMACTL_DYNCLK_OFF); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma_dyncclk reg field: %d\n", ret); + return ret; + } + ret = regmap_fields_write(dmactl->enable, idx, QAIF_DMACTL_ENABLE_OFF); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to dma enable reg: %d\n", ret); + return ret; + } + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + ret = qaif_platform_irq_disable(drvdata, + substream->stream, QAIF_AIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + ret = qaif_platform_irq_disable(drvdata, + substream->stream, QAIF_CIF_IRQ, idx); + if (ret) { + dev_err(soc_runtime->dev, + "error writing to enable irq reg: %d\n", ret); + return ret; + } + break; + default: + dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); + return -EINVAL; + } + break; + } + pr_err("%s:%d: cmd=%d idx=%d ret=%d\n", + __func__, __LINE__, cmd, idx, ret); + return 0; +} + +static snd_pcm_uframes_t qaif_platform_pcmops_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + const struct qaif_variant *v = drvdata->variant; + unsigned int base_addr, curr_addr; + int ret, idx, dir = substream->stream; + struct regmap *map; + unsigned int dai_id = cpu_dai->driver->id; + + //pr_err("%s:%d: dai_id=%u stream=%d\n", + // __func__, __LINE__, dai_id, dir); + + map = drvdata->audio_qaif_map; + idx = v->get_dma_idx(dai_id); + + if (idx < 0) { + dev_err(soc_runtime->dev, "%s: Invalid DMA index: %d\n", __func__, idx); + return -EINVAL; + } + + ret = regmap_read(map, + QAIF_DMABASE_REG(v, idx, dir, dai_id), &base_addr); + if (ret) { + dev_err(soc_runtime->dev, + "error reading from rdmabase reg: %d\n", ret); + return ret; + } + + ret = regmap_read(map, + QAIF_DMACURR_REG(v, idx, dir, dai_id), &curr_addr); + if (ret) { + dev_err(soc_runtime->dev, + "error reading from rdmacurr reg: %d\n", ret); + return ret; + } + + return bytes_to_frames(substream->runtime, curr_addr - base_addr); +} + +static int qaif_platform_cdc_dma_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned long size, offset; + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + size = vma->vm_end - vma->vm_start; + offset = vma->vm_pgoff << PAGE_SHIFT; + return io_remap_pfn_range(vma, vma->vm_start, + (runtime->dma_addr + offset) >> PAGE_SHIFT, + size, vma->vm_page_prot); +} + +static int qaif_platform_pcmops_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + unsigned int dai_id = cpu_dai->driver->id; + + if (is_cif_dma_port(dai_id)) + return qaif_platform_cdc_dma_mmap(substream, vma); + + return snd_pcm_lib_default_mmap(substream, vma); +} + +static irqreturn_t qaif_process_dma_irq(struct qaif_drv_data *drvdata, + u32 stat_reg_addr, + u32 clr_reg_addr, + enum qaif_irq_type_t irq_type, + enum dma_type dma_type, + enum qaif_irq irq, + struct snd_pcm_substream **substream) +{ + const struct qaif_variant *v = drvdata->variant; + struct snd_pcm_substream *stream = NULL; + unsigned int reg = 0; + int dma_idx, stream_dma_idx, rv, num_dma = 0; + int stream_offset = (dma_type == DMA_TYPE_WRDMA) ? v->wrdma_start : 0; + irqreturn_t ret = IRQ_NONE; + u32 mask = 0; + + num_dma = (irq_type == QAIF_AIF_IRQ) ? v->num_rddma : v->num_codec_rddma; + mask = GENMASK(num_dma - 1, 0); + // Read Status + rv = regmap_read(drvdata->audio_qaif_map, stat_reg_addr, ®); + if (rv) { + pr_err("QAIF IRQ: error reading stat reg 0x%x: %d\n", stat_reg_addr, rv); + return IRQ_NONE; + } + + /* Writing the same reg that we just read from the status register, + * SPF also clears before handling. + */ + regmap_write(drvdata->audio_qaif_map, clr_reg_addr, reg & mask); + + for (dma_idx = 0; dma_idx < num_dma; dma_idx++) { + stream_dma_idx = dma_idx + stream_offset; + // Check if bit is set AND substream exists + if ((reg & BIT(dma_idx)) && substream[stream_dma_idx]) { + stream = substream[stream_dma_idx]; + switch (irq) { + case QAIF_IRQ_PERIOD: + snd_pcm_period_elapsed(stream); + ret = IRQ_HANDLED; + break; + + case QAIF_IRQ_OVERFLOW: + case QAIF_IRQ_UNDERFLOW: + // snd_pcm_stop_xrun(stream); + pr_warn_ratelimited("QAIF DMA xRun warning\n"); + ret = IRQ_HANDLED; + break; + + case QAIF_IRQ_ERROR: + snd_pcm_stop(stream, SNDRV_PCM_STATE_DISCONNECTED); + pr_err("QAIF Bus error\n"); + ret = IRQ_HANDLED; + break; + } + } + } + return ret; +} + +static irqreturn_t qaif_aif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status) +{ + const struct qaif_variant *v = drvdata->variant; + irqreturn_t ret = IRQ_NONE; + struct snd_pcm_substream **substream = drvdata->aif_substream; + + // period_irq handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_PERIOD, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_PERIOD, substream); + } + // OVERFLOQW & underflow handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_OVERFLOW, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_UNDERFLOW, substream); + } + // Bus error handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_ERROR, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_AIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_AIF_IRQ), + QAIF_AIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_ERROR, substream); + } + return ret; +} + +static irqreturn_t qaif_cif_irq_handler(struct qaif_drv_data *drvdata, u32 summary_irq_status) +{ + const struct qaif_variant *v = drvdata->variant; + irqreturn_t ret = IRQ_NONE; + struct snd_pcm_substream **substream = drvdata->cif_substream; + + // period_irq handling. + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_PERIOD, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_PERIOD, substream); + } + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_OVERFLOW, substream); + } + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_RDDMA, QAIF_IRQ_UNDERFLOW, substream); + } + + if (summary_irq_status & QAIF_SUMMARY_BITMASK_CIF_ERR_RSP) { + ret |= qaif_process_dma_irq(drvdata, + QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, QAIF_CIF_IRQ), + QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, QAIF_CIF_IRQ), + QAIF_CIF_IRQ, DMA_TYPE_WRDMA, QAIF_IRQ_ERROR, substream); + } + + return ret; +} + +static irqreturn_t asoc_platform_qaif_irq(int irq, void *data) +{ + struct qaif_drv_data *drvdata = data; + const struct qaif_variant *v = drvdata->variant; + u32 summary_irq_status; + int rv, client; + irqreturn_t ret = IRQ_NONE; + + rv = regmap_read(drvdata->audio_qaif_map, + QAIF_SUMMARY_IRQSTAT_REG(v), &summary_irq_status); + if (rv) { + pr_err("error reading from irqstat reg: %d\n", rv); + return IRQ_NONE; + } + pr_debug("%s: summary_irq_status =0x%08x\n", __func__, summary_irq_status); + if (!(summary_irq_status & QAIF_ALL_CLIENTS_MASK)) + return IRQ_NONE; + for (client = 0; client < ARRAY_SIZE(qaif_irq_clients); client++) { + /* Check if the bits for this specific client_id are set in the register */ + if (summary_irq_status & qaif_irq_clients[client].mask) + ret = qaif_irq_clients[client].client_irq_handler(drvdata, + summary_irq_status); + } + return ret; +} + +static int qaif_platform_pcmops_suspend(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + + map = drvdata->audio_qaif_map; + pr_err("%s:%d: suspend\n", __func__, __LINE__); + + regcache_cache_only(map, true); + regcache_mark_dirty(map); + clk_disable(drvdata->aud_dma_clk); + clk_disable(drvdata->aud_dma_mem_clk); + return 0; +} + +static int qaif_platform_pcmops_resume(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + int ret; + + pr_err("%s:%d: resume\n", __func__, __LINE__); + clk_enable(drvdata->aud_dma_clk); + clk_enable(drvdata->aud_dma_mem_clk); + map = drvdata->audio_qaif_map; + + regcache_cache_only(map, false); + ret = regcache_sync(map); + if (ret) + dev_err(component->dev, "%s: regcache_sync failed: %d\n", + __func__, ret); + return ret; +} + +static int qaif_platform_copy(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int channel, + unsigned long pos, struct iov_iter *buf, + unsigned long bytes) +{ + struct snd_pcm_runtime *rt = substream->runtime; + size_t copied; + void *dma_buf; + + // rt->dma_area is the vaddr from iosys_vmap - regular kernel memory + dma_buf = (void *)(rt->dma_area + pos + + channel * (rt->dma_bytes / rt->channels)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + copied = copy_from_iter(dma_buf, bytes, buf); + if (copied != bytes) { + pr_err("DEBUG:%s:%d:Copy failed\n", __func__, __LINE__); + return -EFAULT; + } + } else { + copied = copy_to_iter(dma_buf, bytes, buf); + if (copied != bytes) { + pr_err("DEBUG:%s:%d:Copy failed\n", __func__, __LINE__); + return -EFAULT; + } + } + + return 0; +} + +static const struct snd_soc_component_driver qaif_component_driver = { + .name = DRV_NAME, + .open = qaif_platform_pcmops_open, + .close = qaif_platform_pcmops_close, + .hw_params = qaif_platform_pcmops_hw_params, + .hw_free = qaif_platform_pcmops_hw_free, + .prepare = qaif_platform_pcmops_prepare, + .trigger = qaif_platform_pcmops_trigger, + .pointer = qaif_platform_pcmops_pointer, + .mmap = qaif_platform_pcmops_mmap, + .suspend = qaif_platform_pcmops_suspend, + .resume = qaif_platform_pcmops_resume, + .copy = qaif_platform_copy, +}; + +/** + * qaif_map_ee_resource - Implements Steps 1-6 of Restrictions + * Maps GRP, INTF, RDDMA, WRDMA to the current EE. + */ +static int qaif_map_ee_resource(struct qaif_drv_data *drvdata) +{ + struct qaif_variant *v = drvdata->variant; + struct regmap *map = drvdata->audio_qaif_map; + int ret = 0; + u32 mask; + + mask = GENMASK(v->num_rddma - 1, 0); + ret |= regmap_write(map, QAIF_EE_RDDMA_MAP_REG(v), mask); + + mask = GENMASK(v->num_wrdma - 1, 0); + ret |= regmap_write(map, QAIF_EE_WRDMA_MAP_REG(v), mask); + + mask = GENMASK(v->num_intf - 1, 0); + ret |= regmap_write(map, QAIF_EE_INTF_MAP_REG(v), mask); + + mask = GENMASK(v->num_codec_rddma - 1, 0); + ret |= regmap_write(map, QAIF_EE_CODEC_RDDMA_MAP_REG(v), mask); + + mask = GENMASK(v->num_codec_wrdma - 1, 0); + ret |= regmap_write(map, QAIF_EE_CODEC_WRDMA_MAP_REG(v), mask); + + if (ret) + return ret; + return 0; +} + +static int qaif_map_dma_path(struct qaif_drv_data *drvdata) +{ + struct regmap *map = drvdata->audio_qaif_map; + struct qaif_variant *v = drvdata->variant; + int ret = 0; + int qxm_sel = v->qxm_type; + + if (qxm_sel != QXM0 && qxm_sel != QXM1) + return -EINVAL; + + ret |= regmap_write(map, QAIF_RDDMA_MAP_QXM, qxm_sel); + ret |= regmap_write(map, QAIF_WRDMA_MAP_QXM, qxm_sel); + ret |= regmap_write(map, QAIF_CODEC_RDDMA_MAP_QXM, qxm_sel); + ret |= regmap_write(map, QAIF_CODEC_WRDMA_MAP_QXM, qxm_sel); + + if (ret) + return ret; + + return 0; +} + +static int qaif_config_shram(struct qaif_drv_data *drvdata) +{ + struct qaif_variant *v = drvdata->variant; + u32 start_addr, shram_len; + int ret = 0, i = 0; + struct regmap *map = drvdata->audio_qaif_map; + + if (v->qxm_type != QXM0) + return -EINVAL; + //AIF RDDMA + start_addr = v->rddma_shram_start_addr[QAIF_AIF_DMA]; + shram_len = v->rddma_shram_len; + for (i = 0; i < v->num_rddma; i++) { + ret = regmap_write(map, + QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_RDDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + //AIF WRDMA + start_addr = v->wrdma_shram_start_addr[QAIF_AIF_DMA]; + shram_len = v->wrdma_shram_len; + for (i = 0; i < v->num_wrdma; i++) { + ret = regmap_write(map, + QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_WRDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + //CIF RDDMA + start_addr = v->rddma_shram_start_addr[QAIF_CIF_DMA]; + shram_len = v->rddma_shram_len; + for (i = 0; i < v->num_codec_rddma; i++) { + ret = regmap_write(map, + QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i), shram_len); + if (ret) + return ret; + } + //CIF wrDMA + start_addr = v->wrdma_shram_start_addr[QAIF_CIF_DMA]; + shram_len = v->wrdma_shram_len; + for (i = 0; i < v->num_codec_wrdma; i++) { + ret = regmap_write(map, + QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i), + start_addr + (shram_len * i)); + if (ret) + return ret; + ret = regmap_write(map, QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i), shram_len); + + if (ret) + return ret; + } + return 0; +} + +static int qaif_init(struct snd_soc_component *component) +{ + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component); + int ret = 0; + + if (drvdata->qaif_init_ref_cnt) { + dev_info(component->dev, "%s: QAIF init is done already: ref cnt: %d\n", + __func__, drvdata->qaif_init_ref_cnt); + return 0; + } + + ret = qaif_config_shram(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to config shram: %d\n", ret); + return ret; + } + + ret = qaif_map_ee_resource(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to map EE resources: %d\n", ret); + return ret; + } + + ret = qaif_map_dma_path(drvdata); + if (ret) { + dev_err(component->dev, "QAIF: Failed to map EE resources: %d\n", ret); + return ret; + } + dev_dbg(component->dev, "%s: QAIF init is done ref cnt: %d\n", + __func__, drvdata->qaif_init_ref_cnt); + return 0; +} + +int asoc_qcom_qaif_platform_register(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + int ret = 0; + + if (!drvdata || !drvdata->variant) { + dev_err(&pdev->dev, "Invalid drvdata or variant\n"); + return -EINVAL; + } + + drvdata->smmu_csid_bits = 0; + + drvdata->audio_qaif_irq = platform_get_irq_byname(pdev, "qaif-irq-audio-core"); + if (drvdata->audio_qaif_irq < 0) + return -ENODEV; + + ret = devm_request_irq(&pdev->dev, drvdata->audio_qaif_irq, + asoc_platform_qaif_irq, IRQF_TRIGGER_HIGH, + "qaif-irq-audio-core", drvdata); + if (ret) { + dev_err(&pdev->dev, "irq request failed: %d\n", ret); + return ret; + } + drvdata->qaif_init_ref_cnt = 0; + dev_dbg(&pdev->dev, "%s: Register QAIF Platform\n", __func__); + return devm_snd_soc_register_component(&pdev->dev, + &qaif_component_driver, NULL, 0); +} +EXPORT_SYMBOL_GPL(asoc_qcom_qaif_platform_register); + +MODULE_DESCRIPTION("QTi QAIF Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/qaif-reg.h b/sound/soc/qcom/qaif-reg.h new file mode 100644 index 0000000000000..cccee76a74861 --- /dev/null +++ b/sound/soc/qcom/qaif-reg.h @@ -0,0 +1,689 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-reg.h -- ALSA SoC CPU-Platform DAI driver register header file for QTi QAIF + */ +#ifndef __QAIF_REG_H__ +#define __QAIF_REG_H__ + +#include "qaif.h" + +#define QAIF_REG_ADDR(offset) (offset) +/* Base for AUDIO_CORE_QAIF_HW_VERSION 0xA000000 */ + +#define QAIF_SUMMARY_IRQSTAT_REG(v) \ + (0x19188 + (0x1000 * ((v)->ee))) /* 0xA019188 */ +/* + * #define QAIF_RDDMA_UNDERFLOW_REG(v) + * QAIF_REG_ADDR(0x19188 + (0x1000 * (ee))) + */ + +/* Shikra core registers */ + +/* Core HW info */ +#define QAIF_HW_VERSION_REG() (0x0000) /* 0xA000000 */ +#define QAIF_HW_INFO_REG (0x0004) /* 0xA000004 */ +#define QAIF_HW_INFO2_REG (0x0008) /* 0xA000008 */ + +/* Interface lane and channel info */ +#define QAIF_AUD_INTF_LANE_INFO_REG (0x0020) /* 0xA000020 */ +#define QAIF_AUD_INTF_LANE_INFO2_REG (0x0024) /* 0xA000024 */ +/* 0xA000028 .. 0xA000044 (n:0..7) */ +#define QAIF_CODEC_TX_INTF_CH_INFO_REG(n) (0x0028 + (0x4 * (n))) +/* 0xA000068 .. 0xA000084 (n:0..7) */ +#define QAIF_CODEC_RX_INTF_CH_INFO_REG(n) (0x0068 + (0x4 * (n))) +#define QAIF_QXM1_SHRAM_LENGTH_INFO_REG (0x0088) /* 0xA000088 */ +#define QAIF_QXM0_SHRAM_LENGTH_INFO_REG (0x008C) /* 0xA00008C */ +#define QAIF_NUM_AUD_INTF_TO_RAIL_INFO_REG (0x0090) /* 0xA000090 */ + +/* Debug/control and status */ +#define QAIF_DEBUG_CTL_REG (0x0200) /* 0xA000200 */ +#define QAIF_WRDMA_LOOPBACK_EN_REG (0x0204) /* 0xA000204 */ +#define QAIF_WRDMA_LOOPBACK_SEL_REG (0x0208) /* 0xA000208 */ +#define QAIF_SHRAM_DYNAMIC_CLK_GATING_EN_REG (0x0300) /* 0xA000300 */ +#define QAIF_AXI_STATUS_REG (0x0304) /* 0xA000304 */ +#define QAIF_QSB_DYNAMIC_CLK_GATING_EN_REG (0x0308) /* 0xA000308 */ +#define QAIF_START_STOP_CTRL_BYPASS_EN_REG (0x030C) /* 0xA00030C */ +#define QAIF_QXM0_AXI_ATTR_CFG_REG (0x040C) /* 0xA00040C */ + +/* QXM request/grant debug */ +#define QAIF_QXM0_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0500) /* 0xA000500 */ +#define QAIF_QXM1_AUD_WR_REQ_GNT_DBG_STAT_REG (0x0504) /* 0xA000504 */ +#define QAIF_QXM0_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0508) /* 0xA000508 */ +#define QAIF_QXM0_CODEC_RX_WR_GNT_DBG_STAT_REG (0x050C) /* 0xA00050C */ +#define QAIF_QXM1_CODEC_RX_WR_REQ_DBG_STAT_REG (0x0510) /* 0xA000510 */ +#define QAIF_QXM1_CODEC_RX_WR_GNT_DBG_STAT_REG (0x0514) /* 0xA000514 */ +#define QAIF_QXM0_AUD_RD_REQ_GNT_DBG_STAT_REG (0x0518) /* 0xA000518 */ +#define QAIF_QXM1_AUD_RD_REQ_GNT_DBG_STAT_REG (0x051C) /* 0xA00051C */ +#define QAIF_QXM0_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0520) /* 0xA000520 */ +#define QAIF_QXM0_CODEC_TX_RD_GNT_DBG_STAT_REG (0x0524) /* 0xA000524 */ +#define QAIF_QXM1_CODEC_TX_RD_REQ_DBG_STAT_REG (0x0528) /* 0xA000528 */ +#define QAIF_QXM1_CODEC_TX_RD_GNT_DBG_STAT_REG (0x052C) /* 0xA00052C */ +#define QAIF_QXM0_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0530) /* 0xA000530 */ +#define QAIF_QXM1_EXT_RDDMA_RD_REQ_GNT_DBG_STAT_REG (0x0534) /* 0xA000534 */ + +/* QSB transaction debug */ +#define QAIF_QSB_AUD_WR_TXN_DBG_STAT_REG (0x0538) /* 0xA000538 */ +#define QAIF_QSB_CODEC_RX_WR_TXN_ERR_DBG_STAT_REG (0x053C) /* 0xA00053C */ +#define QAIF_QSB_CODEC_RX_WR_TXN_OKAY_DBG_STAT_REG (0x0540) /* 0xA000540 */ +#define QAIF_QSB_AUD_ADDR_SENT_DBG_STAT_REG (0x0544) /* 0xA000544 */ +#define QAIF_QSB_CODEC_TX_RD_ADDR_SENT_DBG_STAT_REG (0x0548) /* 0xA000548 */ +#define QAIF_QSB_EXT_RDDMA_RD_ADDR_SENT_DBG_STAT_REG (0x054C) /* 0xA00054C */ +#define QAIF_QSB_CODEC_RX_WR_ADDR_SENT_DBG_STAT_REG (0x0550) /* 0xA000550 */ +#define QAIF_QSB_AUD_RD_TXN_DBG_STAT_REG (0x0554) /* 0xA000554 */ +#define QAIF_QSB_CODEC_TX_RD_TXN_ERR_DBG_STAT_REG (0x0558) /* 0xA000558 */ +#define QAIF_QSB_CODEC_TX_RD_TXN_RCVD_DBG_STAT_REG (0x055C) /* 0xA00055C */ +#define QAIF_QSB_EXT_RDDMA_RD_TXN_DBG_STAT_REG (0x0560) /* 0xA000560 */ +#define QAIF_QSB_MISC_DBG_STATUS_REG (0x0564) /* 0xA000564 */ + +/* Global spare and HWE */ +#define QAIF_GLOBAL_SPARE_IN_REG (0x0B00) /* 0xA000B00 */ +#define QAIF_GLOBAL_SPARE_OUT_REG (0x0B04) /* 0xA000B04 */ +#define QAIF_HWE_CFG_REG (0x0B08) /* 0xA000B08 */ + +/* SID maps */ +#define QAIF_WRDMA_SID_MAP_REG (0x1B00) /* 0xA001B00 */ +#define QAIF_CODEC_WRDMA_SID_MAP_REG (0x1B40) /* 0xA001B40 */ +#define QAIF_RDDMA_SID_MAP_REG (0x1C00) /* 0xA001C00 */ +#define QAIF_CODEC_RDDMA_SID_MAP_REG (0x1C40) /* 0xA001C40 */ + +/* EE overlap interrupts */ +#define QAIF_EE_OVERLAP_IRQ_EN_REG (0x1D00) /* 0xA001D00 */ +#define QAIF_EE_OVERLAP_IRQ_RAW_STATUS_REG (0x1D04) /* 0xA001D04 */ +#define QAIF_EE_OVERLAP_IRQ_CLEAR_REG (0x1D08) /* 0xA001D08 */ +#define QAIF_EE_OVERLAP_IRQ_FORCE_REG (0x1D0C) /* 0xA001D0C */ + +/* EE assignments and maps */ +/* 0xA019148 */ +#define QAIF_EE_RDDMA_ASSIGNMENT_REG(v) (0x19148 + (0x1000 * ((v)->ee))) +/* 0xA019150 */ +#define QAIF_EE_WRDMA_ASSIGNMENT_REG(v) (0x19150 + (0x1000 * ((v)->ee))) +/* 0xA019158 */ +#define QAIF_EE_INTF_ASSIGNMENT_REG(v) (0x19158 + (0x1000 * ((v)->ee))) +/* 0xA019308 */ +#define QAIF_EE_CODEC_RDDMA_ASSIGNMENT_REG(v) (0x19308 + (0x1000 * ((v)->ee))) +/* 0xA019318 */ +#define QAIF_EE_CODEC_WRDMA_ASSIGNMENT_REG(v) (0x19318 + (0x1000 * ((v)->ee))) +/* 0xA001920 */ +#define QAIF_EE_RDDMA_MAP_REG(v) (0x1920 + (0x1000 * ((v)->ee))) +/* 0xA001940 */ +#define QAIF_EE_WRDMA_MAP_REG(v) (0x1940 + (0x1000 * ((v)->ee))) +/* 0xA001960 */ +#define QAIF_EE_INTF_MAP_REG(v) (0x1960 + (0x1000 * ((v)->ee))) +/* 0xA001980 */ +#define QAIF_EE_CODEC_RDDMA_MAP_REG(v) (0x1980 + (0x1000 * ((v)->ee))) +/* 0xA001A00 */ +#define QAIF_EE_CODEC_WRDMA_MAP_REG(v) (0x1A00 + (0x1000 * ((v)->ee))) + +/* EE rate-detection and VFR interrupts */ +/* 0xA0190F0 */ +#define QAIF_EE_RATE_DET_IRQ_EN_REG(v) (0x190F0 + (0x1000 * ((v)->ee))) +/* 0xA0190F4 */ +#define QAIF_EE_RATE_DET_IRQ_STATUS_REG(v) (0x190F4 + (0x1000 * ((v)->ee))) +/* 0xA0190F8 */ +#define QAIF_EE_RATE_DET_IRQ_RAW_STATUS_REG(v) (0x190F8 + (0x1000 * ((v)->ee))) +/* 0xA0190FC */ +#define QAIF_EE_RATE_DET_IRQ_CLEAR_REG(v) (0x190FC + (0x1000 * ((v)->ee))) +/* 0xA019100 */ +#define QAIF_EE_RATE_DET_IRQ_FORCE_REG(v) (0x19100 + (0x1000 * ((v)->ee))) + +/* 0xA019104 */ +#define QAIF_EE_VFR_IRQ_EN_REG(v) (0x19104 + (0x1000 * ((v)->ee))) +/* 0xA019108 */ +#define QAIF_EE_VFR_IRQ_STATUS_REG(v) (0x19108 + (0x1000 * ((v)->ee))) +/* 0xA01910C */ +#define QAIF_EE_VFR_IRQ_RAW_STATUS_REG(v) (0x1910C + (0x1000 * ((v)->ee))) +/* 0xA019110 */ +#define QAIF_EE_VFR_IRQ_CLEAR_REG(v) (0x19110 + (0x1000 * ((v)->ee))) +/* 0xA019114 */ +#define QAIF_EE_VFR_IRQ_FORCE_REG(v) (0x19114 + (0x1000 * ((v)->ee))) + +/* EE AUD_INTF underflow/overflow interrupts */ +/* 0xA019160 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_EN_REG(v) \ + (0x19160 + (0x1000 * ((v)->ee))) +/* 0xA019164 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_STATUS_REG(v) \ + (0x19164 + (0x1000 * ((v)->ee))) +/* 0xA019168 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_RAW_STATUS_REG(v) \ + (0x19168 + (0x1000 * ((v)->ee))) +/* 0xA01916C */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_CLEAR_REG(v) \ + (0x1916C + (0x1000 * ((v)->ee))) +/* 0xA019170 */ +#define QAIF_EE_AUD_INTF_UNDERFLOW_IRQ_FORCE_REG(v) \ + (0x19170 + (0x1000 * ((v)->ee))) + +/* 0xA019174 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_EN_REG(v) \ + (0x19174 + (0x1000 * ((v)->ee))) +/* 0xA019178 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_STATUS_REG(v) \ + (0x19178 + (0x1000 * ((v)->ee))) +/* 0xA01917C */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_RAW_STATUS_REG(v) \ + (0x1917C + (0x1000 * ((v)->ee))) +/* 0xA019180 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_CLEAR_REG(v) \ + (0x19180 + (0x1000 * ((v)->ee))) +/* 0xA019184 */ +#define QAIF_EE_AUD_INTF_OVERFLOW_IRQ_FORCE_REG(v) \ + (0x19184 + (0x1000 * ((v)->ee))) + +/* EE L2 Period IRQ mux selection */ +/* 0xA019F00 */ +#define QAIF_EE_L2_PERIOD_IRQ_0_3_MUX_SEL_REG(v) \ + (0x19F00 + (0x1000 * ((v)->ee))) +/* 0xA019F04 */ +#define QAIF_EE_L2_PERIOD_IRQ_4_7_MUX_SEL_REG(v) \ + (0x19F04 + (0x1000 * ((v)->ee))) + +/* AUD_INTF block (per interface, stride 0x1000 starting at 0x4000) */ +#define QAIF_AUD_INTF_REG_ADDR(offset, intf) \ + (0x4000 + (offset) + (0x1000 * (intf))) + +/* 0xA004000 */ +#define QAIF_AUD_INTF_CTL_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0000, (intf)) +/* 0xA004004 */ +#define QAIF_AUD_INTF_SYNC_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0004, (intf)) +/* 0xA004008 */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0008, (intf)) +/* 0xA00400C */ +#define QAIF_AUD_INTF_FRAME_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x000C, (intf)) +/* 0xA004010 */ +#define QAIF_AUD_INTF_ACTV_SLOT_EN_TX_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0010, (intf)) +/* 0xA004030 */ +#define QAIF_AUD_INTF_ACTV_SLOT_EN_RX_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0030, (intf)) +/* 0xA004050 */ +#define QAIF_AUD_INTF_LANE_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0050, (intf)) +/* 0xA004054 */ +#define QAIF_AUD_INTF_MI2S_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0054, (intf)) +/* 0xA004058 */ +#define QAIF_AUD_INTF_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0058, (intf)) +/* 0xA00405C */ +#define QAIF_AUD_INTF_CHAR_CTL_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x005C, (intf)) +/* 0xA004060 */ +#define QAIF_AUD_INTF_CHAR_CFG_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0060, (intf)) +/* 0xA004064 */ +#define QAIF_AUD_INTF_CHAR_DATA_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0064, (intf)) +/* 0xA004068 */ +#define QAIF_AUD_INTF_CHAR_DATA_EXT_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0068, (intf)) +/* 0xA00406C */ +#define QAIF_AUD_INTF_CHAR_SYNC_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x006C, (intf)) +/* 0xA004FF0 */ +#define QAIF_AUD_INTF_INIT_DBG_STATUS_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0FF0, (intf)) +/* 0xA004FF4 */ +#define QAIF_AUD_INTF_TX_DBG_STATUS_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0FF4, (intf)) +/* 0xA004FF8 */ +#define QAIF_AUD_INTF_RX_DBG_STATUS_REG(intf) \ + QAIF_AUD_INTF_REG_ADDR(0x0FF8, (intf)) + +/* RATE_DET block (per detector, stride 0x1000 starting at 0x1E000) */ +#define QAIF_RATE_DET_REG_ADDR(offset, det) \ + (0x1E000 + (offset) + (0x1000 * (det))) + +/* 0xA01E000 */ +#define QAIF_RATE_DET_CONFIG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0000, (det)) +/* 0xA01E004 */ +#define QAIF_RATE_DET_TARGET1_CONFIG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0004, (det)) +/* 0xA01E008 */ +#define QAIF_RATE_DET_TARGET2_CONFIG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0008, (det)) +/* 0xA01E00C */ +#define QAIF_RATE_DET_BIN_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x000C, (det)) +/* 0xA01E010 */ +#define QAIF_RATE_DET_STC_DIFF_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0010, (det)) +/* 0xA01E014 */ +#define QAIF_RATE_DET_SEL_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0014, (det)) +/* 0xA01E018 */ +#define QAIF_RATE_DET_TIMEOUT_CFG_REG(det) \ + QAIF_RATE_DET_REG_ADDR(0x0018, (det)) + +#define QAIF_WRDMA_MAP_QXM (0x1000) +#define QAIF_CODEC_WRDMA_MAP_QXM (0x1004) +#define QAIF_RDDMA_MAP_QXM (0x1010) +#define QAIF_CODEC_RDDMA_MAP_QXM (0x1014) +#define QAIF_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0x1100 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM1_SHRAM_ST_ADDR(i) (0x1140 + (0x4 * (i))) +#define QAIF_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0x1200 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM0_SHRAM_ST_ADDR(i) (0x1240 + (0x4 * (i))) +#define QAIF_RDDMA_QXM1_SHRAM_LEN(i) (0x1300 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM1_SHRAM_LEN(i) (0x1340 + (0x4 * (i))) +#define QAIF_RDDMA_QXM0_SHRAM_LEN(i) (0x1400 + (0x4 * (i))) +#define QAIF_CODEC_RDDMA_QXM0_SHRAM_LEN(i) (0x1440 + (0x4 * (i))) +#define QAIF_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1500 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM1_SHRAM_ST_ADDR(i) (0x1540 + (0x4 * (i))) +#define QAIF_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1600 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM0_SHRAM_ST_ADDR(i) (0x1640 + (0x4 * (i))) +#define QAIF_WRDMA_QXM1_SHRAM_LEN(i) (0x1700 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM1_SHRAM_LEN(i) (0x1740 + (0x4 * (i))) +#define QAIF_WRDMA_QXM0_SHRAM_LEN(i) (0x1800 + (0x4 * (i))) +#define QAIF_CODEC_WRDMA_QXM0_SHRAM_LEN(i) (0x1840 + (0x4 * (i))) + +/* + * RDDMA + * v : ptr to qaif_variant + */ +static inline u32 QAIF_RDDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->rddma_reg_base + offset + (v)->rddma_stride * chan; +} + +#define QAIF_RDDMA_CTL_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_RDDMA_CFG_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_RDDMA_BASE_ADDR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_RDDMA_BUFF_LEN_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_RDDMA_CURR_ADDR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_RDDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_RDDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_RDDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_RDDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_RDDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_RDDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_RDDMA_STC_LSB_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_RDDMA_STC_MSB_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_RDDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_RDDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_RDDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_RDDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_RDDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_RDDMA_PADDING_CFG_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x58, (chan)) +#define QAIF_RDDMA_STATUS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0x60, (chan)) +#define QAIF_RDDMA_DBG_STATUS_REG(v, chan) \ + QAIF_RDDMA_REG_ADDR(v, 0xFF0, (chan)) + +static inline u32 QAIF_CODEC_RDDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->codec_rddma_reg_base + offset + (v)->codec_rddma_stride * chan; +} + +#define QAIF_CODEC_RDDMA_CTL_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_CODEC_RDDMA_CFG_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_CODEC_RDDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_CODEC_RDDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_CODEC_RDDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_CODEC_RDDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_CODEC_RDDMA_STC_LSB_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_CODEC_RDDMA_STC_MSB_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_CODEC_RDDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_CODEC_RDDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_CODEC_RDDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_CODEC_RDDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_CODEC_RDDMA_PADDING_CFG_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x58, (chan)) +#define QAIF_CODEC_RDDMA_INTF_CFG_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x5C, (chan)) +#define QAIF_CODEC_RDDMA_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0x60, (chan)) +#define QAIF_CODEC_RDDMA_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0xFF0, (chan)) +#define QAIF_CODEC_RDDMA_INTF_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_RDDMA_REG_ADDR(v, 0xFF4, (chan)) + +/* + * WRDMA + * v : ptr to qaif_variant + */ +static inline u32 QAIF_WRDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->wrdma_reg_base + offset + (v)->wrdma_stride * chan; +} + +#define QAIF_WRDMA_CTL_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_WRDMA_CFG_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_WRDMA_BASE_ADDR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_WRDMA_BUFF_LEN_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_WRDMA_CURR_ADDR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_WRDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_WRDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_WRDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_WRDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_WRDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_WRDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_WRDMA_STC_LSB_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_WRDMA_STC_MSB_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_WRDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_WRDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_WRDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_WRDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_WRDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_WRDMA_DBG_STATUS_REG(v, chan) \ + QAIF_WRDMA_REG_ADDR(v, 0xFF0, (chan)) + +static inline u32 QAIF_CODEC_WRDMA_REG_ADDR(const struct qaif_variant *v, u32 offset, u32 chan) +{ + return (v)->codec_wrdma_reg_base + offset + (v)->codec_wrdma_stride * chan; +} + +#define QAIF_CODEC_WRDMA_CTL_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x00, (chan)) +#define QAIF_CODEC_WRDMA_CFG_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x04, (chan)) +#define QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x08, (chan)) +#define QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x10, (chan)) +#define QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x14, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x1C, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x20, (chan)) +#define QAIF_CODEC_WRDMA_SHRAM_WORDCNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x24, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x28, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_EXTN_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x2C, (chan)) +#define QAIF_CODEC_WRDMA_FRAME_STATUS_CLR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x30, (chan)) +#define QAIF_CODEC_WRDMA_SET_BUFF_CNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x34, (chan)) +#define QAIF_CODEC_WRDMA_SET_PERIOD_CNT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x38, (chan)) +#define QAIF_CODEC_WRDMA_STC_LSB_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x3C, (chan)) +#define QAIF_CODEC_WRDMA_STC_MSB_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x40, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_DET_STAT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x44, (chan)) +#define QAIF_CODEC_WRDMA_PERIOD_DET_CLR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x48, (chan)) +#define QAIF_CODEC_WRDMA_FORMAT_ERR_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x4C, (chan)) +#define QAIF_CODEC_WRDMA_AHB_BYPASS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x50, (chan)) +#define QAIF_CODEC_WRDMA_SHUTDOWN_STAT_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x54, (chan)) +#define QAIF_CODEC_WRDMA_INTF_CFG_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0x58, (chan)) +#define QAIF_CODEC_WRDMA_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0xFF0, (chan)) +#define QAIF_CODEC_WRDMA_INTF_DBG_STATUS_REG(v, chan) \ + QAIF_CODEC_WRDMA_REG_ADDR(v, 0xFF4, (chan)) + +static inline u32 QAIF_EE_RDDMA_IRQ_REG_ADDR(const struct qaif_variant *v, + enum qaif_irq_type_t dma_type, + u32 offset) +{ + if (dma_type == QAIF_AIF_IRQ) + return (v)->rddma_irq_reg_base + offset + + (v)->rddma_irq_stride * (v)->ee; + return (v)->codec_rddma_irq_reg_base + offset + + (v)->codec_rddma_irq_stride * (v)->ee; +} + +/* RDDMA Period Interrupts */ +#define QAIF_EE_RDDMA_PERIOD_IRQ_EN_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x00) +#define QAIF_EE_RDDMA_PERIOD_IRQ_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x08) +#define QAIF_EE_RDDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x10) +#define QAIF_EE_RDDMA_PERIOD_IRQ_CLR_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x18) +#define QAIF_EE_RDDMA_PERIOD_IRQ_FORCE_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x20) +/* RDDMA Underflow Interrupts */ +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_EN_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x28) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x30) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x38) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_CLR_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x40) +#define QAIF_EE_RDDMA_UNDERFLOW_IRQ_FORCE_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x48) +/* RDDMA Error Response Interrupts */ +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_EN_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x50) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x58) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x60) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_CLR_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x68) +#define QAIF_EE_RDDMA_ERR_RSP_IRQ_FORCE_REG(v, i) \ + QAIF_EE_RDDMA_IRQ_REG_ADDR(v, i, 0x70) + +static inline u32 QAIF_EE_WRDMA_IRQ_REG_ADDR(const struct qaif_variant *v, + enum qaif_irq_type_t dma_type, + u32 offset) +{ + if (dma_type == QAIF_AIF_IRQ) + return (v)->wrdma_irq_reg_base + offset + + (v)->wrdma_irq_stride * (v)->ee; + return (v)->codec_wrdma_irq_reg_base + offset + + (v)->codec_wrdma_irq_stride * (v)->ee; +} + +/* WRDMA Period Interrupts */ +#define QAIF_EE_WRDMA_PERIOD_IRQ_EN_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x00) +#define QAIF_EE_WRDMA_PERIOD_IRQ_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x08) +#define QAIF_EE_WRDMA_PERIOD_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x10) +#define QAIF_EE_WRDMA_PERIOD_IRQ_CLR_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x18) +#define QAIF_EE_WRDMA_PERIOD_IRQ_FORCE_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x20) +/* WRDMA Overflow Interrupts */ +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_EN_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x28) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x30) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x38) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_CLR_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x40) +#define QAIF_EE_WRDMA_OVERFLOW_IRQ_FORCE_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x48) +/* WRDMA Error Response Interrupts */ +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_EN_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x50) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x58) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_RAW_STAT_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x60) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_CLR_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x68) +#define QAIF_EE_WRDMA_ERR_RSP_IRQ_FORCE_REG(v, i) \ + QAIF_EE_WRDMA_IRQ_REG_ADDR(v, i, 0x70) + +static inline u32 QAIF_DMACFG_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_CFG_REG(v, chan); + return QAIF_CODEC_WRDMA_CFG_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_CFG_REG(v, chan); + return QAIF_WRDMA_CFG_REG(v, chan); +} + +static inline u32 QAIF_DMACTL_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_CTL_REG(v, chan); + return QAIF_CODEC_WRDMA_CTL_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_CTL_REG(v, chan); + return QAIF_WRDMA_CTL_REG(v, chan); +} + +static inline u32 QAIF_DMABUFF_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_BUFF_LEN_REG(v, chan); + return QAIF_CODEC_WRDMA_BUFF_LEN_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_BUFF_LEN_REG(v, chan); + return QAIF_WRDMA_BUFF_LEN_REG(v, chan); +} + +static inline u32 QAIF_DMACURR_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_CURR_ADDR_REG(v, chan); + return QAIF_CODEC_WRDMA_CURR_ADDR_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_CURR_ADDR_REG(v, chan); + return QAIF_WRDMA_CURR_ADDR_REG(v, chan); +} + +static inline u32 QAIF_DMAPER_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_PERIOD_CNT_REG(v, chan); + return QAIF_CODEC_WRDMA_PERIOD_CNT_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_PERIOD_CNT_REG(v, chan); + return QAIF_WRDMA_PERIOD_CNT_REG(v, chan); +} + +static inline u32 QAIF_DMAPER_LEN_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_PERIOD_LEN_REG(v, chan); + return QAIF_CODEC_WRDMA_PERIOD_LEN_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_PERIOD_LEN_REG(v, chan); + return QAIF_WRDMA_PERIOD_LEN_REG(v, chan); +} + +static inline u32 QAIF_DMABASE_REG(const struct qaif_variant *v, u32 chan, int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_BASE_ADDR_REG(v, chan); + return QAIF_CODEC_WRDMA_BASE_ADDR_REG(v, chan); + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_BASE_ADDR_REG(v, chan); + return QAIF_WRDMA_BASE_ADDR_REG(v, chan); +} + +static inline u32 QAIF_SID_MAP_REG(int dir, int dai_id) +{ + if (is_cif_dma_port(dai_id)) { + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_CODEC_RDDMA_SID_MAP_REG; + return QAIF_CODEC_WRDMA_SID_MAP_REG; + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + return QAIF_RDDMA_SID_MAP_REG; + return QAIF_WRDMA_SID_MAP_REG; +} + +#endif /* __QAIF_REG_H__ */ diff --git a/sound/soc/qcom/qaif-shikra.c b/sound/soc/qcom/qaif-shikra.c new file mode 100644 index 0000000000000..6e87ec7e22a16 --- /dev/null +++ b/sound/soc/qcom/qaif-shikra.c @@ -0,0 +1,702 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif-shikra.c -- ALSA SoC CPU-Platform DAI driver for QTi QAIF + */ + +#include +#include +#include +#include +#include "qaif.h" + +struct qaif_dmaidx_dai_map shikra_aif_dma_dai_map[] = { + { MI2S_QUATERNARY }, + { MI2S_QUINARY }, + { MI2S_SENARY }, + { MI2S_SEPTENARY } +}; + +struct qaif_dmaidx_dai_map shikra_cif_rx_dma_dai_map[] = { + { LPASS_CDC_DMA_RX0 }, + { LPASS_CDC_DMA_RX1 }, + { LPASS_CDC_DMA_RX2 }, + { LPASS_CDC_DMA_RX3 } +}; + +struct qaif_dmaidx_dai_map shikra_cif_tx_dma_dai_map[] = { + { LPASS_CDC_DMA_TX0 }, + { LPASS_CDC_DMA_TX1 }, + { LPASS_CDC_DMA_TX2 }, + { LPASS_CDC_DMA_TX3 } +}; + +struct qaif_dmaidx_dai_map shikra_cif_va_dma_dai_map[] = { + { LPASS_CDC_DMA_VA_TX0 }, + { LPASS_CDC_DMA_VA_TX1 }, + { LPASS_CDC_DMA_VA_TX2 }, + { LPASS_CDC_DMA_VA_TX3 } +}; + +static struct snd_soc_dai_driver shikra_qaif_cpu_dai_driver[] = { + { + .id = MI2S_PRIMARY, + .name = "Primary MI2S", + .playback = { + .stream_name = "Primary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Primary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_SECONDARY, + .name = "Secondary MI2S", + .playback = { + .stream_name = "Secondary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Secondary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_TERTIARY, + .name = "Tertiary MI2S", + .playback = { + .stream_name = "Tertiary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Tertiary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_QUATERNARY, + .name = "Quaternary MI2S", + .playback = { + .stream_name = "Quaternary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Quaternary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_QUINARY, + .name = "Quinary MI2S", + .playback = { + .stream_name = "Quinary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Quinary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_SENARY, + .name = "Senary MI2S", + .playback = { + .stream_name = "Senary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Senary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = MI2S_SEPTENARY, + .name = "Septenary MI2S", + .playback = { + .stream_name = "Septenary MI2S Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Septenary MI2S Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_aif_cpu_dai_ops, + }, { + .id = LPASS_CDC_DMA_RX0, + .name = "CDC DMA RX0", + .playback = { + .stream_name = "WCD Playback0", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_RX1, + .name = "CDC DMA RX1", + .playback = { + .stream_name = "WCD Playback1", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_TX0, + .name = "CDC DMA TX0", + .capture = { + .stream_name = "WCD Capture0", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_TX3, + .name = "CDC DMA TX3", + .capture = { + .stream_name = "WCD Capture1", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_VA_TX0, + .name = "CDC DMA VA0", + .capture = { + .stream_name = "DMIC Capture0", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, { + .id = LPASS_CDC_DMA_VA_TX1, + .name = "CDC DMA VA1", + .capture = { + .stream_name = "DMIC Capture1", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &asoc_qcom_qaif_cif_dai_ops, + }, +}; + +static int shikra_qaif_get_dma_idx(unsigned int dai_id) +{ + int i; + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + for (i = 0; i < ARRAY_SIZE(shikra_aif_dma_dai_map); i++) { + if (shikra_aif_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + for (i = 0; i < ARRAY_SIZE(shikra_cif_rx_dma_dai_map); i++) { + if (shikra_cif_rx_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + for (i = 0; i < ARRAY_SIZE(shikra_cif_tx_dma_dai_map); i++) { + if (shikra_cif_tx_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + for (i = 0; i < ARRAY_SIZE(shikra_cif_va_dma_dai_map); i++) { + if (shikra_cif_va_dma_dai_map[i].dai_id == dai_id) + return i; + } + break; + default: + pr_debug("DAI ID not Supported\n"); + break; + } + + pr_debug("DAI ID %u not found in map\n", dai_id); + return -EINVAL; +} + +static int shikra_qaif_alloc_stream_dma_idx(struct qaif_drv_data *drvdata, + int direction, unsigned int dai_id) +{ + struct qaif_variant *v = drvdata->variant; + int dma_idx; + int index = 0; + + if (!v) + return -EINVAL; + + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + dma_idx = shikra_qaif_get_dma_idx(dai_id); + if (dma_idx < 0) + return dma_idx; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + index = dma_idx; + if (index >= v->num_rddma) + return -EBUSY; + } else { + index = v->wrdma_start + dma_idx; + if (index >= v->wrdma_start + v->num_wrdma) + return -EBUSY; + } + if (test_bit(index, &drvdata->aif_dma_idx_bit_map)) + return -EBUSY; + + set_bit(index, &drvdata->aif_dma_idx_bit_map); + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + dma_idx = shikra_qaif_get_dma_idx(dai_id); + if (dma_idx < 0) + return dma_idx; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + index = dma_idx; + if (index >= v->num_codec_rddma) + return -EBUSY; + } else { + index = v->codec_wrdma_start + dma_idx; + if (index >= v->codec_wrdma_start + v->num_codec_wrdma) + return -EBUSY; + } + if (test_bit(index, &drvdata->cif_dma_idx_bit_map)) + return -EBUSY; + + set_bit(index, &drvdata->cif_dma_idx_bit_map); + break; + default: + return -EINVAL; + } + + return index; +} + +static int shikra_qaif_free_stream_dma_idx(struct qaif_drv_data *drvdata, + int index, unsigned int dai_id) +{ + switch (dai_id) { + case MI2S_PRIMARY ... MI2S_QUINARY: + case MI2S_SENARY: + case MI2S_SEPTENARY: + clear_bit(index, &drvdata->aif_dma_idx_bit_map); + break; + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + clear_bit(index, &drvdata->cif_dma_idx_bit_map); + break; + default: + break; + } + + return 0; +} + +static int shikra_qaif_init(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + struct qaif_variant *v = drvdata->variant; + struct device *dev = &pdev->dev; + int ret, i; + + if (!v) { + dev_err(dev, "No variant data\n"); + return -EINVAL; + } + if (v->num_clks == 0 || v->num_clks > 32) { + dev_err(dev, "Invalid clock count: %d\n", v->num_clks); + return -EINVAL; + } + drvdata->clks = devm_kcalloc(dev, v->num_clks, + sizeof(*drvdata->clks), GFP_KERNEL); + if (!drvdata->clks) + return -ENOMEM; + + drvdata->num_clks = v->num_clks; + + for (i = 0; i < drvdata->num_clks; i++) + drvdata->clks[i].id = v->clk_name[i]; + + ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "Failed to get clocks %d\n", ret); + return ret; + } + + ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "shikra clk_enable failed\n"); + return ret; + } + + return 0; +} + +static int shikra_qaif_exit(struct platform_device *pdev) +{ + struct qaif_drv_data *drvdata = platform_get_drvdata(pdev); + + if (!drvdata || !drvdata->clks) + return -EINVAL; + + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + return 0; +} + +static int __maybe_unused shikra_qaif_dev_resume(struct device *dev) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + + if (!drvdata || !drvdata->clks) { + dev_err(dev, "Invalid drvdata in resume\n"); + return -EINVAL; + } + return clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); +} + +static int __maybe_unused shikra_qaif_dev_suspend(struct device *dev) +{ + struct qaif_drv_data *drvdata = dev_get_drvdata(dev); + + if (!drvdata || !drvdata->clks) { + dev_err(dev, "Invalid drvdata in suspend\n"); + return -EINVAL; + } + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + return 0; +} + +static const struct dev_pm_ops shikra_qaif_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(shikra_qaif_dev_suspend, + shikra_qaif_dev_resume) +}; + +static struct qaif_variant shikra_qaif_data = { + .ee = 0, + .qaif_type = QAIF, + + .num_rddma = 4, + .num_wrdma = 4, + .wrdma_start = 4, + + .num_codec_rddma = 4, //RX + .num_codec_wrdma = 4, //TX + .codec_wrdma_start = 4, + .num_intf = 0, + + .rddma_reg_base = 0x8000, + .rddma_stride = 0x1000, + .codec_rddma_reg_base = 0xC000, + .codec_rddma_stride = 0x1000, + + .wrdma_reg_base = 0x11000, + .wrdma_stride = 0x1000, + .codec_wrdma_reg_base = 0x15000, + .codec_wrdma_stride = 0x1000, + + .rddma_irq_reg_base = 0x19000, + .rddma_irq_stride = 0x1000, + .codec_rddma_irq_reg_base = 0x191A0, + .codec_rddma_irq_stride = 0x1000, + + .wrdma_irq_reg_base = 0x19078, + .wrdma_irq_stride = 0x1000, + .codec_wrdma_irq_reg_base = 0x19290, + .codec_wrdma_irq_stride = 0x1000, + + .qxm_type = QXM0, + .rd_len = 512, + .rddma_shram_len = 64, + .rddma_shram_start_addr = {0, 256}, + .wr_len = 512, + .wrdma_shram_len = 64, + .wrdma_shram_start_addr = {0, 256}, + + /* ============================================================================ */ + /* AIF RDDMA (Audio Interface Read DMA) Register Fields */ + /* Base: 0x8000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0x8000) */ + .rddma_enable = REG_FIELD_ID(0x8000, 0, 0, 4, 0x1000), /* ENABLE [0] */ + .rddma_reset = REG_FIELD_ID(0x8000, 4, 4, 4, 0x1000), /* RESET [4] */ + + /* CFG register (0x8004) */ + .rddma_shram_wm = REG_FIELD_ID(0x8004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .rddma_burst1 = REG_FIELD_ID(0x8004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .rddma_burst2 = REG_FIELD_ID(0x8004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .rddma_burst4 = REG_FIELD_ID(0x8004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .rddma_burst8 = REG_FIELD_ID(0x8004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .rddma_burst16 = REG_FIELD_ID(0x8004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .rddma_dma_dyncclk = REG_FIELD_ID(0x8004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .rddma_num_ot = REG_FIELD_ID(0x8004, 28, 29, 4, 0x1000), /* RDDMA_NUM_OT [29:28] */ + + /* ============================================================================ */ + /* AIF WRDMA (Audio Interface Write DMA) Register Fields */ + /* Base: 0x11000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0x11000) */ + .wrdma_enable = REG_FIELD_ID(0x11000, 0, 0, 4, 0x1000), /* ENABLE [0] */ + .wrdma_reset = REG_FIELD_ID(0x11000, 4, 4, 4, 0x1000), /* RESET [4] */ + + /* CFG register (0x11004) */ + .wrdma_shram_wm = REG_FIELD_ID(0x11004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .wrdma_burst1 = REG_FIELD_ID(0x11004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .wrdma_burst2 = REG_FIELD_ID(0x11004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .wrdma_burst4 = REG_FIELD_ID(0x11004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .wrdma_burst8 = REG_FIELD_ID(0x11004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .wrdma_burst16 = REG_FIELD_ID(0x11004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .wrdma_dma_dyncclk = REG_FIELD_ID(0x11004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .wrdma_num_ot = REG_FIELD_ID(0x11004, 28, 29, 4, 0x1000), /* WRDMA_NUM_OT [29:28] */ + + /* ============================================================================ */ + /* CODEC RDDMA (RX/Playback) Register Fields */ + /* Base: 0xC000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0xC000) */ + .cif_rddma_enable = REG_FIELD_ID(0xC000, 0, 0, 4, 0x1000), + .cif_rddma_reset = REG_FIELD_ID(0xC000, 4, 4, 4, 0x1000), + + /* CFG register (0xC004) */ + .cif_rddma_shram_wm = REG_FIELD_ID(0xC004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .cif_rddma_burst1 = REG_FIELD_ID(0xC004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .cif_rddma_burst2 = REG_FIELD_ID(0xC004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .cif_rddma_burst4 = REG_FIELD_ID(0xC004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .cif_rddma_burst8 = REG_FIELD_ID(0xC004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .cif_rddma_burst16 = REG_FIELD_ID(0xC004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .cif_rddma_dma_dyncclk = REG_FIELD_ID(0xC004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .cif_rddma_num_ot = REG_FIELD_ID(0xC004, 28, 29, 4, 0x1000), /* RDDMA_NUM_OT [29:28] */ + + /* INTF_CFG register (0xC05C) */ + .cif_rddma_en_16bit_unpack = REG_FIELD_ID(0xC05C, 0, 0, 4, 0x1000), + /* ENABLE_16B_UNPACKING [0] */ + .cif_rddma_intf_dyncclk = REG_FIELD_ID(0xC05C, 2, 2, 4, 0x1000), /* DYNAMIC_CLOCK [2] */ + .cif_rddma_fs_out_gate = REG_FIELD_ID(0xC05C, 3, 3, 4, 0x1000), /* FS_OUT_GATING_EN [3] */ + .cif_rddma_fs_sel = REG_FIELD_ID(0xC05C, 4, 7, 4, 0x1000), /* FS_SEL [7:4] */ + .cif_rddma_fs_delay = REG_FIELD_ID(0xC05C, 8, 11, 4, 0x1000), /* FS_DELAY [11:8] */ + .cif_rddma_active_ch_en = REG_FIELD_ID(0xC05C, 12, 27, 4, 0x1000), + /* ACTIVE_CHANNEL_EN [27:12] */ + + /* ============================================================================ */ + /* CODEC WRDMA (TX/Capture) Register Fields */ + /* Base: 0x15000, 4 channels, stride 0x1000 */ + /* ============================================================================ */ + + /* CTL register (0x15000) */ + .cif_wrdma_enable = REG_FIELD_ID(0x15000, 0, 0, 4, 0x1000), + .cif_wrdma_reset = REG_FIELD_ID(0x15000, 4, 4, 4, 0x1000), + + /* CFG register (0x15004) */ + .cif_wrdma_shram_wm = REG_FIELD_ID(0x15004, 0, 11, 4, 0x1000), /* SHRAM_WATERMRK [11:0] */ + .cif_wrdma_burst1 = REG_FIELD_ID(0x15004, 16, 16, 4, 0x1000), /* BURST1_EN [16] */ + .cif_wrdma_burst2 = REG_FIELD_ID(0x15004, 17, 17, 4, 0x1000), /* BURST2_EN [17] */ + .cif_wrdma_burst4 = REG_FIELD_ID(0x15004, 18, 18, 4, 0x1000), /* BURST4_EN [18] */ + .cif_wrdma_burst8 = REG_FIELD_ID(0x15004, 19, 19, 4, 0x1000), /* BURST8_EN [19] */ + .cif_wrdma_burst16 = REG_FIELD_ID(0x15004, 20, 20, 4, 0x1000), /* BURST16_EN [20] */ + .cif_wrdma_dma_dyncclk = REG_FIELD_ID(0x15004, 24, 24, 4, 0x1000), /* DYNAMIC_CLOCK [24] */ + .cif_wrdma_num_ot = REG_FIELD_ID(0x15004, 28, 29, 4, 0x1000), /* WRDMA_NUM_OT [29:28] */ + + /* INTF_CFG register (0x15058) */ + .cif_wrdma_en_16bit_unpack = REG_FIELD_ID(0x15058, 0, 0, 4, 0x1000), + /* ENABLE_16B_PACKING [0] */ + .cif_wrdma_intf_dyncclk = REG_FIELD_ID(0x15058, 2, 2, 4, 0x1000), /* DYNAMIC_CLOCK [2] */ + .cif_wrdma_fs_out_gate = REG_FIELD_ID(0x15058, 3, 3, 4, 0x1000), /* FS_OUT_GATING_EN [3] */ + .cif_wrdma_fs_sel = REG_FIELD_ID(0x15058, 4, 7, 4, 0x1000), /* FS_SEL [7:4] */ + .cif_wrdma_fs_delay = REG_FIELD_ID(0x15058, 8, 11, 4, 0x1000), /* FS_DELAY [11:8] */ + .cif_wrdma_active_ch_en = REG_FIELD_ID(0x15058, 12, 27, 4, 0x1000), + /* ACTIVE_CHANNEL_EN [27:12] */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_SYNC_CFG (0x4004 + 0x1000*a) */ + .aif_inv_sync = REG_FIELD_ID(0x4004, 12, 12, 4, 0x1000), /* bit 12 */ + .aif_sync_delay = REG_FIELD_ID(0x4004, 8, 9, 4, 0x1000), /* bits 9:8 */ + .aif_sync_mode = REG_FIELD_ID(0x4004, 4, 5, 4, 0x1000), /* bits 5:4 */ + .aif_sync_src = REG_FIELD_ID(0x4004, 0, 0, 4, 0x1000), /* bit 0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_BIT_WIDTH_CFG (0x4008 + 0x1000*a) */ + .aif_sample_width_rx = REG_FIELD_ID(0x4008, 24, 28, 4, 0x1000), /* bits 28:24 */ + .aif_sample_width_tx = REG_FIELD_ID(0x4008, 16, 20, 4, 0x1000), /* bits 20:16 */ + .aif_slot_width_rx = REG_FIELD_ID(0x4008, 8, 12, 4, 0x1000), /* bits 12:8 */ + .aif_slot_width_tx = REG_FIELD_ID(0x4008, 0, 4, 4, 0x1000), /* bits 4:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_FRAME_CFG (0x400C + 0x1000*a) */ + .aif_bits_per_lane = REG_FIELD_ID(0x400C, 0, 9, 4, 0x1000), /* bits 9:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_TX (0x4010 + 0x1000*a) */ + .aif_slot_en_tx_mask = REG_FIELD_ID(0x4010, 0, 31, 4, 0x1000), /* bits 31:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_RX (0x4030 + 0x1000*a) */ + .aif_slot_en_rx_mask = REG_FIELD_ID(0x4030, 0, 31, 4, 0x1000), /* bits 31:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_LANE_CFG (0x4050 + 0x1000*a) */ + .aif_loopback_en = REG_FIELD_ID(0x4050, 31, 31, 4, 0x1000), /* bit 31 */ + .aif_ctrl_data_oe = REG_FIELD_ID(0x4050, 16, 16, 4, 0x1000), /* bit 16 */ + .aif_lane_en = REG_FIELD_ID(0x4050, 8, 15, 4, 0x1000), /* bits 15:8 */ + .aif_lane_dir = REG_FIELD_ID(0x4050, 0, 7, 4, 0x1000), /* bits 7:0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_MI2S_CFG (0x4054 + 0x1000*a) */ + .aif_mono_mode_rx = REG_FIELD_ID(0x4054, 1, 1, 4, 0x1000), /* bit 1 */ + .aif_mono_mode_tx = REG_FIELD_ID(0x4054, 0, 0, 4, 0x1000), /* bit 0 */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_CFG (0x4058 + 0x1000*a) */ + .aif_full_cycle_en = REG_FIELD_ID(0x4058, 0, 0, 4, 0x1000), /* bit 0 */ + + .clk_name = (const char*[]) { + "gcc_lpass_config_clk", + "gcc_lpass_core_axim_clk", + "audio_core_cc_bus_clk" + }, + .num_clks = 3, + + .dai_driver = shikra_qaif_cpu_dai_driver, + .num_dai = ARRAY_SIZE(shikra_qaif_cpu_dai_driver), + /* Below Clocks should be mapped as per interface index */ + .dai_osr_clk_names = (const char *[]) { + "null" + }, + .dai_bit_clk_names = (const char *[]) { + "audio_core_cc_aif_if0_ibit_clk", /* if0 */ + "audio_core_cc_aif_if1_ibit_clk", /* if1 */ + "audio_core_cc_aif_if2_ibit_clk", /* if2 */ + "audio_core_cc_aif_if3_ibit_clk" /* if3 */ + }, + .init = shikra_qaif_init, + .exit = shikra_qaif_exit, + .alloc_stream_dma_idx = shikra_qaif_alloc_stream_dma_idx, + .free_stream_dma_idx = shikra_qaif_free_stream_dma_idx, + .get_dma_idx = shikra_qaif_get_dma_idx, +}; + +static const struct of_device_id shikra_qaif_cpu_device_id[] = { + {.compatible = "qcom,shikra-qaif-cpu", .data = &shikra_qaif_data}, + {} +}; +MODULE_DEVICE_TABLE(of, shikra_qaif_cpu_device_id); + +static struct platform_driver shikra_qaif_cpu_platform_driver = { + .driver = { + .name = "shikra-qaif-cpu", + .of_match_table = of_match_ptr(shikra_qaif_cpu_device_id), + .pm = &shikra_qaif_pm_ops, + }, + .probe = asoc_qcom_qaif_cpu_platform_probe, + .remove = asoc_qcom_qaif_cpu_platform_remove, + .shutdown = asoc_qcom_qaif_cpu_platform_shutdown, +}; +module_platform_driver(shikra_qaif_cpu_platform_driver); + +MODULE_DESCRIPTION("SHIKRA QAIF CPU DRIVER"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/qaif.h b/sound/soc/qcom/qaif.h new file mode 100644 index 0000000000000..f52c92289813f --- /dev/null +++ b/sound/soc/qcom/qaif.h @@ -0,0 +1,576 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2011,2013-2015,2020 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * qaif.h -- ALSA SoC CPU-Platform DAI driver header file for QTi QAIF + */ +#ifndef __QAIF_H__ +#define __QAIF_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MI2S_SEPTENARY 35 + +#define SMMU_SID_OFFSET 32 +#define LPASS_MAX_MI2S_PORTS (8) +#define LPASS_MAX_AIF_DMA_IDX (8) +#define LPASS_MAX_CIF_DMA_IDX (8) +#define QAIF_CIF_DMA_INTF_ONE_CHANNEL (0x01) +#define QAIF_CIF_DMA_INTF_TWO_CHANNEL (0x03) +#define QAIF_CIF_DMA_INTF_FOUR_CHANNEL (0x0F) +#define QAIF_CIF_DMA_INTF_SIX_CHANNEL (0x3F) +#define QAIF_CIF_DMA_INTF_EIGHT_CHANNEL (0xFF) + +#define QAIF_DMACTL_ENABLE_ON 1 +#define QAIF_DMACTL_ENABLE_OFF 0 + +#define QAIF_DMACTL_DYNCLK_ON 1 +#define QAIF_DMACTL_DYNCLK_OFF 0 + +#define QAIF_MAX_AIF_CFG_CNT (LPASS_MAX_AIF_DMA_IDX / 2) + +/* TODO: confirm if only dma0...3 are active. */ +#define QAIF_IRQ_DMA_ALL (0xf) + +/* Individual bit masks (hex) */ +#define QAIF_AUD_INTF_CTL_ENABLE 0x00000001 /* bit 0 ENABLE RX and TX*/ +#define QAIF_AUD_INTF_CTL_ENABLE_TX 0x00000010 /* bit 4 */ +#define QAIF_AUD_INTF_CTL_ENABLE_RX 0x00000100 /* bit 8 */ +#define QAIF_AUD_INTF_CTL_RESET 0x00001000 /* bit 12 RESET RX and TX*/ +#define QAIF_AUD_INTF_CTL_RESET_TX 0x00010000 /* bit 16 */ +#define QAIF_AUD_INTF_CTL_RESET_RX 0x00100000 /* bit 20 */ + +/* Combined masks */ +#define QAIF_AUD_INTF_CTL_ENABLE_ALL 0x00000110 /* bits 4,8 */ +#define QAIF_AUD_INTF_CTL_RESET_ALL 0x00110000 /* bits 16,20 */ + +#define QAIF_AUD_INTF_CTL_MONO 1 /* Mono Mode True */ +#define QAIF_AUD_INTF_CTL_STEREO 0 /* Mono Mode False */ + +#define QAIF_AIF_SAMPLE_WIDTH(bits) ((bits) - 1) +#define QAIF_AIF_SLOT_WIDTH(bits) ((bits) - 1) + +#define QAIF_DMA_CLK_RATE_HZ 153600000 + +#define QAIF_DMACTL_WM_5 4 +#define QAIF_DMACTL_WM_8 7 +#define QAIF_DMACTL_BURSTEN 1 + +#define QAIF_MAX_LANES 8 + +/* QAIF_AUD_INTF_SYNC_CFG_REG bit masks and shifts */ +#define QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_MASK BIT(12) +#define QAIF_AUD_INTF_SYNC_CFG_INV_SYNC_SHFT 12 + +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_MASK GENMASK(9, 8) +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_DELAY_SHFT 8 + +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_MASK GENMASK(5, 4) +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_MODE_SHFT 4 + +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_MASK BIT(0) +#define QAIF_AUD_INTF_SYNC_CFG_SYNC_SRC_SHFT 0 + +/* QAIF_AUD_INTF_LANE_CFG_REG bit masks and shifts */ +#define QAIF_AUD_INTF_LANE_CFG_LOOPBACK_MASK BIT(31) +#define QAIF_AUD_INTF_LANE_CFG_LOOPBACK_SHFT 31 + +#define QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_MASK BIT(16) +#define QAIF_AUD_INTF_LANE_CFG_CTRL_DATA_OE_SHFT 16 + +#define QAIF_AUD_INTF_LANE_CFG_LANE_EN_MASK GENMASK(15, 8) +#define QAIF_AUD_INTF_LANE_CFG_LANE_EN_SHFT 8 + +#define QAIF_AUD_INTF_LANE_CFG_LANE_DIR_MASK GENMASK(7, 0) +#define QAIF_AUD_INTF_LANE_CFG_LANE_DIR_SHFT 0 + +/* ========== QAIF_AUD_INTF_BIT_WIDTH_CFG_REG bit masks and shifts ========== */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_MASK GENMASK(28, 24) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_SHFT 24 + +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_MASK GENMASK(20, 16) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_SHFT 16 + +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_MASK GENMASK(12, 8) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_SHFT 8 + +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_MASK GENMASK(4, 0) +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_SHFT 0 + +/* ========== QAIF_AUD_INTF_BIT_WIDTH_CFG_REG - Combined masks for RMW ========== */ +/* RX-only fields mask (for preserving TX fields) */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_RX_FIELDS_MASK \ + (QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_RX_MASK | \ + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_RX_MASK) + +/* TX-only fields mask (for preserving RX fields) */ +#define QAIF_AUD_INTF_BIT_WIDTH_CFG_TX_FIELDS_MASK \ + (QAIF_AUD_INTF_BIT_WIDTH_CFG_SAMPLE_WIDTH_TX_MASK | \ + QAIF_AUD_INTF_BIT_WIDTH_CFG_SLOT_WIDTH_TX_MASK) + +/* ========== QAIF_AUD_INTF_MI2S_CFG_REG bit masks and shifts ========== */ +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK BIT(1) +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_SHFT 1 + +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK BIT(0) +#define QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_SHFT 0 + +/* Combined masks for Read-Modify-Write operations */ +#define QAIF_AUD_INTF_MI2S_CFG_RX_FIELDS_MASK \ + (QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_RX_MASK) + +#define QAIF_AUD_INTF_MI2S_CFG_TX_FIELDS_MASK \ + (QAIF_AUD_INTF_MI2S_CFG_MONO_MODE_TX_MASK) + +enum qxm_sel { + QXM0 = 0, + QXM1 = 1, + MAX_QXM_TYPE, +}; + +/* Enum list to define the interface direction */ +enum aud_dma_util_direction { + AUD_DMA_SINK = 0, + AUD_DMA_SOURCE = 1, +}; + +static inline bool is_cif_dma_port(int dai_id) +{ + switch (dai_id) { + case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9: + case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8: + case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8: + return true; + } + return false; +} + +/* Enum list to define the list of HW interfaces DMA Util is used for + * example, Display port can be part of the below list in future + */ +enum qaif_type_t { + QAIF_INVALID = -1, + QAIF = 0, + QAIF_VA, + QAIF_MAX_TYPES +}; + +enum qaif_irq_type_t { + QAIF_AIF_IRQ = 0, + QAIF_CIF_IRQ = 1, + QAIF_AUD_INTF_IRQ = 2, + QAIF_IRQ_MAX = 3 +}; + +enum qaif_dma_type { + QAIF_AIF_DMA = 0, + QAIF_CIF_DMA = 1, + DMA_TYPE_MAX +}; + +struct qaif_dmactl { + //AUDIO_CORE_QAIF_CODEC_xDMAa_CTL + struct regmap_field *enable; + struct regmap_field *reset; + + //AUDIO_CORE_QAIF_CODEC_xDMAa_CFG + struct regmap_field *num_ot; //outstanding transaction + struct regmap_field *dma_dyncclk; + struct regmap_field *burst16; + struct regmap_field *burst8; + struct regmap_field *burst4; + struct regmap_field *burst2; + struct regmap_field *burst1; + struct regmap_field *shram_wm; //SHRAM_WATERMRK + +}; + +struct qaif_cdc_intfctl { + //AUDIO_CORE_QAIF_CODEC_xDMAa_INTF_CFG + struct regmap_field *active_ch_en; + struct regmap_field *fs_sel; + struct regmap_field *fs_delay; + struct regmap_field *fs_out_gate; + struct regmap_field *intf_dyncclk; + struct regmap_field *en_16bit_unpack; +}; + +struct qaif_aud_intfctl { + /* AUDIO_CORE_QAIF_AUD_INTFa_SYNC_CFG */ + struct regmap_field *inv_sync; /* qcom,qaif-aif-invert-sync */ + struct regmap_field *sync_delay; /* qcom,qaif-aif-sync-delay */ + struct regmap_field *sync_mode; /* qcom,qaif-aif-sync-mode */ + struct regmap_field *sync_src; /* qcom,qaif-aif-sync-src */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_BIT_WIDTH_CFG */ + struct regmap_field *slot_width_rx; /* qcom,qaif-aif-slot-width-rx (MIC/RX Path) */ + struct regmap_field *slot_width_tx; /* qcom,qaif-aif-slot-width-tx (SPKR/TX Path) */ + struct regmap_field *sample_width_rx; /* qcom,qaif-aif-sample-width-rx (MIC/RX Path) */ + struct regmap_field *sample_width_tx; /* qcom,qaif-aif-sample-width-tx (SPKR/TX Path) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_MI2S_CFG */ + struct regmap_field *mono_mode_rx; /* qcom,qaif-aif-mono-mode-rx (SPKR/TX Path) */ + struct regmap_field *mono_mode_tx; /* qcom,qaif-aif-mono-mode-tx (MIC/RX Path) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_LANE_CFG */ + struct regmap_field *lane_en; /* Lane enable mask (bits 8-15) */ + struct regmap_field *lane_dir; /* Lane direction mask (bits 0-7, 0=TX, 1=RX) */ + struct regmap_field *loopback_en; /* qcom,qaif-aif-loopback-en (bit 31) */ + struct regmap_field *ctrl_data_oe; /* qcom,qaif-aif-ctrl-data-oe (bit 16) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_RX */ + struct regmap_field *slot_en_rx_mask; /* qcom,qaif-aif-slot-en-rx-mask (32-bit mask) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_ACTV_SLOT_EN_TX */ + struct regmap_field *slot_en_tx_mask; /* qcom,qaif-aif-slot-en-tx-mask (32-bit mask) */ + + /* AUDIO_CORE_QAIF_AUD_INTFa_CFG */ + struct regmap_field *full_cycle_en; /* qcom,qaif-aif-full-cycle-en */ + /* AUDIO_CORE_QAIF_AUD_INTFa_FRAME_CFG */ + struct regmap_field *bits_per_lane; /* qcom,qaif-aif-bits-per-lane */ +}; + +/* Lane configuration structure */ +struct qaif_lane_config { + u32 enable; /* 1 = enabled, 0 = disabled */ + u32 direction; /* 0 = TX_SPKR, 1 = RX_MIC */ +}; + +/* QAIF Audio Interface Configuration Structure */ +struct qaif_aif_config { + /* Sync configuration */ + u32 sync_mode; /* qcom,qaif-aif-sync-mode */ + u32 sync_src; /* qcom,qaif-aif-sync-src */ + u32 invert_sync; /* qcom,qaif-aif-invert-sync */ + u32 sync_delay; /* qcom,qaif-aif-sync-delay */ + /* Slot and sample width configuration */ + u32 slot_width_rx; /* qcom,qaif-aif-slot-width-rx (MIC/RX Path) */ + u32 slot_width_tx; /* qcom,qaif-aif-slot-width-tx (SPKR/TX Path) */ + u32 sample_width_rx; /* qcom,qaif-aif-sample-width-rx (MIC/RX Path) */ + u32 sample_width_tx; /* qcom,qaif-aif-sample-width-tx (SPKR/TX Path) */ + /* Slot enable masks (32-bit masks for 32 slots) */ + u32 slot_en_rx_mask; /* qcom,qaif-aif-slot-en-rx-mask (MIC/RX Path) */ + u32 slot_en_tx_mask; /* qcom,qaif-aif-slot-en-tx-mask (SPKR/TX Path) */ + /* Control configuration */ + u32 loopback_en; /* qcom,qaif-aif-loopback-en */ + u32 ctrl_data_oe; /* qcom,qaif-aif-ctrl-data-oe */ + /* Lane configuration */ + u32 num_lanes; /* Number of lanes configured */ + struct qaif_lane_config lane_cfg[QAIF_MAX_LANES]; /* qcom,qaif-aif-lane-config */ + u32 lane_en_mask; + u32 lane_dir_mask; + /* Mono/Stereo mode */ + u32 mono_mode_tx; /* qcom,qaif-aif-mono-mode-tx (MIC/RX Path) */ + u32 mono_mode_rx; /* qcom,qaif-aif-mono-mode-rx (SPKR/TX Path) */ + /* Frame configuration */ + u32 full_cycle_en; /* qcom,qaif-aif-full-cycle-en */ + u32 bits_per_lane; /* qcom,qaif-aif-bits-per-lane (FRAME_CFG) */ +}; + +struct qaif_pcm_data { + int stream_dma_idx; + //int i2s_port; +}; + +struct qaif_dma_mem_info { + dma_addr_t dma_addr; + size_t alloc_size; + void *vaddr; +}; + +struct qaif_dmaidx_dai_map { + unsigned int dai_id; +}; + +/* Both the CPU DAI and platform drivers will access this data */ +struct qaif_drv_data { + /* MI2S system clock */ + struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS]; + + /* MI2S bit clock (derived from system clock by a divider */ + struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS]; + + /* The state of MI2S prepare dai_ops was called */ + bool mi2s_was_prepared[LPASS_MAX_MI2S_PORTS]; + + /* SOC specific clock list */ + struct clk_bulk_data *clks; + int num_clks; + + struct clk *aud_dma_clk; + struct clk *aud_dma_mem_clk; + + /* Qualcomm audio interface (QAIF) registers */ + void __iomem *audio_qaif; + + /* regmap backed by the Qualcomm audio interface (QAIF) registers */ + struct regmap *audio_qaif_map; + + /* interrupts from the Qualcomm audio interface (QAIF) */ + int audio_qaif_irq; + + /* QAIF init config refcount*/ + unsigned int qaif_init_ref_cnt; + + /* SOC specific variations in the QAIF IP integration */ + struct qaif_variant *variant; + + /* bit map to keep track of dma idx allocations */ + unsigned long aif_dma_idx_bit_map; + unsigned long cif_dma_idx_bit_map; + + /* used it for handling interrupt per dma channel */ + struct snd_pcm_substream *aif_substream[LPASS_MAX_AIF_DMA_IDX]; + struct snd_pcm_substream *cif_substream[LPASS_MAX_CIF_DMA_IDX]; + + u64 smmu_csid_bits; + u64 smmu_sid_bits; + + /* DMA Heap handle*/ + struct dma_heap *dma_heap; + /* DMA Heap name*/ + const char *dma_heap_name; + /* DMA info handle per stream/dma idx*/ + struct qaif_dma_mem_info *aif_dma_heap[LPASS_MAX_AIF_DMA_IDX]; + struct qaif_dma_mem_info *cif_dma_heap[LPASS_MAX_CIF_DMA_IDX]; + +}; + +enum qaif_summary_irq_bitmask { + QAIF_SUMMARY_BITMASK_AIF_PERIOD_RDDMA = BIT(0), + QAIF_SUMMARY_BITMASK_AIF_UNDERFLOW_RDDMA = BIT(1), + QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_RDDMA = BIT(2), + QAIF_SUMMARY_BITMASK_AIF_PERIOD_WRDMA = BIT(3), + QAIF_SUMMARY_BITMASK_AIF_OVERFLOW_WRDMA = BIT(4), + QAIF_SUMMARY_BITMASK_AIF_ERR_RSP_WRDMA = BIT(5), + + QAIF_SUMMARY_BITMASK_AUD_OVERFLOW = BIT(6), + QAIF_SUMMARY_BITMASK_AUD_UNDERFLOW = BIT(7), + + QAIF_SUMMARY_BITMASK_RATE_DET = BIT(8), + QAIF_SUMMARY_BITMASK_VFR = BIT(9), + QAIF_SUMMARY_BITMASK_GRP = BIT(10), + QAIF_SUMMARY_BITMASK_RDDMA_OVERLAP = BIT(11), + QAIF_SUMMARY_BITMASK_WRDMA_OVERLAP = BIT(12), + QAIF_SUMMARY_BITMASK_INTF_OVERLAP = BIT(13), + QAIF_SUMMARY_BITMASK_GRP_OVERLAP = BIT(14), + + QAIF_SUMMARY_BITMASK_CIF_OVERLAP_RDDMA = BIT(15), + QAIF_SUMMARY_BITMASK_CIF_OVERLAP_WRDMA = BIT(17), + QAIF_SUMMARY_BITMASK_CIF_PERIOD_RDDMA = BIT(18), + QAIF_SUMMARY_BITMASK_CIF_UNDERFLOW_RDDMA = BIT(19), + QAIF_SUMMARY_BITMASK_CIF_ERR_RSP = BIT(20), + QAIF_SUMMARY_BITMASK_CIF_PERIOD_WRDMA = BIT(24), + QAIF_SUMMARY_BITMASK_CIF_OVERFLOW_WRDMA = BIT(25), + QAIF_SUMMARY_BITMASK_CIF_ERR_RSP_WRDMA = BIT(26) + +}; + +/* defines the bitmask in the status register for each of the clients */ +enum qaif_client_status_register_bitmask_info { + QAIF_BITMASK_GROUP_INF = 0x400, + QAIF_BITMASK_AIF_RDDMA_WRDMA = 0x3F, + QAIF_BITMASK_CIF_RDDMA_WRDMA = 0x71c0000, + QAIF_BITMASK_DP_RDDMA = 0xe00000, + QAIF_BITMASK_AUD_INF = 0xC0, +}; + +struct qaif_irq_map { + int client_id; + u32 mask; + irqreturn_t (*client_irq_handler)(struct qaif_drv_data *drvdata, u32 irq_status); +}; + +enum dma_type { + DMA_TYPE_RDDMA, + DMA_TYPE_WRDMA +}; + +enum qaif_irq { + QAIF_IRQ_PERIOD, + QAIF_IRQ_OVERFLOW, + QAIF_IRQ_UNDERFLOW, + QAIF_IRQ_ERROR +}; + +/* list of clients for IRQ Util */ +enum qaif_client_info { + QAIF_CLIENT_ID_GROUP_INF = 0, + QAIF_CLIENT_ID_AIF_DMA = 1, + QAIF_CLIENT_ID_CIF_DMA = 2, + QAIF_CLIENT_ID_DP_DMA = 3, + QAIF_CLIENT_ID_AUD_INF = 4, + QAIF_CLIENT_ID_MAX +}; + +struct qaif_variant { + u32 ee; + u32 qaif_type; + + u32 num_rddma; + u32 num_wrdma; + u32 wrdma_start; + + u32 num_codec_rddma; //RX + u32 num_codec_wrdma; //TX + u32 codec_wrdma_start; + u32 num_intf; + + u32 rddma_reg_base; + u32 rddma_stride; + u32 codec_rddma_reg_base; + u32 codec_rddma_stride; + + u32 wrdma_reg_base; + u32 wrdma_stride; + u32 codec_wrdma_reg_base; + u32 codec_wrdma_stride; + + u32 rddma_irq_reg_base; + u32 rddma_irq_stride; + u32 codec_rddma_irq_reg_base; + u32 codec_rddma_irq_stride; + + u32 wrdma_irq_reg_base; + u32 wrdma_irq_stride; + u32 codec_wrdma_irq_reg_base; + u32 codec_wrdma_irq_stride; + + u32 qxm_type; + u32 rd_len; + u32 rddma_shram_len; + u32 rddma_shram_start_addr[DMA_TYPE_MAX]; + u32 wr_len; + u32 wrdma_shram_len; + u32 wrdma_shram_start_addr[DMA_TYPE_MAX]; + + /* AIF RDDMA register fields */ + const struct reg_field rddma_enable; + const struct reg_field rddma_reset; + const struct reg_field rddma_num_ot; + const struct reg_field rddma_dma_dyncclk; + const struct reg_field rddma_burst16; + const struct reg_field rddma_burst8; + const struct reg_field rddma_burst4; + const struct reg_field rddma_burst2; + const struct reg_field rddma_burst1; + const struct reg_field rddma_shram_wm; + + /* AIF WRDMA register fields */ + const struct reg_field wrdma_enable; + const struct reg_field wrdma_reset; + const struct reg_field wrdma_num_ot; + const struct reg_field wrdma_dma_dyncclk; + const struct reg_field wrdma_burst16; + const struct reg_field wrdma_burst8; + const struct reg_field wrdma_burst4; + const struct reg_field wrdma_burst2; + const struct reg_field wrdma_burst1; + const struct reg_field wrdma_shram_wm; + + /* CODEC RDDMA register fields */ + const struct reg_field cif_rddma_enable; + const struct reg_field cif_rddma_reset; + const struct reg_field cif_rddma_num_ot; + const struct reg_field cif_rddma_dma_dyncclk; + const struct reg_field cif_rddma_burst16; + const struct reg_field cif_rddma_burst8; + const struct reg_field cif_rddma_burst4; + const struct reg_field cif_rddma_burst2; + const struct reg_field cif_rddma_burst1; + const struct reg_field cif_rddma_shram_wm; + const struct reg_field cif_rddma_active_ch_en; + const struct reg_field cif_rddma_fs_sel; + const struct reg_field cif_rddma_fs_delay; + const struct reg_field cif_rddma_fs_out_gate; + const struct reg_field cif_rddma_intf_dyncclk; + const struct reg_field cif_rddma_en_16bit_unpack; + + /* CODEC WRDMA register fields */ + const struct reg_field cif_wrdma_enable; + const struct reg_field cif_wrdma_reset; + const struct reg_field cif_wrdma_num_ot; + const struct reg_field cif_wrdma_dma_dyncclk; + const struct reg_field cif_wrdma_burst16; + const struct reg_field cif_wrdma_burst8; + const struct reg_field cif_wrdma_burst4; + const struct reg_field cif_wrdma_burst2; + const struct reg_field cif_wrdma_burst1; + const struct reg_field cif_wrdma_shram_wm; + const struct reg_field cif_wrdma_active_ch_en; + const struct reg_field cif_wrdma_fs_sel; + const struct reg_field cif_wrdma_fs_delay; + const struct reg_field cif_wrdma_fs_out_gate; + const struct reg_field cif_wrdma_intf_dyncclk; + const struct reg_field cif_wrdma_en_16bit_unpack; + + /* Regmap fields of AIF interface registers bitfields */ + const struct reg_field aif_inv_sync; + const struct reg_field aif_sync_delay; + const struct reg_field aif_sync_mode; + const struct reg_field aif_sync_src; + const struct reg_field aif_sample_width_rx; + const struct reg_field aif_sample_width_tx; + const struct reg_field aif_slot_width_rx; + const struct reg_field aif_slot_width_tx; + const struct reg_field aif_bits_per_lane; + const struct reg_field aif_slot_en_tx_mask; + const struct reg_field aif_slot_en_rx_mask; + const struct reg_field aif_loopback_en; + const struct reg_field aif_ctrl_data_oe; + const struct reg_field aif_lane_en; + const struct reg_field aif_lane_dir; + const struct reg_field aif_mono_mode_rx; + const struct reg_field aif_mono_mode_tx; + const struct reg_field aif_full_cycle_en; + + /* Regmap fields of DMACTL registers bitfields */ + struct qaif_dmactl *aif_rd_dmactl; + struct qaif_dmactl *aif_wr_dmactl; + + /* Regmap fields of CODEC DMA CTRL registers */ + struct qaif_dmactl *cif_rd_dmactl; + struct qaif_dmactl *cif_wr_dmactl; + + struct qaif_aif_config aif_intf_cfg[QAIF_MAX_AIF_CFG_CNT]; + struct qaif_aud_intfctl *aif_intfctl; + + struct qaif_cdc_intfctl *cif_rddma_intfctl; + struct qaif_cdc_intfctl *cif_wrdma_intfctl; + + /* Platform-specific data */ + const char **clk_name; + int num_clks; + struct snd_soc_dai_driver *dai_driver; + int num_dai; + const char **dai_osr_clk_names; + const char **dai_bit_clk_names; + + /* Platform-specific function pointers */ + int (*init)(struct platform_device *pdev); + int (*exit)(struct platform_device *pdev); + int (*alloc_stream_dma_idx)(struct qaif_drv_data *data, int direction, unsigned int dai_id); + int (*free_stream_dma_idx)(struct qaif_drv_data *data, int chan, unsigned int dai_id); + int (*get_dma_idx)(unsigned int dai_id); + +}; + +/* External DAI ops structures defined in qaif-cpu.c */ +extern const struct snd_soc_dai_ops asoc_qcom_qaif_cif_dai_ops; +extern const struct snd_soc_dai_ops asoc_qcom_qaif_aif_cpu_dai_ops; + +/* Platform driver functions defined in qaif-cpu.c */ +int asoc_qcom_qaif_cpu_platform_probe(struct platform_device *pdev); +int asoc_qcom_qaif_platform_register(struct platform_device *pdev); +void asoc_qcom_qaif_cpu_platform_remove(struct platform_device *pdev); +void asoc_qcom_qaif_cpu_platform_shutdown(struct platform_device *pdev); + +#endif /* __QAIF_H__ */ diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index e6e9eb2e85aa1..b4b082ba87b93 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -152,6 +152,13 @@ struct apm_i2s_module_intf_cfg { #define APM_I2S_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_i2s_module_intf_cfg), 8) +struct apm_audio_if_module_intf_cfg { + struct apm_module_param_data param_data; + struct param_id_audio_if_intf_cfg cfg; +} __packed; + +#define APM_AUDIO_IF_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_audio_if_module_intf_cfg), 8) + struct apm_module_hw_ep_mf_cfg { struct apm_module_param_data param_data; struct param_id_hw_ep_mf mf; @@ -168,6 +175,13 @@ struct apm_module_frame_size_factor_cfg { #define APM_FS_CFG_PSIZE ALIGN(sizeof(struct apm_module_frame_size_factor_cfg), 8) +struct apm_module_hw_ep_frame_duration_cfg { + struct apm_module_param_data param_data; + struct param_id_hw_ep_frame_duration frame_duration; +} __packed; + +#define APM_HW_EP_FRAME_DURATION_PSIZE ALIGN(sizeof(struct apm_module_hw_ep_frame_duration_cfg), 8) + struct apm_module_hw_ep_power_mode_cfg { struct apm_module_param_data param_data; struct param_id_hw_ep_power_mode_cfg power_mode; @@ -227,8 +241,9 @@ struct apm_module_sp_vi_channel_map_cfg { sizeof(struct apm_module_sp_vi_channel_map_cfg) + \ (ch) * sizeof(uint32_t), 8) -static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr) +static void *__audioreach_alloc_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain, + bool has_cmd_hdr) { struct gpr_pkt *pkt; void *p; @@ -248,7 +263,10 @@ static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t pkt->hdr.dest_port = dest_port; pkt->hdr.src_port = src_port; - pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + if (!dest_domain) + dest_domain = GPR_DOMAIN_ID_ADSP; + + pkt->hdr.dest_domain = dest_domain; pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt->hdr.token = token; pkt->hdr.opcode = opcode; @@ -264,31 +282,35 @@ static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t return pkt; } -void *audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port) +void *audioreach_alloc_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain) { - return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, false); + return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, + dest_domain, false); } EXPORT_SYMBOL_GPL(audioreach_alloc_pkt); -void *audioreach_alloc_apm_pkt(int pkt_size, uint32_t opcode, uint32_t token, uint32_t src_port) +void *audioreach_alloc_apm_pkt(int pkt_size, u32 opcode, u32 token, + u32 src_port, u16 dest_domain) { return __audioreach_alloc_pkt(pkt_size, opcode, token, src_port, APM_MODULE_INSTANCE_ID, - false); + dest_domain, false); } EXPORT_SYMBOL_GPL(audioreach_alloc_apm_pkt); -void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port) +void *audioreach_alloc_cmd_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain) { - return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, true); + return __audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, + dest_domain, true); } EXPORT_SYMBOL_GPL(audioreach_alloc_cmd_pkt); -void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token) +void *audioreach_alloc_apm_cmd_pkt(int pkt_size, u32 opcode, u32 token, + u16 dest_domain) { return __audioreach_alloc_pkt(pkt_size, opcode, token, GPR_APM_MODULE_IID, - APM_MODULE_INSTANCE_ID, true); + APM_MODULE_INSTANCE_ID, dest_domain, true); } EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt); @@ -485,6 +507,7 @@ void *audioreach_alloc_graph_pkt(struct q6apm *apm, int num_sub_graphs = 0; int num_modules = 0; int num_modules_list; + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); struct gpr_pkt *pkt; void *p; @@ -519,7 +542,8 @@ void *audioreach_alloc_graph_pkt(struct q6apm *apm, mc_sz = APM_MOD_CONN_PSIZE(mcon, num_connections); payload_size = sg_sz + cont_sz + ml_sz + mp_sz + mc_sz; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_GRAPH_OPEN, 0); + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_GRAPH_OPEN, 0, + dest_domain); if (IS_ERR(pkt)) return pkt; @@ -645,7 +669,10 @@ static int audioreach_display_port_set_media_format(struct q6apm_graph *graph, int size = ic_sz + ep_sz + fs_sz; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -704,7 +731,10 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph, int size = ic_sz + ep_sz + fs_sz + pm_sz; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -764,7 +794,10 @@ int audioreach_send_u32_param(struct q6apm_graph *graph, int payload_size = sizeof(uint32_t) + APM_MODULE_PARAM_DATA_SIZE; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return -ENOMEM; @@ -820,7 +853,10 @@ static int audioreach_set_module_config(struct q6apm_graph *graph, int size = le32_to_cpu(module->data->size); void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -843,7 +879,10 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, int i; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -958,9 +997,12 @@ int audioreach_compr_set_param(struct q6apm_graph *graph, int iid = graph->shm_iid; int payload_size = sizeof(struct apm_sh_module_media_fmt_cmd); - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size, - DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT, - 0, graph->port->id, iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_cmd_pkt(payload_size, + DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT, + 0, graph->port->id, iid, + dest_domain); if (IS_ERR(pkt)) return -ENOMEM; @@ -988,7 +1030,10 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, int size = ic_sz + ep_sz + fs_sz; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1042,6 +1087,82 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, return q6apm_send_cmd_sync(graph->apm, pkt, 0); } +static int audioreach_audio_if_set_media_format(struct q6apm_graph *graph, + const struct audioreach_module *module, + const struct audioreach_module_config *cfg) +{ + struct apm_module_hw_ep_frame_duration_cfg *fd_cfg; + struct apm_module_param_data *param_data; + struct apm_audio_if_module_intf_cfg *intf_cfg; + struct apm_module_hw_ep_mf_cfg *hw_cfg; + int ic_sz = APM_AUDIO_IF_INTF_CFG_PSIZE; + int ep_sz = APM_HW_EP_CFG_PSIZE; + int fd_sz = APM_HW_EP_FRAME_DURATION_PSIZE; + int size = ic_sz + ep_sz + fd_sz; + u32 slot_mask = cfg->slot_mask ? cfg->slot_mask : module->slot_mask; + u16 nslots_per_frame = cfg->nslots_per_frame ? + (u16)cfg->nslots_per_frame : module->nslots_per_frame; + u16 slot_width = cfg->slot_width ? (u16)cfg->slot_width : module->slot_width; + void *p; + + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + if (IS_ERR(pkt)) + return PTR_ERR(pkt); + + p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; + intf_cfg = p; + + param_data = &intf_cfg->param_data; + param_data->module_instance_id = module->instance_id; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_AUDIO_IF_INTF_CFG; + param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE; + + intf_cfg->cfg.qaif_type = module->qaif_type; + intf_cfg->cfg.intf_idx = (u16)module->hw_interface_idx; + intf_cfg->cfg.intf_mode = module->intf_mode; + intf_cfg->cfg.ctrl_data_out_enable = module->ctrl_data_out_enable; + intf_cfg->cfg.active_slot_mask = slot_mask; + intf_cfg->cfg.nslots_per_frame = nslots_per_frame; + intf_cfg->cfg.slot_width = slot_width; + intf_cfg->cfg.active_lane_mask = module->active_lane_mask; + intf_cfg->cfg.frame_sync_rate = module->frame_sync_rate; + intf_cfg->cfg.frame_sync_src = module->sync_src; + intf_cfg->cfg.frame_sync_mode = module->sync_mode; + intf_cfg->cfg.invert_frame_sync_pulse = module->ctrl_invert_sync_pulse; + intf_cfg->cfg.frame_sync_data_delay = module->ctrl_sync_data_delay; + intf_cfg->cfg.bit_clk_type = module->bit_clk_type; + intf_cfg->cfg.inv_int_bit_clk = module->inv_int_bit_clk; + intf_cfg->cfg.inv_ext_bit_clk = module->inv_ext_bit_clk; + + p += ic_sz; + hw_cfg = p; + param_data = &hw_cfg->param_data; + param_data->module_instance_id = module->instance_id; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_HW_EP_MF_CFG; + param_data->param_size = ep_sz - APM_MODULE_PARAM_DATA_SIZE; + + hw_cfg->mf.sample_rate = cfg->sample_rate; + hw_cfg->mf.bit_width = cfg->bit_width; + hw_cfg->mf.num_channels = cfg->num_channels; + hw_cfg->mf.data_format = module->data_format; + + p += ep_sz; + fd_cfg = p; + param_data = &fd_cfg->param_data; + param_data->module_instance_id = module->instance_id; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_HW_EP_FRAME_DURATION; + param_data->param_size = fd_sz - APM_MODULE_PARAM_DATA_SIZE; + fd_cfg->frame_duration.frame_duration_in_us = AUDIO_IF_FRAME_DURATION_US; + fd_cfg->frame_duration.allow_frame_duration_normalization = 1; + fd_cfg->frame_duration.min_normalized_frame_dur_us = 1; + fd_cfg->frame_duration.max_normalized_frame_dur_us = 100000; + + return q6apm_send_cmd_sync(graph->apm, pkt, 0); +} + static int audioreach_logging_set_media_format(struct q6apm_graph *graph, const struct audioreach_module *module) { @@ -1050,7 +1171,10 @@ static int audioreach_logging_set_media_format(struct q6apm_graph *graph, int size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1088,8 +1212,10 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, payload_size = APM_PCM_MODULE_FMT_CMD_PSIZE(num_channels); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1131,8 +1257,10 @@ int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int nu payload_size = sizeof(*event) + sizeof(*level) + num_levels * sizeof(uint32_t); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + pkt = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_REGISTER_MODULE_EVENTS, 0, - graph->port->id, graph->shm_iid); + graph->port->id, graph->shm_iid, dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1172,9 +1300,11 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, payload_size = APM_SHMEM_FMT_CFG_PSIZE(num_channels) + APM_MODULE_PARAM_DATA_SIZE; + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, - graph->port->id, module->instance_id); + graph->port->id, module->instance_id, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1219,7 +1349,10 @@ int audioreach_gain_set_vol_ctrl(struct q6apm *apm, struct apm_module_param_data *param_data; int size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; void *p; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1244,7 +1377,10 @@ static int audioreach_gain_set(struct q6apm_graph *graph, struct apm_module_param_data *param_data; struct apm_gain_module_cfg *cfg; int size = APM_GAIN_CFG_PSIZE; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1280,6 +1416,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, int op_sz, cm_sz, ex_sz; struct apm_module_param_data *param_data; int rc, i, payload_size; + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); struct gpr_pkt *pkt; void *p; @@ -1295,7 +1432,8 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, payload_size = op_sz + cm_sz + ex_sz; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1377,6 +1515,10 @@ int audioreach_set_media_format(struct q6apm_graph *graph, case MODULE_ID_I2S_SINK: rc = audioreach_i2s_set_media_format(graph, module, cfg); break; + case MODULE_ID_AUDIO_IF_SOURCE: + case MODULE_ID_AUDIO_IF_SINK: + rc = audioreach_audio_if_set_media_format(graph, module, cfg); + break; case MODULE_ID_WR_SHARED_MEM_EP: case MODULE_ID_SH_MEM_PULL_MODE: rc = audioreach_shmem_set_media_format(graph, module, cfg); @@ -1449,7 +1591,8 @@ int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys, void *p; payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0, dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1480,8 +1623,12 @@ int audioreach_shared_memory_send_eos(struct q6apm_graph *graph) { struct data_cmd_wr_sh_mem_ep_eos *eos; int iid = graph->shm_iid; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*eos), - DATA_CMD_WR_SH_MEM_EP_EOS, 0, graph->port->id, iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_cmd_pkt(sizeof(*eos), + DATA_CMD_WR_SH_MEM_EP_EOS, 0, + graph->port->id, iid, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 62a2fd79bbcb9..79c28bbe1a690 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -2,6 +2,7 @@ #ifndef __AUDIOREACH_H__ #define __AUDIOREACH_H__ +#include #include #include #include @@ -22,6 +23,8 @@ struct q6apm_graph; #define MODULE_ID_PLACEHOLDER_DECODER 0x07001009 #define MODULE_ID_I2S_SINK 0x0700100A #define MODULE_ID_I2S_SOURCE 0x0700100B +#define MODULE_ID_AUDIO_IF_SINK 0x0700117C +#define MODULE_ID_AUDIO_IF_SOURCE 0x0700117D #define MODULE_ID_SAL 0x07001010 #define MODULE_ID_MFC 0x07001015 #define MODULE_ID_DATA_LOGGING 0x0700101A @@ -544,6 +547,41 @@ struct param_id_i2s_intf_cfg { #define PORT_ID_I2S_OUPUT 1 #define I2S_STACK_SIZE 2048 +#define PARAM_ID_AUDIO_IF_INTF_CFG 0x08001B11 + +#define AUDIO_IF_INTF_MODE_TDM 0x0 +#define AUDIO_IF_INTF_MODE_PCM 0x1 +#define AUDIO_IF_INTF_MODE_I2S 0x2 + +struct param_id_audio_if_intf_cfg { + u16 qaif_type; + u16 intf_idx; + u16 intf_mode; + u16 ctrl_data_out_enable; + u32 active_slot_mask; + u16 nslots_per_frame; + u16 slot_width; + u32 active_lane_mask; + u32 frame_sync_rate; + u16 frame_sync_src; + u16 frame_sync_mode; + u16 invert_frame_sync_pulse; + u16 frame_sync_data_delay; + u16 bit_clk_type; + u8 inv_int_bit_clk; + u8 inv_ext_bit_clk; +} __packed; + +#define PARAM_ID_HW_EP_FRAME_DURATION 0x08001B2F +#define AUDIO_IF_FRAME_DURATION_US 1000 + +struct param_id_hw_ep_frame_duration { + u32 frame_duration_in_us; + u32 allow_frame_duration_normalization; + u32 min_normalized_frame_dur_us; + u32 max_normalized_frame_dur_us; +} __packed; + #define PARAM_ID_DISPLAY_PORT_INTF_CFG 0x08001154 struct param_id_display_port_intf_cfg { @@ -877,6 +915,23 @@ struct audioreach_module { uint32_t data_format; uint32_t hw_interface_type; + /* Audio IF module (TDM/PCM/I2S) */ + u16 qaif_type; + u16 sync_src; + u16 ctrl_data_out_enable; + u32 slot_mask; + u16 nslots_per_frame; + u16 slot_width; + u32 active_lane_mask; + u32 frame_sync_rate; + u16 intf_mode; + u16 sync_mode; + u16 ctrl_invert_sync_pulse; + u16 ctrl_sync_data_delay; + u16 bit_clk_type; + u8 inv_int_bit_clk; + u8 inv_ext_bit_clk; + /* PCM module specific */ uint32_t interleave_type; @@ -907,22 +962,28 @@ struct audioreach_module_config { u32 channel_allocation; u32 sd_line_mask; int fmt; + u32 slot_mask; + u16 nslots_per_frame; + u16 slot_width; struct snd_codec codec; u8 channel_map[AR_PCM_MAX_NUM_CHANNEL]; }; /* Packet Allocation routines */ -void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t - token); +static inline u16 audioreach_gpr_dest_domain(gpr_device_t *gdev) +{ + return gdev && gdev->domain_id ? gdev->domain_id : GPR_DOMAIN_ID_ADSP; +} + +void *audioreach_alloc_apm_cmd_pkt(int pkt_size, u32 opcode, u32 token, + u16 dest_domain); void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels); -void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, - uint32_t token, uint32_t src_port, - uint32_t dest_port); -void *audioreach_alloc_apm_pkt(int pkt_size, uint32_t opcode, uint32_t token, - uint32_t src_port); -void *audioreach_alloc_pkt(int payload_size, uint32_t opcode, - uint32_t token, uint32_t src_port, - uint32_t dest_port); +void *audioreach_alloc_cmd_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain); +void *audioreach_alloc_apm_pkt(int pkt_size, u32 opcode, u32 token, + u32 src_port, u16 dest_domain); +void *audioreach_alloc_pkt(int payload_size, u32 opcode, u32 token, + u32 src_port, u32 dest_port, u16 dest_domain); void *audioreach_alloc_graph_pkt(struct q6apm *apm, const struct audioreach_graph_info *info); /* Topology specific */ diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index bf1f872a09f45..ed4c2013dc3bf 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -1,20 +1,23 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2021, Linaro Limited -#include +#include #include +#include +#include +#include #include #include +#include #include #include -#include -#include #include -#include #include #include -#include +#include #include +#include +#include #include "q6apm.h" #define DRV_NAME "q6apm-dai" @@ -34,6 +37,11 @@ #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024) #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) +#define Q6APM_MAX_VMIDS 8 +#define Q6APM_RESERVED_BUFFER_BYTES_MAX (256 * 1024) +#define Q6APM_SCM_MAX_VMID QCOM_SCM_VMID_ADSP_HEAP +#define Q6APM_STATIC_AUDIO_CARVEOUT_ADDR 0x86200000ULL +#define Q6APM_STATIC_AUDIO_CARVEOUT_SIZE 0x40000 #define SID_MASK_DEFAULT 0xF static const struct snd_compr_codec_caps q6apm_compr_caps = { @@ -67,16 +75,22 @@ struct q6apm_dai_rtd { uint32_t last_pos_index; phys_addr_t phys; phys_addr_t pos_phys; + phys_addr_t dma_addr; + bool dma_addr_valid; unsigned int pcm_size; unsigned int push_pull_size; unsigned int pcm_count; unsigned int periods; + size_t scm_size; uint64_t bytes_sent; uint64_t bytes_received; uint64_t copied_total; uint16_t bits_per_sample; snd_pcm_uframes_t queue_ptr; bool next_track; + bool scm_assigned; + bool memory_mapped; + u64 scm_src_perms; enum stream_state state; struct q6apm_graph *graph; spinlock_t lock; @@ -84,9 +98,362 @@ struct q6apm_dai_rtd { }; struct q6apm_dai_data { + struct device *dev; long long sid; + int num_vmids; + u32 vmids[Q6APM_MAX_VMIDS]; + u32 src_vmid; + bool use_scm_assign; + bool use_reserved_mem; + bool reserved_mem_assigned; + phys_addr_t reserved_mem_addr; + size_t reserved_mem_size; + bool aux_mem_assigned; + phys_addr_t aux_mem_addr; + size_t aux_mem_size; + size_t buffer_bytes_max; + u64 reserved_mem_src_perms; + u64 aux_mem_src_perms; }; +static int q6apm_dai_assign_memory(struct q6apm_dai_rtd *prtd, + const struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm *dst_vmids; + phys_addr_t aligned_addr; + size_t aligned_size; + phys_addr_t addr; + size_t offset; + int dst_count = 0; + int ret; + int i; + struct device *dev = prtd->substream->pcm->card->dev; + + if (!pdata->use_scm_assign || pdata->use_reserved_mem || + pdata->num_vmids <= 0 || prtd->scm_assigned) + return 0; + + /* hw_params() validates and sets dma_addr_valid before prepare(). */ + if (!prtd->dma_addr_valid || !prtd->pcm_size) { + dev_err(dev, + "SCM assign: buffer not ready (dma_addr_valid=%d pcm_size=%u)\n", + prtd->dma_addr_valid, prtd->pcm_size); + return -EINVAL; + } + + dst_vmids = kcalloc(pdata->num_vmids + 1, sizeof(*dst_vmids), GFP_KERNEL); + if (!dst_vmids) + return -ENOMEM; + + /* Always keep HLOS RW so CPU can continue buffer access. */ + dst_vmids[dst_count].vmid = QCOM_SCM_VMID_HLOS; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + + for (i = 0; i < pdata->num_vmids; i++) { + /* HLOS is already added above; skip it if listed in qcom,vmid. */ + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) + continue; + + dst_vmids[dst_count].vmid = pdata->vmids[i]; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + } + + /* Nothing to assign beyond HLOS access. */ + if (dst_count == 1) { + kfree(dst_vmids); + return 0; + } + + addr = prtd->dma_addr; + aligned_addr = ALIGN_DOWN(addr, PAGE_SIZE); + offset = addr - aligned_addr; + aligned_size = PAGE_ALIGN(prtd->pcm_size + offset); + + prtd->scm_size = aligned_size; + prtd->scm_src_perms = BIT_ULL(pdata->src_vmid); + + dev_dbg(dev, + "SCM assign: addr=%pa size=%zu src_vmid=0x%x dst_count=%d\n", + &aligned_addr, prtd->scm_size, pdata->src_vmid, dst_count); + for (i = 0; i < dst_count; i++) + dev_dbg(dev, "SCM assign: dst[%d] vmid=0x%x perm=0x%x\n", + i, dst_vmids[i].vmid, dst_vmids[i].perm); + + ret = qcom_scm_assign_mem(aligned_addr, prtd->scm_size, + &prtd->scm_src_perms, dst_vmids, dst_count); + kfree(dst_vmids); + if (ret) { + dev_err(dev, + "SCM assign failed: addr=%pa size=%zu src_vmid=0x%x ret=%d\n", + &aligned_addr, prtd->scm_size, pdata->src_vmid, ret); + return ret; + } + + dev_dbg(dev, + "SCM assign ok: addr=%pa size=%zu src_perms_after=0x%llx\n", + &aligned_addr, prtd->scm_size, prtd->scm_src_perms); + prtd->scm_assigned = true; + return 0; +} + +static int q6apm_dai_unassign_memory(struct q6apm_dai_rtd *prtd, + const struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + struct device *dev = prtd->substream->pcm->card->dev; + phys_addr_t aligned_addr; + size_t aligned_size; + phys_addr_t addr; + size_t offset; + int ret; + + if (!pdata->use_scm_assign || !prtd->scm_assigned) + return 0; + + addr = prtd->dma_addr; + aligned_addr = ALIGN_DOWN(addr, PAGE_SIZE); + offset = addr - aligned_addr; + aligned_size = PAGE_ALIGN(prtd->pcm_size + offset); + + dev_dbg(dev, + "SCM unassign: addr=%pa size=%zu src_perms=0x%llx\n", + &aligned_addr, aligned_size, prtd->scm_src_perms); + + ret = qcom_scm_assign_mem(aligned_addr, aligned_size, + &prtd->scm_src_perms, &hlos, 1); + if (!ret) { + prtd->scm_assigned = false; + prtd->scm_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "SCM unassign ok: addr=%pa\n", &aligned_addr); + } else { + dev_err(dev, "Failed to unassign DMA buffer %pa from VMIDs: %d\n", + &prtd->dma_addr, ret); + dev_err(dev, + "SCM unassign failed: addr=%pa size=%zu src_perms=0x%llx ret=%d\n", + &aligned_addr, aligned_size, prtd->scm_src_perms, ret); + } + + return ret; +} + +static int q6apm_dai_assign_reserved_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm *dst_vmids; + struct device *dev = pdata->dev; + int dst_count = 0; + int ret; + int i; + + if (!pdata->use_reserved_mem || !pdata->use_scm_assign || + pdata->reserved_mem_assigned) + return 0; + + dst_vmids = kcalloc(pdata->num_vmids + 1, sizeof(*dst_vmids), GFP_KERNEL); + if (!dst_vmids) + return -ENOMEM; + + dst_vmids[dst_count].vmid = QCOM_SCM_VMID_HLOS; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + + for (i = 0; i < pdata->num_vmids; i++) { + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) + continue; + + dst_vmids[dst_count].vmid = pdata->vmids[i]; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + } + if (dst_count == 1) { + kfree(dst_vmids); + return 0; + } + + pdata->reserved_mem_src_perms = BIT_ULL(pdata->src_vmid); + + dev_dbg(dev, + "SCM reserved assign begin: addr=%pa size=%zu src_vmid=0x%x dst_count=%d already_assigned=%d\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->src_vmid, dst_count, pdata->reserved_mem_assigned); + for (i = 0; i < dst_count; i++) + dev_dbg(dev, "SCM reserved assign dst[%d]: vmid=0x%x perm=0x%x\n", + i, dst_vmids[i].vmid, dst_vmids[i].perm); + + ret = qcom_scm_assign_mem(pdata->reserved_mem_addr, + pdata->reserved_mem_size, + &pdata->reserved_mem_src_perms, + dst_vmids, dst_count); + if (ret) { + dev_err(dev, + "SCM reserved assign failed: addr=%pa size=%zu src_vmid=0x%x ret=%d\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->src_vmid, ret); + } else { + pdata->reserved_mem_assigned = true; + dev_dbg(dev, + "SCM reserved assign ok: addr=%pa size=%zu src_perms_after=0x%llx\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->reserved_mem_src_perms); + } + + kfree(dst_vmids); + return ret; +} + +static int q6apm_dai_assign_aux_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm *dst_vmids; + struct device *dev = pdata->dev; + int dst_count = 0; + int ret; + int i; + + if (!pdata->use_scm_assign || pdata->aux_mem_assigned || + !pdata->aux_mem_addr || !pdata->aux_mem_size) + return 0; + + dst_vmids = kcalloc(pdata->num_vmids + 1, sizeof(*dst_vmids), GFP_KERNEL); + if (!dst_vmids) + return -ENOMEM; + + dst_vmids[dst_count].vmid = QCOM_SCM_VMID_HLOS; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + + for (i = 0; i < pdata->num_vmids; i++) { + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) + continue; + + dst_vmids[dst_count].vmid = pdata->vmids[i]; + dst_vmids[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + } + if (dst_count == 1) { + kfree(dst_vmids); + return 0; + } + + pdata->aux_mem_src_perms = BIT_ULL(pdata->src_vmid); + + dev_dbg(dev, + "SCM aux assign begin: addr=%pa size=%zu src_vmid=0x%x dst_count=%d already_assigned=%d\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->src_vmid, dst_count, pdata->aux_mem_assigned); + for (i = 0; i < dst_count; i++) + dev_dbg(dev, "SCM aux assign dst[%d]: vmid=0x%x perm=0x%x\n", + i, dst_vmids[i].vmid, dst_vmids[i].perm); + + ret = qcom_scm_assign_mem(pdata->aux_mem_addr, pdata->aux_mem_size, + &pdata->aux_mem_src_perms, dst_vmids, dst_count); + if (ret) { + dev_err(dev, + "SCM aux assign failed: addr=%pa size=%zu src_vmid=0x%x ret=%d\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->src_vmid, ret); + } else { + pdata->aux_mem_assigned = true; + dev_dbg(dev, + "SCM aux assign ok: addr=%pa size=%zu src_perms_after=0x%llx\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->aux_mem_src_perms); + } + + kfree(dst_vmids); + return ret; +} + +static int q6apm_dai_unassign_reserved_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + struct device *dev = pdata->dev; + int ret; + + if (!pdata->use_reserved_mem || !pdata->reserved_mem_assigned) { + dev_dbg(dev, + "SCM reserved unassign skipped: use_reserved=%d assigned=%d\n", + pdata->use_reserved_mem, pdata->reserved_mem_assigned); + return 0; + } + + dev_dbg(dev, + "SCM reserved unassign begin: addr=%pa size=%zu src_perms=0x%llx\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->reserved_mem_src_perms); + + ret = qcom_scm_assign_mem(pdata->reserved_mem_addr, + pdata->reserved_mem_size, + &pdata->reserved_mem_src_perms, &hlos, 1); + if (ret) { + dev_err(dev, + "SCM reserved unassign failed: addr=%pa size=%zu src_perms=0x%llx ret=%d\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->reserved_mem_src_perms, ret); + return ret; + } + + pdata->reserved_mem_assigned = false; + pdata->reserved_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "SCM reserved unassign ok: addr=%pa\n", + &pdata->reserved_mem_addr); + + return 0; +} + +static int q6apm_dai_unassign_aux_memory(struct q6apm_dai_data *pdata) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + struct device *dev = pdata->dev; + int ret; + + if (!pdata->aux_mem_assigned) { + dev_dbg(dev, "SCM aux unassign skipped: assigned=%d\n", + pdata->aux_mem_assigned); + return 0; + } + + dev_dbg(dev, + "SCM aux unassign begin: addr=%pa size=%zu src_perms=0x%llx\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->aux_mem_src_perms); + + ret = qcom_scm_assign_mem(pdata->aux_mem_addr, pdata->aux_mem_size, + &pdata->aux_mem_src_perms, &hlos, 1); + if (ret) { + dev_err(dev, + "SCM aux unassign failed: addr=%pa size=%zu src_perms=0x%llx ret=%d\n", + &pdata->aux_mem_addr, pdata->aux_mem_size, + pdata->aux_mem_src_perms, ret); + return ret; + } + + pdata->aux_mem_assigned = false; + pdata->aux_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "SCM aux unassign ok: addr=%pa\n", + &pdata->aux_mem_addr); + + return 0; +} + +static void q6apm_dai_release_reserved_memory(void *data) +{ + struct q6apm_dai_data *pdata = data; + + q6apm_dai_unassign_aux_memory(pdata); + q6apm_dai_unassign_reserved_memory(pdata); + of_reserved_mem_device_release(pdata->dev); +} + static const struct snd_pcm_hardware q6apm_dai_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | @@ -155,7 +522,7 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void * } static void event_handler_compr(uint32_t opcode, uint32_t token, - void *payload, void *priv) + void *payload, void *priv) { struct q6apm_dai_rtd *prtd = priv; struct snd_compr_stream *substream = prtd->cstream; @@ -211,14 +578,23 @@ static void event_handler_compr(uint32_t opcode, uint32_t token, } } +static int q6apm_dai_memory_unmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream); + +static int q6apm_dai_memory_map(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + int graph_id, bool is_push_pull, size_t size); + static int q6apm_dai_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream) + struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; struct audioreach_module_config cfg; struct device *dev = component->dev; + bool reserved_mapped_now = false; struct q6apm_dai_data *pdata; + bool assigned_now = false; int ret; pdata = snd_soc_component_get_drvdata(component); @@ -226,10 +602,49 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, return -EINVAL; if (!prtd || !prtd->graph) { - dev_err(dev, "%s: private data null or audio client freed\n", __func__); + dev_err(dev, "private data null or audio client freed\n"); return -EINVAL; } + if (pdata->use_reserved_mem && !prtd->memory_mapped) { + dev_dbg(dev, + "reserved prepare entry: assigned=%d mapped=%d dma=%pa phys=%pa pcm_size=%zu reserved=%pa/%zu graph=%d\n", + pdata->reserved_mem_assigned, prtd->memory_mapped, + &prtd->dma_addr, &prtd->phys, (size_t)prtd->pcm_size, + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + prtd->graph->id); + + ret = q6apm_dai_assign_aux_memory(pdata); + if (ret) { + dev_err(dev, "SCM aux assign failed at prepare: ret=%d\n", + ret); + return ret; + } + + if (!pdata->reserved_mem_assigned) { + ret = q6apm_dai_assign_reserved_memory(pdata); + if (ret) { + dev_err(dev, "SCM reserved assign failed at prepare: ret=%d\n", + ret); + return ret; + } + } + + dev_dbg(dev, + "reserved prepare: dma=%pa phys=%pa size=%zu graph=%d\n", + &prtd->dma_addr, &prtd->phys, (size_t)prtd->pcm_size, + prtd->graph->id); + + ret = q6apm_dai_memory_map(component, substream, + prtd->graph->id, false, prtd->pcm_size); + if (ret) + return ret; + prtd->memory_mapped = true; + reserved_mapped_now = true; + dev_dbg(dev, "reserved prepare map ok: graph=%d\n", + prtd->graph->id); + } + cfg.direction = substream->stream; cfg.sample_rate = runtime->rate; cfg.num_channels = runtime->channels; @@ -244,13 +659,23 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, prtd->last_pos_index = 0; prtd->pcm_count = snd_pcm_lib_period_bytes(substream); + if (!prtd->scm_assigned) { + ret = q6apm_dai_assign_memory(prtd, pdata); + if (ret) { + dev_err(dev, "SCM memory assign failed at prepare: ret=%d\n", + ret); + return ret; + } + assigned_now = prtd->scm_assigned; + } + if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) { if (prtd->pcm_size != prtd->push_pull_size) { ret = q6apm_push_pull_config(prtd->graph, prtd->phys, prtd->pos_phys, prtd->pcm_size); if (ret < 0) { dev_err(dev, "Push/Pull config failed rc = %d\n", ret); - return ret; + goto err_unassign; } ret = q6apm_register_watermark_event(prtd->graph, @@ -258,7 +683,7 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, prtd->periods); if (ret < 0) { dev_err(dev, "WaterMark event config failed rc = %d\n", ret); - return ret; + goto err_unassign; } prtd->push_pull_size = prtd->pcm_size; } @@ -267,34 +692,47 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, (prtd->pcm_size / prtd->periods), prtd->periods); if (ret < 0) { dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); - return ret; + goto err_unassign; } - } + dev_dbg(dev, "media_format_shmem success: graph=%d\n", + prtd->graph->id); + dev_dbg(dev, + "media_format_pcm begin: graph=%d dir=%u rate=%u channels=%u bit_width=%u\n", + prtd->graph->id, cfg.direction, cfg.sample_rate, + cfg.num_channels, cfg.bit_width); ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg); if (ret < 0) { dev_err(dev, "%s: CMD Format block failed\n", __func__); - return ret; + goto err_unassign; } /* rate and channels are sent to audio driver */ ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); if (ret < 0) { dev_err(dev, "Failed to set media format %d\n", ret); - return ret; + goto err_unassign; } + dev_dbg(dev, "alloc_fragments success: graph=%d\n", + prtd->graph->id); + dev_dbg(dev, "graph_prepare begin: graph=%d\n", + prtd->graph->id); ret = q6apm_graph_prepare(prtd->graph); if (ret) { - dev_err(dev, "Failed to prepare Graph %d\n", ret); - return ret; + dev_err(dev, "q6apm_graph_prepare failed ret=%d\n", ret); + goto err_unassign; } + dev_dbg(dev, "graph_prepare success: graph=%d\n", + prtd->graph->id); + dev_dbg(dev, "graph_start begin: graph=%d\n", + prtd->graph->id); ret = q6apm_graph_start(prtd->graph); if (ret) { - dev_err(dev, "Failed to Start Graph %d\n", ret); - return ret; + dev_err(dev, "q6apm_graph_start failed ret=%d\n", ret); + goto err_unassign; } if (!q6apm_is_graph_in_push_pull_mode(prtd->graph)) { if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -309,6 +747,17 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, prtd->state = Q6APM_STREAM_RUNNING; return 0; + +err_unassign: + if (assigned_now) + q6apm_dai_unassign_memory(prtd, pdata); + if (reserved_mapped_now) { + dev_err(dev, "reserved prepare error: unmapping graph after ret=%d\n", ret); + if (!q6apm_dai_memory_unmap(component, substream)) + prtd->memory_mapped = false; + } + + return ret; } static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) @@ -325,7 +774,7 @@ static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_sub for (i = 0; i < avail_periods; i++) { ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP); if (ret < 0) { - dev_err(component->dev, "Error queuing playback buffer %d\n", ret); + dev_err(component->dev, "q6apm_write_async failed ret=%d\n", ret); return ret; } prtd->queue_ptr += runtime->period_size; @@ -379,7 +828,7 @@ static int q6apm_dai_open(struct snd_soc_component *component, pdata = snd_soc_component_get_drvdata(component); if (!pdata) { - dev_err(dev, "Drv data not found ..\n"); + dev_err(dev, "Drv data not found\n"); return -EINVAL; } @@ -391,7 +840,7 @@ static int q6apm_dai_open(struct snd_soc_component *component, prtd->substream = substream; prtd->graph = q6apm_graph_open(dev, event_handler, prtd, graph_id, substream->stream); if (IS_ERR(prtd->graph)) { - dev_err(dev, "%s: Could not allocate memory\n", __func__); + dev_err(dev, "q6apm_graph_open failed stream=%d\n", substream->stream); ret = PTR_ERR(prtd->graph); goto err; } @@ -400,19 +849,22 @@ static int q6apm_dai_open(struct snd_soc_component *component, runtime->hw = q6apm_dai_hardware_playback; else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) runtime->hw = q6apm_dai_hardware_capture; + runtime->hw.buffer_bytes_max = pdata->buffer_bytes_max; /* Ensure that buffer size is a multiple of period size */ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) { - dev_err(dev, "snd_pcm_hw_constraint_integer failed\n"); + dev_err(dev, "snd_pcm_hw_constraint_integer failed ret=%d\n", ret); goto err; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - BUFFER_BYTES_MIN, BUFFER_BYTES_MAX); + BUFFER_BYTES_MIN, + pdata->buffer_bytes_max); if (ret < 0) { - dev_err(dev, "constraint for buffer bytes min max ret = %d\n", ret); + dev_err(dev, "buffer bytes minmax constraint failed ret=%d max=%zu\n", + ret, pdata->buffer_bytes_max); goto err; } } @@ -420,18 +872,21 @@ static int q6apm_dai_open(struct snd_soc_component *component, /* setup 10ms latency to accommodate DSP restrictions */ ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480); if (ret < 0) { - dev_err(dev, "constraint for period bytes step ret = %d\n", ret); + dev_err(dev, "period size step constraint failed ret=%d\n", ret); goto err; } ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480); if (ret < 0) { - dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); + dev_err(dev, "buffer size step constraint failed ret=%d\n", ret); goto err; } runtime->private_data = prtd; - runtime->dma_bytes = BUFFER_BYTES_MAX; + runtime->dma_bytes = pdata->buffer_bytes_max; + prtd->scm_assigned = false; + prtd->dma_addr_valid = false; + prtd->dma_addr = substream->dma_buffer.addr; if (pdata->sid < 0) prtd->phys = substream->dma_buffer.addr; else @@ -456,7 +911,9 @@ static int q6apm_dai_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); struct q6apm_dai_rtd *prtd = runtime->private_data; + int ret; if (prtd->state) { /* only stop graph that is started */ @@ -464,6 +921,27 @@ static int q6apm_dai_close(struct snd_soc_component *component, q6apm_free_fragments(prtd->graph, substream->stream); } + if (prtd->memory_mapped) { + ret = q6apm_dai_memory_unmap(component, substream); + if (ret) + dev_err(component->dev, + "close(): memory unmap failed graph=%d ret=%d\n", + prtd->graph->id, ret); + else + prtd->memory_mapped = false; + } + + if (pdata && prtd->scm_assigned) { + ret = q6apm_dai_unassign_memory(prtd, pdata); + if (ret) { + dev_err(component->dev, + "close(): VMID unassign failed for DMA buffer %pa: %d\n", + &prtd->dma_addr, ret); + WARN_ONCE(1, "q6apm-dai: SCM VMID unassign leak for DMA buffer %pa\n", + &prtd->dma_addr); + } + } + q6apm_graph_close(prtd->graph); prtd->graph = NULL; kfree(prtd); @@ -506,11 +984,40 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component, } static int q6apm_dai_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai; struct q6apm_dai_rtd *prtd = runtime->private_data; + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); + dma_addr_t dma_addr; + int ret; + + if (!pdata) + return -EINVAL; + + if (prtd->scm_assigned) { + ret = q6apm_dai_unassign_memory(prtd, pdata); + if (ret) { + dev_err(component->dev, + "hw_params(): failed to release previous VMID assignment: %d\n", + ret); + return ret; + } + } + + dma_addr = runtime->dma_addr ? runtime->dma_addr : substream->dma_buffer.addr; + if (!dma_addr) + return -ENOMEM; + + prtd->dma_addr = dma_addr; + prtd->dma_addr_valid = true; + if (pdata->sid < 0) + prtd->phys = dma_addr; + else + prtd->phys = dma_addr | (pdata->sid << 32); prtd->pcm_size = params_buffer_bytes(params); prtd->periods = params_periods(params); @@ -526,32 +1033,86 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component, return -EINVAL; } + if (pdata->use_reserved_mem) { + if (!soc_prtd) + return -EINVAL; + + cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0); + if (!cpu_dai) + return -EINVAL; + + dev_dbg(component->dev, + "reserved hw_params: dma=%pad size=%zu periods=%u\n", + &dma_addr, (size_t)prtd->pcm_size, prtd->periods); + } + + return 0; +} + +static int q6apm_dai_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); + struct q6apm_dai_rtd *prtd = substream->runtime->private_data; + int ret; + + if (pdata && prtd->scm_assigned) { + ret = q6apm_dai_unassign_memory(prtd, pdata); + if (ret) + dev_err(component->dev, + "hw_free(): VMID unassign failed for DMA buffer %pa: %d\n", + &prtd->dma_addr, ret); + } + + /* PCM DMA buffer is released by the ALSA managed buffer helpers. */ + prtd->dma_addr_valid = false; + return 0; } static int q6apm_dai_memory_map(struct snd_soc_component *component, struct snd_pcm_substream *substream, - int graph_id, bool is_push_pull) + int graph_id, bool is_push_pull, size_t size) { struct q6apm_dai_data *pdata; struct device *dev = component->dev; + struct snd_pcm_runtime *runtime = substream->runtime; + dma_addr_t dma_addr; phys_addr_t phys; int ret; pdata = snd_soc_component_get_drvdata(component); if (!pdata) { - dev_err(component->dev, "Drv data not found ..\n"); + dev_err(component->dev, "Drv data not found\n"); return -EINVAL; } - if (pdata->sid < 0) - phys = substream->dma_buffer.addr; - else - phys = substream->dma_buffer.addr | (pdata->sid << 32); + if (pdata->use_reserved_mem) { + phys = pdata->reserved_mem_addr; + size = pdata->reserved_mem_size; + dev_dbg(dev, "reserved map begin: phys=%pa size=%zu graph=%d\n", + &phys, size, graph_id); + } else { + if (runtime && runtime->dma_addr) + dma_addr = runtime->dma_addr; + else + dma_addr = substream->dma_buffer.addr; + if (!dma_addr) + return -ENOMEM; - ret = q6apm_map_memory_fixed_region(dev, graph_id, phys, BUFFER_BYTES_MAX); + if (pdata->sid < 0) + phys = dma_addr; + else + phys = dma_addr | (pdata->sid << 32); + } + + ret = q6apm_map_memory_fixed_region(dev, graph_id, phys, size); if (ret < 0) - dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); + dev_err(dev, "q6apm_map_memory_fixed_region failed rc=%d phys=%pa size=%zu graph=%d\n", + ret, &phys, size, graph_id); + else + dev_dbg(dev, "memory map done: phys=%pa size=%zu graph=%d\n", + &phys, size, graph_id); if (is_push_pull) { if (pdata->sid < 0) @@ -573,18 +1134,33 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc { struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_pcm *pcm = rtd->pcm; - /* - * Allocate one extra page as a workaround for a DSP bug where 32-bit - * address arithmetic can overflow when the buffer is placed near the - * end of the addressable range. - */ + struct q6apm_dai_data *pdata = snd_soc_component_get_drvdata(component); int size = BUFFER_BYTES_MAX + PAGE_SIZE; int graph_id, ret; bool is_push_pull; struct snd_pcm_substream *substream = NULL; + if (!pdata) + return -EINVAL; + graph_id = cpu_dai->driver->id; + if (pdata->use_reserved_mem) { + ret = snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, + component->dev, 0, + pdata->buffer_bytes_max); + if (ret) + return ret; + + return 0; + } + + /* + * Allocate one extra page as a workaround for a DSP bug where 32-bit + * address arithmetic can overflow when the buffer is placed near the + * end of the addressable range. + */ + /* Note: DSP backend dais are uni-directional ONLY(either playback or capture) */ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; @@ -603,7 +1179,8 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc if (ret) return ret; - ret = q6apm_dai_memory_map(component, substream, graph_id, is_push_pull); + ret = q6apm_dai_memory_map(component, substream, graph_id, + is_push_pull, BUFFER_BYTES_MAX); if (ret) return ret; } @@ -611,26 +1188,32 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc return 0; } -static void q6apm_dai_memory_unmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream) +static int q6apm_dai_memory_unmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_prtd; struct snd_soc_dai *cpu_dai; int graph_id; + int ret; soc_prtd = snd_soc_substream_to_rtd(substream); if (!soc_prtd) - return; + return -EINVAL; cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0); if (!cpu_dai) - return; + return -EINVAL; graph_id = cpu_dai->driver->id; - q6apm_unmap_memory_fixed_region(component->dev, graph_id); + ret = q6apm_unmap_memory_fixed_region(component->dev, graph_id); + if (ret) + dev_err(component->dev, + "memory unmap failed: graph=%d ret=%d\n", graph_id, ret); if (q6apm_is_graph_in_push_pull_mode_from_id(component->dev, graph_id, substream->stream)) q6apm_unmap_pos_buffer(component->dev, graph_id); + + return ret; } static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm) @@ -638,12 +1221,16 @@ static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_p struct snd_pcm_substream *substream; substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - if (substream) + if (substream) { + dev_dbg(component->dev, "pcm_free(): capture memory unmap\n"); q6apm_dai_memory_unmap(component, substream); + } substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - if (substream) + if (substream) { + dev_dbg(component->dev, "pcm_free(): playback memory unmap\n"); q6apm_dai_memory_unmap(component, substream); + } } static int q6apm_dai_compr_open(struct snd_soc_component *component, @@ -1006,6 +1593,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = { .open = q6apm_dai_open, .close = q6apm_dai_close, .prepare = q6apm_dai_prepare, + .hw_free = q6apm_dai_hw_free, .pcm_new = q6apm_dai_pcm_new, .pcm_free = q6apm_dai_pcm_free, .hw_params = q6apm_dai_hw_params, @@ -1023,17 +1611,136 @@ static int q6apm_dai_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; struct q6apm_dai_data *pdata; struct of_phandle_args args; + struct resource reserved_mem; + size_t required_mem_size = max_t(size_t, BUFFER_BYTES_MIN, + CAPTURE_MIN_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE); + u32 src_vmid; + int vmids; int rc; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; + pdata->dev = dev; + pdata->buffer_bytes_max = BUFFER_BYTES_MAX; + pdata->aux_mem_addr = Q6APM_STATIC_AUDIO_CARVEOUT_ADDR; + pdata->aux_mem_size = Q6APM_STATIC_AUDIO_CARVEOUT_SIZE; + pdata->aux_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, "probe: static aux memory addr=%pa size=%zu\n", + &pdata->aux_mem_addr, pdata->aux_mem_size); rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args); if (rc < 0) pdata->sid = -1; else pdata->sid = args.args[0] & SID_MASK_DEFAULT; + dev_dbg(dev, "probe: sid=%lld iommus_rc=%d\n", pdata->sid, rc); + + if (of_property_present(node, "memory-region")) { + rc = of_reserved_mem_region_to_resource(node, 0, &reserved_mem); + if (rc) { + dev_err(dev, "failed to parse reserved memory region: %d\n", rc); + return rc; + } + + rc = of_reserved_mem_device_init_by_idx(dev, node, 0); + if (rc) { + dev_err(dev, "failed to attach reserved memory region: %d\n", rc); + return rc; + } + + pdata->use_reserved_mem = true; + pdata->reserved_mem_addr = reserved_mem.start; + pdata->reserved_mem_size = resource_size(&reserved_mem); + pdata->buffer_bytes_max = min_t(size_t, pdata->reserved_mem_size / 2, + BUFFER_BYTES_MAX); + pdata->buffer_bytes_max = min_t(size_t, pdata->buffer_bytes_max, + Q6APM_RESERVED_BUFFER_BYTES_MAX); + pdata->reserved_mem_src_perms = BIT_ULL(QCOM_SCM_VMID_HLOS); + dev_dbg(dev, + "probe: reserved memory addr=%pa size=%zu buffer_bytes_max=%zu\n", + &pdata->reserved_mem_addr, pdata->reserved_mem_size, + pdata->buffer_bytes_max); + + rc = devm_add_action_or_reset(dev, + q6apm_dai_release_reserved_memory, pdata); + if (rc) + return rc; + } + + /* + * Default src_vmid to HLOS. Platforms where PCM DMA buffers reside in + * S2-only memory pre-owned by a non-HLOS VMID must override this via + * qcom,src-vmid so qcom_scm_assign_mem() receives the correct srcvm. + */ + pdata->src_vmid = QCOM_SCM_VMID_HLOS; + if (!of_property_read_u32(node, "qcom,src-vmid", &src_vmid)) { + if (src_vmid == 0 || src_vmid > Q6APM_SCM_MAX_VMID) { + dev_err(dev, "qcom,src-vmid=%u out of range [1..%u]\n", + src_vmid, Q6APM_SCM_MAX_VMID); + return -EINVAL; + } + pdata->src_vmid = src_vmid; + dev_dbg(dev, "probe: SCM src_vmid set to 0x%x from DT\n", src_vmid); + } + + vmids = of_property_count_u32_elems(node, "qcom,vmid"); + if (vmids == -EINVAL) { + pdata->num_vmids = 0; + pdata->use_scm_assign = false; + } else if (vmids < 0) { + return vmids; + } else if (vmids == 0) { + dev_err(dev, "qcom,vmid must contain at least one VMID\n"); + return -EINVAL; + } else if (vmids > Q6APM_MAX_VMIDS) { + dev_err(dev, "qcom,vmid: %d VMIDs exceeds maximum of %d\n", + vmids, Q6APM_MAX_VMIDS); + return -EINVAL; + } + + if (vmids > 0) { + int i; + + rc = of_property_read_u32_array(node, "qcom,vmid", + pdata->vmids, vmids); + if (rc) + return rc; + for (i = 0; i < vmids; i++) { + if (pdata->vmids[i] == QCOM_SCM_VMID_HLOS) { + dev_err(dev, "qcom,vmid must not include HLOS VMID (%u)\n", + QCOM_SCM_VMID_HLOS); + return -EINVAL; + } + if (pdata->vmids[i] > Q6APM_SCM_MAX_VMID) { + dev_err(dev, "qcom,vmid[%d]=%u exceeds SCM max VMID %u\n", + i, pdata->vmids[i], Q6APM_SCM_MAX_VMID); + return -EINVAL; + } + } + pdata->num_vmids = vmids; + pdata->use_scm_assign = true; + dev_dbg(dev, "probe: SCM assign enabled src_vmid=0x%x num_dst=%d\n", + pdata->src_vmid, pdata->num_vmids); + for (rc = 0; rc < vmids; rc++) + dev_dbg(dev, "probe: SCM dst vmid[%d]=0x%x\n", rc, + pdata->vmids[rc]); + } + + if (pdata->use_scm_assign && !qcom_scm_is_available()) + return -EPROBE_DEFER; + + if (pdata->use_reserved_mem && pdata->reserved_mem_size < required_mem_size) { + dev_err(dev, "reserved memory size %zu is smaller than required %zu\n", + pdata->reserved_mem_size, required_mem_size); + return -EINVAL; + } + + dev_dbg(dev, + "probe done: use_reserved=%d reserved=%pa/%zu use_scm=%d src_vmid=0x%x num_vmids=%d buffer_bytes_max=%zu\n", + pdata->use_reserved_mem, &pdata->reserved_mem_addr, + pdata->reserved_mem_size, pdata->use_scm_assign, + pdata->src_vmid, pdata->num_vmids, pdata->buffer_bytes_max); dev_set_drvdata(dev, pdata); @@ -1059,3 +1766,4 @@ module_platform_driver(q6apm_dai_platform_driver); MODULE_DESCRIPTION("Q6APM dai driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("DMA_BUF"); diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 006b283484d9e..ff92ac7e522d3 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -2,10 +2,12 @@ // Copyright (c) 2021, Linaro Limited #include +#include #include #include #include #include +#include #include #include #include @@ -15,15 +17,74 @@ #include "q6dsp-common.h" #include "audioreach.h" #include "q6apm.h" +#include "q6prm.h" #define AUDIOREACH_BE_PCM_BASE 16 +struct q6apm_dai_priv_data { + struct clk *mclk; + struct clk *bclk; + struct clk *eclk; + bool mclk_enabled; + bool bclk_enabled; + bool eclk_enabled; +}; + struct q6apm_lpass_dai_data { struct q6apm_graph *graph[APM_PORT_MAX]; bool is_port_started[APM_PORT_MAX]; struct audioreach_module_config module_config[APM_PORT_MAX]; + struct q6apm_dai_priv_data priv[APM_PORT_MAX]; }; +static struct clk *q6apm_lpass_get_child_clk(struct device *dev, struct device_node *node, + const char *name) +{ + struct clk *clk; + + clk = devm_get_clk_from_child(dev, node, name); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) == -EPROBE_DEFER) + return ERR_PTR(dev_err_probe(dev, PTR_ERR(clk), + "unable to get %s\n", name)); + + return NULL; + } + + return clk; +} + +static int of_q6apm_parse_dai_data(struct device *dev, + struct q6apm_lpass_dai_data *data) +{ + struct device_node *node; + + for_each_child_of_node(dev->of_node, node) { + struct q6apm_dai_priv_data *priv; + int ret; + int id; + + ret = of_property_read_u32(node, "reg", &id); + if (ret || id < 0 || id >= APM_PORT_MAX) + continue; + + priv = &data->priv[id]; + priv->mclk = q6apm_lpass_get_child_clk(dev, node, "mclk"); + if (IS_ERR(priv->mclk)) + return PTR_ERR(priv->mclk); + + priv->bclk = q6apm_lpass_get_child_clk(dev, node, "bclk"); + if (IS_ERR(priv->bclk)) + return PTR_ERR(priv->bclk); + + priv->eclk = q6apm_lpass_get_child_clk(dev, node, "eclk"); + if (IS_ERR(priv->eclk)) + return PTR_ERR(priv->eclk); + } + + return 0; +} + static int q6dma_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num, const unsigned int *tx_ch_mask, @@ -159,6 +220,33 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct } } +static void q6lpass_disable_clocks(struct q6apm_dai_priv_data *priv) +{ + if (priv->mclk_enabled) { + clk_disable_unprepare(priv->mclk); + priv->mclk_enabled = false; + } + + if (priv->bclk_enabled) { + clk_disable_unprepare(priv->bclk); + priv->bclk_enabled = false; + } + + if (priv->eclk_enabled) { + clk_disable_unprepare(priv->eclk); + priv->eclk_enabled = false; + } +} + +static void q6lpass_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + + q6lpass_disable_clocks(&dai_data->priv[dai->id]); + q6apm_lpass_dai_shutdown(substream, dai); +} + static int q6apm_lpass_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -202,7 +290,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s * It is recommend to load DSP with source graph first and then sink * graph, so sequence for playback and capture will be different */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !dai_data->graph[dai->id]) { graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id, substream->stream); if (IS_ERR(graph)) { dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id); @@ -261,6 +349,106 @@ static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } +static int q6tdm_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, int slot_width) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; + unsigned int cap_mask; + + if (slot_width != 16 && slot_width != 32) { + dev_err(dai->dev, "%s: invalid slot_width %d\n", + __func__, slot_width); + return -EINVAL; + } + + switch (slots) { + case 2: + cap_mask = 0x03; + break; + case 4: + cap_mask = 0x0f; + break; + case 8: + cap_mask = 0xff; + break; + case 16: + cap_mask = 0xffff; + break; + default: + dev_err(dai->dev, "%s: invalid slots %d\n", + __func__, slots); + return -EINVAL; + } + + switch (dai->id) { + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: + cfg->nslots_per_frame = slots; + cfg->slot_width = slot_width; + cfg->slot_mask = ((dai->id & 0x1) ? tx_mask : rx_mask) & cap_mask; + break; + default: + dev_err(dai->dev, "%s: invalid dai id 0x%x\n", + __func__, dai->id); + return -EINVAL; + } + + return 0; +} + +static int q6i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6apm_dai_priv_data *priv = &dai_data->priv[dai->id]; + struct clk *sysclk = NULL; + bool *enabled = NULL; + int ret; + + switch (clk_id) { + case LPAIF_MI2S_TDM_MCLK: + sysclk = priv->mclk; + enabled = &priv->mclk_enabled; + break; + case LPAIF_MI2S_TDM_BCLK: + sysclk = priv->bclk; + enabled = &priv->bclk_enabled; + break; + case LPAIF_MI2S_TDM_ECLK: + sysclk = priv->eclk; + enabled = &priv->eclk_enabled; + break; + default: + return 0; + } + + if (!sysclk || !freq) + return 0; + + ret = clk_set_rate(sysclk, freq); + if (ret) + return ret; + + if (*enabled) + return 0; + + ret = clk_prepare_enable(sysclk); + if (ret) + return ret; + + *enabled = true; + + return 0; +} + +static int q6lpass_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + return q6i2s_set_sysclk(dai, clk_id, freq, dir); +} + static const struct snd_soc_dai_ops q6dma_ops = { .prepare = q6apm_lpass_dai_prepare, .startup = q6apm_lpass_dai_startup, @@ -273,10 +461,11 @@ static const struct snd_soc_dai_ops q6dma_ops = { static const struct snd_soc_dai_ops q6i2s_ops = { .prepare = q6apm_lpass_dai_prepare, .startup = q6apm_lpass_dai_startup, - .shutdown = q6apm_lpass_dai_shutdown, + .shutdown = q6lpass_dai_shutdown, .set_channel_map = q6dma_set_channel_map, .hw_params = q6dma_hw_params, .set_fmt = q6i2s_set_fmt, + .set_sysclk = q6lpass_set_sysclk, .trigger = q6apm_lpass_dai_trigger, }; @@ -289,6 +478,18 @@ static const struct snd_soc_dai_ops q6hdmi_ops = { .trigger = q6apm_lpass_dai_trigger, }; +static const struct snd_soc_dai_ops q6tdm_ops = { + .prepare = q6apm_lpass_dai_prepare, + .startup = q6apm_lpass_dai_startup, + .shutdown = q6lpass_dai_shutdown, + .set_channel_map = q6dma_set_channel_map, + .set_tdm_slot = q6tdm_set_tdm_slot, + .hw_params = q6dma_hw_params, + .set_fmt = q6i2s_set_fmt, + .set_sysclk = q6lpass_set_sysclk, + .trigger = q6apm_lpass_dai_trigger, +}; + static const struct snd_soc_component_driver q6apm_lpass_dai_component = { .name = "q6apm-be-dai-component", .of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name, @@ -304,17 +505,22 @@ static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev) struct snd_soc_dai_driver *dais; struct device *dev = &pdev->dev; int num_dais; + int ret; dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL); if (!dai_data) return -ENOMEM; dev_set_drvdata(dev, dai_data); + ret = of_q6apm_parse_dai_data(dev, dai_data); + if (ret) + return ret; memset(&cfg, 0, sizeof(cfg)); cfg.q6i2s_ops = &q6i2s_ops; cfg.q6dma_ops = &q6dma_ops; cfg.q6hdmi_ops = &q6hdmi_ops; + cfg.q6tdm_ops = &q6tdm_ops; dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais); return devm_snd_soc_register_component(dev, &q6apm_lpass_dai_component, dais, num_dais); diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 641d6d2432299..99d0f30e31a34 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -102,7 +102,10 @@ static int audioreach_graph_mgmt_cmd(struct audioreach_graph *graph, uint32_t op struct q6apm *apm = graph->apm; int i = 0, payload_size = APM_GRAPH_MGMT_PSIZE(mgmt_cmd, num_sub_graphs); - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, opcode, 0); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, opcode, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -142,8 +145,10 @@ static void q6apm_put_audioreach_graph(struct kref *ref) static int q6apm_get_apm_state(struct q6apm *apm) { - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(0, - APM_CMD_GET_SPF_STATE, 0); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(0, APM_CMD_GET_SPF_STATE, 0, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -216,8 +221,11 @@ static int __q6apm_map_memory_fixed_region(struct device *dev, unsigned int grap uint32_t buf_sz; void *p; uint32_t pos_mask = is_pos_buf ? APM_MMAP_TOKEN_MAP_TYPE_POS_BUF : 0; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, - APM_CMD_SHARED_MEM_MAP_REGIONS, (graph_id | pos_mask)); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(payload_size, + APM_CMD_SHARED_MEM_MAP_REGIONS, + graph_id | pos_mask, dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -326,8 +334,11 @@ static int __q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int gr struct q6apm *apm = dev_get_drvdata(dev->parent); struct audioreach_graph_info *info; uint32_t mem_map_handle; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(sizeof(*cmd), - APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id); + u16 dest_domain = audioreach_gpr_dest_domain(apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_apm_cmd_pkt(sizeof(*cmd), + APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -475,10 +486,14 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts, struct apm_data_cmd_wr_sh_mem_ep_data_buffer_v2 *write_buffer; struct audio_buffer *ab; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*write_buffer), - DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2, - graph->rx_data.dsp_buf | (len << APM_WRITE_TOKEN_LEN_SHIFT), - graph->port->id, graph->shm_iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_pkt(sizeof(*write_buffer), + DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2, + graph->rx_data.dsp_buf | + (len << APM_WRITE_TOKEN_LEN_SHIFT), + graph->port->id, graph->shm_iid, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -512,9 +527,13 @@ int q6apm_read(struct q6apm_graph *graph) struct audioreach_graph_data *port; struct audio_buffer *ab; - struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*read_buffer), - DATA_CMD_RD_SH_MEM_EP_DATA_BUFFER_V2, - graph->tx_data.dsp_buf, graph->port->id, graph->shm_iid); + u16 dest_domain = audioreach_gpr_dest_domain(graph->apm->gdev); + struct gpr_pkt *pkt __free(kfree) = + audioreach_alloc_pkt(sizeof(*read_buffer), + DATA_CMD_RD_SH_MEM_EP_DATA_BUFFER_V2, + graph->tx_data.dsp_buf, + graph->port->id, graph->shm_iid, + dest_domain); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -946,14 +965,13 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op) wake_up(&apm->wait); break; case APM_CMD_SHARED_MEM_UNMAP_REGIONS: - apm->result.opcode = hdr->opcode; - apm->result.status = 0; - rsp = data->payload; + apm->result.opcode = result->opcode; + apm->result.status = result->status; info = idr_find(&apm->graph_info_idr, hdr->token); - if (info) + if (info && !result->status) info->mem_map_handle = 0; - else + else if (!info || result->status) dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status, result->opcode); diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c b/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c index 03838582aeade..7bb4383fcb35a 100644 --- a/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c +++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c @@ -12,7 +12,7 @@ #include #include "q6dsp-lpass-clocks.h" -#define Q6DSP_MAX_CLK_ID 104 +#define Q6DSP_MAX_CLK_ID 132 #define Q6DSP_LPASS_CLK_ROOT_DEFAULT 0 diff --git a/sound/soc/qcom/qdsp6/q6prm-clocks.c b/sound/soc/qcom/qdsp6/q6prm-clocks.c index 4c574b48ab004..b6755da6a6da8 100644 --- a/sound/soc/qcom/qdsp6/q6prm-clocks.c +++ b/sound/soc/qcom/qdsp6/q6prm-clocks.c @@ -42,6 +42,11 @@ static const struct q6dsp_clk_init q6prm_clks[] = { Q6PRM_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT), Q6PRM_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT), Q6PRM_CLK(LPASS_CLK_ID_QUI_MI2S_OSR), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_1), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_2), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_3), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_4), + Q6PRM_CLK(LPASS_CLK_ID_MCLK_5), Q6PRM_CLK(LPASS_CLK_ID_WSA_CORE_MCLK), Q6PRM_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK), Q6PRM_CLK(LPASS_CLK_ID_VA_CORE_MCLK), @@ -59,6 +64,34 @@ static const struct q6dsp_clk_init q6prm_clks[] = { Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_MCLK), Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_2X_MCLK), Q6PRM_CLK(LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_EBIT), Q6DSP_VOTE_CLK(LPASS_HW_MACRO_VOTE, Q6PRM_HW_CORE_ID_LPASS, "LPASS_HW_MACRO"), Q6DSP_VOTE_CLK(LPASS_HW_DCODEC_VOTE, Q6PRM_HW_CORE_ID_DCODEC, diff --git a/sound/soc/qcom/qdsp6/q6prm.c b/sound/soc/qcom/qdsp6/q6prm.c index 04892fb4423fe..15ca51ce33b80 100644 --- a/sound/soc/qcom/qdsp6/q6prm.c +++ b/sound/soc/qcom/qdsp6/q6prm.c @@ -71,8 +71,9 @@ static int q6prm_set_hw_core_req(struct device *dev, uint32_t hw_block_id, bool rsp_opcode = PRM_CMD_RSP_RELEASE_HW_RSC; } - struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_cmd_pkt(sizeof(*req), opcode, 0, gdev->svc.id, GPR_PRM_MODULE_IID); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*req), + opcode, 0, gdev->svc.id, GPR_PRM_MODULE_IID, + audioreach_gpr_dest_domain(gdev)); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -112,9 +113,10 @@ static int q6prm_request_lpass_clock(struct device *dev, int clk_id, int clk_att struct prm_cmd_request_rsc *req; gpr_device_t *gdev = prm->gdev; - struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_cmd_pkt(sizeof(*req), PRM_CMD_REQUEST_HW_RSC, 0, - gdev->svc.id, GPR_PRM_MODULE_IID); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*req), + PRM_CMD_REQUEST_HW_RSC, 0, gdev->svc.id, + GPR_PRM_MODULE_IID, + audioreach_gpr_dest_domain(gdev)); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -144,9 +146,10 @@ static int q6prm_release_lpass_clock(struct device *dev, int clk_id, int clk_att struct prm_cmd_release_rsc *rel; gpr_device_t *gdev = prm->gdev; - struct gpr_pkt *pkt __free(kfree) = - audioreach_alloc_cmd_pkt(sizeof(*rel), PRM_CMD_RELEASE_HW_RSC, 0, - gdev->svc.id, GPR_PRM_MODULE_IID); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*rel), + PRM_CMD_RELEASE_HW_RSC, 0, gdev->svc.id, + GPR_PRM_MODULE_IID, + audioreach_gpr_dest_domain(gdev)); if (IS_ERR(pkt)) return PTR_ERR(pkt); diff --git a/sound/soc/qcom/qdsp6/q6prm.h b/sound/soc/qcom/qdsp6/q6prm.h index a988a32086fe1..a4903990f859a 100644 --- a/sound/soc/qcom/qdsp6/q6prm.h +++ b/sound/soc/qcom/qdsp6/q6prm.h @@ -3,6 +3,14 @@ #ifndef __Q6PRM_H__ #define __Q6PRM_H__ +#define LPAIF_MI2S_TDM_MCLK 1 +#define LPAIF_MI2S_TDM_BCLK 2 +#define LPAIF_MI2S_TDM_ECLK 3 + +#define LPAIF_MI2S_MCLK LPAIF_MI2S_TDM_MCLK +#define LPAIF_MI2S_BCLK LPAIF_MI2S_TDM_BCLK +#define LPAIF_MI2S_ECLK LPAIF_MI2S_TDM_ECLK + /* Clock ID for Primary I2S IBIT */ #define Q6PRM_LPASS_CLK_ID_PRI_MI2S_IBIT 0x100 /* Clock ID for Primary I2S EBIT */ @@ -52,6 +60,17 @@ /* Clock ID for QUINARY MI2S OSR CLK */ #define Q6PRM_LPASS_CLK_ID_QUI_MI2S_OSR 0x116 +/* Clock ID for MCLK1 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_1 0x300 +/* Clock ID for MCLK2 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_2 0x301 +/* Clock ID for MCLK3 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_3 0x302 +/* Clock ID for MCLK4 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_4 0x303 +/* Clock ID for MCLK5 */ +#define Q6PRM_LPASS_CLK_ID_MCLK_5 0x304 + #define Q6PRM_LPASS_CLK_ID_WSA_CORE_MCLK 0x305 #define Q6PRM_LPASS_CLK_ID_WSA_CORE_NPL_MCLK 0x306 @@ -83,6 +102,63 @@ /* Clock ID for RX CORE MCLK2 2X MCLK */ #define Q6PRM_LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK 0x318 +/** Clock ID of the Audio Intf 0 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_IBIT 0x500 +/** Clock ID of the Audio Intf 0 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_EBIT 0x501 +/** Clock ID of the Audio Intf 1 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_IBIT 0x502 +/** Clock ID of the Audio Intf 1 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_EBIT 0x503 +/** Clock ID of the Audio Intf 2 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_IBIT 0x504 +/** Clock ID of the Audio Intf 2 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_EBIT 0x505 +/** Clock ID of the Audio Intf 3 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_IBIT 0x506 +/** Clock ID of the Audio Intf 3 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_EBIT 0x507 +/** Clock ID of the Audio Intf 4 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_IBIT 0x508 +/** Clock ID of the Audio Intf 4 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_EBIT 0x509 +/** Clock ID of the Audio Intf 5 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_IBIT 0x50A +/** Clock ID of the Audio Intf 5 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_EBIT 0x50B +/** Clock ID of the Audio Intf 6 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_IBIT 0x50C +/** Clock ID of the Audio Intf 6 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_EBIT 0x50D +/** Clock ID of the Audio Intf 7 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_IBIT 0x50E +/** Clock ID of the Audio Intf 7 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_EBIT 0x50F +/** Clock ID of the Audio Intf 8 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_IBIT 0x510 +/** Clock ID of the Audio Intf 8 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_EBIT 0x511 +/** Clock ID of the Audio Intf 9 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_IBIT 0x512 +/** Clock ID of the Audio Intf 9 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_EBIT 0x513 +/** Clock ID of the Audio Intf 10 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_IBIT 0x514 +/** Clock ID of the Audio Intf 10 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_EBIT 0x515 +/** Clock ID of the Audio Intf 11 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_IBIT 0x516 +/** Clock ID of the Audio Intf 11 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_EBIT 0x517 +/** Clock ID of the Audio Intf 12 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_IBIT 0x518 +/** Clock ID of the Audio Intf 12 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_EBIT 0x519 +/** Clock ID of the Audio VA Intf 0 internal bit clock (IBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_IBIT 0x550 +/** Clock ID of the Audio VA Intf 0 external bit clock (EBIT). */ +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_EBIT 0x551 + #define Q6PRM_LPASS_CLK_SRC_INTERNAL 1 #define Q6PRM_LPASS_CLK_ROOT_DEFAULT 0 #define Q6PRM_HW_CORE_ID_LPASS 1 diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c index 1f69fba6de26d..7faba3bfb6338 100644 --- a/sound/soc/qcom/qdsp6/topology.c +++ b/sound/soc/qcom/qdsp6/topology.c @@ -753,6 +753,80 @@ static int audioreach_widget_i2s_module_load(struct audioreach_module *mod, return 0; } +static int audioreach_widget_audio_if_module_load(struct audioreach_module *mod, + const struct snd_soc_tplg_vendor_array *mod_array) +{ + const struct snd_soc_tplg_vendor_value_elem *mod_elem; + int tkn_count = 0; + + mod_elem = mod_array->value; + + while (tkn_count < le32_to_cpu(mod_array->num_elems)) { + switch (le32_to_cpu(mod_elem->token)) { + case AR_TKN_U32_MODULE_HW_IF_IDX: + mod->hw_interface_idx = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_FMT_DATA: + mod->data_format = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_HW_IF_TYPE: + mod->hw_interface_type = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SYNC_SRC: + mod->sync_src = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_CTRL_DATA_OUT_ENABLE: + mod->ctrl_data_out_enable = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SLOT_MASK: + mod->slot_mask = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_NSLOTS_PER_FRAME: + mod->nslots_per_frame = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SLOT_WIDTH: + mod->slot_width = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_INTF_MODE: + mod->intf_mode = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_SYNC_MODE: + mod->sync_mode = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_CTRL_INVERT_SYNC_PULSE: + mod->ctrl_invert_sync_pulse = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_CTRL_SYNC_DATA_DELAY: + mod->ctrl_sync_data_delay = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_QAIF_TYPE: + mod->qaif_type = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_ACTIVE_LANE_MASK: + mod->active_lane_mask = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_FRAME_SYNC_RATE: + mod->frame_sync_rate = le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_BIT_CLK_TYPE: + mod->bit_clk_type = (u16)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_INV_INT_BIT_CLK: + mod->inv_int_bit_clk = (u8)le32_to_cpu(mod_elem->value); + break; + case AR_TKN_U32_MODULE_INV_EXT_BIT_CLK: + mod->inv_ext_bit_clk = (u8)le32_to_cpu(mod_elem->value); + break; + default: + break; + } + tkn_count++; + mod_elem++; + } + + return 0; +} + static int audioreach_widget_dp_module_load(struct audioreach_module *mod, const struct snd_soc_tplg_vendor_array *mod_array) { @@ -806,6 +880,10 @@ static int audioreach_widget_load_buffer(struct snd_soc_component *component, case MODULE_ID_I2S_SOURCE: audioreach_widget_i2s_module_load(mod, mod_array); break; + case MODULE_ID_AUDIO_IF_SINK: + case MODULE_ID_AUDIO_IF_SOURCE: + audioreach_widget_audio_if_module_load(mod, mod_array); + break; case MODULE_ID_DISPLAY_PORT_SINK: audioreach_widget_dp_module_load(mod, mod_array); break; diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 7925aa3f63ba0..5e98f8c428338 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2022, Linaro Limited +#include #include +#include #include #include #include @@ -12,17 +14,125 @@ #include #include #include "qdsp6/q6afe.h" +#include "qdsp6/q6prm.h" #include "common.h" #include "sdw.h" +#define MCLK_FREQ 12288000 +#define MCLK_NATIVE_FREQ 11289600 + +static const struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("DP0 Jack", NULL), + SND_SOC_DAPM_SPK("DP1 Jack", NULL), + SND_SOC_DAPM_SPK("DP2 Jack", NULL), + SND_SOC_DAPM_SPK("DP3 Jack", NULL), + SND_SOC_DAPM_SPK("DP4 Jack", NULL), + SND_SOC_DAPM_SPK("DP5 Jack", NULL), + SND_SOC_DAPM_SPK("DP6 Jack", NULL), + SND_SOC_DAPM_SPK("DP7 Jack", NULL), +}; + +static const struct snd_soc_dapm_widget shikra_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new shikra_controls[] = { + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Int Mic"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +struct snd_soc_common { + const char *driver_name; + const struct snd_soc_dapm_widget *dapm_widgets; + int num_dapm_widgets; + const struct snd_soc_dapm_route *dapm_routes; + int num_dapm_routes; + const struct snd_kcontrol_new *controls; + int num_controls; + bool mi2s_mclk_enable; + bool mi2s_bclk_enable; + unsigned int codec_dai_fmt; + bool codec_sysclk_set; +}; + struct sc8280xp_snd_data { bool stream_prepared[AFE_PORT_MAX]; struct snd_soc_card *card; struct snd_soc_jack jack; struct snd_soc_jack dp_jack[8]; + const struct snd_soc_common *snd_soc_common_priv; + bool dsp_bypass_mode; bool jack_setup; }; +static int sc8280xp_tdm_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *cpu_dai) +{ + int ret; + + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); + if (ret && ret != -EOPNOTSUPP) + dev_err(rtd->dev, "%s: failed to set cpu fmt: %d\n", __func__, ret); + + return ret < 0 && ret != -EOPNOTSUPP ? ret : 0; +} + +static int sc8280xp_tdm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + struct qcom_snd_tdm_slot_cfg cpu_cfg; + struct qcom_snd_tdm_slot_cfg codec_cfg; + unsigned int bclk_freq; + int ret; + int i; + + ret = qcom_snd_get_dai_tdm_slots(rtd, &cpu_cfg, &codec_cfg); + if (ret) + return ret == -EINVAL ? 0 : ret; + + if (!cpu_cfg.slots) + return 0; + + ret = sc8280xp_tdm_set_dai_fmt(rtd, cpu_dai); + if (ret) + return ret; + + ret = qcom_snd_apply_dai_tdm_slots(rtd); + if (ret) + return ret; + + bclk_freq = snd_soc_tdm_params_to_bclk(params, cpu_cfg.slot_width, cpu_cfg.slots, 1); + if (!bclk_freq) + return -EINVAL; + + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_TDM_BCLK, bclk_freq, SND_SOC_CLOCK_IN); + if (ret < 0 && ret != -EOPNOTSUPP) { + dev_err(rtd->dev, "%s: failed to set cpu sysclk: %d\n", __func__, ret); + return ret; + } + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, bclk_freq, SND_SOC_CLOCK_IN); + if (ret < 0 && ret != -EOPNOTSUPP) { + dev_err(rtd->dev, "%s: failed to set codec sysclk on %s: %d\n", + __func__, codec_dai->name, ret); + return ret; + } + } + + return 0; +} + static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) { struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); @@ -32,10 +142,6 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) int dp_pcm_id = 0; switch (cpu_dai->id) { - case PRIMARY_MI2S_RX...QUATERNARY_MI2S_TX: - case QUINARY_MI2S_RX...QUINARY_MI2S_TX: - snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); - break; case WSA_CODEC_DMA_RX_0: case WSA_CODEC_DMA_RX_1: /* @@ -67,6 +173,23 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); } +static inline int sc8280xp_get_mclk_feq(unsigned int rate) +{ + int freq = MCLK_FREQ; + + switch (rate) { + case SNDRV_PCM_RATE_11025: + case SNDRV_PCM_RATE_44100: + case SNDRV_PCM_RATE_88200: + freq = MCLK_NATIVE_FREQ; + break; + default: + break; + } + + return freq; +} + static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -82,10 +205,12 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = 2; channels->max = 2; switch (cpu_dai->id) { + case VA_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: + case LPASS_CDC_DMA_VA_TX1: channels->min = 1; break; default: @@ -105,6 +230,49 @@ static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); } +static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); + unsigned int mclk_freq = sc8280xp_get_mclk_feq(params_rate(params)); + int ret; + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + + if (data->dsp_bypass_mode) + return 0; + + switch (cpu_dai->id) { + case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); + if (ret < 0 && ret != -EOPNOTSUPP) + return ret; + + if (data->snd_soc_common_priv->codec_dai_fmt) + snd_soc_dai_set_fmt(codec_dai, + data->snd_soc_common_priv->codec_dai_fmt); + + if (data->snd_soc_common_priv->codec_sysclk_set) + snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, + SND_SOC_CLOCK_IN); + + if (!data->snd_soc_common_priv->mi2s_bclk_enable) + return 0; + + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_MCLK, + mclk_freq, SND_SOC_CLOCK_IN); + return ret < 0 && ret != -EOPNOTSUPP ? ret : 0; + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: + return sc8280xp_tdm_hw_params(substream, params); + default: + break; + } + + return 0; +} + static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); @@ -117,6 +285,7 @@ static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) static const struct snd_soc_ops sc8280xp_be_ops = { .startup = qcom_snd_sdw_startup, .shutdown = qcom_snd_sdw_shutdown, + .hw_params = sc8280xp_snd_hw_params, .hw_free = sc8280xp_snd_hw_free, .prepare = sc8280xp_snd_prepare, }; @@ -127,7 +296,7 @@ static void sc8280xp_add_be_ops(struct snd_soc_card *card) int i; for_each_card_prelinks(card, i, link) { - if (link->no_pcm == 1) { + if (link->no_pcm == 1 || link->num_codecs > 0) { link->init = sc8280xp_snd_init; link->be_hw_params_fixup = sc8280xp_be_hw_params_fixup; link->ops = &sc8280xp_be_ops; @@ -145,37 +314,132 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; - card->owner = THIS_MODULE; - /* Allocate the private data */ + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; + data->snd_soc_common_priv = of_device_get_match_data(dev); + if (!data->snd_soc_common_priv) + return -EINVAL; + + card->owner = THIS_MODULE; card->dev = dev; dev_set_drvdata(dev, card); snd_soc_card_set_drvdata(card, data); + card->dapm_widgets = data->snd_soc_common_priv->dapm_widgets; + card->num_dapm_widgets = data->snd_soc_common_priv->num_dapm_widgets; + card->dapm_routes = data->snd_soc_common_priv->dapm_routes; + card->num_dapm_routes = data->snd_soc_common_priv->num_dapm_routes; + card->controls = data->snd_soc_common_priv->controls; + card->num_controls = data->snd_soc_common_priv->num_controls; + ret = qcom_snd_parse_of(card); if (ret) return ret; - card->driver_name = of_device_get_match_data(dev); + data->dsp_bypass_mode = of_property_read_bool(dev->of_node, + "qcom,adsp-bypass-mode"); + + card->driver_name = data->snd_soc_common_priv->driver_name; sc8280xp_add_be_ops(card); return devm_snd_soc_register_card(dev, card); } +static const struct snd_soc_common kaanapali_priv_data = { + .driver_name = "kaanapali", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common qcm6490_priv_data = { + .driver_name = "qcm6490", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common qcs615_priv_data = { + .driver_name = "qcs615", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), + .mi2s_mclk_enable = true, +}; + +static const struct snd_soc_common qcs6490_priv_data = { + .driver_name = "qcs6490", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common qcs8275_priv_data = { + .driver_name = "qcs8300", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common qcs9100_priv_data = { + .driver_name = "sa8775p", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common sc8280xp_priv_data = { + .driver_name = "sc8280xp", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common shikra_priv_data = { + .driver_name = "shikra", + .dapm_widgets = shikra_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(shikra_dapm_widgets), + .controls = shikra_controls, + .num_controls = ARRAY_SIZE(shikra_controls), + .mi2s_bclk_enable = true, + .codec_dai_fmt = SND_SOC_DAIFMT_CBP_CFP | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S, + .codec_sysclk_set = true, +}; + +static const struct snd_soc_common sm8450_priv_data = { + .driver_name = "sm8450", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common sm8550_priv_data = { + .driver_name = "sm8550", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common sm8650_priv_data = { + .driver_name = "sm8650", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + +static const struct snd_soc_common sm8750_priv_data = { + .driver_name = "sm8750", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), +}; + static const struct of_device_id snd_sc8280xp_dt_match[] = { - {.compatible = "qcom,kaanapali-sndcard", "kaanapali"}, - {.compatible = "qcom,qcm6490-idp-sndcard", "qcm6490"}, - {.compatible = "qcom,qcs615-sndcard", "qcs615"}, - {.compatible = "qcom,qcs6490-rb3gen2-sndcard", "qcs6490"}, - {.compatible = "qcom,qcs8275-sndcard", "qcs8300"}, - {.compatible = "qcom,qcs9075-sndcard", "sa8775p"}, - {.compatible = "qcom,qcs9100-sndcard", "sa8775p"}, - {.compatible = "qcom,sc8280xp-sndcard", "sc8280xp"}, - {.compatible = "qcom,sm8450-sndcard", "sm8450"}, - {.compatible = "qcom,sm8550-sndcard", "sm8550"}, - {.compatible = "qcom,sm8650-sndcard", "sm8650"}, - {.compatible = "qcom,sm8750-sndcard", "sm8750"}, + { .compatible = "qcom,kaanapali-sndcard", .data = &kaanapali_priv_data }, + { .compatible = "qcom,qcm6490-idp-sndcard", .data = &qcm6490_priv_data }, + { .compatible = "qcom,qcs615-sndcard", .data = &qcs615_priv_data }, + { .compatible = "qcom,qcs6490-rb3gen2-sndcard", .data = &qcs6490_priv_data }, + { .compatible = "qcom,qcs8275-sndcard", .data = &qcs8275_priv_data }, + { .compatible = "qcom,qcs9075-sndcard", .data = &qcs9100_priv_data }, + { .compatible = "qcom,qcs9100-sndcard", .data = &qcs9100_priv_data }, + { .compatible = "qcom,sc8280xp-sndcard", .data = &sc8280xp_priv_data }, + { .compatible = "qcom,shikra-sndcard", .data = &shikra_priv_data }, + { .compatible = "qcom,sm8450-sndcard", .data = &sm8450_priv_data }, + { .compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data }, + { .compatible = "qcom,sm8650-sndcard", .data = &sm8650_priv_data }, + { .compatible = "qcom,sm8750-sndcard", .data = &sm8750_priv_data }, {} }; diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 0ce9dff4dc525..509d7a551397e 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -294,13 +294,26 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) return 0; for_each_rtd_codec_dais(rtd, i, codec_dai) { - rval = snd_soc_dai_set_channel_map(codec_dai, - ARRAY_SIZE(tx_ch), - tx_ch, - ARRAY_SIZE(rx_ch), - rx_ch); - if (rval != 0 && rval != -ENOTSUPP) - return rval; + component = codec_dai->component; + + if (!component || !component->dev) + continue; + + /* + * Only wcd934x (SLIM codec) needs these static channel maps. + * DAIs that own an SDW stream — the qcom SWR master and SWR + * slave speaker codecs — implement .set_stream; skip them. + */ + if (!codec_dai->driver || !codec_dai->driver->ops || + !codec_dai->driver->ops->set_stream) { + rval = snd_soc_dai_set_channel_map(codec_dai, + ARRAY_SIZE(tx_ch), + tx_ch, + ARRAY_SIZE(rx_ch), + rx_ch); + if (rval != 0 && rval != -ENOTSUPP) + return rval; + } snd_soc_dai_set_sysclk(codec_dai, 0, WCD934X_DEFAULT_MCLK_RATE, diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index 6576b47a4c8c3..cf70ffec71c17 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -41,6 +41,7 @@ static bool qcom_snd_is_sdw_dai(int id) switch (id) { case LPASS_CDC_DMA_TX3: case LPASS_CDC_DMA_RX0: + case LPASS_CDC_DMA_VA_TX1: return true; default: break;