diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000000000..fc5f8e783747ee --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0-only + +name: build + +on: + push: + +env: + DEFCONFIG: lenovo-blade_defconfig + ARCH: arm + LLVM: 1 + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: Install build dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + bc binutils bison flex build-essential \ + dwarves libelf-dev libssl-dev python3 \ + llvm-dev clang lld git rsync cpio kmod pahole zstd + + - name: Cache ccache + uses: hendrikmuhs/ccache-action@v1.2.24 + with: + key: ${{ env.DEFCONFIG }}-linux + + - name: Configure + run: | + make ${{ env.DEFCONFIG }} + + - name: Build + run: | + make -j"$(nproc)" CC="ccache clang" + + dtbs_check: + name: dtbs_check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: Install dtc and build dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + bc binutils bison flex build-essential libelf-dev \ + python3 python3-pip python3-setuptools llvm-dev clang lld + + - name: Install dtschema + run: | + python3 -m pip install dtschema + + - name: Configure + run: make ${{ env.DEFCONFIG }} + + - name: Run dtbs_check + run: make dtbs_check + + dt_binding_check: + name: dt_binding_check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: Install build dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + bc binutils bison flex build-essential libelf-dev \ + python3 python3-pip python3-setuptools llvm-dev clang lld + + - name: Install dtschema + run: | + python3 -m pip install dtschema + + - name: Run dt_binding_check + run: | + make dt_binding_check diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml index 382d0eb4d0af6d..e6b67daf229959 100644 --- a/Documentation/devicetree/bindings/arm/mediatek.yaml +++ b/Documentation/devicetree/bindings/arm/mediatek.yaml @@ -45,6 +45,11 @@ properties: - enum: - fairphone,fp1 - mundoreader,bq-aquaris5 + - lenovo,b6000-f + - lenovo,b6000-h + - lenovo,b6000-hv + - lenovo,b8000-f + - lenovo,b8000-h - const: mediatek,mt6589 - items: - enum: diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.yaml index 9aa39b002361d9..52ac8c635d2920 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.yaml +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.yaml @@ -18,6 +18,7 @@ properties: - items: - enum: - mediatek,mt2701-audsys + - mediatek,mt6589-audsys - mediatek,mt6765-audsys - mediatek,mt6779-audsys - mediatek,mt7622-audsys diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml index 3f4262e93c789c..5a57e918d65411 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml @@ -23,6 +23,7 @@ properties: - enum: - mediatek,mt2701-mmsys - mediatek,mt2712-mmsys + - mediatek,mt6589-dispsys - mediatek,mt6765-mmsys - mediatek,mt6779-mmsys - mediatek,mt6795-mmsys diff --git a/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml b/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml index 591a9e862c7d46..dfa3b2840c9af7 100644 --- a/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml +++ b/Documentation/devicetree/bindings/clock/mediatek,apmixedsys.yaml @@ -35,6 +35,7 @@ properties: - enum: - mediatek,mt2701-apmixedsys - mediatek,mt2712-apmixedsys + - mediatek,mt6589-apmixedsys - mediatek,mt6735-apmixedsys - mediatek,mt6765-apmixedsys - mediatek,mt6779-apmixed diff --git a/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml b/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml index d1d30700d9b0e4..9b54493393ce96 100644 --- a/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml +++ b/Documentation/devicetree/bindings/clock/mediatek,infracfg.yaml @@ -23,6 +23,7 @@ properties: - enum: - mediatek,mt2701-infracfg - mediatek,mt2712-infracfg + - mediatek,mt6589-infracfg - mediatek,mt6735-infracfg - mediatek,mt6765-infracfg - mediatek,mt6795-infracfg diff --git a/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml b/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml index b98cf45efe2f63..63c80a4ac2e8c2 100644 --- a/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml +++ b/Documentation/devicetree/bindings/clock/mediatek,pericfg.yaml @@ -20,6 +20,7 @@ properties: - enum: - mediatek,mt2701-pericfg - mediatek,mt2712-pericfg + - mediatek,mt6589-pericfg - mediatek,mt6735-pericfg - mediatek,mt6765-pericfg - mediatek,mt6795-pericfg diff --git a/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml b/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml index a52f90bfc9f92b..8ba3aea07dc2e3 100644 --- a/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml +++ b/Documentation/devicetree/bindings/clock/mediatek,syscon.yaml @@ -28,6 +28,10 @@ properties: - mediatek,mt2712-mfgcfg - mediatek,mt2712-vdecsys - mediatek,mt2712-vencsys + - mediatek,mt6589-imgsys + - mediatek,mt6589-mfgsys + - mediatek,mt6589-vdecsys + - mediatek,mt6589-vencsys - mediatek,mt6735-imgsys - mediatek,mt6735-mfgcfg - mediatek,mt6735-vdecsys diff --git a/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml b/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml index c080fb0a161819..82e1e602e62991 100644 --- a/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml +++ b/Documentation/devicetree/bindings/clock/mediatek,topckgen.yaml @@ -32,6 +32,7 @@ properties: - enum: - mediatek,mt2701-topckgen - mediatek,mt2712-topckgen + - mediatek,mt6589-topckgen - mediatek,mt6735-topckgen - mediatek,mt6765-topckgen - mediatek,mt6779-topckgen diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml index cc8d795df732c3..c31f5a5ddde31e 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml @@ -31,8 +31,12 @@ properties: # AU Optronics Corporation 8.0" WUXGA TFT LCD panel - auo,b080uan01 + # BOE Technology 10.1" WXGA panel with Himax HX8896-A01 TCON + - boe,hx8896-a01-panel # Boe Corporation 8.0" WUXGA TFT LCD panel - boe,tv080wum-nl0 + # CMI 10.1" WXGA panel with Himax HX8896-A01 TCON + - innolux,hx8896-a01-panel # Innolux P079ZCA 7.85" 768x1024 TFT LCD panel - innolux,p079zca # JDI FHD_R63452 1080x1920 5.2" IPS LCD Panel diff --git a/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml b/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml index 3708518fe7fc1a..423587057e954e 100644 --- a/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml +++ b/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml @@ -23,6 +23,7 @@ properties: - items: - enum: - mediatek,mt2712-uart-dma + - mediatek,mt6589-uart-dma - mediatek,mt6795-uart-dma - mediatek,mt8173-uart-dma - mediatek,mt8183-uart-dma diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-sgx.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-sgx.yaml index f5898b04381cb6..43870d1c660390 100644 --- a/Documentation/devicetree/bindings/gpu/img,powervr-sgx.yaml +++ b/Documentation/devicetree/bindings/gpu/img,powervr-sgx.yaml @@ -27,6 +27,7 @@ properties: - items: - enum: - allwinner,sun6i-a31-gpu # MP2 Rev 115 + - mediatek,mt6589-gpu # MP1 Rev 115 - ti,omap4470-gpu # MP1 Rev 112 - ti,omap5432-gpu # MP2 Rev 105 - ti,am5728-gpu # MP2 Rev 116 diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml index ecd5783f001b3e..3884b37c55c03c 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml @@ -96,6 +96,14 @@ properties: description: SCL frequency to use (in Hz). If omitted, 100kHz is used. + resets: + maxItems: 1 + + reset-names: + items: + - const: reset + maxItems: 1 + mediatek,have-pmic: description: Platform controls I2C from PMIC side type: boolean diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml index d9e825e5054fe5..50f6cc318cd266 100644 --- a/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml @@ -24,6 +24,7 @@ properties: - enum: - mediatek,mt2701-auxadc - mediatek,mt2712-auxadc + - mediatek,mt6589-auxadc - mediatek,mt6765-auxadc - mediatek,mt7622-auxadc - mediatek,mt7986-auxadc @@ -38,6 +39,7 @@ properties: - const: mediatek,mt7986-auxadc - items: - enum: + - mediatek,mt6572-auxadc - mediatek,mt6893-auxadc - mediatek,mt8183-auxadc - mediatek,mt8186-auxadc diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,mt6323-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,mt6323-auxadc.yaml new file mode 100644 index 00000000000000..935ed004c43fd4 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/mediatek,mt6323-auxadc.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/mediatek,mt6323-auxadc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6320 and MT6323 PMIC Auxiliary ADC + +maintainers: + - Flora Fu + +description: | + AUXADC is the auxiliary ADC of the PMIC, used for sampling a variety + of channels like battery voltage, PMIC internal temperature, accessory + detection resistance, and other internal components. + +properties: + compatible: + enum: + - mediatek,mt6320-auxadc + + "#io-channel-cells": + const: 1 + +required: + - compatible + - "#io-channel-cells" + +additionalProperties: false + +examples: + - | + pmic { + #address-cells = <1>; + #size-cells = <0>; + + adc { + compatible = "mediatek,mt6323-auxadc"; + #io-channel-cells = <1>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/light/dynaimage,al3320a.yaml b/Documentation/devicetree/bindings/iio/light/dynaimage,al3320a.yaml index d06db737cd9edd..e80686dc1c2fbe 100644 --- a/Documentation/devicetree/bindings/iio/light/dynaimage,al3320a.yaml +++ b/Documentation/devicetree/bindings/iio/light/dynaimage,al3320a.yaml @@ -4,14 +4,16 @@ $id: http://devicetree.org/schemas/iio/light/dynaimage,al3320a.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Dyna-Image AL3320A sensor +title: Dyna-Image AL3320A and AL3320B sensors maintainers: - David Heidelberg properties: compatible: - const: dynaimage,al3320a + enum: + - dynaimage,al3320a + - dynaimage,al3320b reg: maxItems: 1 @@ -43,3 +45,15 @@ examples: interrupts = <99 IRQ_TYPE_LEVEL_HIGH>; }; }; + + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + light-sensor@1c { + compatible = "dynaimage,al3320b"; + reg = <0x1c>; + vdd-supply = <&vdd_reg>; + }; + }; diff --git a/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml b/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml index 914dd3283df330..3e245b89e25bfb 100644 --- a/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml +++ b/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml @@ -26,6 +26,7 @@ properties: - const: mediatek,mt6779-keypad - items: - enum: + - mediatek,mt6589-keypad - mediatek,mt6873-keypad - mediatek,mt8183-keypad - mediatek,mt8365-keypad diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml index b95435bd6a9b5f..970e1f6de3102a 100644 --- a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml +++ b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml @@ -24,6 +24,7 @@ description: | properties: compatible: enum: + - mediatek,mt6320-keys - mediatek,mt6323-keys - mediatek,mt6328-keys - mediatek,mt6331-keys diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml index 8685ef4481f4ab..7a1414ddefcec8 100644 --- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml +++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml @@ -45,6 +45,27 @@ properties: description: Delay to wait after resetting the device. + syna,initial-reset-control: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: + Optional value written to RMI4 Function 01 Control 0 before the + initial reset command. + + syna,initial-reset-delay-ms: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + description: + Delay to wait after the initial reset command. + + syna,reset-after-power-on: + type: boolean + description: + Keep reset deasserted while powering the device, then pulse reset + after syna,startup-delay-ms. This is needed by devices whose power-on + sequence requires reset to be asserted only after the supplies settle. + syna,startup-delay-ms: description: Delay to wait after powering on the device. diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml index 79c573c47b08ea..1b505e82a80cc2 100644 --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml @@ -72,6 +72,7 @@ properties: - enum: - mediatek,mt2701-m4u # generation one - mediatek,mt2712-m4u # generation two + - mediatek,mt6589-m4u # generation one (dual core) - mediatek,mt6779-m4u # generation two - mediatek,mt6795-m4u # generation two - mediatek,mt6893-iommu-mm # generation two @@ -97,10 +98,20 @@ properties: - const: mediatek,mt2701-m4u reg: - maxItems: 1 + minItems: 1 + maxItems: 4 # MT6589 needs 4 regions (global, m4u0, m4u1, l2cache) + + reg-names: + minItems: 1 + maxItems: 4 interrupts: - maxItems: 1 + minItems: 1 + maxItems: 4 # MT6589: m4u0, m4u1 and the two L2 IRQs + + interrupt-names: + minItems: 1 + maxItems: 2 clocks: items: @@ -133,6 +144,7 @@ properties: dt-binding/memory/mediatek,mt8188-memory-port.h for mt8188, dt-binding/memory/mediatek,mt8189-memory-port.h for mt8189, dt-binding/memory/mt2701-larb-port.h for mt2701 and mt7623, + dt-binding/memory/mt6589-larb-port.h for mt6589, dt-binding/memory/mt2712-larb-port.h for mt2712, dt-binding/memory/mt6779-larb-port.h for mt6779, dt-binding/memory/mt6795-larb-port.h for mt6795, @@ -155,6 +167,42 @@ required: - '#iommu-cells' allOf: + - if: + properties: + compatible: + not: + contains: + const: mediatek,mt6589-m4u + then: + properties: + reg: + maxItems: 1 + interrupts: + maxItems: 1 + required: + - reg + else: + properties: + reg: + minItems: 4 + maxItems: 4 + interrupts: + minItems: 2 + maxItems: 2 + reg-names: + items: + - const: global + - const: m4u0 + - const: m4u1 + - const: l2cache + interrupt-names: + items: + - const: m4u0 + - const: m4u1 + required: + - reg-names + - interrupt-names + - if: properties: compatible: @@ -162,6 +210,7 @@ allOf: enum: - mediatek,mt2701-m4u - mediatek,mt2712-m4u + - mediatek,mt6589-m4u - mediatek,mt6795-m4u - mediatek,mt6893-iommu-mm - mediatek,mt8173-m4u @@ -240,3 +289,23 @@ examples: <&larb3>, <&larb4>, <&larb5>; #iommu-cells = <1>; }; + + - | + #include + + iommu@10205000 { + compatible = "mediatek,mt6589-m4u"; + reg = <0x10205000 0x100>, + <0x10205200 0x600>, + <0x10205800 0x600>, + <0x10205100 0x100>; + reg-names = "global", "m4u0", "m4u1", "l2cache"; + interrupts = , + ; + interrupt-names = "m4u0", "m4u1"; + clocks = <&infracfg CLK_INFRA_M4U>; + clock-names = "bclk"; + mediatek,larbs = <&larb0>, <&larb1>, <&larb2>, + <&larb3>, <&larb4>; + #iommu-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml index a4aacd3eb189bb..6bb4e41c3b2bb0 100644 --- a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml +++ b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml @@ -19,6 +19,7 @@ properties: - enum: - mediatek,mt8173-jpgdec - mediatek,mt2701-jpgdec + - mediatek,mt6589-jpgdec - items: - enum: - mediatek,mt7623-jpgdec diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml index 5b15f8977f67f7..ffb22241e39331 100644 --- a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml +++ b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml @@ -17,6 +17,7 @@ properties: items: - enum: - mediatek,mt2701-jpgenc + - mediatek,mt6589-jpgenc - mediatek,mt8183-jpgenc - mediatek,mt8186-jpgenc - mediatek,mt8188-jpgenc @@ -28,10 +29,13 @@ properties: maxItems: 1 clocks: - maxItems: 1 + minItems: 1 + maxItems: 2 clock-names: + minItems: 1 items: + - const: jpgenc-smi - const: jpgenc power-domains: diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml index 0762e0ff66ef02..35d7d4c1ca6b65 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml @@ -31,6 +31,7 @@ properties: - enum: - mediatek,mt2701-smi-common - mediatek,mt2712-smi-common + - mediatek,mt6589-smi-common - mediatek,mt6779-smi-common - mediatek,mt6795-smi-common - mediatek,mt6893-smi-common @@ -51,9 +52,6 @@ properties: - const: mediatek,mt7623-smi-common - const: mediatek,mt2701-smi-common - reg: - maxItems: 1 - power-domains: maxItems: 1 @@ -86,6 +84,24 @@ required: - clock-names allOf: + - if: # Generation 0 HW (mt6589) + properties: + compatible: + contains: + const: mediatek,mt6589-smi-common + then: + properties: + reg: + items: + - description: SMI AO base + - description: SMI base + minItems: 2 + maxItems: 2 + else: + properties: + reg: + maxItems: 1 + - if: # only for gen1 HW properties: compatible: diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml index 2e7fac4b50945d..0a4ea1865c2f64 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml @@ -19,6 +19,7 @@ properties: - enum: - mediatek,mt2701-smi-larb - mediatek,mt2712-smi-larb + - mediatek,mt6589-smi-larb - mediatek,mt6779-smi-larb - mediatek,mt6795-smi-larb - mediatek,mt6893-smi-larb diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml index 05c121b0cb3d86..68a116ee3177c9 100644 --- a/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml @@ -24,6 +24,7 @@ description: | - LED - Keys - Power controller + - Accessory detection It is interfaced to host controller using SPI interface by a proprietary hardware called PMIC wrapper or pwrap. MT6397/MT6323 PMIC is a child device of pwrap. @@ -34,6 +35,7 @@ properties: compatible: oneOf: - enum: + - mediatek,mt6320 - mediatek,mt6323 - mediatek,mt6331 # "mediatek,mt6331" for PMIC MT6331 and MT6332. - mediatek,mt6328 @@ -64,6 +66,7 @@ properties: compatible: oneOf: - enum: + - mediatek,mt6320-rtc - mediatek,mt6323-rtc - mediatek,mt6331-rtc - mediatek,mt6358-rtc @@ -72,6 +75,10 @@ properties: - enum: - mediatek,mt6366-rtc - const: mediatek,mt6358-rtc + - items: + - enum: + - mediatek,mt6320-rtc + - const: mediatek,mt6397-rtc start-year: true @@ -88,6 +95,7 @@ properties: compatible: oneOf: - enum: + - mediatek,mt6320-regulator - mediatek,mt6323-regulator - mediatek,mt6328-regulator - mediatek,mt6331-regulator @@ -102,21 +110,65 @@ properties: required: - compatible + accdet: + type: object + description: + Accessory detection support with MT6320 or MT6323. + oneOf: + - $ref: /schemas/sound/mediatek,mt6320-accdet.yaml# + - properties: + compatible: + const: mediatek,mt6323-accdet + + interrupts: + minItems: 2 + maxItems: 2 + items: + - description: Interrupt from the GPIO to wake up accdet. + - description: PMIC interrupt for insertion, removal and keys events. + + interrupt-names: + minItems: 2 + maxItems: 2 + items: + - const: eint + - const: pmic + + required: + - compatible + - interrupts + - interrupt-names + additionalProperties: false + unevaluatedProperties: false + adc: type: object - $ref: /schemas/iio/adc/mediatek,mt6359-auxadc.yaml# + oneOf: + - $ref: /schemas/iio/adc/mediatek,mt6323-auxadc.yaml# + - $ref: /schemas/iio/adc/mediatek,mt6359-auxadc.yaml# unevaluatedProperties: false + efuse: + type: object + description: + eFuse support with MT6320. + additionalProperties: false + + properties: + compatible: + const: mediatek,mt6320-efuse + audio-codec: type: object description: - Audio codec support with MT6358 and MT6397. + Audio codec support with MT6320, MT6358 and MT6397. additionalProperties: true properties: compatible: oneOf: - enum: + - mediatek,mt6320-sound - mediatek,mt6358-sound - mediatek,mt6359-codec - mediatek,mt6397-codec @@ -125,6 +177,11 @@ properties: - mediatek,mt6366-sound - const: mediatek,mt6358-sound + clocks: + minItems: 1 + + clock-names: true + required: - compatible @@ -137,7 +194,9 @@ properties: properties: compatible: - const: mediatek,mt6397-clk + enum: + - mediatek,mt6320-clk + - mediatek,mt6397-clk '#clock-cells': const: 1 @@ -213,7 +272,12 @@ properties: properties: compatible: - const: mediatek,mt6323-pwrc + oneOf: + - const: mediatek,mt6323-pwrc + - items: + - enum: + - mediatek,mt6320-pwrc + - const: mediatek,mt6323-pwrc '#power-domain-cells': const: 0 diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml index 4cafa381979bf3..338a576085246f 100644 --- a/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml @@ -19,6 +19,7 @@ properties: compatible: items: - enum: + - mediatek,mt6589-scpsys - mediatek,mt6795-scpsys - mediatek,mt6893-scpsys - mediatek,mt8167-scpsys diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index eb3755bdfdf7e0..cc6fa2bddf9605 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -31,6 +31,10 @@ properties: - items: - const: mediatek,mt7623-mmc - const: mediatek,mt2701-mmc + - items: + - enum: + - mediatek,mt6589-mmc + - const: mediatek,mt8135-mmc - items: - enum: - mediatek,mt6893-mmc diff --git a/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml b/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml index ab503a33a26985..a367e3122a3dfa 100644 --- a/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml +++ b/Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml @@ -66,6 +66,20 @@ allOf: enum: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60] + - if: + properties: + compatible: + contains: + const: mediatek,mt6589-nfc + then: + patternProperties: + "^nand@[a-f0-9]$": + properties: + nand-ecc-step-size: + enum: [ 512 ] + nand-ecc-strength: + enum: [4, 8, 12] + - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/mtd/mediatek,nand-ecc-engine.yaml b/Documentation/devicetree/bindings/mtd/mediatek,nand-ecc-engine.yaml index 505baf1e88302f..1620b3a9d58b6d 100644 --- a/Documentation/devicetree/bindings/mtd/mediatek,nand-ecc-engine.yaml +++ b/Documentation/devicetree/bindings/mtd/mediatek,nand-ecc-engine.yaml @@ -16,6 +16,7 @@ properties: compatible: enum: - mediatek,mt2701-ecc + - mediatek,mt6589-ecc - mediatek,mt2712-ecc - mediatek,mt7622-ecc - mediatek,mt7986-ecc diff --git a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml index f9323b3ecfc83e..eb3bbfc5e65219 100644 --- a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml +++ b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml @@ -59,6 +59,12 @@ properties: - const: mediatek,mt8173-efuse deprecated: true + - const: mediatek,mt6572-efuse + - items: + - enum: + - mediatek,mt6589-efuse + - const: mediatek,mt6572-efuse + reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml index c6d0bbdbe0e227..dd573714fa4bc9 100644 --- a/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml +++ b/Documentation/devicetree/bindings/phy/mediatek,dsi-phy.yaml @@ -37,6 +37,7 @@ properties: - mediatek,mt8365-mipi-tx - const: mediatek,mt8183-mipi-tx - const: mediatek,mt2701-mipi-tx + - const: mediatek,mt6589-mipi-tx - const: mediatek,mt8173-mipi-tx - const: mediatek,mt8183-mipi-tx diff --git a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml index ff5c77ef11765c..983b038cee661b 100644 --- a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml +++ b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml @@ -34,6 +34,10 @@ description: | u2 port2 0x1800 U2PHY_COM ... + Some V1 SoCs (e.g. MT6589) have the FMREG bank at a non-standard + offset (0x0f00 instead of 0x0100). These use a separate reg entry + with name "legacy-fm". + Version 2/3: port offset bank u2 port0 0x0000 MISC @@ -96,6 +100,7 @@ properties: deprecated: true - const: mediatek,mt2712-u3phy deprecated: true + - const: mediatek,mt6589-tphy - const: mediatek,mt8173-u3phy reg: @@ -103,7 +108,19 @@ properties: Register shared by multiple ports, exclude port's private register. It is needed for T-PHY V1, such as mt2701 and mt8173, but not for T-PHY V2/V3, such as mt2712. - maxItems: 1 + Some V1 SoCs (e.g. MT6589) require a second register range for the + legacy frequency meter block. + minItems: 1 + maxItems: 2 + + reg-names: + description: + Names for the shared register ranges. + minItems: 1 + maxItems: 2 + items: + - const: sif + - const: legacy-fm "#address-cells": enum: [1, 2] @@ -331,4 +348,24 @@ examples: }; }; + - | + #include + t-phy@11220000 { + compatible = "mediatek,mt6589-tphy", "mediatek,generic-tphy-v1"; + reg = <0x11220000 0x0800>, + <0x11220f00 0x0100>; + reg-names = "sif", "legacy-fm"; + mediatek,src-ref-clk-mhz = <48>; + mediatek,src-coef = <22>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + u2port0: usb-phy@11220800 { + reg = <0x11220800 0x0100>; + clocks = <&topckgen CLK_TOP_UNIVPLL_D26>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; ... diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6589-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6589-pinctrl.yaml new file mode 100644 index 00000000000000..445fe3dcc58687 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6589-pinctrl.yaml @@ -0,0 +1,175 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/mediatek,mt6589-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6589 Pin Controller + +maintainers: + - Akari Tsuyukusa + +description: + The MediaTek pin controller on MT6589 is used to control pin functions, pull + up/down resistance and drive strength options. + +properties: + compatible: + enum: + - mediatek,mt6589-pinctrl + + reg: + minItems: 3 + maxItems: 3 + description: Physical addresses for GPIO base(s) and EINT registers. + + reg-names: + items: + - const: gpio + - const: gpio1 + - const: eint + + gpio-controller: true + + "#gpio-cells": + const: 2 + description: + Number of cells in GPIO specifier. Since the generic GPIO binding is used, + the amount of cells must be specified as 2. See the below mentioned gpio + binding representation for description of particular cells. + + gpio-ranges: + minItems: 1 + maxItems: 5 + description: + GPIO valid number range. + + interrupt-controller: true + + interrupts: + maxItems: 1 + description: + Specifies the summary IRQ. + + "#interrupt-cells": + const: 2 + +required: + - compatible + - reg + - reg-names + - gpio-controller + - "#gpio-cells" + - interrupts + - interrupt-controller + - "#interrupt-cells" + +patternProperties: + '^(.*)?_pins(_default|_uhs)?$': + type: object + additionalProperties: false + + patternProperties: + '.*pins.*$|^pin-': + type: object + description: + A pinctrl node should contain at least one subnodes representing the + pinctrl groups available on the machine. Each subnode will list the + pins it needs, and how they should be configured, with regard to muxer + configuration, pullups, drive strength, input enable/disable and input + schmitt. + $ref: /schemas/pinctrl/pincfg-node.yaml + + properties: + pinmux: + description: + Integer array, represents gpio pin number and mux setting. + Supported pin number and mux varies for different SoCs, and are + defined as macros in dt-bindings/pinctrl/-pinfunc.h directly. + + bias-disable: true + + bias-pull-up: true + + bias-pull-down: true + + input-enable: true + + input-disable: true + + output-low: true + + output-high: true + + input-schmitt-enable: true + + input-schmitt-disable: true + + drive-strength: + enum: [2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32] + + slew-rate: + enum: [0, 1] + + mediatek,pull-up-adv: + description: | + Pull up settings for 2 pull resistors, R0 and R1. User can + configure those special pins. Valid arguments are described as + below: + 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled. + 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled. + 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled. + 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + mediatek,pull-down-adv: + description: | + Pull down settings for 2 pull resistors, R0 and R1. User can + configure those special pins. Valid arguments are described as + below: + 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled. + 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled. + 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled. + 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + required: + - pinmux + + additionalProperties: false + +additionalProperties: false + +examples: + - | + #include + #include + soc { + #address-cells = <1>; + #size-cells = <1>; + + pio: pinctrl@10005000 { + compatible = "mediatek,mt6589-pinctrl"; + reg = <0x10005000 0x1000>, + <0x1020c000 0x1000>, + <0x1000b000 0x1000>; + reg-names = "gpio", "gpio1", "eint"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pio 0 0 232>; + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + interrupts = ; + + usb_pins_default: usb-pins { + pins_iddig { + pinmux = ; + input-enable; + bias-pull-up; + } + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml index aa71398cf522fd..7e8b93b5dd2d53 100644 --- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml @@ -17,6 +17,7 @@ properties: enum: - mediatek,mt2701-pinctrl - mediatek,mt2712-pinctrl + - mediatek,mt6320-pinctrl - mediatek,mt6397-pinctrl - mediatek,mt7623-pinctrl - mediatek,mt8127-pinctrl diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml index 07f046277f8a6a..456e73e43bd7ff 100644 --- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml +++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml @@ -23,6 +23,7 @@ properties: compatible: enum: + - mediatek,mt6589-power-controller - mediatek,mt6735-power-controller - mediatek,mt6795-power-controller - mediatek,mt6893-power-controller diff --git a/Documentation/devicetree/bindings/power/supply/bq24190.yaml b/Documentation/devicetree/bindings/power/supply/bq24190.yaml index 938554a9fb02c2..aa0d52099254e7 100644 --- a/Documentation/devicetree/bindings/power/supply/bq24190.yaml +++ b/Documentation/devicetree/bindings/power/supply/bq24190.yaml @@ -65,10 +65,23 @@ properties: above recharge threshold, and the current is below this setting (typically 10% of battery capacity). + poll-interval: + description: + Polling interval in milliseconds. If this property is set and no interrupt + is specified, the driver will periodically check the charger status instead + of using the hardware interrupt line. Ignored if an interrupt is available. + minimum: 100 + maximum: 60000 + required: - compatible - reg - - interrupts + +anyOf: + - required: + - interrupts + - required: + - poll-interval additionalProperties: false diff --git a/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml b/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml index fc31758a40b06b..af830aabbfc9b3 100644 --- a/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/mediatek,mt2712-pwm.yaml @@ -37,6 +37,10 @@ properties: - enum: - mediatek,mt8196-pwm - const: mediatek,mt6991-pwm + - items: + - enum: + - mediatek,mt6589-pwm + - const: mediatek,mt6795-pwm reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml index 68ef30414325a5..48aff8e58e05b5 100644 --- a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml +++ b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml @@ -17,6 +17,7 @@ properties: oneOf: - enum: - mediatek,mt2701-disp-pwm + - mediatek,mt6589-disp-pwm - mediatek,mt6595-disp-pwm - mediatek,mt8173-disp-pwm - mediatek,mt8183-disp-pwm diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6320-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6320-regulator.yaml new file mode 100644 index 00000000000000..0e6454787a0fe8 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6320-regulator.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mediatek,mt6320-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6320 Regulator + +maintainers: + - Akari Tsuyukusa + +description: + Regulator function of the MT6320 PMIC. The regulators are children + of the "regulators" node; each child carries the standard regulator + properties. + +properties: + compatible: + const: mediatek,mt6320-regulator + +patternProperties: + "^(buck_vproc|buck_vsram|buck_vcore|buck_vm|buck_vio18|buck_vpa|buck_vrf18|buck_vrf18_2)$": + type: object + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + + "^ldo_(vrf28|va|va28|vcama|vrf28_2|vtcxo|vtcxo_2|vmc1|vmch1|vemc_3v3|vemc_1v8|vgp1|vgp2|vgp3|vgp4|vgp5|vgp6|vsim1|vsim2|vibr|vast)$": + type: object + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + +required: + - compatible + +additionalProperties: false + +examples: + - | + regulators { + compatible = "mediatek,mt6320-regulator"; + + buck_vproc { + regulator-name = "vproc"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + }; + + ldo_vtcxo { + regulator-name = "vtcxo"; + regulator-always-on; + }; + }; diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml index e7c4a3984c601f..0eb93817496c9a 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml @@ -19,7 +19,8 @@ description: IP Pairing - On MT8135 the pins of some SoC internal peripherals can be on the PMIC. + On MT6589 and MT8135 the pins of some SoC internal peripherals can be on the + PMIC. The signals of these pins are routed over the SPI bus using the pwrap bridge. In the binding description below the properties needed for bridging are marked with "IP Pairing". These are optional on SoCs which do not support @@ -31,6 +32,7 @@ properties: - items: - enum: - mediatek,mt2701-pwrap + - mediatek,mt6589-pwrap - mediatek,mt6765-pwrap - mediatek,mt6779-pwrap - mediatek,mt6795-pwrap diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6320-accdet.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6320-accdet.yaml new file mode 100644 index 00000000000000..896c8f469d742f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6320-accdet.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt6320-accdet.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6320 headset accessory detector + +maintainers: + - Akari Tsuyukusa + +properties: + compatible: + const: mediatek,mt6320-accdet + + detect-gpios: + maxItems: 1 + + io-channels: + maxItems: 1 + + io-channel-names: + const: key + + clocks: + maxItems: 1 + + clock-names: + const: accdet + +required: + - compatible + - detect-gpios + - io-channels + - io-channel-names + - clocks + - clock-names + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6589-audio.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6589-audio.yaml new file mode 100644 index 00000000000000..72d2190e128c8e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6589-audio.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt6589-audio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6589 Audio Front End (AFE) + +maintainers: + - Akari Tsuyukusa + +description: | + The audio front end of the MT6589 hosts the memory interfaces (DL1 + playback, VUL capture), the interconnect that routes between them, the + I2S input and output blocks, and the AFE<->PMIC serial link driven + through the audsys syscon it is a child of. + + Note that there is no ADDA block on this part: no ADDA register is + documented for the MT6589, and chapter 63's register map has nothing + between AFE_MEMIF_MON4 (0x00e0) and AFE_FOC_CON (0x0170). Sample-rate + conversion for the PMIC link is done in the MT6320 codec, not here. + +properties: + compatible: + enum: + - mediatek,mt6589-audio + + clocks: + minItems: 2 + maxItems: 2 + + clock-names: + items: + - const: afe + - const: i2s + + interrupts: + maxItems: 1 + + iram: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Genalloc-backed on-chip SRAM used for the AFE PCM DMA buffer. + +required: + - compatible + - clocks + - clock-names + - iram + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + #include + + afe_sram: sram@12008000 { + compatible = "mmio-sram"; + reg = <0x12008000 0x4000>; + }; + + audsys: clock-controller@12070000 { + compatible = "mediatek,mt6589-audsys", "syscon", "simple-mfd"; + reg = <0x12070000 0x1000>; + #clock-cells = <1>; + + afe: audio-controller { + compatible = "mediatek,mt6589-audio"; + clocks = <&audsys CLK_AUDIO_AFE>, + <&audsys CLK_AUDIO_I2S>; + clock-names = "afe", "i2s"; + iram = <&afe_sram>; + interrupts = ; + }; + }; diff --git a/Documentation/devicetree/bindings/thermal/mediatek,thermal.yaml b/Documentation/devicetree/bindings/thermal/mediatek,thermal.yaml index 7bd0955e6d045d..cdb651cd6ac8e5 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek,thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/mediatek,thermal.yaml @@ -24,6 +24,7 @@ properties: - enum: - mediatek,mt2701-thermal - mediatek,mt2712-thermal + - mediatek,mt6589-thermal - mediatek,mt7622-thermal - mediatek,mt7986-thermal - mediatek,mt8173-thermal diff --git a/Documentation/devicetree/bindings/usb/mediatek,musb.yaml b/Documentation/devicetree/bindings/usb/mediatek,musb.yaml index a39d38db771471..c827518b310f8d 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,musb.yaml +++ b/Documentation/devicetree/bindings/usb/mediatek,musb.yaml @@ -19,6 +19,7 @@ properties: - enum: - mediatek,mt8516-musb - mediatek,mt2701-musb + - mediatek,mt6589-musb - mediatek,mt7623-musb - const: mediatek,mtk-musb @@ -67,6 +68,16 @@ properties: description: Connector for dual role switch type: object + vusb-supply: + description: Regulator for USB 3.3V power + + resets: + maxItems: 1 + + reset-names: + items: + - const: hrst + dependencies: usb-role-switch: [ connector ] connector: [ usb-role-switch ] @@ -103,6 +114,7 @@ examples: <&pericfg CLK_PERI_USB_SLV>; clock-names = "main","mcu","univpll"; power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>; + vusb-supply = <&usb_vusb>; usb-role-switch; connector { diff --git a/arch/arm/boot/dts/mediatek/Makefile b/arch/arm/boot/dts/mediatek/Makefile index 37c4cded0eae8c..b67b94b7cbd018 100644 --- a/arch/arm/boot/dts/mediatek/Makefile +++ b/arch/arm/boot/dts/mediatek/Makefile @@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ mt6582-prestigio-pmt5008-3g.dtb \ mt6589-aquaris5.dtb \ mt6589-fairphone-fp1.dtb \ + mt6589-lenovo-b8000-f.dtb \ mt6592-evb.dtb \ mt7623a-rfb-emmc.dtb \ mt7623a-rfb-nand.dtb \ diff --git a/arch/arm/boot/dts/mediatek/mt6320.dtsi b/arch/arm/boot/dts/mediatek/mt6320.dtsi new file mode 100644 index 00000000000000..b7b883a875ca0c --- /dev/null +++ b/arch/arm/boot/dts/mediatek/mt6320.dtsi @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#include +#include +#include + +&pwrap { + pmic: mt6320 { + compatible = "mediatek,mt6320"; + + interrupt-parent = <&pio>; + interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <2>; + + pio6320: pinctrl { + compatible = "mediatek,mt6320-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + }; + + power-controller { + compatible = "mediatek,mt6320-pwrc", + "mediatek,mt6323-pwrc"; + #power-domain-cells = <0>; + }; + + rtc { + compatible = "mediatek,mt6320-rtc", + "mediatek,mt6397-rtc"; + }; + + mt6320keys: keys { + compatible = "mediatek,mt6320-keys"; + mediatek,long-press-mode = <1>; + power-off-time-sec = <0>; + + power { + linux,keycodes = ; + wakeup-source; + }; + + home { + linux,keycodes = ; + }; + }; + + mt6320clock: clocks { + compatible = "mediatek,mt6320-clk"; + #clock-cells = <1>; + }; + + audio-codec { + compatible = "mediatek,mt6320-sound"; + clocks = <&mt6320clock MT6320_TOPCKPDN_AUD_26M>; + clock-names = "top-aud26m"; + }; + + mt6320_accdet: accdet { + compatible = "mediatek,mt6320-accdet"; + clocks = <&mt6320clock MT6320_TOPCKPDN_ACCDET_CK>; + clock-names = "accdet"; + }; + + mt6320_adc: adc { + compatible = "mediatek,mt6320-auxadc"; + #io-channel-cells = <1>; + }; + + /* + * Expose the PMIC's own junction temperature sensor (AUXADC + * channel 4) as a hardware monitoring device so that the + * thermal framework can pick it up. + */ + efuse { + compatible = "mediatek,mt6320-efuse"; + }; + + mt6320regulator: regulators { + compatible = "mediatek,mt6320-regulator"; + + /* BUCK regulators */ + mt6320_buck_vproc: buck_vproc { + regulator-name = "vproc"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-always-on; + }; + + mt6320_buck_vsram: buck_vsram { + regulator-name = "vsram"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-always-on; + }; + + mt6320_buck_vcore: buck_vcore { + regulator-name = "vcore"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-always-on; + }; + + mt6320_buck_vm: buck_vm { + regulator-name = "vm"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1493750>; + regulator-ramp-delay = <12500>; + regulator-always-on; + }; + + mt6320_buck_vio18: buck_vio18 { + regulator-name = "vio18"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2120000>; + regulator-ramp-delay = <25000>; + regulator-always-on; + }; + + mt6320_buck_vpa: buck_vpa { + regulator-name = "vpa"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3650000>; + }; + + mt6320_buck_vrf18: buck_vrf18 { + regulator-name = "vrf18"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1825000>; + regulator-ramp-delay = <25000>; + }; + + /* TODO: add GPU OD */ + mt6320_buck_vrf18_2: buck_vrf18_2 { + regulator-name = "vrf18_2"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1825000>; + regulator-ramp-delay = <25000>; + }; + + /* Analog LDOs */ + mt6320_ldo_vrf28: ldo_vrf28 { + regulator-name = "vrf28"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2850000>; + regulator-enable-ramp-delay = <100>; + }; + + mt6320_ldo_vtcxo: ldo_vtcxo { + regulator-name = "vtcxo"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <90>; + regulator-always-on; + }; + + mt6320_ldo_va: ldo_va { + regulator-name = "va"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2500000>; + regulator-enable-ramp-delay = <216>; + regulator-always-on; + }; + + mt6320_ldo_va28: ldo_va28 { + regulator-name = "va28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <216>; + regulator-always-on; + }; + + mt6320_ldo_vcama: ldo_vcama { + regulator-name = "vcama"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vrf28_2: ldo_vrf28_2 { + regulator-name = "vrf28_2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2850000>; + regulator-enable-ramp-delay = <100>; + }; + + mt6320_ldo_vtcxo_2: ldo_vtcxo_2 { + regulator-name = "vtcxo_2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2850000>; + regulator-enable-ramp-delay = <90>; + }; + + /* Digital LDOs */ + mt6320_ldo_vio28: ldo_vio28 { + regulator-name = "vio28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <216>; + regulator-always-on; + }; + + mt6320_ldo_vusb: ldo_vusb { + regulator-name = "vusb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + regulator-boot-on; + }; + + mt6320_ldo_vmc1: ldo_vmc1 { + regulator-name = "vmc1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <36>; + regulator-boot-on; + }; + + mt6320_ldo_vmch1: ldo_vmch1 { + regulator-name = "vmch1"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <36>; + regulator-boot-on; + }; + + mt6320_ldo_vemc_3v3: ldo_vemc_3v3 { + regulator-name = "vemc_3v3"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <36>; + regulator-boot-on; + }; + + mt6320_ldo_vemc_1v8: ldo_vemc_1v8 { + regulator-name = "vemc_1v8"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <36>; + regulator-boot-on; + }; + + mt6320_ldo_vgp1: ldo_vgp1 { + regulator-name = "vgp1"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vgp2: ldo_vgp2 { + regulator-name = "vgp2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vgp3: ldo_vgp3 { + regulator-name = "vgp3"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vgp4: ldo_vgp4 { + regulator-name = "vgp4"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vgp5: ldo_vgp5 { + regulator-name = "vgp5"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vgp6: ldo_vgp6 { + regulator-name = "vgp6"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vsim1: ldo_vsim1 { + regulator-name = "vsim1"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vsim2: ldo_vsim2 { + regulator-name = "vsim2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <216>; + }; + + mt6320_ldo_vibr: ldo_vibr { + regulator-name = "vibr"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <36>; + }; + + mt6320_ldo_vrtc: ldo_vrtc { + regulator-name = "vrtc"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + mt6320_ldo_vast: ldo_vast { + regulator-name = "vast"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1200000>; + regulator-enable-ramp-delay = <216>; + }; + }; + }; +}; + +&pio6320 { + mt6320_i2c0_pins: i2c0_pins-default { + pin-i2c0{ + pinmux = , + ; + bias-pull-up; + }; + }; + + mt6320_i2c1_pins: i2c1-default { + pin-i2c1 { + pinmux = , + ; + bias-pull-up; + }; + }; + + mt6320_i2c2_pins: i2c2-default { + pin-i2c2 { + pinmux = , + ; + bias-pull-up; + }; + }; +}; diff --git a/arch/arm/boot/dts/mediatek/mt6589-lenovo-b6000.dtsi b/arch/arm/boot/dts/mediatek/mt6589-lenovo-b6000.dtsi new file mode 100644 index 00000000000000..d9cc6b3417455d --- /dev/null +++ b/arch/arm/boot/dts/mediatek/mt6589-lenovo-b6000.dtsi @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#include "mt6589-lenovo-blade.dtsi" + +/ { + // TODO: recheck it + framebuffer0: framebuffer@bf600000 { + compatible = "simple-framebuffer"; + memory-region = <&framebuffer_reserved>; + width = <800>; + height = <1280>; + stride = <(800 * 2)>; + format = "r5g6b5"; + }; + + battery: battery { + compatible = "simple-battery"; + device-chemistry = "lithium-ion-polymer"; + + charge-full-design-microamp-hours = <6000000>; + energy-full-design-microwatt-hours = <22500000>; + + /* + * Stock fuel-gauge voltage/SOC table uses 3400mV as 0%. + * This is a vendor software threshold, not a proven + * physical cell absolute minimum voltage. + */ + voltage-min-design-microvolt = <3400000>; + + /* + * Full-charge/design maximum voltage. The stock BQ24196 + * configuration programs VREG to 4.352V. + */ + voltage-max-design-microvolt = <4352000>; + + /* BQ24196 stock configuration. */ + precharge-current-microamp = <256000>; + charge-term-current-microamp = <256000>; + + constant-charge-voltage-max-microvolt = <4352000>; + }; +}; + +&bq27541 { + monitored-battery = <&battery>; +}; + +&bq24196 { + monitored-battery = <&battery>; +}; diff --git a/arch/arm/boot/dts/mediatek/mt6589-lenovo-b8000-f.dts b/arch/arm/boot/dts/mediatek/mt6589-lenovo-b8000-f.dts new file mode 100644 index 00000000000000..e00f88ddc3ff5f --- /dev/null +++ b/arch/arm/boot/dts/mediatek/mt6589-lenovo-b8000-f.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#include "mt6589-lenovo-b8000.dtsi" + +/ { + model = "Lenovo YOGA Tablet 10 (Wi-Fi)"; + compatible = "lenovo,b8000-f", "mediatek,mt6589"; +}; diff --git a/arch/arm/boot/dts/mediatek/mt6589-lenovo-b8000.dtsi b/arch/arm/boot/dts/mediatek/mt6589-lenovo-b8000.dtsi new file mode 100644 index 00000000000000..ca134aac10dcae --- /dev/null +++ b/arch/arm/boot/dts/mediatek/mt6589-lenovo-b8000.dtsi @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#include "mt6589-lenovo-blade.dtsi" + +/ { + framebuffer0: framebuffer@bf600000 { + compatible = "simple-framebuffer"; + memory-region = <&framebuffer_reserved>; + width = <1280>; + height = <800>; + stride = <(1280 * 2)>; + format = "r5g6b5"; + }; + + battery: battery { + compatible = "simple-battery"; + device-chemistry = "lithium-ion-polymer"; + + charge-full-design-microamp-hours = <9000000>; + energy-full-design-microwatt-hours = <33750000>; + + /* + * Stock fuel-gauge voltage/SOC table uses 3400mV as 0%. + * This is a vendor software threshold, not a proven + * physical cell absolute minimum voltage. + */ + voltage-min-design-microvolt = <3400000>; + + /* + * Full-charge/design maximum voltage. The stock BQ24196 + * configuration programs VREG to 4.352V. + */ + voltage-max-design-microvolt = <4352000>; + + /* BQ24196 stock configuration. */ + precharge-current-microamp = <512000>; + charge-term-current-microamp = <256000>; + + constant-charge-voltage-max-microvolt = <4352000>; + }; +}; + +&bq27541 { + monitored-battery = <&battery>; +}; + +&bq24196 { + monitored-battery = <&battery>; +}; diff --git a/arch/arm/boot/dts/mediatek/mt6589-lenovo-blade.dtsi b/arch/arm/boot/dts/mediatek/mt6589-lenovo-blade.dtsi new file mode 100644 index 00000000000000..c74efa98a8ace2 --- /dev/null +++ b/arch/arm/boot/dts/mediatek/mt6589-lenovo-blade.dtsi @@ -0,0 +1,524 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +/dts-v1/; +#include +#include + +#include "mt6589.dtsi" +#include "mt6320.dtsi" + +#include + +/ { + chosen { + /* DEBUG: testing clock drivers */ + bootargs = "clk_ignore_unused printk.always_kmsg_dump=1 log_buf_len=16M"; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + ranges; + + /* + * The SoC's ramoops in 7 KiB of SRAM cannot hold one oops. Use + * 1 MiB of DRAM right below LK's framebuffer instead, which LK + * and the kernel leave alone across a warm reset. + */ + /delete-node/ ramoops@10dc00; + + ramoops@bf500000 { + compatible = "ramoops"; + reg = <0xbf500000 0x100000>; + record-size = <0x8000>; + console-size = <0x40000>; + ecc-size = <16>; + no-map; + }; + + framebuffer_reserved: memory@bf600000{ + reg = <0xbf600000 0xa00000>; + no-map; + }; + }; + + sound: sound { + compatible = "mediatek,mt6589-mt6320-sound"; + mediatek,platform = <&afe>; + aux-devs = <&mt6320_accdet>; + }; +}; + +&cpu0 { + proc-supply = <&mt6320_buck_vproc>; + sram-supply = <&mt6320_buck_vsram>; +}; + +&cpu1 { + proc-supply = <&mt6320_buck_vproc>; + sram-supply = <&mt6320_buck_vsram>; +}; + +&cpu2 { + proc-supply = <&mt6320_buck_vproc>; + sram-supply = <&mt6320_buck_vsram>; +}; + +&cpu3 { + proc-supply = <&mt6320_buck_vproc>; + sram-supply = <&mt6320_buck_vsram>; +}; + +&pio { + pmic_eint_pins: pmic-eint-pins { + pin-pmic-eint { + pinmux = ; + input-enable; + }; + }; + + alsps_eint_pins: alsps-eint-pins { + pin-alsps-int { + pinmux = ; + input-enable; + bias-pull-up; + }; + }; + + usb_pins: usb-pins { + pins_iddig { + pinmux = ; + bias-pull-up; + input-enable; + }; + + pins_eint34_conflict { + pinmux = ; + bias-pull-up; + input-enable; + input-schmitt-enable; + }; + + pins_drvvbus { + pinmux = ; + }; + }; + + ts_pins: touchscreen-default { + pin-int { + pinmux = ; + input-enable; + bias-pull-up; + }; + + pin-reset { + pinmux = ; + output-high; + }; + }; + + accdet_pins: accdet-pins { + pin-accdet { + pinmux = ; + input-enable; + bias-pull-up; + }; + }; +}; + +&pmic { + pinctrl-names = "default"; + pinctrl-0 = <&pmic_eint_pins>; +}; + +&mt6320_accdet { + pinctrl-names = "default"; + pinctrl-0 = <&accdet_pins>; + detect-gpios = <&pio 115 GPIO_ACTIVE_LOW>; + io-channels = <&mt6320_adc 5>; + io-channel-names = "key"; +}; + +&mt6320_ldo_vgp4 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; +}; + +&mt6320_ldo_vgp6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + +&usb0 { + status = "okay"; + usb-role-switch; + vusb-supply = <&mt6320_ldo_vusb>; + pinctrl-names = "default"; + pinctrl-0 = <&usb_pins>; + + connector { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + type = "micro"; + id-gpios = <&pio 57 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb_otg_vbus>; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + // clock-frequency = <400000>; + + /* Synaptics ClearPad 7300 */ + touchscreen@38 { + compatible = "syna,rmi4-i2c"; + reg = <0x38>; + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&ts_pins>; + + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&pio>; + + reset-gpios = <&pio 140 GPIO_ACTIVE_LOW>; + + vdd-supply = <&mt6320_ldo_vgp4>; + vio-supply = <&mt6320_ldo_vgp6>; + + syna,startup-delay-ms = <10>; + syna,reset-delay-ms = <50>; + syna,reset-after-power-on; + syna,initial-reset-control = <0x80>; + syna,initial-reset-delay-ms = <200>; + + rmi4-f01@1 { + reg = <0x1>; + }; + + rmi4-f11@11 { + reg = <0x11>; + syna,sensor-type = <1>; + }; + + rmi4-f34@34 { + reg = <0x34>; + }; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + clock-frequency = <100000>; + + accelerometer@11 { + compatible = "bosch,bma255"; + reg = <0x11>; + + // TODO: check + vdd-supply = <&mt6320_ldo_vio28>; + vddio-supply = <&mt6320_buck_vio18>; + // mount-matrix = ?; + }; + + magnetometer@13 { + compatible = "bosch,bmm150"; + reg = <0x13>; + + // TODO: check + vdd-supply = <&mt6320_ldo_vio28>; + vddio-supply = <&mt6320_buck_vio18>; + // mount-matrix = ? + }; + + light-sensor@1c { + compatible = "dynaimage,al3320b"; + reg = <0x1c>; + pinctrl-names = "default"; + pinctrl-0 = <&alsps_eint_pins>; + + vdd-supply = <&mt6320_buck_vio18>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&pio>; + }; +}; + +&i2c4 { + status = "okay"; + clocks = <&pericfg CLK_PERI0_I2C4>, + <&mt6320clock MT6320_WRPCKPDN_I2C0>, + <&pericfg CLK_PERI0_APDMA>; + pinctrl-names = "default"; + pinctrl-0 = <&mt6320_i2c0_pins>; + clock-frequency = <100000>; + + bq27541: fuel-gauge@55 { + compatible = "ti,bq27541"; + reg = <0x55>; + }; +}; + +&i2c5 { + status = "okay"; + clocks = <&pericfg CLK_PERI0_I2C5>, + <&mt6320clock MT6320_WRPCKPDN_I2C1>, + <&pericfg CLK_PERI0_APDMA>; + pinctrl-names = "default"; + pinctrl-0 = <&mt6320_i2c1_pins>; +}; + +&i2c6 { + status = "okay"; + clocks = <&pericfg CLK_PERI1_I2C6>, + <&mt6320clock MT6320_WRPCKPDN_I2C2>, + <&pericfg CLK_PERI0_APDMA>; + pinctrl-names = "default"; + pinctrl-0 = <&mt6320_i2c2_pins>; + clock-frequency = <100000>; + + bq24196: charger@6b { + compatible = "ti,bq24196"; + reg = <0x6b>; + + poll-interval = <10000>; + + // interrupts = ; // KP row2 R1? + interrupt-parent = <&pio>; + + // ce-gpios = ??; // KP col7 P5? + + ti,system-minimum-microvolt = <3700000>; + + usb_otg_vbus: usb-otg-vbus { }; + }; +}; + +&uart0 { + status = "okay"; +}; + +/* Internal storage */ +&mmc0 { + status = "okay"; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + vmmc-supply = <&mt6320_ldo_vemc_3v3>; + vqmmc-supply = <&mt6320_ldo_vemc_1v8>; + + non-removable; + no-sd; + no-sdio; + bus-width = <8>; + + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-ddr-1_8v; + + #address-cells = <1>; + #size-cells = <0>; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <2>; + #size-cells = <2>; + + partition@1e0000 { + label = "MBR"; + reg = <0x00000000 0x001e0000 0x00000000 0x00080000>; + }; + + partition@260000 { + label = "EBR1"; + reg = <0x00000000 0x00260000 0x00000000 0x00080000>; + }; + + partition@2e0000 { + label = "__NODL_PMT"; + reg = <0x00000000 0x002e0000 0x00000000 0x00400000>; + }; + + partition@6e0000 { + label = "__NODL_PRO_INFO"; + reg = <0x00000000 0x006e0000 0x00000000 0x00300000>; + }; + + partition@9e0000 { + label = "__NODL_NVRAM"; + reg = <0x00000000 0x009e0000 0x00000000 0x00500000>; + }; + + partition@ee0000 { + label = "__NODL_PROTECT_F"; + reg = <0x00000000 0x00ee0000 0x00000000 0x00a00000>; + }; + + partition@18e0000 { + label = "__NODL_PROTECT_S"; + reg = <0x00000000 0x018e0000 0x00000000 0x00a00000>; + }; + + partition@22e0000 { + label = "__NODL_SECCFG"; + reg = <0x00000000 0x022e0000 0x00000000 0x00020000>; + }; + + partition@2300000 { + label = "UBOOT"; + reg = <0x00000000 0x02300000 0x00000000 0x00060000>; + }; + + partition@2360000 { + label = "BOOTIMG"; + reg = <0x00000000 0x02360000 0x00000000 0x00600000>; + }; + + partition@2960000 { + label = "RECOVERY"; + reg = <0x00000000 0x02960000 0x00000000 0x00600000>; + }; + + partition@2f60000 { + label = "SEC_RO"; + reg = <0x00000000 0x02f60000 0x00000000 0x00600000>; + }; + + partition@3560000 { + label = "__NODL_MISC"; + reg = <0x00000000 0x03560000 0x00000000 0x00080000>; + }; + + partition@35e0000 { + label = "LOGO"; + reg = <0x00000000 0x035e0000 0x00000000 0x00300000>; + }; + + partition@38e0000 { + label = "EBR2"; + reg = <0x00000000 0x038e0000 0x00000000 0x00080000>; + }; + + partition@3960000 { + label = "__NODL_EXPDB"; + reg = <0x00000000 0x03960000 0x00000000 0x00a00000>; + }; + + partition@4360000 { + label = "FAC"; + reg = <0x00000000 0x04360000 0x00000000 0x0c800000>; + }; + + partition@10b60000 { + label = "ANDROID"; + reg = <0x00000000 0x10b60000 0x00000000 0x40000000>; + }; + + partition@50b60000 { + label = "CACHE"; + reg = <0x00000000 0x50b60000 0x00000000 0x07e00000>; + }; + + partition@58960000 { + label = "USRDATA"; + reg = <0x00000000 0x58960000 0x00000003 0x49fa0000>; + }; + + partition@3a2900000 { + label = "__NODL_BMTPOOL"; + reg = <0x00000003 0xa2900000 0x00000000 0x01500000>; + }; + }; + }; +}; + +/* SD Card */ +&mmc1 { + status = "okay"; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_uhs>; + vmmc-supply = <&mt6320_ldo_vmch1>; + vqmmc-supply = <&mt6320_ldo_vmc1>; + + bus-width = <4>; + no-mmc; + no-sdio; + /* TODO: recheck */ + cd-gpios = <&pio 171 GPIO_ACTIVE_HIGH>; + + max-frequency = <200000000>; + cap-sd-highspeed; + sd-uhs-sdr104; + sd-uhs-sdr50; + sd-uhs-ddr50; +}; + +/* SDIO */ +&mmc3 { + status = "disabled"; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc3_pins_default>; + pinctrl-1 = <&mmc3_pins_uhs>; + /* FIXME: always 1.8V? */ + vmmc-supply = <&mt6320_ldo_vemc_3v3>; + vqmmc-supply = <&mt6320_ldo_vemc_1v8>; + + bus-width = <4>; + cap-sdio-irq; + non-removable; + no-mmc; + no-sd; + + max-frequency = <200000000>; + cap-sd-highspeed; + sd-uhs-sdr104; + sd-uhs-sdr50; + sd-uhs-ddr50; +}; + +&keyboard { + status = "okay"; + linux,keymap = ; + keypad,num-rows = <1>; + keypad,num-columns = <3>; + debounce-delay-ms = <32>; +}; + +&pwm { + status = "okay"; +}; + +&bls { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/mediatek/mt6589.dtsi b/arch/arm/boot/dts/mediatek/mt6589.dtsi index c6babc8ad2ba6c..d613d36a9569c7 100644 --- a/arch/arm/boot/dts/mediatek/mt6589.dtsi +++ b/arch/arm/boot/dts/mediatek/mt6589.dtsi @@ -7,6 +7,13 @@ #include #include +#include +#include +#include +#include +#include +#include +#include / { #address-cells = <1>; @@ -14,32 +21,209 @@ compatible = "mediatek,mt6589"; interrupt-parent = <&sysirq>; + cpu_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; + + /* + * CONFIG_MTK_FORCE_CPU_89T : 1.5 GHz : PTP 3 + * bit 0 : free mode : ptp_free_grade + * bit 1 : 1.5 GHz : PTP 3 : mt6589_freqs_e1_2 + * bit 2 : 1.4 GHz : PTP 2 : mt6589_freqs_e1_3 + * bit 3 : 1.3 GHz : PTP 1 : mt6589_freqs_e1_4 + * bit 4 : 1.2 GHz : PTP 0 : mt6589_freqs_e1 + * bit 5 : 1.1 GHz : PTP 8 : mt6589_freqs_e1 (fallback) + * bit 6 : 1.0 GHz : PTP 9 : mt6589_freqs_e1_5 + * bit 7 : 1.0 GHz : PTP 10: mt6589_freqs_e1 (fallback) + * ----- : ------- : PTP 4 : mt6589_freqs_e1_1 + * ----- : ------- : PTP 5 : mt6589_freqs_e1_0 + ** preloader + * 6, 7 : 806 MHz + * other : 1001MHz + */ + + opp-497250000 { + opp-hz = /bits/ 64 <497250000>; + opp-microvolt = <950000>; + opp-supported-hw = <0xff>; /* bits 0-7 */ + }; + + opp-754000000 { + opp-hz = /bits/ 64 <754000000>; + opp-microvolt = <1050000>; + opp-supported-hw = <0xff>; + }; + + /* TODO: can bit 6 hw run this freq with 1.15 V ? */ + opp-806000000 { + opp-hz = /bits/ 64 <806000000>; + opp-microvolt = <1150000>; + opp-supported-hw = <0xff>; + }; + + opp-988000000-1150 { + opp-hz = /bits/ 64 <988000000>; + opp-microvolt = <1150000>; + opp-supported-hw = <0xbf>; /* bits 0-5,7 */ + }; + + opp-988000000-1200 { + opp-hz = /bits/ 64 <988000000>; + opp-microvolt = <1200000>; + opp-supported-hw = <0x40>; /* bit 6 */ + }; + + opp-1001000000 { + opp-hz = /bits/ 64 <1001000000>; + opp-microvolt = <1150000>; + opp-supported-hw = <0x3f>; /* bits 0-5 */ + }; + + opp-1209000000 { + opp-hz = /bits/ 64 <1209000000>; + opp-microvolt = <1200000>; + opp-supported-hw = <0xbf>; + }; + + opp-1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-microvolt = <1250000>; + opp-supported-hw = <0x0f>; /* bits 0-3 */ + }; + + opp-1404000000 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <1250000>; + opp-supported-hw = <0x07>; /* bits 0-2 */ + }; + + opp-1508000000 { + opp-hz = /bits/ 64 <1508000000>; + opp-microvolt = <1250000>; + opp-supported-hw = <0x03>; /* bits 0-1 */ + }; + + /* + * TODO: check devinfo[10][6:4] (ptp-free@120) + */ + // opp-1599000000 { + // opp-hz = /bits/ 64 <1599000000>; + // opp-microvolt = <1250000>; + // opp-supported-hw = <0x01>; /* bit 0 */ + // }; + + // opp-1703000000 { + // opp-hz = /bits/ 64 <1703000000>; + // opp-microvolt = <1250000>; + // opp-supported-hw = <0x01>; /* bit 0 */ + // }; + }; + cpus: cpus { #address-cells = <1>; #size-cells = <0>; enable-method = "mediatek,mt6589-smp"; - cpu@0 { + cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x0>; + + i-cache-size = <32768>; + i-cache-line-size = <32>; + i-cache-sets = <512>; + d-cache-size = <32768>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; + + clocks = <&infracfg CLK_INFRA_MUX1>, + <&clk26m>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cpu_opp_table>; + nvmem-cells = <&chip_grade>; + nvmem-cell-names = "speed_grade"; }; - cpu@1 { + cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x1>; + + i-cache-size = <32768>; + i-cache-line-size = <32>; + i-cache-sets = <512>; + d-cache-size = <32768>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; + + clocks = <&infracfg CLK_INFRA_MUX1>, + <&clk26m>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cpu_opp_table>; + nvmem-cells = <&chip_grade>; + nvmem-cell-names = "speed_grade"; }; - cpu@2 { + cpu2: cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x2>; + + i-cache-size = <32768>; + i-cache-line-size = <32>; + i-cache-sets = <512>; + d-cache-size = <32768>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; + + clocks = <&infracfg CLK_INFRA_MUX1>, + <&clk26m>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cpu_opp_table>; + nvmem-cells = <&chip_grade>; + nvmem-cell-names = "speed_grade"; }; - cpu@3 { + cpu3: cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x3>; + + i-cache-size = <32768>; + i-cache-line-size = <32>; + i-cache-sets = <512>; + d-cache-size = <32768>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2>; + + clocks = <&infracfg CLK_INFRA_MUX1>, + <&clk26m>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cpu_opp_table>; + nvmem-cells = <&chip_grade>; + nvmem-cell-names = "speed_grade"; }; + l2: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <2048>; + cache-unified; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + clock-frequency = <13000000>; + arm,cpu-registers-not-fw-configured; }; clocks { @@ -48,6 +232,13 @@ compatible = "simple-bus"; ranges; + clk26m: oscillator@0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "clk26m"; + }; + system_clk: dummy13m { compatible = "fixed-clock"; clock-frequency = <13000000>; @@ -57,13 +248,45 @@ rtc_clk: dummy32k { compatible = "fixed-clock"; clock-frequency = <32000>; + clock-output-names = "rtc_clk"; #clock-cells = <0>; }; + }; - uart_clk: dummy26m { - compatible = "fixed-clock"; - clock-frequency = <26000000>; - #clock-cells = <0>; + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + + thermal-sensors = <&thermal 0>; + + trips { + cpu_alert: cpu-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_crit: cpu-crit { + temperature = <115000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* part of on-chip sram */ + ramoops@10dc00 { + compatible = "ramoops"; + reg = <0x0010dc00 0x1c00>; + record-size = <0x400>; + console-size = <0x1000>; }; }; @@ -73,14 +296,705 @@ compatible = "simple-bus"; ranges; + bootrom@0 { + compatible = "mediatek,mt6589-efuse", + "mediatek,mt6572-efuse"; + reg = <0x00000000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + /* + * 0x08000000 CHIP_ID 0x8a006583 Main(0x6583) / Sub(0x8a00) + * 0x08000004 CHIP_VER 0x0000ca00 HW ID(0xca00) / SW ID(0x0000) + */ + chipid@08000000 { + compatible = "mediatek,mt6589-efuse", + "mediatek,mt6572-efuse"; + reg = <0x08000000 0xc>; + #address-cells = <1>; + #size-cells = <1>; + + chip-id@0 { + reg = <0x0 0x4>; + }; + + chip-ver@4 { + reg = <0x4 0x4>; + }; + }; + + wdt: watchdog@10000000 { + compatible = "mediatek,mt6589-wdt"; + reg = <0x10000000 0x44>; + #reset-cells = <1>; + }; + + topckgen: syscon@10000100 { + compatible = "mediatek,mt6589-topckgen", "syscon"; + reg = <0x10000100 0x7c>; + #clock-cells = <1>; + }; + + infracfg: syscon@10001000 { + compatible = "mediatek,mt6589-infracfg", "syscon"; + reg = <0x10001000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pericfg: syscon@10003000 { + compatible = "mediatek,mt6589-pericfg", "syscon"; + reg = <0x10003000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + scpsys: syscon@10006000 { + compatible = "mediatek,mt6589-scpsys", "syscon", "simple-mfd"; + reg = <0x10006000 0x1000>; + + spm: power-controller { + compatible = "mediatek,mt6589-power-controller"; + #address-cells = <1>; + #size-cells = <0>; + #power-domain-cells = <1>; + + power-domain@MT6589_POWER_DOMAIN_MD1 { + reg = ; + #power-domain-cells = <0>; + mediatek,infracfg = <&infracfg>; + }; + + power-domain@MT6589_POWER_DOMAIN_MD2 { + reg = ; + #power-domain-cells = <0>; + mediatek,infracfg = <&infracfg>; + }; + + power-domain@MT6589_POWER_DOMAIN_DPY { + reg = ; + #power-domain-cells = <0>; + }; + + power-domain@MT6589_POWER_DOMAIN_DIS { + reg = ; + clocks = <&topckgen CLK_TOP_MUX_DISP>; + clock-names = "disp"; + #power-domain-cells = <0>; + }; + + power-domain@MT6589_POWER_DOMAIN_MFG { + reg = ; + clocks = <&topckgen CLK_TOP_MUX_MFG>, + <&topckgen CLK_TOP_MUX_SMI_MFG_AS>; + clock-names = "mfg", "mfg_as"; + #power-domain-cells = <0>; + mediatek,infracfg = <&infracfg>; + }; + + power-domain@MT6589_POWER_DOMAIN_ISP { + reg = ; + #power-domain-cells = <0>; + }; + + power-domain@MT6589_POWER_DOMAIN_IFR { + reg = ; + #power-domain-cells = <0>; + }; + + power-domain@MT6589_POWER_DOMAIN_VEN { + reg = ; + clocks = <&topckgen CLK_TOP_MUX_VENC>; + clock-names = "venc"; + #power-domain-cells = <0>; + }; + + power-domain@MT6589_POWER_DOMAIN_VDE { + reg = ; + clocks = <&topckgen CLK_TOP_MUX_VDEC>; + clock-names = "vdec"; + #power-domain-cells = <0>; + }; + }; + }; + + efuse: efuse@10009000 { + compatible = "mediatek,mt6589-efuse", + "mediatek,mt6572-efuse"; + reg = <0x10009000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + cell@20 { + reg = <0x20 0x4>; + }; + + cell@30 { + reg = <0x30 0x4>; + }; + + cell@38 { + reg = <0x38 0x4>; + }; + + /* + * bit[2:0] chip_grade + * + * bit[27:24] core_count_flag + * 0x0 : 4 cores + * others: 2 cores + */ + chip_grade: chip-grade@40 { + reg = <0x40 0x4>; + bits = <0 3>; + }; + + core_count_flag: core-count@40 { + reg = <0x40 0x4>; + bits = <24 4>; + }; + + cell@40 { + reg = <0x40 0x4>; + }; + + cell@44 { + reg = <0x44 0x4>; + }; + + cell@48 { + reg = <0x48 0x4>; + }; + + /* + * Secure boot flag + * bit[1] sbc_enabled Secure Boot Check + * bit[2] daa_enabled Device Authentication Auth + * bit[3] sla_enabled Secure Lock Auth + */ + sbc_enabled: sbc@60 { + reg = <0x60 0x4>; + bits = <1 1>; + }; + + daa_enabled: daa@60 { + reg = <0x60 0x4>; + bits = <2 1>; + }; + + sla_enabled: sla@60 { + reg = <0x60 0x4>; + bits = <3 1>; + }; + + thermal_cal_data: thermal-cal@100 { + reg = <0x100 0xc>; + }; + + dis_3g: dis-3g@100 { + reg = <0x100 0x4>; + bits = <24 1>; + }; + + ptp_free_grade: ptp-free@120 { + reg = <0x120 0x4>; + bits = <4 3>; + }; + + cell@120 { + reg = <0x120 0x4>; + }; + + cell@130 { + reg = <0x130 0x4>; + }; + + usb_serial_lo: usb-serial-lo@140 { + reg = <0x140 0x4>; + }; + + usb_serial_hi: usb-serial-hi@144 { + reg = <0x144 0x4>; + }; + + /* + * bit[15:13] RG_USB20_TERM_VREF_SEL offset (3bit) + * bit[12:10] RG_USB20_CLKREF_REF offset (3bit) + * bit[9:7] RG_USB20_VRT_VREF_SEL offset (3bit) + */ + usb_term_vref: usb-term-vref@170 { + reg = <0x170 0x2>; + bits = <13 3>; + }; + + usb_clkref: usb-clkref@170 { + reg = <0x170 0x2>; + bits = <10 3>; + }; + + usb_vrt_vref: usb-vrt-vref@170 { + reg = <0x170 0x2>; + bits = <7 3>; + }; + + cell@170 { + reg = <0x170 0x4>; + }; + + cell@174 { + reg = <0x174 0x4>; + }; + + ptp_od_data: ptp-od@178 { + reg = <0x178 0x10>; + }; + + ptp_initen: ptp-initen@178 { + reg = <0x178 0x4>; + bits = <0 1>; + }; + + ptp_monen: ptp-monen@178 { + reg = <0x178 0x4>; + bits = <1 1>; + }; + + ptp_mdes: ptp-mdes@178 { + reg = <0x178 0x4>; + bits = <8 8>; + }; + + ptp_bdes: ptp-bdes@178 { + reg = <0x178 0x4>; + bits = <16 8>; + }; + + ptp_dcmdet: ptp-dcmdet@178 { + reg = <0x178 0x4>; + bits = <24 8>; + }; + + ptp_dcconfig: ptp-dcconfig@17c { + reg = <0x17c 0x4>; + bits = <0 24>; + }; + + ptp_dcbdet: ptp-dcbdet@17c { + reg = <0x17c 0x4>; + bits = <24 8>; + }; + + ptp_ageconfig: ptp-ageconfig@180 { + reg = <0x180 0x4>; + bits = <0 24>; + }; + + ptp_agem: ptp-agem@180 { + reg = <0x180 0x4>; + bits = <24 8>; + }; + + ptp_agedelta: ptp-agedelta@184 { + reg = <0x184 0x4>; + bits = <0 8>; + }; + + ptp_dvtfixed: ptp-dvtfixed@184 { + reg = <0x184 0x4>; + bits = <8 8>; + }; + + ptp_mtdes: ptp-mtdes@184 { + reg = <0x184 0x4>; + bits = <16 8>; + }; + + ptp_vco: ptp-vco@184 { + reg = <0x184 0x4>; + bits = <24 8>; + }; + + cell@178 { + reg = <0x178 0x4>; + }; + + cell@17c { + reg = <0x17c 0x4>; + }; + + cell@180 { + reg = <0x180 0x4>; + }; + + cell@184 { + reg = <0x184 0x4>; + }; + + cell@188 { + reg = <0x188 0x4>; + }; + }; + + keyboard: keyboard@10015000 { + compatible = "mediatek,mt6589-keypad", + "mediatek,mt6779-keypad"; + reg = <0x10015000 0x1000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_KP>; + clock-names = "kpd"; + status = "disabled"; + }; + + mcusys: syscon@10200000 { + compatible = "mediatek,mt6589-mcusys", "syscon"; + reg = <0x10200000 0x1000>; + }; + + mfgsys: syscon@10206000 { + compatible = "mediatek,mt6589-mfgsys", "syscon"; + reg = <0x10206000 0x1000>; + #clock-cells = <1>; + }; + + apmixedsys: syscon@10209000 { + compatible = "mediatek,mt6589-apmixedsys", "syscon"; + reg = <0x10209000 0x1000>; + #clock-cells = <1>; + }; + + auxadc: adc@11003000 { + compatible = "mediatek,mt6589-auxadc"; + reg = <0x11003000 0x1000>; + clocks = <&pericfg CLK_PERI1_AUXADC>; + clock-names = "main"; + #io-channel-cells = <1>; + }; + + thermal: thermal@1100c000 { + compatible = "mediatek,mt6589-thermal"; + reg = <0x1100c000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_THERM>, + <&pericfg CLK_PERI1_AUXADC>; + clock-names = "therm", "auxadc"; + mediatek,auxadc = <&auxadc>; + mediatek,apmixedsys = <&apmixedsys>; + nvmem-cells = <&thermal_cal_data>; + nvmem-cell-names = "calibration-data"; + #thermal-sensor-cells = <1>; + }; + + jpgdec: jpeg-decoder@15009000 { + compatible = "mediatek,mt6589-jpgdec"; + reg = <0x15009000 0x1000>; + interrupts = ; + clocks = <&imgsys CLK_IMAGE_JPGD_SMI>, + <&imgsys CLK_IMAGE_JPGD_JPG>; + clock-names = "jpgdec-smi", + "jpgdec"; + power-domains = <&spm MT6589_POWER_DOMAIN_ISP>; + iommus = <&iommu MT6589_M4U_PORT_JPGDEC_WDMA>, + <&iommu MT6589_M4U_PORT_JPGDEC_BSDMA>; + }; + + jpgenc: jpeg-encoder@1500a000 { + compatible = "mediatek,mt6589-jpgenc", + "mediatek,mtk-jpgenc"; + reg = <0x1500a000 0x1000>; + interrupts = ; + clocks = <&imgsys CLK_IMAGE_JPGE_SMI>, + <&imgsys CLK_IMAGE_JPGE_JPG>; + clock-names = "jpgenc-smi", + "jpgenc"; + power-domains = <&spm MT6589_POWER_DOMAIN_ISP>; + iommus = <&iommu MT6589_M4U_PORT_JPGENC_RDMA>, + <&iommu MT6589_M4U_PORT_JPGENC_BSDMA>; + }; + + afe_sram: sram@12008000 { + compatible = "mmio-sram"; + reg = <0x12008000 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x12008000 0x4000>; + no-memory-wc; + }; + + audsys: syscon@12070000 { + compatible = "mediatek,mt6589-audsys", "syscon", + "simple-mfd"; + reg = <0x12070000 0x1000>; + #clock-cells = <1>; + + afe: audio-controller { + compatible = "mediatek,mt6589-audio"; + clocks = <&audsys CLK_AUDIO_AFE>, + <&audsys CLK_AUDIO_I2S>; + clock-names = "afe", "i2s"; + iram = <&afe_sram>; + interrupts = ; + }; + }; + + pwm: pwm@1100b000 { + compatible = "mediatek,mt6589-pwm", + "mediatek,mt6795-pwm"; + reg = <0x1100b000 0x1000>; + #pwm-cells = <2>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_PWM>, + <&pericfg CLK_PERI0_PWM>, + <&pericfg CLK_PERI0_PWM1>, + <&pericfg CLK_PERI0_PWM2>, + <&pericfg CLK_PERI0_PWM3>, + <&pericfg CLK_PERI0_PWM4>, + <&pericfg CLK_PERI0_PWM5>, + <&pericfg CLK_PERI0_PWM6>, + <&pericfg CLK_PERI0_PWM7>; + clock-names = "top", "main", "pwm1", "pwm2", "pwm3", + "pwm4", "pwm5", "pwm6", "pwm7"; + status = "disabled"; + }; + + i2c0: i2c@1100d000 { + compatible = "mediatek,mt6589-i2c"; + reg = <0x1100d000 0x1000>, + <0x11000300 0x80>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_I2C0>, + <&pericfg CLK_PERI0_APDMA>; + clock-names = "main", "dma"; + clock-div = <16>; + resets = <&pericfg MT6589_PERI_I2C0_SW_RST>; + reset-names = "reset"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c@1100e000 { + compatible = "mediatek,mt6589-i2c"; + reg = <0x1100e000 0x1000>, + <0x11000380 0x80>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_I2C1>, + <&pericfg CLK_PERI0_APDMA>; + clock-names = "main", "dma"; + clock-div = <16>; + resets = <&pericfg MT6589_PERI_I2C1_SW_RST>; + reset-names = "reset"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c@1100f000 { + compatible = "mediatek,mt6589-i2c"; + reg = <0x1100f000 0x1000>, + <0x11000400 0x80>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_I2C2>, + <&pericfg CLK_PERI0_APDMA>; + clock-names = "main", "dma"; + clock-div = <16>; + resets = <&pericfg MT6589_PERI_I2C2_SW_RST>; + reset-names = "reset"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c3: i2c@11010000 { + compatible = "mediatek,mt6589-i2c"; + reg = <0x11010000 0x1000>, + <0x11000480 0x80>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_I2C3>, + <&pericfg CLK_PERI0_APDMA>; + clock-names = "main", "dma"; + clock-div = <16>; + resets = <&pericfg MT6589_PERI_I2C3_SW_RST>; + reset-names = "reset"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c4: i2c@11011000 { + compatible = "mediatek,mt6589-i2c"; + reg = <0x11011000 0x1000>, + <0x11000500 0x80>; + interrupts = ; + clock-names = "main", "pmic", "dma"; + clock-div = <1>; + resets = <&pericfg MT6589_PERI_I2C4_SW_RST>; + reset-names = "reset"; + mediatek,have-pmic; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c5: i2c@11012000 { + compatible = "mediatek,mt6589-i2c"; + reg = <0x11012000 0x1000>, + <0x11000580 0x80>; + interrupts = ; + clock-names = "main", "pmic", "dma"; + clock-div = <1>; + resets = <&pericfg MT6589_PERI_I2C5_SW_RST>; + reset-names = "reset"; + mediatek,have-pmic; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c6: i2c@11013000 { + compatible = "mediatek,mt6589-i2c"; + reg = <0x11013000 0x1000>, + <0x11000600 0x80>; + interrupts = ; + clock-names = "main", "pmic", "dma"; + clock-div = <1>; + resets = <&pericfg MT6589_PERI_I2C6_SW_RST>; + reset-names = "reset"; + mediatek,have-pmic; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + spi1: spi@11016000 { + compatible = "mediatek,mt6589-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11016000 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_SYSPLL_D6>, + <&topckgen CLK_TOP_MUX_SPI>, + <&pericfg CLK_PERI1_SPI1>; + clock-names = "parent-clk", "sel-clk", "spi-clk"; + status = "disabled"; + }; + + gpu: gpu@13000000 { + compatible = "mediatek,mt6589-gpu", "img,powervr-sgx544"; + reg = <0x13000000 0x10000>; + interrupts = ; + clocks = <&mfgsys CLK_MFG_G3D>, + <&mfgsys CLK_MFG_MEM>, + <&mfgsys CLK_MFG_AXI>; + clock-names = "core", "mem", "sys"; + }; + + dispsys: syscon@14000000 { + compatible = "mediatek,mt6589-dispsys", "syscon"; + reg = <0x14000000 0x1000>; + #clock-cells = <1>; + }; + + bls: pwm@14008000 { + compatible = "mediatek,mt6589-disp-pwm"; + reg = <0x14008000 0x1000>; + #pwm-cells = <2>; + clocks = <&dispsys CLK_DISP0_BLS>; + clock-names = "main"; + power-domains = <&spm MT6589_POWER_DOMAIN_DIS>; + status = "disabled"; + }; + + /* NAND flash controller */ + nfi: nand-controller@11001000 { + compatible = "mediatek,mt6589-nfc"; + reg = <0x11001000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_NFI>, + <&pericfg CLK_PERI0_NFI>; + clock-names = "nfi_clk", "pad_clk"; + resets = <&pericfg MT6589_PERI_NFI_SW_RST_RST>; + reset-names = "nfi"; + ecc-engine = <&nfiecc>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + nfiecc: ecc@11002000 { + compatible = "mediatek,mt6589-ecc"; + reg = <0x11002000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_NFI>; + clock-names = "nfiecc_clk"; + }; + + imgsys: syscon@15000000 { + compatible = "mediatek,mt6589-imgsys", "syscon"; + reg = <0x15000000 0x1000>; + #clock-cells = <1>; + }; + + vdecsys: syscon@16000000 { + compatible = "mediatek,mt6589-vdecsys", "syscon"; + reg = <0x16000000 0x1000>; + #clock-cells = <1>; + }; + + vencsys: syscon@17000000 { + compatible = "mediatek,mt6589-vencsys", "syscon"; + reg = <0x17000000 0x1000>; + #clock-cells = <1>; + }; + + pio: pinctrl@10005000 { + compatible = "mediatek,mt6589-pinctrl"; + reg = <0x10005000 0x1000>, + <0x1020c000 0x1000>, + <0x1000b000 0x1000>; + reg-names = "gpio", "gpio1", "eint"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pio 0 0 232>; + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + interrupts = ; + }; + timer: timer@10008000 { - compatible = "mediatek,mt6577-timer"; + compatible = "mediatek,mt6589-timer", + "mediatek,mt6577-timer"; reg = <0x10008000 0x80>; interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + pwrap: pwrap@1000f000 { + compatible = "mediatek,mt6589-pwrap"; + reg = <0x1000f000 0x1000>, + <0x11017000 0x1000>; + reg-names = "pwrap", "pwrap-bridge"; + interrupts = ; + clocks = <&infracfg CLK_INFRA_PMICSPI>, + <&infracfg CLK_INFRA_PMICWRAP>; + clock-names = "spi", "wrap"; + resets = <&infracfg MT6589_INFRA_PMIC_WRAP_RST>, + <&pericfg MT6589_PERI_PWRAP_BRIDGE_SW_RST>; + reset-names = "pwrap", "pwrap-bridge"; + }; + + mipi_tx0: dsi-phy@10012000 { + compatible = "mediatek,mt6589-mipi-tx"; + reg = <0x10012000 0x90>; + clocks = <&clk26m>; + /* <&dispsys CLK_DISP1_DSI_DIGITAL_LANE> ? */ + clock-output-names = "mipi_tx0_pll"; + #clock-cells = <0>; + #phy-cells = <0>; + }; + sysirq: interrupt-controller@10200100 { compatible = "mediatek,mt6589-sysirq", "mediatek,mt6577-sysirq"; @@ -90,6 +1004,33 @@ reg = <0x10200100 0x1c>; }; + smi_common: smi@10202000 { + compatible = "mediatek,mt6589-smi-common"; + reg = <0x10202000 0x1000>, <0x1000e000 0x1000>; + clocks = <&infracfg CLK_INFRA_SMI>, + <&infracfg CLK_INFRA_SMI>; + clock-names = "apb", "smi"; + power-domains = <&spm MT6589_POWER_DOMAIN_IFR>; + }; + + iommu: iommu@10205000 { + compatible = "mediatek,mt6589-m4u"; + reg = <0x10205000 0x100>, + <0x10205200 0x600>, + <0x10205800 0x600>, + <0x10205100 0x100>; + reg-names = "global", "m4u0", "m4u1", "l2cache"; + interrupts = , + ; + interrupt-names = "m4u0", "m4u1"; + clocks = <&infracfg CLK_INFRA_M4U>; + clock-names = "bclk"; + mediatek,larbs = <&larb0>, <&larb1>, <&larb2>, + <&larb3>, <&larb4>; + #iommu-cells = <1>; + power-domains = <&spm MT6589_POWER_DOMAIN_IFR>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; @@ -101,11 +1042,35 @@ <0x10216000 0x2000>; }; + apdma: dma-controller@11000680 { + compatible = "mediatek,mt6589-uart-dma", + "mediatek,mt6577-uart-dma"; + reg = <0x11000680 0x54>, + <0x11000700 0x54>, + <0x11000780 0x54>, + <0x11000800 0x54>, + <0x11000880 0x54>, + <0x11000900 0x54>; + interrupts = , + , + , + , + , + ; + dma-requests = <6>; + clocks = <&pericfg CLK_PERI0_APDMA>; + clock-names = "apdma"; + #dma-cells = <1>; + }; + uart0: serial@11006000 { compatible = "mediatek,mt6577-uart"; reg = <0x11006000 0x400>; interrupts = ; - clocks = <&uart_clk>; + clocks = <&pericfg CLK_PERI_MUX_UART0>, <&pericfg CLK_PERI0_UART0>; + clock-names = "baud", "bus"; + dmas = <&apdma 0>, <&apdma 1>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -113,7 +1078,10 @@ compatible = "mediatek,mt6577-uart"; reg = <0x11007000 0x400>; interrupts = ; - clocks = <&uart_clk>; + clocks = <&pericfg CLK_PERI_MUX_UART1>, <&pericfg CLK_PERI0_UART1>; + clock-names = "baud", "bus"; + dmas = <&apdma 2>, <&apdma 3>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -121,21 +1089,468 @@ compatible = "mediatek,mt6577-uart"; reg = <0x11008000 0x400>; interrupts = ; - clocks = <&uart_clk>; + clocks = <&pericfg CLK_PERI_MUX_UART2>, <&pericfg CLK_PERI0_UART2>; + clock-names = "baud", "bus"; + dmas = <&apdma 4>, <&apdma 5>; + dma-names = "tx", "rx"; status = "disabled"; }; uart3: serial@11009000 { + /* NOTE: MT6589 does not have DMA for UART3 */ compatible = "mediatek,mt6577-uart"; reg = <0x11009000 0x400>; interrupts = ; - clocks = <&uart_clk>; + clocks = <&pericfg CLK_PERI_MUX_UART3>, <&pericfg CLK_PERI0_UART3>; + clock-names = "baud", "bus"; status = "disabled"; }; - wdt: watchdog@10000000 { - compatible = "mediatek,mt6589-wdt"; - reg = <0x10000000 0x44>; + /* USB 2.0 */ + usb0: usb@11200000 { + compatible = "mediatek,mt6589-musb", + "mediatek,mtk-musb"; + reg = <0x11200000 0x1000>; + interrupts = ; + interrupt-names = "mc"; + phys = <&usb_port0 PHY_TYPE_USB2>; + dr_mode = "otg"; + clocks = <&pericfg CLK_PERI0_USB0>, + <&pericfg CLK_PERI0_USB0>, + <&apmixedsys CLK_APMIXED_UNIVPLL_USB_48M>; + clock-names = "main", "mcu", "univpll"; + resets = <&pericfg MT6589_PERI_USB_SW_RST>; + reset-names = "hrst"; + status = "disabled"; + }; + + u2phy0: t-phy@11220000 { + compatible = "mediatek,mt6589-tphy"; + reg = <0x11220000 0x0800>, + <0x11220f00 0x0100>; + reg-names = "sif", "legacy-fm"; + mediatek,src-ref-clk-mhz = <48>; + mediatek,src-coef = <22>; + ranges; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + /* USB 2.0 */ + usb_port0: usb-phy@11220800 { + reg = <0x11220800 0x0100>; + clocks = <&apmixedsys CLK_APMIXED_UNIVPLL_USB_48M>; + clock-names = "ref"; + #phy-cells = <1>; + status = "okay"; + }; + + /* USB 1.1 */ + usb_port1: usb-phy@11220900 { + reg = <0x11220900 0x0100>; + clocks = <&apmixedsys CLK_APMIXED_UNIVPLL_USB_48M>; + clock-names = "ref"; + #phy-cells = <1>; + status = "disabled"; + }; + }; + + mmc0: mmc@11230000 { + compatible = "mediatek,mt6589-mmc", + "mediatek,mt8135-mmc"; + reg = <0x11230000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_MSDC0>, + <&topckgen CLK_TOP_MUX_MSDC0>; + clock-names = "source", "hclk"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc1: mmc@11240000 { + compatible = "mediatek,mt6589-mmc", + "mediatek,mt8135-mmc"; + reg = <0x11240000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_MSDC1>, + <&topckgen CLK_TOP_MUX_MSDC1>; + clock-names = "source", "hclk"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc2: mmc@11250000 { + compatible = "mediatek,mt6589-mmc", + "mediatek,mt8135-mmc"; + reg = <0x11250000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_MSDC2>, + <&topckgen CLK_TOP_MUX_MSDC2>; + clock-names = "source", "hclk"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc3: mmc@11260000 { + compatible = "mediatek,mt6589-mmc", + "mediatek,mt8135-mmc"; + reg = <0x11260000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_MSDC3>, + <&topckgen CLK_TOP_MUX_MSDC3>; + clock-names = "source", "hclk"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc4: mmc@11270000 { + compatible = "mediatek,mt6589-mmc", + "mediatek,mt8135-mmc"; + reg = <0x11270000 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI0_MSDC4>, + <&topckgen CLK_TOP_MUX_MSDC4>; + clock-names = "source", "hclk"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + larb0: larb@17001000 { + compatible = "mediatek,mt6589-smi-larb"; + reg = <0x17001000 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <0>; + clocks = <&vencsys CLK_VENC_VEN>, + <&vencsys CLK_VENC_VEN>; + clock-names = "apb", "smi"; + power-domains = <&spm MT6589_POWER_DOMAIN_VEN>; + }; + + larb1: larb@16010000 { + compatible = "mediatek,mt6589-smi-larb"; + reg = <0x16010000 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <1>; + clocks = <&vdecsys CLK_VDEC0_VDE>, + <&vdecsys CLK_VDEC1_SMI>; + clock-names = "apb", "smi"; + power-domains = <&spm MT6589_POWER_DOMAIN_VDE>; + }; + + larb2: larb@14010000 { + compatible = "mediatek,mt6589-smi-larb"; + reg = <0x14010000 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <2>; + clocks = <&dispsys CLK_DISP0_LARB2_SMI>, + <&dispsys CLK_DISP0_LARB2_SMI>; + clock-names = "apb", "smi"; + power-domains = <&spm MT6589_POWER_DOMAIN_DIS>; + }; + + larb3: larb@15001000 { + compatible = "mediatek,mt6589-smi-larb"; + reg = <0x15001000 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <3>; + clocks = <&imgsys CLK_IMAGE_LARB3_SMI>, + <&imgsys CLK_IMAGE_LARB3_SMI>; + clock-names = "apb", "smi"; + power-domains = <&spm MT6589_POWER_DOMAIN_ISP>; + }; + + larb4: larb@15002000 { + compatible = "mediatek,mt6589-smi-larb"; + reg = <0x15002000 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <4>; + clocks = <&imgsys CLK_IMAGE_LARB4_SMI>, + <&imgsys CLK_IMAGE_LARB4_SMI>; + clock-names = "apb", "smi"; + power-domains = <&spm MT6589_POWER_DOMAIN_ISP>; + }; + }; +}; + +&pio { + mmc0_pins_default: mmc0default { +/* + pins-cmd-dat { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + drive-strength = <6>; + // bias-pull-up = ; + }; + + pins-clk { + pinmux = ; + drive-strength = <6>; + mediatek,pull-up-adv = <2>; + }; +*/ + pins-rst { + pinmux = ; + bias-pull-up; + }; + }; + + mmc0_pins_uhs: mmc0 { + pins-cmd-dat { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + drive-strength = <6>; + // bias-pull-up; + }; + + pins-clk { + pinmux = ; + drive-strength = <6>; + mediatek,pull-up-adv = <2>; + }; + + pins-rst { + pinmux = ; + }; + }; + + mmc1_pins_default: mmc1default { + pins-cmd-dat { + pinmux = , + , + , + , + ; + input-enable; + drive-strength = <4>; + bias-pull-up; + }; + + pins-clk { + pinmux = ; + bias-pull-down; + drive-strength = <4>; + }; + + pins-wp { + pinmux = ; + input-enable; + bias-pull-up; + }; + + pins-insert { + pinmux = ; + bias-pull-up; + }; + }; + + mmc1_pins_uhs: mmc1 { + pins-cmd-dat { + pinmux = , + , + , + , + ; + input-enable; + drive-strength = <8>; + mediatek,pull-up-adv = <2>; + }; + + pins-clk { + pinmux = ; + drive-strength = <8>; + mediatek,pull-down-adv = <2>; + }; + }; + + mmc2_pins_default: mmc2default { + pins-cmd-dat { + pinmux = , + , + , + , + ; + input-enable; + drive-strength = <4>; + }; + + pins-clk { + pinmux = ; + bias-pull-down; + drive-strength = <4>; + }; + + pins-wp { + pinmux = ; + input-enable; + bias-pull-up; + }; + + pins-insert { + pinmux = ; + bias-pull-up; + }; + }; + + mmc2_pins_uhs: mmc2 { + pins-cmd-dat { + pinmux = , + , + , + , + ; + input-enable; + drive-strength = <4>; + }; + + pins-clk { + pinmux = ; + drive-strength = <4>; + }; + }; + + mmc3_pins_default: mmc3default { + pins-cmd-dat { + pinmux = , + , + , + , + ; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <2>; + }; + + pins-clk { + pinmux = ; + mediatek,pull-up-adv = <2>; + drive-strength = <4>; + }; + }; + + mmc3_pins_uhs: mmc3 { + pins-cmd-dat { + pinmux = , + , + , + , + ; + input-enable; + drive-strength = <4>; + }; + + pins-clk { + pinmux = ; + drive-strength = <4>; + }; + }; + + mmc4_pins_default: mmc4default { + pins-cmd-dat { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + mediatek,pull-up-adv = <2>; + }; + + pins-clk { + pinmux = ; + mediatek,pull-down-adv = <2>; + }; + + pins-rst { + pinmux = ; + bias-pull-up; + }; + }; + + mmc4_pins_uhs: mmc4 { + pins-cmd-dat { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + drive-strength = <2>; + }; + + pins-clk { + pinmux = ; + drive-strength = <2>; + bias-pull-down; + }; + + pins-rst { + pinmux = ; + bias-pull-up; + }; + }; + + i2c0_pins: i2c0-default { + pins-i2c0 { + pinmux = , + ; + input-enable; + bias-pull-up; + }; + }; + + i2c1_pins: i2c1-default { + pin-i2c1 { + pinmux = , + ; + input-enable; + bias-pull-up; + }; + }; + + i2c2_pins: i2c2-default { + pin-i2c2 { + pinmux = , + ; + input-enable; + bias-pull-up; + }; + }; + + i2c3_pins: i2c3-default { + pin-i2c3 { + pinmux = , + ; + input-enable; + bias-pull-up; }; }; }; diff --git a/arch/arm/configs/lenovo-blade_defconfig b/arch/arm/configs/lenovo-blade_defconfig new file mode 100644 index 00000000000000..aab6364882dabc --- /dev/null +++ b/arch/arm/configs/lenovo-blade_defconfig @@ -0,0 +1,285 @@ +### SoC +## MediaTek MT8125/MT8389 basic support +CONFIG_ARM=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_MACH_MT6589=y +CONFIG_SMP=y +CONFIG_VFP=y +CONFIG_NEON=y +# auto select +CONFIG_VFPv3=y +CONFIG_ARM_THUMBEE=y +CONFIG_SCHED_MC=y + +CONFIG_MODULES=y + +### Drivers +CONFIG_OF=y +# Automatically enabled +CONFIG_MTK_INFRACFG=y + +# is needed? +#CONFIG_INTERCONNECT=y +#CONFIG_INTERCONNECT_MTK=y + +## CPU +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_ARM_MEDIATEK_CPUFREQ=y + +## IOMMU +CONFIG_IOMMU_SUPPORT=y +CONFIG_MTK_IOMMU_V1=y + +## SMI +CONFIG_MEMORY=y +CONFIG_MTK_SMI=y + +## Display +CONFIG_DRM=y +CONFIG_DRM_SIMPLEDRM=y +CONFIG_DRM_MEDIATEK=y +CONFIG_DRM_PANEL=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_PHY_MTK_MIPI_DSI=y +CONFIG_MTK_MMSYS=y + +## Framebuffer +CONFIG_FB=y +CONFIG_FRAMEBUFFER_CONSOLE=y + +## Clock +CONFIG_HAVE_CLK=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_MT6589=y +CONFIG_COMMON_CLK_MT6589_AUDSYS=y +CONFIG_COMMON_CLK_MT6589_DISPSYS=y +CONFIG_COMMON_CLK_MT6589_IMGSYS=y +CONFIG_COMMON_CLK_MT6589_MFGSYS=y +CONFIG_COMMON_CLK_MT6589_VDECSYS=y +CONFIG_COMMON_CLK_MT6589_VENCSYS=y +CONFIG_COMMON_CLK_MT6320=y + +## Timer +CONFIG_TIMER_OF=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_MTK_TIMER=y + +## Watchdog +CONFIG_WATCHDOG=y +CONFIG_MEDIATEK_WATCHDOG=y + +## UART +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_MT6577=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_MTK_UART_APDMA=y + +## I2C +CONFIG_I2C=y +CONFIG_I2C_MT65XX=y +CONFIG_I2C_CHARDEV=y + +## SPI +CONFIG_SPI=y +CONFIG_SPI_MT65XX=y + +## Pinctrl +CONFIG_PINCTRL=y +CONFIG_PINCTRL_MTK=y +CONFIG_EINT_MTK=y +CONFIG_PINCTRL_MT6589=y +CONFIG_PINCTRL_MT6320=y + +## USB +CONFIG_USB=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_MEDIATEK=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_SERIAL=y +CONFIG_PHY_MTK_TPHY=y +CONFIG_USB_INVENTRA_DMA=y +CONFIG_USB_CONN_GPIO=y +CONFIG_USB_GPIO_VBUS=y +CONFIG_USB_OTG=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_NET_DRIVERS=y +#CONFIG_USB_ETH=y +CONFIG_USB_CONFIGFS_ECM=y +#CONFIG_USB_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_U_SERIAL_CONSOLE=y + +## MMC (eMMC/SD) +CONFIG_MMC=y +CONFIG_MMC_MTK=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_OF_PARTITION=y + +## NAND +CONFIG_MTD=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC_MEDIATEK=y +CONFIG_MTD_NAND_MTK=y + +CONFIG_IIO=y +CONFIG_MEDIATEK_MT6577_AUXADC=y +## Accelerometer +CONFIG_BMC150_ACCEL=y +CONFIG_BMC150_ACCEL_I2C=y + +## Magnetometer +CONFIG_BMC150_MAGN=y +CONFIG_BMC150_MAGN_I2C=y + +## Ambient light +CONFIG_AL3320A=y + +## PMIC +CONFIG_MTK_PMIC_WRAP=y +CONFIG_MFD_MT6397=y +CONFIG_MEDIATEK_MT6320_AUXADC=y +CONFIG_NVMEM_MT6320_EFUSE=y +CONFIG_REGULATOR_MT6320=y + +## Power +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_MT6323=y + +## Power Management +CONFIG_MTK_SCPSYS_PM_DOMAINS=y + +## Input +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_MT6779=y +CONFIG_KEYBOARD_MTK_PMIC=y + +## Battery +CONFIG_CHARGER_BQ24190=y +CONFIG_BATTERY_BQ27XXX=y +CONFIG_BATTERY_BQ27XXX_I2C=y + +## Regulator +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y + +## Battery + +## Audio +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_MEDIATEK=y +CONFIG_SND_SOC_MT6589=y +CONFIG_SND_SOC_MT6589_MT6320=y +CONFIG_SND_SOC_MT6320=y +CONFIG_SND_SOC_MT6320_ACCDET=y +CONFIG_SRAM=y + +## Video Accelerator +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_PLATFORM_SUPPORT=y +CONFIG_VIDEO_DEV=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_MEDIATEK_JPEG=y + +## GPU +#CONFIG_SGX=y # not ported + +## Networking +CONFIG_NET=y +CONFIG_INET=y +CONFIG_IPV6=y +CONFIG_UNIX=y +CONFIG_NETDEVICES=y +CONFIG_PACKET=y + +## Wi-Fi / Bluetooth + +## Thermal +CONFIG_THERMAL=y +CONFIG_MTK_THERMAL=y +CONFIG_MTK_SOC_THERMAL=y + +## Modem + +## GPS + +## Camera + +## Touchpanel +CONFIG_RMI4_CORE=y +CONFIG_RMI4_I2C=y +CONFIG_RMI4_F11=y +CONFIG_RMI4_F34=y + +## PWM +CONFIG_PWM=y +CONFIG_PWM_MEDIATEK=y +CONFIG_PWM_MT6589_DISP=y + +## RTC +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_MT6397=y + +## pstore +CONFIG_PSTORE=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y + +## Android +#CONFIG_ANDROID_BINDER_IPC=y + +## eFuse +CONFIG_NVMEM_MTK_EFUSE=y + +## Block Device +CONFIG_BLK_DEV_LOOP=y + +### FS +CONFIG_UNICODE=y +CONFIG_DEBUG_FS=y +CONFIG_EXT4_FS=y +CONFIG_VFAT_FS=y +# VFAT +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_TMPFS=y +# pmOS +CONFIG_DEVTMPFS_MOUNT=n +CONFIG_CONFIGFS_FS=y + +### Initramfs +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_RAM=y + +### Other +CONFIG_KERNEL_GZIP=y +CONFIG_VMSPLIT_3G_OPT=y +CONFIG_THUMB2_KERNEL=y +CONFIG_PRINTK_TIME=y + +### Hacking +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y + +### postmarketOS (must be removed!!!!!) +CONFIG_DEVTMPFS=y +CONFIG_SYSVIPC=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CGROUPS=y diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index f22c50d4bd4173..687ee7063a7392 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -383,6 +383,7 @@ ENDPROC(__create_page_tables) ENTRY(secondary_startup_arm) THUMB( badr r9, 1f ) @ Kernel is entered in ARM. THUMB( bx r9 ) @ If this is a Thumb-2 kernel, +ENDPROC(secondary_startup_arm) THUMB( .thumb ) @ switch to Thumb now. THUMB(1: ) ENTRY(secondary_startup) @@ -429,7 +430,6 @@ ARM_BE8(eor r4, r4, r5) @ without using a temp reg. @ (return control reg) ret r12 ENDPROC(secondary_startup) -ENDPROC(secondary_startup_arm) ENTRY(__secondary_switched) #if defined(CONFIG_VMAP_STACK) && !defined(CONFIG_ARM_LPAE) diff --git a/arch/arm/mach-mediatek/platsmp.c b/arch/arm/mach-mediatek/platsmp.c index 6b0943d95555af..2176cf789932b0 100644 --- a/arch/arm/mach-mediatek/platsmp.c +++ b/arch/arm/mach-mediatek/platsmp.c @@ -6,21 +6,76 @@ * Author: Shunli Wang * Yingjoe Chen */ +#include +#include +#include #include #include #include #include #include #include +#include "../drivers/pmdomain/mediatek/mtk-pm-domains.h" #define MTK_MAX_CPU 8 #define MTK_SMP_REG_SIZE 0x1000 +#ifdef CONFIG_HOTPLUG_CPU +#define SPM_L1_PDN(n) (0x25c + (8 * n)) + +#define SPM_SLEEP_TIMER_STA 0x0720 +#define CPU_SLEEP(n) BIT(15 + n) + +#define L1RSTDISABLE1 BIT(1) + +#define BOOT_SLAVE_CONFIG 0x0000 +#define BOOT_SLAVE_ADDR 0x0004 +#define BOOT_SLAVE_KEY 0x13800000 + +enum mtk_cpu_target_state { + POWER_DOWN, + POWER_UP, +}; + +struct mtk_hotplug_info { + const char *const spm_compat; + const char *const mcusys_compat; + + unsigned int spm_pwr_con[MTK_MAX_CPU - 1]; + unsigned int spm_pwr_status_bits[MTK_MAX_CPU - 1]; + unsigned int spm_l1_pdn_bits[MTK_MAX_CPU - 1]; + unsigned int spm_l1_pdn_ack_bits[MTK_MAX_CPU - 1]; + bool mt6589_seq; +}; + +static const struct mtk_hotplug_info mtk_mt6572_hotplug = { + .spm_compat = "mediatek,mt6572-scpsys", + .mcusys_compat = "mediatek,mt6572-mcusys", + .spm_pwr_con = { 0x218 }, + .spm_pwr_status_bits = { BIT(11) }, + .spm_l1_pdn_bits = { BIT(0) }, + .spm_l1_pdn_ack_bits = { BIT(8) }, +}; + +static const struct mtk_hotplug_info mtk_mt6589_hotplug = { + .spm_compat = "mediatek,mt6589-scpsys", + .mcusys_compat = "mediatek,mt6589-mcusys", + .spm_pwr_con = { 0x218, 0x21c, 0x220 }, + .spm_pwr_status_bits = { BIT(17), BIT(16), BIT(15) }, + .spm_l1_pdn_bits = { 0xFFFF, 0xFFFF, 0xFFFF }, + .spm_l1_pdn_ack_bits = { 0, 0, 0 }, + .mt6589_seq = true, +}; +#endif + struct mtk_smp_boot_info { unsigned long smp_base; unsigned int jump_reg; unsigned int core_keys[MTK_MAX_CPU - 1]; unsigned int core_regs[MTK_MAX_CPU - 1]; +#ifdef CONFIG_HOTPLUG_CPU + const struct mtk_hotplug_info *hotplug; +#endif }; static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = { @@ -33,12 +88,18 @@ static const struct mtk_smp_boot_info mtk_mt6572_boot = { 0x10001400, 0x08, { 0x534c4131 }, { 0x0c }, +#ifdef CONFIG_HOTPLUG_CPU + &mtk_mt6572_hotplug, +#endif }; static const struct mtk_smp_boot_info mtk_mt6589_boot = { 0x10002000, 0x34, { 0x534c4131, 0x4c415332, 0x41534c33 }, { 0x38, 0x3c, 0x40 }, +#ifdef CONFIG_HOTPLUG_CPU + .hotplug = &mtk_mt6589_hotplug, +#endif }; static const struct mtk_smp_boot_info mtk_mt7623_boot = { @@ -66,16 +127,190 @@ static const struct of_device_id mtk_smp_boot_infos[] __initconst = { static void __iomem *mtk_smp_base; static const struct mtk_smp_boot_info *mtk_smp_info; +#ifdef CONFIG_HOTPLUG_CPU +static void __iomem *spm_base; +static void __iomem *mcusys_base; + +static void spm_cpu_wait_busy(enum mtk_cpu_target_state state, unsigned int cpu) +{ + u32 val, mask = mtk_smp_info->hotplug->spm_pwr_status_bits[cpu - 1]; + do { + val = readl(spm_base + SPM_PWR_STATUS) & mask; + val |= readl(spm_base + SPM_PWR_STATUS_2ND) & mask; + } while (state == POWER_DOWN ? !!val : !val); +} + +static void spm_l1_wait_busy(enum mtk_cpu_target_state state, unsigned int cpu) +{ + u32 val; + do { + val = readl(spm_base + SPM_L1_PDN(cpu)) & + mtk_smp_info->hotplug->spm_l1_pdn_ack_bits[cpu - 1]; + } while (state == POWER_DOWN ? !val : !!val); +} + +static void spm_ctrl_cpu(enum mtk_cpu_target_state state, unsigned int cpu) +{ + u32 val, pwr_con = mtk_smp_info->hotplug->spm_pwr_con[cpu - 1], + l1_pdn_bits = mtk_smp_info->hotplug->spm_l1_pdn_bits[cpu - 1]; + + writel(SPM_PROJECT_CODE << 16 | BIT(0), spm_base + SPM_POWERON_CONFIG_SET); + + switch (state) { + case POWER_DOWN: + while (!(readl(spm_base + SPM_SLEEP_TIMER_STA) & + CPU_SLEEP(cpu))) + ; + + val = readl(spm_base + pwr_con); + val |= PWR_SRAM_CLKISO_BIT; + val &= ~PWR_SRAM_ISOINT_B_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + SPM_L1_PDN(cpu)); + val |= l1_pdn_bits; + writel(val, spm_base + SPM_L1_PDN(cpu)); + if (mtk_smp_info->hotplug->spm_l1_pdn_ack_bits[cpu - 1]) + spm_l1_wait_busy(state, cpu); + + val = readl(spm_base + pwr_con); + val |= PWR_ISO_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val |= PWR_CLK_DIS_BIT; + val &= ~PWR_RST_B_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val &= ~PWR_ON_BIT; + writel(val, spm_base + pwr_con); + udelay(1); + + val = readl(spm_base + pwr_con); + val &= ~PWR_ON_2ND_BIT; + writel(val, spm_base + pwr_con); + udelay(1); + + spm_cpu_wait_busy(state, cpu); + + break; + case POWER_UP: + val = readl(spm_base + pwr_con); + val |= PWR_ON_BIT; + writel(val, spm_base + pwr_con); + udelay(1); + + val = readl(spm_base + pwr_con); + val |= PWR_ON_2ND_BIT; + writel(val, spm_base + pwr_con); + udelay(3); + + spm_cpu_wait_busy(state, cpu); + + if (mtk_smp_info->hotplug->mt6589_seq) { + val = readl(spm_base + pwr_con); + val &= ~PWR_CLK_DIS_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + SPM_L1_PDN(cpu)); + val &= ~l1_pdn_bits; + writel(val, spm_base + SPM_L1_PDN(cpu)); + udelay(1); + + val = readl(spm_base + pwr_con); + val |= PWR_SRAM_ISOINT_B_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val &= ~PWR_SRAM_CLKISO_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val &= ~PWR_ISO_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val |= PWR_RST_B_BIT; + writel(val, spm_base + pwr_con); + } else { + val = readl(spm_base + SPM_L1_PDN(cpu)); + val &= ~l1_pdn_bits; + writel(val, spm_base + SPM_L1_PDN(cpu)); + udelay(1); + if (mtk_smp_info->hotplug->spm_l1_pdn_ack_bits[cpu - 1]) + spm_l1_wait_busy(state, cpu); + + val = readl(spm_base + pwr_con); + val |= PWR_SRAM_ISOINT_B_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val &= ~(PWR_CLK_DIS_BIT | PWR_ISO_BIT); + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val |= PWR_CLK_DIS_BIT; + writel(val, spm_base + pwr_con); + + val = readl(spm_base + pwr_con); + val &= ~PWR_SRAM_CLKISO_BIT; + writel(val, spm_base + pwr_con); + + val = readl(mcusys_base); + writel(val | L1RSTDISABLE1, mcusys_base); + dsb(); + + val = readl(spm_base + pwr_con); + val &= ~PWR_CLK_DIS_BIT; + writel(val, spm_base + pwr_con); + dsb(); + + val = readl(spm_base + pwr_con); + val |= PWR_RST_B_BIT; + writel(val, spm_base + pwr_con); + } + + break; + } +} + +static bool mtk_hotplug_is_available(void) +{ + return spm_base && mcusys_base; +} + +static bool mtk_hotplug_is_off(unsigned int cpu) +{ + u32 val = readl_relaxed(spm_base + SPM_PWR_STATUS); + return !(val & mtk_smp_info->hotplug->spm_pwr_status_bits[cpu - 1]); +} +#endif + static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle) { + u32 val; + if (!mtk_smp_base) return -EINVAL; - if (!mtk_smp_info->core_keys[cpu-1]) + if (!mtk_smp_info->core_keys[cpu - 1]) return -EINVAL; - writel_relaxed(mtk_smp_info->core_keys[cpu-1], - mtk_smp_base + mtk_smp_info->core_regs[cpu-1]); + if (mtk_hotplug_is_available() && mtk_hotplug_is_off(cpu)) { + val = readl(mcusys_base); + writel(val & ~BIT(cpu), mcusys_base); + + writel(BOOT_SLAVE_KEY | 1, mtk_smp_base + BOOT_SLAVE_CONFIG); + writel(__pa_symbol(secondary_startup_arm), + mtk_smp_base + BOOT_SLAVE_ADDR); + + wmb(); + spm_ctrl_cpu(POWER_UP, cpu); + dsb_sev(); + } else + writel(mtk_smp_info->core_keys[cpu - 1], + mtk_smp_base + mtk_smp_info->core_regs[cpu - 1]); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); @@ -128,6 +363,43 @@ static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone) mtk_smp_base + mtk_smp_info->jump_reg); } +#ifdef CONFIG_HOTPLUG_CPU +static void __mtk_hotplug_prepare(void) +{ + struct device_node *np; + + if (!mtk_smp_info->hotplug || !mtk_smp_info->hotplug->spm_compat || + !mtk_smp_info->hotplug->mcusys_compat) { + pr_err("%s: hotplug data is incomplete, disabling hotplug\n", + __func__); + return; + } + + np = of_find_compatible_node(NULL, NULL, + mtk_smp_info->hotplug->spm_compat); + if (!np) { + pr_err("%s: SPM node not found, hotplug won't be available\n", + __func__); + return; + } + + spm_base = of_iomap(np, 0); + of_node_put(np); + + np = of_find_compatible_node(NULL, NULL, + mtk_smp_info->hotplug->mcusys_compat); + if (!np) { + pr_err("%s: MCUSYS node not found, hotplug won't be available\n", + __func__); + iounmap(spm_base); + return; + } + + mcusys_base = of_iomap(np, 0); + of_node_put(np); +} +#endif + static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus) { __mtk_smp_prepare_cpus(max_cpus, 1); @@ -136,7 +408,38 @@ static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus) static void __init mtk_smp_prepare_cpus(unsigned int max_cpus) { __mtk_smp_prepare_cpus(max_cpus, 0); +#ifdef CONFIG_HOTPLUG_CPU + __mtk_hotplug_prepare(); +#endif +} + +#ifdef CONFIG_HOTPLUG_CPU +static bool mtk_cpu_can_disable(unsigned int cpu) +{ + return mtk_hotplug_is_available() && cpu != 0; +} + +static int mtk_cpu_disable(unsigned int cpu) +{ + if (mtk_cpu_can_disable(cpu)) + return 0; + + return -EPERM; +} + +static void mtk_cpu_die(unsigned int cpu) +{ + v7_exit_coherency_flush(louis); + + while (1) + wfi(); +} +static int mtk_cpu_kill(unsigned int cpu) +{ + spm_ctrl_cpu(POWER_DOWN, cpu); + return 1; } +#endif static const struct smp_operations mt81xx_tz_smp_ops __initconst = { .smp_prepare_cpus = mtk_tz_smp_prepare_cpus, @@ -147,5 +450,11 @@ CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_op static const struct smp_operations mt6589_smp_ops __initconst = { .smp_prepare_cpus = mtk_smp_prepare_cpus, .smp_boot_secondary = mtk_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_can_disable = mtk_cpu_can_disable, + .cpu_disable = mtk_cpu_disable, + .cpu_die = mtk_cpu_die, + .cpu_kill = mtk_cpu_kill, +#endif }; CPU_METHOD_OF_DECLARE(mt6589_smp, "mediatek,mt6589-smp", &mt6589_smp_ops); diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 2c09fd729bab04..039e398661ea32 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -124,6 +124,63 @@ config COMMON_CLK_MT2712_VENCSYS help This driver supports MediaTek MT2712 vencsys clocks. +config COMMON_CLK_MT6320 + tristate "Clock driver for MediaTek MT6320 PMIC" + depends on ARCH_MEDIATEK || MFD_MT6397 || COMPILE_TEST + select COMMON_CLK_MEDIATEK + help + This enables driver for clocks on the MediaTek MT6320 PMIC. + +config COMMON_CLK_MT6589 + tristate "Main clock drivers for MediaTek MT6589" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + help + This enables drivers for main clocks (apmixedsys, topckgen, + pericfg, infracfg) on the MediaTek MT6589 SoC. + +config COMMON_CLK_MT6589_AUDSYS + tristate "Clock driver for MediaTek MT6589 audsys" + depends on COMMON_CLK_MT6589 + help + This enables a driver for clocks provided by audsys + on the MediaTek MT6589 SoC. + +config COMMON_CLK_MT6589_DISPSYS + tristate "Clock driver for MediaTek MT6589 dispsys" + depends on COMMON_CLK_MT6589 + help + This enables a driver for clocks provided by dispsys + on the MediaTek MT6589 SoC. + +config COMMON_CLK_MT6589_IMGSYS + tristate "Clock driver for MediaTek MT6589 imgsys" + depends on COMMON_CLK_MT6589 + help + This enables a driver for clocks provided by imgsys + on the MediaTek MT6589 SoC. + +config COMMON_CLK_MT6589_MFGSYS + tristate "Clock driver for MediaTek MT6589 mfgsys" + depends on COMMON_CLK_MT6589 + help + This enables a driver for clocks provided by mfgsys + on the MediaTek MT6589 SoC. + +config COMMON_CLK_MT6589_VDECSYS + tristate "Clock driver for MediaTek MT6589 vdecsys" + depends on COMMON_CLK_MT6589 + help + This enables a driver for clocks provided by vdecsys + on the MediaTek MT6589 SoC. + +config COMMON_CLK_MT6589_VENCSYS + tristate "Clock driver for MediaTek MT6589 vencsys" + depends on COMMON_CLK_MT6589 + help + This enables a driver for clocks provided by vencsys + on the MediaTek MT6589 SoC. + config COMMON_CLK_MT6735 tristate "Main clock drivers for MediaTek MT6735" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index d8736a060dbdca..1b66e39f638f30 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -2,6 +2,14 @@ obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o obj-$(CONFIG_COMMON_CLK_MEDIATEK_FHCTL) += clk-fhctl.o clk-pllfh.o +obj-$(CONFIG_COMMON_CLK_MT6320) += clk-mt6320.o +obj-$(CONFIG_COMMON_CLK_MT6589) += clk-mt6589-apmixedsys.o clk-mt6589-infracfg.o clk-mt6589-pericfg.o clk-mt6589-topckgen.o +obj-$(CONFIG_COMMON_CLK_MT6589_AUDSYS) += clk-mt6589-aud.o +obj-$(CONFIG_COMMON_CLK_MT6589_DISPSYS) += clk-mt6589-disp.o +obj-$(CONFIG_COMMON_CLK_MT6589_IMGSYS) += clk-mt6589-img.o +obj-$(CONFIG_COMMON_CLK_MT6589_MFGSYS) += clk-mt6589-mfg.o +obj-$(CONFIG_COMMON_CLK_MT6589_VDECSYS) += clk-mt6589-vdec.o +obj-$(CONFIG_COMMON_CLK_MT6589_VENCSYS) += clk-mt6589-venc.o obj-$(CONFIG_COMMON_CLK_MT6735) += clk-mt6735-apmixedsys.o clk-mt6735-infracfg.o clk-mt6735-pericfg.o clk-mt6735-topckgen.o obj-$(CONFIG_COMMON_CLK_MT6735_IMGSYS) += clk-mt6735-imgsys.o obj-$(CONFIG_COMMON_CLK_MT6735_MFGCFG) += clk-mt6735-mfgcfg.o diff --git a/drivers/clk/mediatek/clk-mt6320.c b/drivers/clk/mediatek/clk-mt6320.c new file mode 100644 index 00000000000000..dd3412dd929018 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6320.c @@ -0,0 +1,531 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + * + * Based on MT6397 clock driver: + * Copyright (c) 2014 MediaTek Inc. + * Author: Flora Fu + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +static const struct mtk_gate_regs top_ckpdn_regs = { + .sta_ofs = MT6320_TOP_CKPDN, +}; +static const struct mtk_gate_regs top_ckpdn2_regs = { + .sta_ofs = MT6320_TOP_CKPDN2, +}; +static const struct mtk_gate_regs wrp_ckpdn_regs = { + .sta_ofs = MT6320_WRP_CKPDN, +}; + +struct mt6320_gate { + struct clk_hw hw; + struct regmap *regmap; + const struct mtk_gate *gate; +}; + +#define to_mt6320_gate(_hw) container_of(_hw, struct mt6320_gate, hw) + +static int mt6320_gate_prepare(struct clk_hw *hw) +{ + struct mt6320_gate *cg = to_mt6320_gate(hw); + regmap_clear_bits(cg->regmap, cg->gate->regs->sta_ofs, + BIT(cg->gate->shift)); + return 0; +} + +static void mt6320_gate_unprepare(struct clk_hw *hw) +{ + struct mt6320_gate *cg = to_mt6320_gate(hw); + regmap_set_bits(cg->regmap, cg->gate->regs->sta_ofs, + BIT(cg->gate->shift)); +} + +static int mt6320_gate_is_prepared(struct clk_hw *hw) +{ + struct mt6320_gate *cg = to_mt6320_gate(hw); + u32 val; + + regmap_read(cg->regmap, cg->gate->regs->sta_ofs, &val); + return (val & BIT(cg->gate->shift)) == 0; +} + +static const struct clk_ops mt6320_gate_ops = { + .prepare = mt6320_gate_prepare, + .unprepare = mt6320_gate_unprepare, + .is_prepared = mt6320_gate_is_prepared, +}; + +#define GATE_TOP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top_ckpdn_regs, _shift, &mt6320_gate_ops) + +#define GATE_TOP2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top_ckpdn2_regs, _shift, &mt6320_gate_ops) + +#define GATE_WRP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &wrp_ckpdn_regs, _shift, &mt6320_gate_ops) + +static const struct mtk_fixed_clk mt6320_fixed_clks[] = { + FIXED_CLK(MT6320_CLK_AUD26M, "aud26m", NULL, 26000000), + FIXED_CLK(MT6320_CLK_SMPS24M, "smps24m", NULL, 24000000), + FIXED_CLK(MT6320_CLK_PMU75K, "pmu75k", NULL, 75000), + FIXED_CLK(MT6320_CLK_PMU12M, "pmu12m", NULL, 12000000), + FIXED_CLK(MT6320_CLK_FG32K, "fg32k", NULL, 32000), + FIXED_CLK(MT6320_CLK_RTC32K, "rtc32k", NULL, 32000), + FIXED_CLK(MT6320_CLK_CHR1M, "chr1m", NULL, 1000000), +}; + +static const struct mtk_fixed_factor mt6320_factors[] = { + FACTOR(MT6320_CLK_AUD13M, "aud13m", "aud26m", 1, 2), + FACTOR(MT6320_CLK_AUD26M_DIV64, "aud26m_div64", "aud26m", 1, 64), + FACTOR(MT6320_CLK_SMPS12M, "smps12m", "smps24m", 1, 2), + FACTOR(MT6320_CLK_SMPS6M, "smps6m", "smps24m", 1, 4), + FACTOR(MT6320_CLK_SMPS3M, "smps3m", "smps24m", 1, 8), + FACTOR(MT6320_CLK_SMPS2M, "smps2m", "smps24m", 1, 12), + FACTOR(MT6320_CLK_SMPS1M, "smps1m", "smps24m", 1, 24), +}; + +static const struct mtk_gate mt6320_gates[] = { + GATE_TOP(MT6320_TOPCKPDN_AUD_26M, "top-aud26m", "aud26m", 0), + GATE_TOP(MT6320_TOPCKPDN_AUD_13M, "top-aud13m", "aud13m", 1), + GATE_TOP(MT6320_TOPCKPDN_SPK_CK, "top-spk", "smps1m", 2), + GATE_TOP(MT6320_TOPCKPDN_PWMOC_CK, "top-pwmoc", "smps2m", 3), + GATE_TOP(MT6320_TOPCKPDN_EFUSE_CK, "top-efuse", "pmu75k", 4), + GATE_TOP(MT6320_TOPCKPDN_FGADC_CK, "top-fgadc", "fg32k", 5), + GATE_TOP(MT6320_TOPCKPDN_BST_DRV_1M_CK,"top-bstdrv1m", "smps1m", 7), + GATE_TOP(MT6320_TOPCKPDN_SMPS_CK_DIV2, "top-smpsdiv2", "smps12m", 11), + GATE_TOP(MT6320_TOPCKPDN_SMPS_CK_DIV, "top-smpsdiv", "smps24m", 12), + GATE_TOP(MT6320_TOPCKPDN_STRUP_6M, "top-strup6m", "smps6m", 15), + + GATE_TOP2(MT6320_TOPCKPDN2_RTC32K_1V8, "top2-rtc32k1v8", "rtc32k", 0), + GATE_TOP2(MT6320_TOPCKPDN2_STRUP_75K_CK, "top2-starup75k", "pmu75k", 2), + GATE_TOP2(MT6320_TOPCKPDN2_RTC_32K_CK, "top2-rtc32k", "rtc32k", 3), + GATE_TOP2(MT6320_TOPCKPDN2_PCHR_32K_CK, "top2-pchr32k", "rtc32k", 4), + GATE_TOP2(MT6320_TOPCKPDN2_LDOSTB_1M_CK, "top2-ldostb1m", "smps1m", 5), + GATE_TOP2(MT6320_TOPCKPDN2_INTRP_CK, "top2-intr", "pmu75k", 6), + GATE_TOP2(MT6320_TOPCKPDN2_DRV_32K_CK, "top2-drv32k", "smps1m", 7), + GATE_TOP2(MT6320_TOPCKPDN2_CHR1M_CK, "top2-chr1m", "chr1m", 8), + GATE_TOP2(MT6320_TOPCKPDN2_BUCK_CK, "top2-buck", "pmu12m", 9), + GATE_TOP2(MT6320_TOPCKPDN2_BUCK_ANA_CK, "top2-buckana", "smps2m", 10), + GATE_TOP2(MT6320_TOPCKPDN2_BUCK32K, "top2-buck32k", "rtc32k", 11), + GATE_TOP2(MT6320_TOPCKPDN2_BUCK_1M_CK, "top2-buck1m", "smps1m", 12), + GATE_TOP2(MT6320_TOPCKPDN2_STRUP_32K_CK, "top2-starup32k", "rtc32k", 13), + GATE_TOP2(MT6320_TOPCKPDN2_RTC_75K_CK, "top2-rtc75k", "pmu75k", 14), + GATE_TOP2(MT6320_TOPCKPDN2_RSV_15, "top2-rsv", "smps24m",15), + + // TOP_GPIO_CKPDN + + GATE_WRP(MT6320_WRPCKPDN_32K, "wrap-32k", "rtc32k", 6), + + // AUDENCCLKSQ_CON0 +}; + +struct mt6320_clk_composite { + struct clk_hw hw; + struct regmap *regmap; + u32 enable_reg; + u32 enable_shift; + u32 div_reg; + u32 div_shift; + u32 div_width; + u32 div_base; + u32 div_factor; + u32 mux_reg; + u32 mux_shift; + u32 mux_width; +}; + +#define to_mt6320_composite(_hw) \ + container_of(_hw, struct mt6320_clk_composite, hw) + +static int mt6320_composite_prepare(struct clk_hw *hw) +{ + struct mt6320_clk_composite *c = to_mt6320_composite(hw); + return regmap_clear_bits(c->regmap, c->enable_reg, + BIT(c->enable_shift)); +} + +static void mt6320_composite_unprepare(struct clk_hw *hw) +{ + struct mt6320_clk_composite *c = to_mt6320_composite(hw); + regmap_set_bits(c->regmap, c->enable_reg, BIT(c->enable_shift)); +} + +static int mt6320_composite_is_prepared(struct clk_hw *hw) +{ + struct mt6320_clk_composite *c = to_mt6320_composite(hw); + u32 val; + regmap_read(c->regmap, c->enable_reg, &val); + return !(val & BIT(c->enable_shift)); +} + +static unsigned long mt6320_composite_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mt6320_clk_composite *c = to_mt6320_composite(hw); + u32 val, div; + + if (c->div_width == 0) + return parent_rate; + + regmap_read(c->regmap, c->div_reg, &val); + val >>= c->div_shift; + val &= GENMASK(c->div_width - 1, 0); + + if (val) + div = (1 << val) * c->div_base * c->div_factor; + else + div = c->div_base; + + return parent_rate / div; +} + +static u8 mt6320_composite_get_parent(struct clk_hw *hw) +{ + struct mt6320_clk_composite *c = to_mt6320_composite(hw); + int num_parents = clk_hw_get_num_parents(hw); + u32 val; + + if (num_parents == 1) + return 0; + + regmap_read(c->regmap, c->mux_reg, &val); + val >>= c->mux_shift; + val &= GENMASK(c->mux_width - 1, 0); + + if (val >= num_parents) + return -EINVAL; + + return val; +} + +static int mt6320_composite_set_parent(struct clk_hw *hw, u8 index) +{ + struct mt6320_clk_composite *c = to_mt6320_composite(hw); + u32 mask = GENMASK(c->mux_width - 1, 0); + + return regmap_update_bits(c->regmap, c->mux_reg, + mask << c->mux_shift, + index << c->mux_shift); +} + +static const struct clk_ops mt6320_composite_ops = { + .prepare = mt6320_composite_prepare, + .unprepare = mt6320_composite_unprepare, + .is_prepared = mt6320_composite_is_prepared, + .recalc_rate = mt6320_composite_recalc_rate, + .get_parent = mt6320_composite_get_parent, + .set_parent = mt6320_composite_set_parent, + .determine_rate = __clk_mux_determine_rate_closest, +}; + +struct mt6320_comp_desc { + int id; + const char *name; + const char * const *parent_names; + int num_parents; + u32 enable_reg; + u32 enable_shift; + u32 div_reg; + u32 div_shift; + u32 div_width; + u32 div_base; + u32 div_factor; + u32 mux_reg; + u32 mux_shift; + u32 mux_width; + unsigned long flags; +}; + +#define COMP_GATE_DIV(_id, _name, _parent, _reg, _shift, \ + _div_reg, _div_shift, _div_width, \ + _div_base, _div_factor) \ + { \ + .id = _id, .name = _name, \ + .parent_names = (const char * const []){ _parent }, \ + .num_parents = 1, \ + .enable_reg = _reg, .enable_shift = _shift, \ + .div_reg = _div_reg, .div_shift = _div_shift, \ + .div_width = _div_width, .div_base = _div_base, \ + .div_factor = _div_factor, \ + .flags = CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, \ + } + +#define COMP_MUX(_id, _name, _parents, _num_p, _reg, _shift, \ + _mux_reg, _mux_shift, _mux_width) \ + { \ + .id = _id, .name = _name, \ + .parent_names = _parents, \ + .num_parents = _num_p, \ + .enable_reg = _reg, .enable_shift = _shift, \ + .mux_reg = _mux_reg, .mux_shift = _mux_shift, \ + .mux_width = _mux_width, \ + .flags = CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, \ + } + +/* unknown parent */ +static const char * const accdet_parents[] = { + "rtc32k", "pmu12m", "top-accdet", "aud26m", +}; +static const char * const fgadc_ana_parents[] = { + "rtc32k", "aud26m_div64", +}; +static const char * const fgmtr_parents[] = { + "rtc32k", "aud26m", +}; + +static const struct mt6320_comp_desc mt6320_composites[] = { + COMP_MUX(MT6320_TOPCKPDN_FGADC_ANA_CK, "top-fgadc-ana", + fgadc_ana_parents, ARRAY_SIZE(fgadc_ana_parents), + MT6320_TOP_CKPDN, 6, + MT6320_TOP_CKCON1, 12, 1), + // PMIC_RG_CLKSQ_HW_AUTO_EN? + + COMP_GATE_DIV(MT6320_TOPCKPDN_RTC_MCLK, "top-rtc-mclk", + "smps24m", MT6320_TOP_CKPDN, 8, + MT6320_TOP_CKCON2, 14, 2, 1, 1), + // PMIC_RG_ACCDET_CKSEL? + + COMP_GATE_DIV(MT6320_TOPCKPDN_SPK_PWM_DIV, "top-spkpwm", + "smps1m", MT6320_TOP_CKPDN, 9, + MT6320_TOP_CKCON2, 3, 2, 1, 8), + + COMP_GATE_DIV(MT6320_TOPCKPDN_SPK_DIV, "top-spkdiv", + "smps1m", MT6320_TOP_CKPDN, 10, + MT6320_TOP_CKCON2, 5, 2, 1, 1), + + COMP_GATE_DIV(MT6320_TOPCKPDN_AUXADC_CK, "top-auxadc", + "pmu12m", MT6320_TOP_CKPDN, 13, + MT6320_TOP_CKCON2, 0, 2, 6, 1), + // [0:3]? + + COMP_MUX(MT6320_TOPCKPDN_ACCDET_CK, "top-accdet", + accdet_parents, ARRAY_SIZE(accdet_parents), + MT6320_TOP_CKPDN, 14, + MT6320_TOP_CKCON2, 13, 2), + + COMP_MUX(MT6320_TOPCKPDN2_FQMTR, "top2-fqmtr", + fgmtr_parents, ARRAY_SIZE(fgmtr_parents), + MT6320_TOP_CKPDN2, 1, + MT6320_TOP_CKCON2, 15, 1), + + /* WRAP clocks (gate + divider only) */ + // FIXME: shred div, accdet area? + COMP_GATE_DIV(MT6320_WRPCKPDN_I2C0, "wrap-i2c0", + "smps24m", MT6320_WRP_CKPDN, 0, + MT6320_TOP_CKCON2, 14, 2, 1, 1), + COMP_GATE_DIV(MT6320_WRPCKPDN_I2C1, "wrap-i2c1", + "smps24m", MT6320_WRP_CKPDN, 1, + MT6320_TOP_CKCON2, 14, 2, 1, 1), + COMP_GATE_DIV(MT6320_WRPCKPDN_I2C2, "wrap-i2c2", + "smps24m", MT6320_WRP_CKPDN, 2, + MT6320_TOP_CKCON2, 14, 2, 1, 1), + COMP_GATE_DIV(MT6320_WRPCKPDN_PWM, "wrap-pwm", + "smps24m", MT6320_WRP_CKPDN, 3, + MT6320_TOP_CKCON2, 14, 2, 1, 1), + COMP_GATE_DIV(MT6320_WRPCKPDN_KP, "wrap-kp", + "smps24m", MT6320_WRP_CKPDN, 4, + MT6320_TOP_CKCON2, 14, 2, 1, 1), + COMP_GATE_DIV(MT6320_WRPCKPDN_EINT, "wrap-eint", + "smps24m", MT6320_WRP_CKPDN, 5, + MT6320_TOP_CKCON2, 14, 2, 1, 1), + // PMIC_RG_WRP_32K_PDN 6 + COMP_GATE_DIV(MT6320_WRPCKPDN_WRP, "wrap-wrp", + "smps24m", MT6320_WRP_CKPDN, 7, + MT6320_TOP_CKCON2, 14, 2, 1, 1), +}; + +// NCP_CLKDIV_CON0 +// NCP_CLKDIV_CON1 +// TOP_CKTST1 +// TOP_CKTST2 +// PMIC_FQMTR_TCKSEL + +// resets +// TOP_RST_CON +// WRP_RST_CON +// TOP_RST_MISC + +static const struct of_device_id mt6320_clk_match_table[] = { + { .compatible = "mediatek,mt6320-clk" }, + { } +}; +MODULE_DEVICE_TABLE(of, mt6320_clk_match_table); + +static int mt6320_clk_probe(struct platform_device *pdev) +{ + int i, ret; + struct device *dev = &pdev->dev; + struct mt6397_chip *mt6320 = dev_get_drvdata(pdev->dev.parent); + struct clk_hw_onecell_data *clk_data; + + clk_data = mtk_alloc_clk_data(MT6320_CLK_MAX); + if (!clk_data) + return -ENOMEM; + + ret = mtk_clk_register_fixed_clks(mt6320_fixed_clks, + ARRAY_SIZE(mt6320_fixed_clks), + clk_data); + if (ret) + goto err_free_data; + + ret = mtk_clk_register_factors(mt6320_factors, + ARRAY_SIZE(mt6320_factors), + clk_data); + if (ret) + goto err_unreg_fixed; + + for (i = 0; i < ARRAY_SIZE(mt6320_gates); i++) { + const struct mtk_gate *gate = &mt6320_gates[i]; + struct mt6320_gate *cg; + struct clk_init_data init = {}; + + if (!IS_ERR_OR_NULL(clk_data->hws[gate->id])) { + dev_warn(dev, "Duplicate gate ID %d\n", gate->id); + continue; + } + + cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL); + if (!cg) { + ret = -ENOMEM; + goto err_unreg_factors; + } + + init.name = gate->name; + init.ops = gate->ops; + init.flags = gate->flags | CLK_IGNORE_UNUSED; + init.parent_names = gate->parent_name ? &gate->parent_name : NULL; + init.num_parents = gate->parent_name ? 1 : 0; + + cg->regmap = mt6320->regmap; + cg->gate = gate; + cg->hw.init = &init; + + ret = clk_hw_register(dev, &cg->hw); + if (ret) { + dev_err(dev, "Failed to register gate %s\n", gate->name); + goto err_unreg_factors; + } + clk_data->hws[gate->id] = &cg->hw; + } + + for (i = 0; i < ARRAY_SIZE(mt6320_composites); i++) { + const struct mt6320_comp_desc *d = &mt6320_composites[i]; + struct mt6320_clk_composite *c; + struct clk_init_data init = {}; + + if (!IS_ERR_OR_NULL(clk_data->hws[d->id])) { + dev_warn(dev, "Duplicate composite ID %d\n", d->id); + continue; + } + + c = devm_kzalloc(dev, sizeof(*c), GFP_KERNEL); + if (!c) { + ret = -ENOMEM; + goto err_unreg_composites; + } + + init.name = d->name; + init.ops = &mt6320_composite_ops; + init.parent_names = d->parent_names; + init.num_parents = d->num_parents; + init.flags = d->flags; + + c->regmap = mt6320->regmap; + c->enable_reg = d->enable_reg; + c->enable_shift = d->enable_shift; + c->div_reg = d->div_reg; + c->div_shift = d->div_shift; + c->div_width = d->div_width; + c->div_base = d->div_base; + c->div_factor = d->div_factor; + c->mux_reg = d->mux_reg; + c->mux_shift = d->mux_shift; + c->mux_width = d->mux_width; + c->hw.init = &init; + + ret = clk_hw_register(dev, &c->hw); + if (ret) { + dev_err(dev, "Failed to register composite %s\n", d->name); + goto err_unreg_composites; + } + clk_data->hws[d->id] = &c->hw; + } + + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, clk_data); + if (ret) { + dev_err(dev, "Failed to add clock provider\n"); + goto err_unreg_composites; + } + + platform_set_drvdata(pdev, clk_data); + return 0; + +err_unreg_composites: + for (i = ARRAY_SIZE(mt6320_composites) - 1; i >= 0; i--) { + struct clk_hw *hw = clk_data->hws[mt6320_composites[i].id]; + if (!IS_ERR_OR_NULL(hw)) + clk_hw_unregister(hw); + } + for (i = ARRAY_SIZE(mt6320_gates) - 1; i >= 0; i--) { + struct clk_hw *hw = clk_data->hws[mt6320_gates[i].id]; + if (!IS_ERR_OR_NULL(hw)) + clk_hw_unregister(hw); + } +err_unreg_factors: + mtk_clk_unregister_factors(mt6320_factors, ARRAY_SIZE(mt6320_factors), clk_data); +err_unreg_fixed: + mtk_clk_unregister_fixed_clks(mt6320_fixed_clks, ARRAY_SIZE(mt6320_fixed_clks), clk_data); +err_free_data: + mtk_free_clk_data(clk_data); + return ret; +} + +static void mt6320_clk_remove(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + int i; + + of_clk_del_provider(pdev->dev.of_node); + + for (i = ARRAY_SIZE(mt6320_composites) - 1; i >= 0; i--) { + struct clk_hw *hw = clk_data->hws[mt6320_composites[i].id]; + if (!IS_ERR_OR_NULL(hw)) + clk_hw_unregister(hw); + } + + for (i = ARRAY_SIZE(mt6320_gates) - 1; i >= 0; i--) { + struct clk_hw *hw = clk_data->hws[mt6320_gates[i].id]; + if (!IS_ERR_OR_NULL(hw)) + clk_hw_unregister(hw); + } + + mtk_clk_unregister_factors(mt6320_factors, ARRAY_SIZE(mt6320_factors), clk_data); + mtk_clk_unregister_fixed_clks(mt6320_fixed_clks, ARRAY_SIZE(mt6320_fixed_clks), clk_data); + + mtk_free_clk_data(clk_data); +} + +static struct platform_driver mt6320_clk_driver = { + .probe = mt6320_clk_probe, + .remove = mt6320_clk_remove, + .driver = { + .name = "mt6320-clk", + .of_match_table = mt6320_clk_match_table, + }, +}; +module_platform_driver(mt6320_clk_driver); + +MODULE_AUTHOR("Akari Tsuyukusa "); +MODULE_DESCRIPTION("Clock Driver for MediaTek MT6320 PMIC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-apmixedsys.c b/drivers/clk/mediatek/clk-mt6589-apmixedsys.c new file mode 100644 index 00000000000000..ff5c79f533b6b8 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-apmixedsys.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + * + * Based on clk-mt2712-apmixedsys.c + * Copyright (c) 2017 MediaTek Inc. + * Weiyi Lu + * Copyright (c) 2023 Collabora Ltd. + * AngeloGioacchino Del Regno + */ +#include +#include +#include +#include + +#include "clk-pll.h" +#include "clk-gate.h" +#include "clk-mtk.h" + +#include + +#define AP_PLL_CON0 0x0000 +#define AP_PLL_CON1 0x0004 +#define AP_PLL_CON2 0x0008 +#define AP_PLL_CON3 0x000c + +#define PLL_HP_CON0 0x0014 + +#define ARMPLL_CON0 0x0200 +#define ARMPLL_CON1 0x0204 +#define ARMPLL_CON2 0x0208 +#define ARMPLL_PWR_CON0 0x0218 + +#define MAINPLL_CON0 0x021c +#define MAINPLL_CON1 0x0220 +#define MAINPLL_CON2 0x0224 +#define MAINPLL_PWR_CON0 0x0234 + +#define UNIVPLL_CON0 0x0238 +#define MMPLL_CON0 0x0240 +#define ISPPLL_CON0 0x0248 + +#define MSDCPLL_CON0 0x0250 +#define MSDCPLL_CON1 0x0254 +#define MSDCPLL_CON2 0x0258 +#define MSDCPLL_PWR_CON0 0x0268 + +#define TVDPLL_CON0 0x026c +#define TVDPLL_CON1 0x0270 +#define TVDPLL_CON2 0x0274 +#define TVDPLL_CON3 0x0278 +#define TVDPLL_PWR_CON0 0x0284 + +#define LVDSPLL_CON0 0x0288 +#define LVDSPLL_CON1 0x028c +#define LVDSPLL_CON2 0x0290 +#define LVDSPLL_CON3 0x0294 +#define LVDSPLL_PWR_CON0 0x02a0 + +#define VOID_REG 0x0 + +#define CON0_MT6589_RST_BAR BIT(27) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _pcw_reg, _pcw_shift, \ + _ops, _fmax, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT6589_RST_BAR, \ + .fmax = _fmax, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_mask = 0x3, \ + .pd_shift = _pd_shift, \ + .tuner_reg = VOID_REG, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + .ops = _ops, \ + } + +static int mt6589_lc_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 pcw = 0; + u32 postdiv; + u32 mask, val; + bool prepared; + int ret; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate); + prepared = mtk_pll_is_prepared(hw); + + if (prepared) + mtk_pll_unprepare(hw); + + /* LC PLL: write directly to CON0, no PCW_CHG trigger */ + val = readl(pll->base_addr); + /* Clear postdiv field (2 bits) */ + mask = pll->data->pd_mask ?: 0x3; + val &= ~(mask << pll->data->pd_shift); + /* Clear FBKDIV field (pcwbits, from pcw_shift) */ + val &= ~(GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1, + pll->data->pcw_shift)); + /* Set new postdiv and pcw */ + val |= ((ffs(postdiv) - 1) << pll->data->pd_shift); + val |= (pcw << pll->data->pcw_shift); + + writel(val, pll->base_addr); + udelay(20); /* stabilize */ + + if (prepared) { + ret = mtk_pll_prepare(hw); + if (ret) + return ret; + } + + return 0; +} + +static const struct clk_ops mt6589_lc_pll_ops = { + .is_prepared = mtk_pll_is_prepared, + .prepare = mtk_pll_prepare, + .unprepare = mtk_pll_unprepare, + .recalc_rate = mtk_pll_recalc_rate, + .determine_rate = mtk_pll_determine_rate, + .set_rate = mt6589_lc_pll_set_rate, +}; + +static const struct clk_ops mt6589_fixed_lc_pll_ops = { + .is_prepared = mtk_pll_is_prepared, + .prepare = mtk_pll_prepare, + .unprepare = mtk_pll_unprepare, + .recalc_rate = mtk_pll_recalc_rate, + .determine_rate = mtk_pll_determine_rate, + /* no .set_rate */ +}; + +static const struct mtk_pll_div_table mt6589_isppll_div_table[] = { + { .div = 0, .freq = 1664 * MHZ }, + { .div = 1, .freq = 1000 * MHZ }, + { .div = 2, .freq = 500 * MHZ }, + { } +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", ARMPLL_CON0, ARMPLL_PWR_CON0, 0x80000001, + PLL_AO, 21, ARMPLL_CON1, 24, ARMPLL_CON1, 0, NULL, 1508 * MHZ, NULL), + PLL(CLK_APMIXED_MAINPLL, "mainpll", MAINPLL_CON0, MAINPLL_PWR_CON0, 0xf0000001, + HAVE_RST_BAR, 21, MAINPLL_CON0, 6, MAINPLL_CON1, 0, NULL, 1768 * MHZ, NULL), + PLL(CLK_APMIXED_UNIVPLL, "univpll", UNIVPLL_CON0, VOID_REG, 0xf3000001, + HAVE_RST_BAR, 7, UNIVPLL_CON0, 6, UNIVPLL_CON0, 8, + &mt6589_fixed_lc_pll_ops, 1248 * MHZ, NULL), + PLL(CLK_APMIXED_MMPLL, "mmpll", MMPLL_CON0, VOID_REG, 0xf0000001, + HAVE_RST_BAR, 7, MMPLL_CON0, 6, MMPLL_CON0, 8, + &mt6589_fixed_lc_pll_ops, 1690 * MHZ, NULL), + PLL(CLK_APMIXED_ISPPLL, "isppll", ISPPLL_CON0, VOID_REG, 0x80000001, + 0, 7, ISPPLL_CON0, 6, ISPPLL_CON0, 8, + &mt6589_lc_pll_ops, 1664 * MHZ, mt6589_isppll_div_table), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", MSDCPLL_CON0, MSDCPLL_PWR_CON0, 0x80000001, + 0, 21, MSDCPLL_CON0, 6, MSDCPLL_CON1, 0, NULL, 1664 * MHZ, NULL), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", TVDPLL_CON0, TVDPLL_PWR_CON0, 0x80000001, + 0, 21, TVDPLL_CON0, 6, TVDPLL_CON1, 0, NULL, 2376UL * MHZ, NULL), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", LVDSPLL_CON0, LVDSPLL_PWR_CON0, 0x80000001, + 0, 21, LVDSPLL_CON0, 6, LVDSPLL_CON1, 0, NULL, 1440 * MHZ, NULL), +}; + +/* TODO: convert to gate */ +static const struct mtk_fixed_factor pll_divs[] = { + FACTOR(CLK_APMIXED_ARMPLL_1300M, "armpll_1300m", "armpll", 1, 1), + + FACTOR(CLK_APMIXED_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2), + FACTOR(CLK_APMIXED_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3), + FACTOR(CLK_APMIXED_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5), + FACTOR(CLK_APMIXED_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7), + + FACTOR(CLK_APMIXED_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2), + FACTOR(CLK_APMIXED_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3), + FACTOR(CLK_APMIXED_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5), + FACTOR(CLK_APMIXED_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7), + FACTOR(CLK_APMIXED_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26), + FACTOR(CLK_APMIXED_UNIVPLL_USB_48M, "univpll_usb_48m", "univpll", 1, 26), + + FACTOR(CLK_APMIXED_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_APMIXED_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3), + FACTOR(CLK_APMIXED_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5), + FACTOR(CLK_APMIXED_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7), + + FACTOR(CLK_APMIXED_ISPPLL_208M, "isppll_208m", "isppll", 1, 2), + + FACTOR(CLK_APMIXED_MSDCPLL_208M, "msdcpll_208m", "msdcpll", 1, 2), + + FACTOR(CLK_APMIXED_TVDPLL_148P5M, "tvdpll_148p5m", "tvdpll", 1, 16), + + FACTOR(CLK_APMIXED_LVDSPLL_180M, "lvdspll_180m", "lvdspll", 1, 2), +}; + +static const struct mtk_clk_desc apmixed_desc = { + .plls = plls, + .num_plls = ARRAY_SIZE(plls), + .factor_clks = pll_divs, + .num_factor_clks = ARRAY_SIZE(pll_divs), +}; + +static const struct of_device_id of_match_clk_mt6589_apmixed[] = { + { .compatible = "mediatek,mt6589-apmixedsys", .data = &apmixed_desc }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_apmixed); + +static struct platform_driver clk_mt6589_apmixed_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-apmixed", + .of_match_table = of_match_clk_mt6589_apmixed, + }, +}; +module_platform_driver(clk_mt6589_apmixed_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 apmixedsys clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-aud.c b/drivers/clk/mediatek/clk-mt6589-aud.c new file mode 100644 index 00000000000000..68dc4dbeb26385 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-aud.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define AUDIO_TOP_CON0 0x0000 + +static const struct mtk_gate_regs aud_cg_regs = { + .sta_ofs = AUDIO_TOP_CON0, +}; + +#define GATE_AUDIO(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &aud_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate aud_clks[] = { + GATE_AUDIO(CLK_AUDIO_AFE, "audio_afe", "infra_audio", 2), + GATE_AUDIO(CLK_AUDIO_I2S, "audio_i2s", "infra_audio", 6), +}; + +static const struct mtk_clk_desc aud_desc = { + .clks = aud_clks, + .num_clks = ARRAY_SIZE(aud_clks), +}; + +static const struct of_device_id of_match_clk_mt6589_aud[] = { + { + .compatible = "mediatek,mt6589-audsys", + .data = &aud_desc, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_aud); + +static struct platform_driver clk_mt6589_aud_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-aud", + .of_match_table = of_match_clk_mt6589_aud, + }, +}; +module_platform_driver(clk_mt6589_aud_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 audio clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-disp.c b/drivers/clk/mediatek/clk-mt6589-disp.c new file mode 100644 index 00000000000000..96afc6126972f4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-disp.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define DISP_CG_CON0 0x0100 +#define DISP_CG_SET0 0x0104 +#define DISP_CG_CLR0 0x0108 + +#define DISP_CG_CON1 0x0110 +#define DISP_CG_SET1 0x0114 +#define DISP_CG_CLR1 0x0118 + +static const struct mtk_gate_regs disp0_cg_regs = { + .set_ofs = DISP_CG_SET0, + .clr_ofs = DISP_CG_CLR0, + .sta_ofs = DISP_CG_CON0, +}; + +static const struct mtk_gate_regs disp1_cg_regs = { + .set_ofs = DISP_CG_SET1, + .clr_ofs = DISP_CG_CLR1, + .sta_ofs = DISP_CG_CON1, +}; + +#define GATE_DISP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &disp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_DISP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &disp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate disp_clks[] = { + GATE_DISP0(CLK_DISP0_LARB2_SMI, "disp0_larb2_smi", "smi_sel", 0), /* mt8135 */ + GATE_DISP0(CLK_DISP0_ROT_ENGINE, "disp0_rot_engine", "disp_sel", 1), + GATE_DISP0(CLK_DISP0_ROT_SMI, "disp0_rot_smi", "smi_sel", 2), /* mt8135 */ + GATE_DISP0(CLK_DISP0_SCL, "disp0_scl", "disp_sel", 3), + GATE_DISP0(CLK_DISP0_OVL_ENGINE, "disp0_ovl_engine", "disp_sel", 4), + GATE_DISP0(CLK_DISP0_OVL_SMI, "disp0_ovl_smi", "smi_sel", 5), /* mt8135 */ + GATE_DISP0(CLK_DISP0_COLOR, "disp0_color", "disp_sel", 6), + GATE_DISP0(CLK_DISP0_2DSHP, "disp0_2dshp", "disp_sel", 7), + GATE_DISP0(CLK_DISP0_BLS, "disp0_bls", "disp_sel", 8), + GATE_DISP0(CLK_DISP0_WDMA0_ENGINE, "disp0_wdma0_engine", "disp_sel", 9), + GATE_DISP0(CLK_DISP0_WDMA0_SMI, "disp0_wdma0_smi", "smi_sel", 10), /* mt8135 */ + GATE_DISP0(CLK_DISP0_WDMA1_ENGINE, "disp0_wdma1_engine", "disp_sel", 11), + GATE_DISP0(CLK_DISP0_WDMA1_SMI, "disp0_wdma1_smi", "smi_sel", 12), /* mt8135 */ + GATE_DISP0(CLK_DISP0_RDMA0_ENGINE, "disp0_rdma0_engine", "disp_sel", 13), + GATE_DISP0(CLK_DISP0_RDMA0_SMI, "disp0_rdma0_smi", "clk_null", 14), /* mt8135 */ + GATE_DISP0(CLK_DISP0_RDMA0_OUTPUT, "disp0_rdma0_output", "clk_null", 15), /* mt8135 */ + GATE_DISP0(CLK_DISP0_RDMA1_ENGINE, "disp0_rdma1_engine", "disp_sel", 16), + GATE_DISP0(CLK_DISP0_RDMA1_SMI, "disp0_rdma1_smi", "clk_null", 17), /* mt8135 */ + GATE_DISP0(CLK_DISP0_RDMA1_OUTPUT, "disp0_rdma1_output", "clk_null", 18), /* mt8135 */ + GATE_DISP0(CLK_DISP0_GAMMA_ENGINE, "disp0_gamma_engine", "disp_sel", 19), + GATE_DISP0(CLK_DISP0_GAMMA_PIXEL, "disp0_gamma_pixel", "clk_null", 20), /* mt8135 */ + GATE_DISP0(CLK_DISP0_CMDQ_ENGINE, "disp0_cmdq_engine", "disp_sel", 21), + GATE_DISP0(CLK_DISP0_CMDQ_SMI, "disp0_cmdq_smi", "smi_sel", 22), /* mt8135 */ + GATE_DISP0(CLK_DISP0_G2D_ENGINE, "disp0_g2d_engine", "disp_sel", 23), + GATE_DISP0(CLK_DISP0_G2D_SMI, "disp0_g2d_smi", "smi_sel", 24), /* mt8135 */ + + GATE_DISP1(CLK_DISP1_DBI_ENGINE, "disp1_dbi_engine", "disp_sel", 0), + GATE_DISP1(CLK_DISP1_DBI_SMI, "disp1_dbi_smi", "smi_sel", 1), /* maybe */ + GATE_DISP1(CLK_DISP1_DBI_OUTPUT, "disp1_dbi_output", "disp_sel", 2), + GATE_DISP1(CLK_DISP1_DSI_ENGINE, "disp1_dsi_engine", "disp_sel", 3), + GATE_DISP1(CLK_DISP1_DSI_DIGITAL, "disp1_dsi_digital", "disp_sel", 4), + GATE_DISP1(CLK_DISP1_DSI_DIGITAL_LANE, "disp1_dsi_digital_lane", "disp_sel", 5), + GATE_DISP1(CLK_DISP1_DPI0, "disp1_dpi0", "disp_sel", 6), + GATE_DISP1(CLK_DISP1_DPI1, "disp1_dpi1", "disp_sel", 7), + GATE_DISP1(CLK_DISP1_LCD, "disp1_lcd", "disp_sel", 8), + GATE_DISP1(CLK_DISP1_SLCD, "disp1_slcd", "disp_sel", 9), +}; + +static const struct mtk_clk_desc disp_desc = { + .clks = disp_clks, + .num_clks = ARRAY_SIZE(disp_clks), +}; + +static const struct platform_device_id clk_mt6589_disp_id_table[] = { + { .name = "clk-mt6589-disp", .driver_data = (kernel_ulong_t)&disp_desc }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, clk_mt6589_disp_id_table); + +static struct platform_driver clk_mt6589_disp_drv = { + .id_table = clk_mt6589_disp_id_table, + .probe = mtk_clk_pdev_probe, + .remove = mtk_clk_pdev_remove, + .driver = { + .name = "clk-mt6589-disp", + }, +}; +module_platform_driver(clk_mt6589_disp_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 display clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-img.c b/drivers/clk/mediatek/clk-mt6589-img.c new file mode 100644 index 00000000000000..3a8db58a549c41 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-img.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define IMG_CG_CON 0x0000 +#define IMG_CG_SET 0x0004 +#define IMG_CG_CLR 0x0008 + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = IMG_CG_SET, + .clr_ofs = IMG_CG_CLR, + .sta_ofs = IMG_CG_CON, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMAGE_LARB3_SMI, "image_larb3_smi", "smi_sel", 0), /* mt8135 */ + GATE_IMG(CLK_IMAGE_LARB4_SMI, "image_larb4_smi", "smi_sel", 2), /* mt8135 */ + GATE_IMG(CLK_IMAGE_COMMON_SMI, "image_common_smi", "smi_sel", 4), /* mt8135 */ + GATE_IMG(CLK_IMAGE_CAM_SMI, "image_cam_smi", "smi_sel", 5), /* mt8135 */ + GATE_IMG(CLK_IMAGE_CAM_CAM, "image_cam_cam", "cam_sel", 6), + GATE_IMG(CLK_IMAGE_SEN_TG, "image_sen_tg", "camtg_sel", 7), + GATE_IMG(CLK_IMAGE_SEN_CAM, "image_sen_cam", "cam_sel", 8), + GATE_IMG(CLK_IMAGE_JPGD_SMI, "image_jpgd_smi", "smi_sel", 9), /* mt8135 */ + GATE_IMG(CLK_IMAGE_JPGD_JPG, "image_jpgd_jpg", "jpg_sel", 10), + GATE_IMG(CLK_IMAGE_JPGE_SMI, "image_jpge_smi", "smi_sel", 11), /* mt8135 */ + GATE_IMG(CLK_IMAGE_JPGE_JPG, "image_jpge_jpg", "jpg_sel", 12), + GATE_IMG(CLK_IMAGE_FPC, "image_fpc", "smi_sel", 13), /* mt8135 */ +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct of_device_id of_match_clk_mt6589_img[] = { + { + .compatible = "mediatek,mt6589-imgsys", + .data = &img_desc, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_img); + +static struct platform_driver clk_mt6589_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-img", + .of_match_table = of_match_clk_mt6589_img, + }, +}; +module_platform_driver(clk_mt6589_img_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 imgsys clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-infracfg.c b/drivers/clk/mediatek/clk-mt6589-infracfg.c new file mode 100644 index 00000000000000..e549fa36b8d738 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-infracfg.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define TOP_CKMUXSEL 0x0000 +#define INFRA_RST0 0x0030 +#define INFRA_RST1 0x0034 +#define INFRA_PDN_SET 0x0040 +#define INFRA_PDN_CLR 0x0044 +#define INFRA_PDN_STA 0x0048 + +static DEFINE_SPINLOCK(mt6589_infra_clk_lock); + +static const char * const infra_mux1_parents[] = { + "clk26m", + "armpll", + "mainpll", + "mmpll_d2", +}; + +static const struct mtk_composite cpu_muxes[] = { + MUX(CLK_INFRA_MUX1, "infra_mux1_sel", infra_mux1_parents, TOP_CKMUXSEL, 2, 2), +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = INFRA_PDN_SET, + .clr_ofs = INFRA_PDN_CLR, + .sta_ofs = INFRA_PDN_STA, +}; + +#define GATE_INFRA(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), /* mt8135 */ + GATE_INFRA(CLK_INFRA_SMI, "infra_smi", "smi_sel", 1), /* mt8135 */ + GATE_INFRA(CLK_INFRA_SPI0, "infra_spi0", "spi_sel", 2), /* maybe, is it infra_mfg_bus? */ + GATE_INFRA(CLK_INFRA_AUDIO, "infra_audio", "audintbus_sel", 5), + GATE_INFRA(CLK_INFRA_DEVAPC, "infra_devapc", "axi_sel", 6), /* axi_sel? */ + GATE_INFRA(CLK_INFRA_MFGAXI, "infra_mfgaxi", "axi_sel", 7), /* mt8135 */ + GATE_INFRA(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8), /* mt8135 */ + GATE_INFRA(CLK_INFRA_MD1MCUAXI, "infra_md1mcuaxi", "axi_sel", 9), /* maybe */ + GATE_INFRA(CLK_INFRA_MD1HWMIXAXI, "infra_md1hwmixaxi", "axi_sel", 10), /* maybe */ + GATE_INFRA(CLK_INFRA_MD1AHB, "infra_md1ahb", "axi_sel", 11), /* maybe */ + GATE_INFRA(CLK_INFRA_MD2MCUAXI, "infra_md2mcuaxi", "axi_sel", 12), /* maybe */ + GATE_INFRA(CLK_INFRA_MD2HWMIXAXI, "infra_md2hwmixaxi", "axi_sel", 13), /* maybe */ + GATE_INFRA(CLK_INFRA_MD2AHB, "infra_md2ahb", "axi_sel", 14), /* maybe */ + GATE_INFRA(CLK_INFRA_CPUM, "infra_cpum", "cpum_tck_in", 15), /* mt8135 */ + GATE_INFRA(CLK_INFRA_KP, "infra_kp", "axi_sel", 16), /* mt8135 */ + GATE_INFRA(CLK_INFRA_CCIF0, "infra_ccif0", "axi_sel", 20), /* mt8135 */ + GATE_INFRA(CLK_INFRA_CCIF1, "infra_ccif1", "axi_sel", 21), /* mt8135 */ + GATE_INFRA(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22), /* mt8135 */ + GATE_INFRA(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23), /* mt8135 */ +}; + +static u16 infrasys_rst_ofs[] = { INFRA_RST0, INFRA_RST1 }; + +static const struct mtk_clk_rst_desc infra_clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = infrasys_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infrasys_rst_ofs), +}; + +static const struct mtk_clk_desc infra_desc = { + .clks = infra_clks, + .num_clks = ARRAY_SIZE(infra_clks), + .cpumuxes = cpu_muxes, + .num_cpumuxes = ARRAY_SIZE(cpu_muxes), + .rst_desc = &infra_clk_rst_desc, + .clk_lock = &mt6589_infra_clk_lock, +}; + +static const struct of_device_id of_match_clk_mt6589_infracfg[] = { + { .compatible = "mediatek,mt6589-infracfg", .data = &infra_desc }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_infracfg); + +static struct platform_driver clk_mt6589_infracfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-infracfg", + .of_match_table = of_match_clk_mt6589_infracfg, + }, +}; +module_platform_driver(clk_mt6589_infracfg_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 infracfg clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-mfg.c b/drivers/clk/mediatek/clk-mt6589-mfg.c new file mode 100644 index 00000000000000..83b7a37a82b828 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-mfg.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define MFG_CG_CON 0x0000 +#define MFG_CG_SET 0x0004 +#define MFG_CG_CLR 0x0008 +#define MFG_RESET 0x000c + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = MFG_CG_SET, + .clr_ofs = MFG_CG_CLR, + .sta_ofs = MFG_CG_CON, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_AXI, "mfg_axi", "axi_sel", 0), /* mt8135 (or infra_mfgaxi) */ + GATE_MFG(CLK_MFG_MEM, "mfg_mem", "smi_mfg_as_sel", 1), + GATE_MFG(CLK_MFG_G3D, "mfg_g3d", "mfg_sel", 2), + GATE_MFG(CLK_MFG_HYD, "mfg_hyd", "hyd_sel", 3), +}; + +static u16 mfg_rst_ofs[] = { MFG_RESET }; + +static const struct mtk_clk_rst_desc mfg_clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = mfg_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(mfg_rst_ofs), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), + .rst_desc = &mfg_clk_rst_desc, +}; + +static const struct of_device_id of_match_clk_mt6589_mfg[] = { + { + .compatible = "mediatek,mt6589-mfgsys", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_mfg); + +static struct platform_driver clk_mt6589_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-mfg", + .of_match_table = of_match_clk_mt6589_mfg, + }, +}; +module_platform_driver(clk_mt6589_mfg_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 mfgsys clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-pericfg.c b/drivers/clk/mediatek/clk-mt6589-pericfg.c new file mode 100644 index 00000000000000..593f0f8f5de510 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-pericfg.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define PERI_RST0 0x0000 +#define PERI_RST1 0x0004 +#define PERI_PDN0_SET 0x0008 +#define PERI_PDN0_CLR 0x0010 +#define PERI_PDN0_STA 0x0018 +#define PERI_PDN1_SET 0x000c +#define PERI_PDN1_CLR 0x0014 +#define PERI_PDN1_STA 0x001c + +static DEFINE_SPINLOCK(mt6589_peri_clk_lock); + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = PERI_PDN0_SET, + .clr_ofs = PERI_PDN0_CLR, + .sta_ofs = PERI_PDN0_STA, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = PERI_PDN1_SET, + .clr_ofs = PERI_PDN1_CLR, + .sta_ofs = PERI_PDN1_STA, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate peri_clks[] = { + GATE_PERI0(CLK_PERI0_NFI, "peri_nfi", "axi_sel", 0), /* mt8135 */ + GATE_PERI0(CLK_PERI0_THERM, "peri_therm", "axi_sel", 1), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM1, "peri_pwm1", "axi_sel", 2), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM2, "peri_pwm2", "axi_sel", 3), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM3, "peri_pwm3", "axi_sel", 4), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM4, "peri_pwm4", "axi_sel", 5), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM5, "peri_pwm5", "axi_sel", 6), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM6, "peri_pwm6", "axi_sel", 7), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM7, "peri_pwm7", "axi_sel", 8), /* mt8135 */ + GATE_PERI0(CLK_PERI0_PWM, "peri_pwm", "axi_sel", 9), /* mt8135 */ + GATE_PERI0(CLK_PERI0_USB0, "peri_usb0", "usb20_sel", 10), + GATE_PERI0(CLK_PERI0_USB1, "peri_usb1", "usb20_sel", 11), + GATE_PERI0(CLK_PERI0_APDMA, "peri_apdma", "axi_sel", 12), /* mt8135 */ + GATE_PERI0(CLK_PERI0_MSDC0, "peri_msdc0", "msdc0_sel", 13), + GATE_PERI0(CLK_PERI0_MSDC1, "peri_msdc1", "msdc1_sel", 14), + GATE_PERI0(CLK_PERI0_MSDC2, "peri_msdc2", "msdc2_sel", 15), + GATE_PERI0(CLK_PERI0_MSDC3, "peri_msdc3", "msdc3_sel", 16), + GATE_PERI0(CLK_PERI0_MSDC4, "peri_msdc4", "msdc4_sel", 17), + GATE_PERI0(CLK_PERI0_APHIF, "peri_aphif", "axi_sel", 18), /* mt8135 */ + GATE_PERI0(CLK_PERI0_MDHIF, "peri_mdhif", "axi_sel", 19), /* mt8135 */ + GATE_PERI0(CLK_PERI0_NLI, "peri_nli", "axi_sel", 20), /* mt8135 */ + GATE_PERI0(CLK_PERI0_IRDA, "peri_irda", "irda_sel", 21), + GATE_PERI0(CLK_PERI0_UART0, "peri_uart0", "axi_sel", 22), /* mt2701 */ + GATE_PERI0(CLK_PERI0_UART1, "peri_uart1", "axi_sel", 23), /* mt2701 */ + GATE_PERI0(CLK_PERI0_UART2, "peri_uart2", "axi_sel", 24), /* mt2701 */ + GATE_PERI0(CLK_PERI0_UART3, "peri_uart3", "axi_sel", 25), /* mt2701 */ + GATE_PERI0(CLK_PERI0_I2C0, "peri_i2c0", "axi_sel", 26), /* mt8135 */ + GATE_PERI0(CLK_PERI0_I2C1, "peri_i2c1", "axi_sel", 27), /* mt8135 */ + GATE_PERI0(CLK_PERI0_I2C2, "peri_i2c2", "axi_sel", 28), /* mt8135 */ + GATE_PERI0(CLK_PERI0_I2C3, "peri_i2c3", "axi_sel", 29), /* mt8135 */ + GATE_PERI0(CLK_PERI0_I2C4, "peri_i2c4", "axi_sel", 30), /* mt8135 */ + GATE_PERI0(CLK_PERI0_I2C5, "peri_i2c5", "axi_sel", 31), /* mt8135 */ + + GATE_PERI1(CLK_PERI1_I2C6, "peri_i2c6", "axi_sel", 0), /* mt8135 */ + GATE_PERI1(CLK_PERI1_PWRAP, "peri_pwrap", "axi_sel", 1), /* mt8135 */ + GATE_PERI1(CLK_PERI1_AUXADC, "peri_auxadc", "axi_sel", 2), /* mt8135 */ + GATE_PERI1(CLK_PERI1_SPI1, "peri_spi1", "spi_sel", 3), + GATE_PERI1(CLK_PERI1_FHCTL, "peri_fhctl", "clk26m", 4), /* mt8135 */ +}; + +static const char * const uart_mux_parents[] = { + "clk26m", /* 26 MHz */ + "uart_sel", /* or univpll2_d8, 52 MHz */ +}; + +static const struct mtk_composite peri_muxes[] = { + MUX(CLK_PERI_MUX_UART0, "peri_uart0_sel", uart_mux_parents, + 0x040c, 0, 1), + MUX(CLK_PERI_MUX_UART1, "peri_uart1_sel", uart_mux_parents, + 0x040c, 1, 1), + MUX(CLK_PERI_MUX_UART2, "peri_uart2_sel", uart_mux_parents, + 0x040c, 2, 1), + MUX(CLK_PERI_MUX_UART3, "peri_uart3_sel", uart_mux_parents, + 0x040c, 3, 1), +}; + +static u16 pericfg_rst_ofs[] = { PERI_RST0, PERI_RST1 }; + +static const struct mtk_clk_rst_desc peri_clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = pericfg_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(pericfg_rst_ofs), +}; + +static const struct mtk_clk_desc peri_desc = { + .clks = peri_clks, + .num_clks = ARRAY_SIZE(peri_clks), + .composite_clks = peri_muxes, + .num_composite_clks = ARRAY_SIZE(peri_muxes), + .rst_desc = &peri_clk_rst_desc, + .clk_lock = &mt6589_peri_clk_lock, +}; + +static const struct of_device_id of_match_clk_mt6589_pericfg[] = { + { .compatible = "mediatek,mt6589-pericfg", .data = &peri_desc, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_pericfg); + +static struct platform_driver clk_mt6589_pericfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-pericfg", + .of_match_table = of_match_clk_mt6589_pericfg, + }, +}; +module_platform_driver(clk_mt6589_pericfg_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 pericfg clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-topckgen.c b/drivers/clk/mediatek/clk-mt6589-topckgen.c new file mode 100644 index 00000000000000..fb03916e9f1c13 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-topckgen.c @@ -0,0 +1,430 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static DEFINE_SPINLOCK(mt6589_topckgen_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_CLK_NULL, "clk_null", NULL, 0), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1), + FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1), + + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 2), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_806m", 1, 3), + FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_806m", 2, 7), + FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_806m", 1, 5), + FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 6), + FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 8), + FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 10), + FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 16), + FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 24), + + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1), + + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10), + + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8), + + FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2), + FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2), + + FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1, 1), + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), // lvdspll_180m ? + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + + FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll_d3", + "syspll_d4", + "syspll_d6", + "univpll_d5", + "univpll2_d2", + "syspll_d3p5", +}; + +static const char * const smi_parents[] = { + "clk26m", + "syspll_d3", + "syspll_d8", + "univpll_d5", + "univpll1_d6", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6", +}; + +static const char * const mfg_parents[] = { + "univpll1_d4", + "mmpll_d6", + "syspll_d2", + "syspll_d3", + "univpll1_d2", + "mmpll_d3", + "mmpll_d4", + "mmpll_d5", +}; + +static const char * const irda_parents[] = { + "clk26m", + "univpll2_d8", + "univpll1_d6", +}; + +static const char * const cam_parents[] = { + "clk26m", + "syspll_d3", + "syspll_d3p5", + "syspll_d4", + "syspll_d6", + "syspll_d8", + "isppll_208m", + "univpll_d5", + "univpll2_d2", + "univpll_d7", + "univpll1_d4", +}; + +static const char * const audintbus_parents[] = { + "clk26m", + "syspll_d6", + "univpll_d10", +}; + +static const char * const jpg_parents[] = { + "clk26m", + "syspll_d5", + "syspll_d4", + "univpll2_d2", + "univpll_d7", +}; + +static const char * const disp_parents[] = { + "clk26m", + "syspll_d3p5", + "syspll_d3", + "univpll2_d2", + "univpll_d5", +}; + +static const char * const msdc1_parents[] = { + "clk26m", + "syspll_d6", + "syspll_d5", + "univpll1_d4", + "univpll2_d4", + "msdcpll_208m", +}; + +static const char * const msdc2_parents[] = { + "clk26m", + "syspll_d6", + "syspll_d5", + "univpll1_d4", + "univpll2_d4", + "msdcpll_208m", +}; + +static const char * const msdc3_parents[] = { + "clk26m", + "syspll_d6", + "syspll_d5", + "univpll1_d4", + "univpll2_d4", + "msdcpll_208m", +}; + +static const char * const msdc4_parents[] = { + "clk26m", + "syspll_d6", + "syspll_d5", + "univpll1_d4", + "univpll2_d4", + "msdcpll_208m", +}; + +static const char * const usb20_parents[] = { + "clk26m", + "univpll2_d6", + "univpll1_d10", +}; + +static const char * const hyd_parents[] = { + "univpll1_d4", + "mmpll_d6", + "syspll_d2", + "syspll_d3", + "univpll1_d2", + "mmpll_d3", + "mmpll_d4", + "mmpll_d5", +}; + +static const char * const venc_parents[] = { + "clk26m", + "syspll_d3", + "syspll_d8", + "univpll_d5", + "univpll1_d6", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6", +}; + +static const char * const spi_parents[] = { + "clk26m", + "syspll_d6", + "syspll_d8", + "syspll_d10", + "univpll1_d6", + "univpll1_d8", +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8", +}; + +static const char * const mem_parents[] = { + "clk26m", + "clkph_mck", + "clk_null", + "clk_null", +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_d26", + "univpll1_d6", + "syspll_d16", + "syspll_d8", + "isppll_208m", +}; + +static const char * const fd_parents[] = { + "clk26m", + "syspll_d6", + "syspll_d8", + "univpll_d10", + "univpll2_d4", +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll_d24", +}; + +static const char * const fix_parents[] = { + "rtc_clk", + "clk26m", /* f_f26m_ck" */ + "univpll_d5", + "univpll_d7", + "univpll1_d2", + "univpll1_d4", + "univpll1_d6", + "univpll1_d8", +}; + +static const char * const vdec_parents[] = { + "clk26m", + "syspll_d3p5", + "syspll_d4", + "syspll_d5", + "syspll_d6", + "syspll_d8", + "univpll2_d2", + "univpll_d7", + "univpll_d10", + "univpll2_d4", +}; + +static const char * const dpilvds_parents[] = { + "clk26m", + "lvdspll_ck", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8", +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "univpll2_d6", + "syspll_d8", + "syspll_d10", + "univpll1_d10", + "mempll_mck_d4", + "univpll_d26", + "syspll_d24", +}; + +static const char * const msdc0_parents[] = { + "clk26m", + "syspll_d6", + "syspll_d5", + "univpll1_d4", + "univpll2_d4", + "msdcpll_208m", +}; + +static const char * const smi_mfg_as_parents[] = { + "clk26m", + "smi_sel", + "mfg_sel", + "hyd_sel", +}; + +#define CLK_CFG_0 0x40 +#define CLK_CFG_1 0x44 +#define CLK_CFG_2 0x48 +#define CLK_CFG_3 0x4c +#define CLK_CFG_4 0x50 +#define CLK_CFG_5 0x54 +#define CLK_CFG_6 0x58 +#define CLK_CFG_7 0x5c +#define CLK_CFG_8 0x64 + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX(CLK_TOP_MUX_AXI, "axi_sel", axi_parents, + CLK_CFG_0, 0, 3), + MUX_GATE(CLK_TOP_MUX_SMI, "smi_sel", smi_parents, + CLK_CFG_0, 8, 3, 15), + MUX_GATE(CLK_TOP_MUX_MFG, "mfg_sel", mfg_parents, + CLK_CFG_0, 16, 3, 23), + MUX_GATE(CLK_TOP_MUX_IRDA, "irda_sel", irda_parents, + CLK_CFG_0, 24, 2, 31), + + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_MUX_CAM, "cam_sel", cam_parents, + CLK_CFG_1, 0, 4, 7), + MUX_GATE(CLK_TOP_MUX_AUDINTBUS, "audintbus_sel", audintbus_parents, + CLK_CFG_1, 8, 2, 15), + MUX_GATE(CLK_TOP_MUX_JPG, "jpg_sel", jpg_parents, + CLK_CFG_1, 16, 3, 23), + MUX_GATE(CLK_TOP_MUX_DISP, "disp_sel", disp_parents, + CLK_CFG_1, 24, 3, 31), + + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_MUX_MSDC1, "msdc1_sel", msdc1_parents, + CLK_CFG_2, 0, 3, 7), + MUX_GATE(CLK_TOP_MUX_MSDC2, "msdc2_sel", msdc2_parents, + CLK_CFG_2, 8, 3, 15), + MUX_GATE(CLK_TOP_MUX_MSDC3, "msdc3_sel", msdc3_parents, + CLK_CFG_2, 16, 3, 23), + MUX_GATE(CLK_TOP_MUX_MSDC4, "msdc4_sel", msdc4_parents, + CLK_CFG_2, 24, 3, 31), + + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_MUX_USB20, "usb20_sel", usb20_parents, + CLK_CFG_3, 0, 2, 7), + + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_MUX_HYD, "hyd_sel", hyd_parents, + CLK_CFG_4, 0, 3, 7), + MUX_GATE(CLK_TOP_MUX_VENC, "venc_sel", venc_parents, + CLK_CFG_4, 8, 3, 15), + MUX_GATE(CLK_TOP_MUX_SPI, "spi_sel", spi_parents, + CLK_CFG_4, 16, 3, 23), + MUX_GATE(CLK_TOP_MUX_UART, "uart_sel", uart_parents, + CLK_CFG_4, 24, 2, 31), + + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_MUX_MEM, "mem_sel", mem_parents, + CLK_CFG_6, 0, 2, 7), + MUX_GATE(CLK_TOP_MUX_CAMTG, "camtg_sel", camtg_parents, + CLK_CFG_6, 8, 3, 15), + MUX_GATE(CLK_TOP_MUX_FD, "fd_sel", fd_parents, + CLK_CFG_6, 16, 3, 23), + MUX_GATE(CLK_TOP_MUX_AUDIO, "audio_sel", audio_parents, + CLK_CFG_6, 24, 2, 31), + + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_MUX_FIX, "fix_sel", fix_parents, + CLK_CFG_7, 0, 3, 7), + MUX_GATE(CLK_TOP_MUX_VDEC, "vdec_sel", vdec_parents, + CLK_CFG_7, 8, 4, 15), + MUX_GATE(CLK_TOP_MUX_DPILVDS, "dpilvds_sel", dpilvds_parents, + CLK_CFG_7, 24, 3, 31), + + /* CLK_CFG_8 */ + MUX_GATE(CLK_TOP_MUX_PMICSPI, "pmicspi_sel", pmicspi_parents, + CLK_CFG_8, 0, 3, 7), + MUX_GATE(CLK_TOP_MUX_MSDC0, "msdc0_sel", msdc0_parents, + CLK_CFG_8, 8, 3, 15), + MUX_GATE(CLK_TOP_MUX_SMI_MFG_AS, "smi_mfg_as_sel", smi_mfg_as_parents, + CLK_CFG_8, 16, 2, 23), +}; + +#define TOPCK_PDN_SET 0x70 +#define TOPCK_PDN_CLR 0x74 +#define TOPCK_PDN_STA 0x78 + +static const struct mtk_gate_regs topck_cg_regs = { + .set_ofs = TOPCK_PDN_SET, + .clr_ofs = TOPCK_PDN_CLR, + .sta_ofs = TOPCK_PDN_STA, +}; + +#define GATE_TOPCK(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &topck_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate top_clks[] = { + GATE_TOPCK(CLK_TOPCK_PMICSPI, "topck_pmicspi", "pmicspi_sel", 0), +}; + +static const struct mtk_clk_desc topck_desc = { + .clks = top_clks, + .num_clks = ARRAY_SIZE(top_clks), + .fixed_clks = top_fixed_clks, + .num_fixed_clks = ARRAY_SIZE(top_fixed_clks), + .factor_clks = top_divs, + .num_factor_clks = ARRAY_SIZE(top_divs), + .composite_clks = top_muxes, + .num_composite_clks = ARRAY_SIZE(top_muxes), + .clk_lock = &mt6589_topckgen_clk_lock, +}; + +static const struct of_device_id of_match_clk_mt6589_topckgen[] = { + { .compatible = "mediatek,mt6589-topckgen", .data = &topck_desc }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_topckgen); + +static struct platform_driver clk_mt6589_topckgen_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-topckgen", + .of_match_table = of_match_clk_mt6589_topckgen, + }, +}; +module_platform_driver(clk_mt6589_topckgen_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 topckgen driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-vdec.c b/drivers/clk/mediatek/clk-mt6589-vdec.c new file mode 100644 index 00000000000000..dba6ff725f7d5e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-vdec.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define VDEC_CKEN_SET 0x0000 +#define VDEC_CKEN_CLR 0x0004 +#define LARB_CKEN_SET 0x0008 +#define LARB_CKEN_CLR 0x000c + +static const struct mtk_gate_regs vdec_cg_regs = { + .set_ofs = VDEC_CKEN_SET, + .clr_ofs = VDEC_CKEN_CLR, + .sta_ofs = VDEC_CKEN_SET, +}; + +static const struct mtk_gate_regs larb_cg_regs = { + .set_ofs = LARB_CKEN_SET, + .clr_ofs = LARB_CKEN_CLR, + .sta_ofs = LARB_CKEN_SET, +}; + +#define GATE_VDEC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_LARB(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &larb_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + GATE_VDEC(CLK_VDEC0_VDE, "vdec0_vde", "vdec_sel", 0), + GATE_LARB(CLK_VDEC1_SMI, "vdec1_smi", "smi_sel", 0), /* mt8135 */ +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt6589_vdec[] = { + { + .compatible = "mediatek,mt6589-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_vdec); + +static struct platform_driver clk_mt6589_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-vdec", + .of_match_table = of_match_clk_mt6589_vdec, + }, +}; +module_platform_driver(clk_mt6589_vdec_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 video decoder clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6589-venc.c b/drivers/clk/mediatek/clk-mt6589-venc.c new file mode 100644 index 00000000000000..ac9f642b8a4eda --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6589-venc.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define VENCSYS_CG_CON 0x0000 +#define VENCSYS_CG_SET 0x0004 +#define VENCSYS_CG_CLR 0x0008 + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = VENCSYS_CG_SET, + .clr_ofs = VENCSYS_CG_CLR, + .sta_ofs = VENCSYS_CG_CON, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_VEN, "venc_ven", "venc_sel", 0), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt6589_venc[] = { + { + .compatible = "mediatek,mt6589-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, of_match_clk_mt6589_venc); + +static struct platform_driver clk_mt6589_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6589-venc", + .of_match_table = of_match_clk_mt6589_venc, + }, +}; +module_platform_driver(clk_mt6589_venc_drv); + +MODULE_DESCRIPTION("MediaTek MT6589 video encoder clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 3dfdd3a422f802..c3369a04cdecf0 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -19,6 +19,8 @@ #include "clk-mtk.h" #include "clk-gate.h" #include "clk-mux.h" +#include "clk-cpumux.h" +#include "clk-pll.h" const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 }; EXPORT_SYMBOL_GPL(cg_regs_dummy); @@ -485,7 +487,7 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, } /* Composite and divider clocks needs us to pass iomem pointer */ - if (mcd->composite_clks || mcd->divider_clks) { + if (mcd->composite_clks || mcd->divider_clks || mcd->plls) { if (!mcd->shared_io) base = devm_platform_ioremap_resource(pdev, 0); else @@ -513,6 +515,7 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, num_clks = mcd->num_clks + mcd->num_composite_clks; num_clks += mcd->num_fixed_clks + mcd->num_factor_clks; num_clks += mcd->num_mux_clks + mcd->num_divider_clks; + num_clks += mcd->num_cpumuxes + mcd->num_plls; clk_data = mtk_alloc_clk_data(num_clks); if (!clk_data) { @@ -520,11 +523,18 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, goto free_base; } + if (mcd->plls) { + r = mtk_clk_register_plls(&pdev->dev, mcd->plls, + mcd->num_plls, clk_data); + if (r) + goto free_data; + } + if (mcd->fixed_clks) { r = mtk_clk_register_fixed_clks(mcd->fixed_clks, mcd->num_fixed_clks, clk_data); if (r) - goto free_data; + goto unregister_plls; } if (mcd->factor_clks) { @@ -542,6 +552,13 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, goto unregister_factors; } + if (mcd->cpumuxes) { + r = mtk_clk_register_cpumuxes(&pdev->dev, node, mcd->cpumuxes, + mcd->num_cpumuxes, clk_data); + if (r) + goto unregister_muxes; + } + if (mcd->composite_clks) { /* We don't check composite_lock because it's optional */ r = mtk_clk_register_composites(&pdev->dev, @@ -549,7 +566,7 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, mcd->num_composite_clks, base, mcd->clk_lock, clk_data); if (r) - goto unregister_muxes; + goto unregister_cpumuxes; } if (mcd->divider_clks) { @@ -605,6 +622,10 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, if (mcd->composite_clks) mtk_clk_unregister_composites(mcd->composite_clks, mcd->num_composite_clks, clk_data); +unregister_cpumuxes: + if (mcd->cpumuxes) + mtk_clk_unregister_cpumuxes(mcd->cpumuxes, + mcd->num_cpumuxes, clk_data); unregister_muxes: if (mcd->mux_clks) mtk_clk_unregister_muxes(mcd->mux_clks, @@ -617,6 +638,9 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, if (mcd->fixed_clks) mtk_clk_unregister_fixed_clks(mcd->fixed_clks, mcd->num_fixed_clks, clk_data); +unregister_plls: + if (mcd->plls) + mtk_clk_unregister_plls(mcd->plls, mcd->num_plls, clk_data); free_data: mtk_free_clk_data(clk_data); free_base: @@ -643,6 +667,9 @@ static void __mtk_clk_simple_remove(struct platform_device *pdev, if (mcd->composite_clks) mtk_clk_unregister_composites(mcd->composite_clks, mcd->num_composite_clks, clk_data); + if (mcd->cpumuxes) + mtk_clk_unregister_cpumuxes(mcd->cpumuxes, + mcd->num_cpumuxes, clk_data); if (mcd->mux_clks) mtk_clk_unregister_muxes(mcd->mux_clks, mcd->num_mux_clks, clk_data); @@ -652,6 +679,8 @@ static void __mtk_clk_simple_remove(struct platform_device *pdev, if (mcd->fixed_clks) mtk_clk_unregister_fixed_clks(mcd->fixed_clks, mcd->num_fixed_clks, clk_data); + if (mcd->plls) + mtk_clk_unregister_plls(mcd->plls, mcd->num_plls, clk_data); mtk_free_clk_data(clk_data); } diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 5417b9264e6df9..b6504b3e77ed6a 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -23,6 +23,7 @@ #define MTK_WAIT_HWV_DONE_US 30 struct platform_device; +struct mtk_pll_data; /* * We need the clock IDs to start from zero but to maintain devicetree @@ -252,6 +253,10 @@ struct mtk_clk_desc { size_t num_factor_clks; const struct mtk_mux *mux_clks; size_t num_mux_clks; + const struct mtk_composite *cpumuxes; + size_t num_cpumuxes; + const struct mtk_pll_data *plls; + size_t num_plls; const struct mtk_clk_rst_desc *rst_desc; spinlock_t *clk_lock; bool shared_io; diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index e9706486890849..87c2b78e3828a9 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -102,13 +102,14 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw, int postdiv) { u32 chg, val; + u32 mask = pll->data->pd_mask ?: POSTDIV_MASK; /* disable tuner */ __mtk_pll_tuner_disable(pll); /* set postdiv */ val = readl(pll->pd_addr); - val &= ~(POSTDIV_MASK << pll->data->pd_shift); + val &= ~(mask << pll->data->pd_shift); val |= (ffs(postdiv) - 1) << pll->data->pd_shift; /* postdiv and pcw need to set at the same time if on same register */ @@ -198,8 +199,9 @@ unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); u32 postdiv; u32 pcw; + u32 mask = pll->data->pd_mask ?: POSTDIV_MASK; - postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK; + postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & mask; postdiv = 1 << postdiv; pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift; @@ -228,13 +230,15 @@ int mtk_pll_prepare(struct clk_hw *hw) struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); u32 r; - r = readl(pll->pwr_addr) | CON0_PWR_ON; - writel(r, pll->pwr_addr); - udelay(1); + if (pll->pwr_addr) { + r = readl(pll->pwr_addr) | CON0_PWR_ON; + writel(r, pll->pwr_addr); + udelay(1); - r = readl(pll->pwr_addr) & ~CON0_ISO_EN; - writel(r, pll->pwr_addr); - udelay(1); + r = readl(pll->pwr_addr) & ~CON0_ISO_EN; + writel(r, pll->pwr_addr); + udelay(1); + } r = readl(pll->en_addr) | BIT(pll->data->pll_en_bit); writel(r, pll->en_addr); @@ -278,11 +282,13 @@ void mtk_pll_unprepare(struct clk_hw *hw) r = readl(pll->en_addr) & ~BIT(pll->data->pll_en_bit); writel(r, pll->en_addr); - r = readl(pll->pwr_addr) | CON0_ISO_EN; - writel(r, pll->pwr_addr); + if (pll->pwr_addr) { + r = readl(pll->pwr_addr) | CON0_ISO_EN; + writel(r, pll->pwr_addr); - r = readl(pll->pwr_addr) & ~CON0_PWR_ON; - writel(r, pll->pwr_addr); + r = readl(pll->pwr_addr) & ~CON0_PWR_ON; + writel(r, pll->pwr_addr); + } } static int mtk_pll_prepare_setclr(struct clk_hw *hw) @@ -333,7 +339,8 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, const char *parent_name = "clk26m"; pll->base_addr = base + data->reg; - pll->pwr_addr = base + data->pwr_reg; + if (data->pwr_reg) + pll->pwr_addr = base + data->pwr_reg; pll->pd_addr = base + data->pd_reg; pll->pcw_addr = base + data->pcw_reg; if (data->pcw_chg_reg) diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h index f49dc2732ffee5..06e9daced68114 100644 --- a/drivers/clk/mediatek/clk-pll.h +++ b/drivers/clk/mediatek/clk-pll.h @@ -30,6 +30,7 @@ struct mtk_pll_data { u32 en_mask; u32 fenc_sta_ofs; u32 pd_reg; + u32 pd_mask; /* default POSTDIV_MASK if 0 */ u32 tuner_reg; u32 tuner_en_reg; u8 tuner_en_bit; diff --git a/drivers/clocksource/timer-mediatek.c b/drivers/clocksource/timer-mediatek.c index 7bcb4a3f26fb0e..58d96ab1199332 100644 --- a/drivers/clocksource/timer-mediatek.c +++ b/drivers/clocksource/timer-mediatek.c @@ -9,9 +9,11 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include +#include #include #include #include @@ -27,6 +29,7 @@ #define GPT_IRQ_ENABLE(val) BIT((val) - 1) #define GPT_IRQ_ACK_REG 0x08 #define GPT_IRQ_ACK(val) BIT((val) - 1) +#define GPT_IRQ_STA_REG 0x04 #define GPT_CTRL_REG(val) (0x10 * (val)) #define GPT_CTRL_OP(val) (((val) & 0x3) << 4) @@ -46,6 +49,148 @@ #define GPT_CNT_REG(val) (0x08 + (0x10 * (val))) #define GPT_CMP_REG(val) (0x0C + (0x10 * (val))) +#define GPT_CNTH_REG(val) (0x18 + (0x10 * (val))) + +/* + * MT6589 system counter assist. + * + * GPT6 is the source of the ARM Generic Timer counter on this SoC. + * Its upper word may fail to propagate to the Generic Timer until GPT6 + * is accessed through the APB interface. The downstream workaround + * uses GPT3 to access GPT6 at each 32-bit rollover. + * + * GPT6 is already running when Linux initializes this driver, so do not + * reset it. Instead, align GPT3's first interrupt with the next GPT6 + * rollover, then use a 0xffffffff-count repeating interval. + */ +#define MTK_SYSCNT_GPT 6 +#define MTK_SYSCNT_ASSIST_GPT 3 + +#define MTK_SYSCNT_ASSIST_IRQ GPT_IRQ_ACK(MTK_SYSCNT_ASSIST_GPT) + +static bool mtk_syscnt_assist_enabled; +static bool mtk_syscnt_assist_first; +static u32 mtk_syscnt_loop; + +static void mtk_syscnt_assist_prepare(struct timer_of *to) +{ + void __iomem *base = timer_of_base(to); + u32 syscnt_low; + u32 syscnt_high; + u32 first_cmp; + + /* Stop and clear GPT3 before programming it. */ + writel(GPT_CTRL_CLEAR | GPT_CTRL_DISABLE, + base + GPT_CTRL_REG(MTK_SYSCNT_ASSIST_GPT)); + + writel(GPT_CLK_SRC(GPT_CLK_SRC_SYS13M) | GPT_CLK_DIV1, + base + GPT_CLK_REG(MTK_SYSCNT_ASSIST_GPT)); + + /* + * Reading CNT_L snapshots the corresponding CNT_H value. + * Keep this order for a coherent 64-bit read. + */ + syscnt_low = readl(base + GPT_CNT_REG(MTK_SYSCNT_GPT)); + syscnt_high = readl(base + GPT_CNTH_REG(MTK_SYSCNT_GPT)); + + mtk_syscnt_loop = syscnt_high; + mtk_syscnt_assist_first = true; + + /* + * GPT3 starts at zero. Schedule its first interrupt after the + * remaining GPT6 low-word ticks, so the interrupt occurs at the + * next 32-bit rollover. + * + * If the low word is already 0xffffffff, use one tick rather than + * programming a zero compare value. + */ + first_cmp = ~syscnt_low; + if (!first_cmp) + first_cmp = 1; + + writel(first_cmp, base + GPT_CMP_REG(MTK_SYSCNT_ASSIST_GPT)); + + /* Acknowledge any stale GPT3 interrupt before enabling it. */ + writel(MTK_SYSCNT_ASSIST_IRQ, base + GPT_IRQ_ACK_REG); + + /* First event is one-shot; the handler switches to repeat mode. */ + writel(GPT_CTRL_OP(GPT_CTRL_OP_ONESHOT) | GPT_CTRL_DISABLE, + base + GPT_CTRL_REG(MTK_SYSCNT_ASSIST_GPT)); +} + +static void mtk_syscnt_assist_start(struct timer_of *to) +{ + void __iomem *base = timer_of_base(to); + + writel(GPT_CTRL_OP(GPT_CTRL_OP_ONESHOT) | GPT_CTRL_ENABLE, + base + GPT_CTRL_REG(MTK_SYSCNT_ASSIST_GPT)); +} + +#if defined(CONFIG_ARM) && defined(CONFIG_ARM_ARCH_TIMER) +static u32 mtk_syscnt_read_cntpct_high(void) +{ + u32 low, high; + + asm volatile("mrrc p15, 0, %0, %1, c14" + : "=r" (low), "=r" (high)); + + return high; +} +#endif + +static void mtk_syscnt_assist_interrupt(struct timer_of *to) +{ + void __iomem *base = timer_of_base(to); + u32 assist_cnt; + u32 syscnt_low; + u32 syscnt_high; + u32 cnt = 0; + + assist_cnt = readl(base + GPT_CNT_REG(MTK_SYSCNT_ASSIST_GPT)); + + /* + * Access GPT6 to make its upper word propagate to the Generic + * Timer counter. Read low before high as required by the GPT6 + * register interface. + */ + syscnt_low = readl(base + GPT_CNT_REG(MTK_SYSCNT_GPT)); + syscnt_high = readl(base + GPT_CNTH_REG(MTK_SYSCNT_GPT)); + + /* + * This handler is expected to run once per GPT6 low-word rollover. + * Match the downstream workaround: wait until the GPT6 upper word + * reaches the expected value before returning. + */ + mtk_syscnt_loop++; + + while (syscnt_high != mtk_syscnt_loop) { + cnt++; + syscnt_high = readl(base + GPT_CNTH_REG(MTK_SYSCNT_GPT)); + } + + /* + * The first event was aligned to the current GPT6 rollover. + * Subsequent events use the downstream 0xffffffff-count repeat + * interval. + */ + if (mtk_syscnt_assist_first) { + mtk_syscnt_assist_first = false; + + writel(0xffffffff, + base + GPT_CMP_REG(MTK_SYSCNT_ASSIST_GPT)); + writel(GPT_CTRL_CLEAR | + GPT_CTRL_OP(GPT_CTRL_OP_REPEAT) | + GPT_CTRL_ENABLE, + base + GPT_CTRL_REG(MTK_SYSCNT_ASSIST_GPT)); + } + +#if defined(CONFIG_ARM) && defined(CONFIG_ARM_ARCH_TIMER) + WARN_ON_ONCE(mtk_syscnt_read_cntpct_high() != mtk_syscnt_loop); +#endif + + pr_debug("syscnt assist: GPT3=%08x GPT6=%08x:%08x loop=%08x polls=%u\n", + assist_cnt, syscnt_high, syscnt_low, mtk_syscnt_loop, cnt); +} /* system timer */ #define SYST_BASE (0x40) @@ -205,14 +350,28 @@ static int mtk_gpt_clkevt_next_event(unsigned long event, static irqreturn_t mtk_gpt_interrupt(int irq, void *dev_id) { - struct clock_event_device *clkevt = (struct clock_event_device *)dev_id; + struct clock_event_device *clkevt = dev_id; struct timer_of *to = to_timer_of(clkevt); - - /* Acknowledge timer0 irq */ - writel(GPT_IRQ_ACK(TIMER_CLK_EVT), timer_of_base(to) + GPT_IRQ_ACK_REG); - clkevt->event_handler(clkevt); - - return IRQ_HANDLED; + void __iomem *base = timer_of_base(to); + u32 sta; + bool handled = false; + + sta = readl(base + GPT_IRQ_STA_REG); + + if (mtk_syscnt_assist_enabled && + (sta & MTK_SYSCNT_ASSIST_IRQ)) { + writel(MTK_SYSCNT_ASSIST_IRQ, base + GPT_IRQ_ACK_REG); + mtk_syscnt_assist_interrupt(to); + handled = true; + } + + if (sta & GPT_IRQ_ACK(TIMER_CLK_EVT)) { + writel(GPT_IRQ_ACK(TIMER_CLK_EVT), base + GPT_IRQ_ACK_REG); + clkevt->event_handler(clkevt); + handled = true; + } + + return handled ? IRQ_HANDLED : IRQ_NONE; } static void @@ -230,26 +389,36 @@ __init mtk_gpt_setup(struct timer_of *to, u8 timer, u8 option) timer_of_base(to) + GPT_CTRL_REG(timer)); } -static void mtk_gpt_enable_irq(struct timer_of *to, u8 timer) +static void mtk_gpt_enable_irqs(struct timer_of *to) { - u32 val; + void __iomem *base = timer_of_base(to); + u32 mask; - /* Disable all interrupts */ - writel(0x0, timer_of_base(to) + GPT_IRQ_EN_REG); + /* Disable all GPT interrupts while rebuilding the mask. */ + writel(0, base + GPT_IRQ_EN_REG); - /* Acknowledge all spurious pending interrupts */ - writel(0x3f, timer_of_base(to) + GPT_IRQ_ACK_REG); + /* Clear stale pending interrupts from all GPT channels. */ + writel(0x3f, base + GPT_IRQ_ACK_REG); + + mask = GPT_IRQ_ENABLE(TIMER_CLK_EVT); + + if (mtk_syscnt_assist_enabled) + mask |= GPT_IRQ_ENABLE(MTK_SYSCNT_ASSIST_GPT); - val = readl(timer_of_base(to) + GPT_IRQ_EN_REG); - writel(val | GPT_IRQ_ENABLE(timer), - timer_of_base(to) + GPT_IRQ_EN_REG); + writel(mask, base + GPT_IRQ_EN_REG); } static void mtk_gpt_resume(struct clock_event_device *clk) { struct timer_of *to = to_timer_of(clk); - mtk_gpt_enable_irq(to, TIMER_CLK_EVT); + if (mtk_syscnt_assist_enabled) + mtk_syscnt_assist_prepare(to); + + mtk_gpt_enable_irqs(to); + + if (mtk_syscnt_assist_enabled) + mtk_syscnt_assist_start(to); } static void mtk_gpt_suspend(struct clock_event_device *clk) @@ -291,6 +460,7 @@ static int __init mtk_syst_init(struct device_node *node) to.clkevt.tick_resume = mtk_syst_clkevt_resume; to.clkevt.set_next_event = mtk_syst_clkevt_next_event; to.of_irq.handler = mtk_syst_handler; + to.of_irq.flags = IRQF_TIMER | IRQF_IRQPOLL; ret = timer_of_init(node, &to); if (ret) @@ -306,6 +476,9 @@ static int __init mtk_gpt_init(struct device_node *node) { int ret; + mtk_syscnt_assist_enabled = + of_device_is_compatible(node, "mediatek,mt6589-timer"); + to.clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; to.clkevt.set_state_shutdown = mtk_gpt_clkevt_shutdown; to.clkevt.set_state_periodic = mtk_gpt_clkevt_set_periodic; @@ -316,26 +489,49 @@ static int __init mtk_gpt_init(struct device_node *node) to.clkevt.resume = mtk_gpt_resume; to.of_irq.handler = mtk_gpt_interrupt; + /* + * Keep the parent IRQ disabled until GPT1 and the optional GPT3 + * assist timer have been configured and their pending IRQs cleared. + */ + to.of_irq.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NO_AUTOEN; + ret = timer_of_init(node, &to); if (ret) return ret; - /* Configure clock source */ + /* Configure clock source. */ mtk_gpt_setup(&to, TIMER_CLK_SRC, GPT_CTRL_OP_FREERUN); clocksource_mmio_init(timer_of_base(&to) + GPT_CNT_REG(TIMER_CLK_SRC), node->name, timer_of_rate(&to), 300, 32, clocksource_mmio_readl_up); gpt_sched_reg = timer_of_base(&to) + GPT_CNT_REG(TIMER_CLK_SRC); - sched_clock_register(mtk_gpt_read_sched_clock, 32, timer_of_rate(&to)); + sched_clock_register(mtk_gpt_read_sched_clock, 32, + timer_of_rate(&to)); - /* Configure clock event */ + /* Configure clock event. */ mtk_gpt_setup(&to, TIMER_CLK_EVT, GPT_CTRL_OP_REPEAT); clockevents_config_and_register(&to.clkevt, timer_of_rate(&to), TIMER_SYNC_TICKS, 0xffffffff); - mtk_gpt_enable_irq(&to, TIMER_CLK_EVT); + /* + * GPT6 is already running. Prepare GPT3 only after GPT1 setup, + * so the initial GPT6 sample is close to the assist timer start. + */ + if (mtk_syscnt_assist_enabled) + mtk_syscnt_assist_prepare(&to); + + /* Enable GPT1 and, on MT6589, GPT3 interrupts. */ + mtk_gpt_enable_irqs(&to); + + if (mtk_syscnt_assist_enabled) + mtk_syscnt_assist_start(&to); + + /* All timer channels are ready; enable the parent IRQ last. */ + enable_irq(timer_of_irq(&to)); return 0; } + +TIMER_OF_DECLARE(mtk_mt6589, "mediatek,mt6589-timer", mtk_gpt_init); TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_gpt_init); TIMER_OF_DECLARE(mtk_mt6765, "mediatek,mt6765-timer", mtk_syst_init); diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index 052ca7cd2f4fd8..80b1b984f6ea8f 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ struct mtk_cpu_dvfs_info { const struct mtk_cpufreq_platform_data *soc_data; int vtrack_max; bool ccifreq_bound; + int opp_token; }; static struct platform_device *cpufreq_pdev; @@ -381,6 +383,47 @@ static struct device *of_get_cci(struct device *cpu_dev) return &pdev->dev; } +static int mtk_cpu_parse_speedbin(struct mtk_cpu_dvfs_info *info, int cpu) { + struct device *cpu_dev = get_cpu_device(cpu); + struct dev_pm_opp_config config = {}; + struct nvmem_cell *speedbin_cell; + u32 opp_hw_ver; + u8 *speedbin; + size_t len; + + speedbin_cell = of_nvmem_cell_get(cpu_dev->of_node, "speed_grade"); + + if (IS_ERR(speedbin_cell)) { + if (PTR_ERR(speedbin_cell) == -ENOENT) + /* speedbin is optional */ + return 0; + + return dev_err_probe(cpu_dev, PTR_ERR(speedbin_cell), + "cpu%d: failed to get speedbin\n", cpu); + } + + speedbin = nvmem_cell_read(speedbin_cell, &len); + nvmem_cell_put(speedbin_cell); + + if (IS_ERR(speedbin)) + return dev_err_probe(cpu_dev, PTR_ERR(speedbin), + "cpu%d: failed to read speedbin\n", cpu); + + /* Convert the raw value to a bitmask */ + opp_hw_ver = BIT(*speedbin); + kfree(speedbin); + + config.supported_hw = &opp_hw_ver; + config.supported_hw_count = 1; + + info->opp_token = dev_pm_opp_set_config(cpu_dev, &config); + if (info->opp_token < 0) + return dev_err_probe(cpu_dev, info->opp_token, + "cpu%d: failed to set OPP config\n", cpu); + + return 0; +} + static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) { struct device *cpu_dev; @@ -450,18 +493,22 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) } } + ret = mtk_cpu_parse_speedbin(info, cpu); + if (ret) + goto out_disable_sram_reg; + /* Get OPP-sharing information from "operating-points-v2" bindings */ ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus); if (ret) { dev_err_probe(cpu_dev, ret, "cpu%d: failed to get OPP-sharing information\n", cpu); - goto out_disable_sram_reg; + goto out_free_speedbin; } ret = dev_pm_opp_of_cpumask_add_table(&info->cpus); if (ret) { dev_err_probe(cpu_dev, ret, "cpu%d: no OPP table\n", cpu); - goto out_disable_sram_reg; + goto out_free_speedbin; } ret = clk_prepare_enable(info->cpu_clk); @@ -533,6 +580,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) out_free_opp_table: dev_pm_opp_of_cpumask_remove_table(&info->cpus); +out_free_speedbin: + dev_pm_opp_clear_config(info->opp_token); + out_disable_sram_reg: if (info->sram_reg) regulator_disable(info->sram_reg); @@ -573,6 +623,10 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) clk_disable_unprepare(info->inter_clk); clk_put(info->inter_clk); dev_pm_opp_of_cpumask_remove_table(&info->cpus); + + if (info->opp_token > 0) + dev_pm_opp_clear_config(info->opp_token); + dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb); if (info->soc_data->ccifreq_supported) put_device(info->cci_dev); @@ -691,6 +745,15 @@ static const struct mtk_cpufreq_platform_data mt2701_platform_data = { .ccifreq_supported = false, }; +static const struct mtk_cpufreq_platform_data mt6589_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 200000, + .proc_max_volt = 1250000, + .sram_min_volt = 0, + .sram_max_volt = 1493750, /* need confirm */ + .ccifreq_supported = false, +}; + static const struct mtk_cpufreq_platform_data mt7622_platform_data = { .min_volt_shift = 100000, .max_volt_shift = 200000, @@ -747,6 +810,7 @@ static const struct mtk_cpufreq_platform_data mt8516_platform_data = { static const struct of_device_id mtk_cpufreq_machines[] __initconst __maybe_unused = { { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt6589", .data = &mt6589_platform_data }, { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, { .compatible = "mediatek,mt7623", .data = &mt7623_platform_data }, { .compatible = "mediatek,mt7988a", .data = &mt7988_platform_data }, diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c index c269d84d7bd2bd..32d8f75aa4d425 100644 --- a/drivers/dma/mediatek/mtk-uart-apdma.c +++ b/drivers/dma/mediatek/mtk-uart-apdma.c @@ -274,10 +274,8 @@ static int mtk_uart_apdma_alloc_chan_resources(struct dma_chan *chan) int ret; ret = pm_runtime_resume_and_get(mtkd->ddev.dev); - if (ret < 0) { - pm_runtime_put_noidle(chan->device->dev); + if (ret < 0) return ret; - } mtk_uart_apdma_write(c, VFF_ADDR, 0); mtk_uart_apdma_write(c, VFF_THRE, 0); @@ -300,6 +298,8 @@ static int mtk_uart_apdma_alloc_chan_resources(struct dma_chan *chan) if (mtkd->support_ext_addr) mtk_uart_apdma_write(c, VFF_ADDR2, VFF_ADDR2_CLR_B); + return 0; + err_pm: pm_runtime_put_noidle(mtkd->ddev.dev); return ret; diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 236bd56208ccfc..38ca899a36bcb4 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -5790,6 +5790,36 @@ static const struct panel_desc_dsi auo_b080uan01 = { .lanes = 4, }; +static const struct drm_display_mode boe_hx8896_a01_mode = { + .clock = 69837, /* 1416 * 822 * 60 / 1000 kHz */ + .hdisplay = 1280, + .hsync_start = 1280 + 100, + .hsync_end = 1280 + 100 + 4, + .htotal = 1280 + 100 + 4 + 32, + .vdisplay = 800, + .vsync_start = 800 + 10, + .vsync_end = 800 + 10 + 2, + .vtotal = 800 + 10 + 2 + 10, +}; + +static const struct panel_desc_dsi boe_hx8896_a01 = { + .desc = { + .modes = &boe_hx8896_a01_mode, + .num_modes = 1, + .bpc = 8, + .size = { .width = 217, .height = 136 }, /* TODO */ + .connector_type = DRM_MODE_CONNECTOR_DSI, + .delay = { + .prepare = 120, /* or 120 */ + .enable = 100, /* or 0 */ + .disable = 320, + }, + }, + .flags = MIPI_DSI_MODE_VIDEO, + .format = MIPI_DSI_FMT_RGB888, + .lanes = 4, +}; + static const struct drm_display_mode boe_tv080wum_nl0_mode = { .clock = 160000, .hdisplay = 1200, @@ -5820,6 +5850,36 @@ static const struct panel_desc_dsi boe_tv080wum_nl0 = { .lanes = 4, }; +static const struct drm_display_mode innolux_hx8896_a01_mode = { + .clock = 76019, /* 1521 * 833 * 60 / 1000 kHz */ + .hdisplay = 1280, + .hsync_start = 1280 + 186, /* + HFP */ + .hsync_end = 1280 + 186 + 5, /* + HSW */ + .htotal = 1280 + 186 + 5 + 50, /* + HBP */ + .vdisplay = 800, + .vsync_start = 800 + 21, /* + VFP */ + .vsync_end = 800 + 21 + 2, /* + VSW */ + .vtotal = 800 + 21 + 2 + 10, /* + VBP */ +}; + +static const struct panel_desc_dsi innolux_hx8896_a01 = { + .desc = { + .modes = &innolux_hx8896_a01_mode, + .num_modes = 1, + .bpc = 8, + .size = { .width = 217, .height = 136 }, /* TODO */ + .connector_type = DRM_MODE_CONNECTOR_DSI, + .delay = { + .prepare = 120, /* or 120 */ + .enable = 100, /* or 0 */ + .disable = 320, + }, + }, + .flags = MIPI_DSI_MODE_VIDEO, + .format = MIPI_DSI_FMT_RGB888, + .lanes = 4, +}; + static const struct drm_display_mode lg_lh500wx1_sd03_mode = { .clock = 67000, .hdisplay = 720, @@ -5940,9 +6000,15 @@ static const struct of_device_id dsi_of_match[] = { { .compatible = "auo,b080uan01", .data = &auo_b080uan01 + }, { + .compatible = "boe,hx8896-a01-panel", + .data = &boe_hx8896_a01 }, { .compatible = "boe,tv080wum-nl0", .data = &boe_tv080wum_nl0 + }, { + .compatible = "innolux,hx8896-a01-panel", + .data = &innolux_hx8896_a01 }, { .compatible = "lg,lh500wx1-sd03", .data = &lg_lh500wx1_sd03 diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 126040ca05f147..cb0548602b635b 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -269,6 +270,7 @@ struct mtk_i2c_compatible { unsigned char dma_sync: 1; unsigned char ltiming_adjust: 1; unsigned char apdma_sync: 1; + unsigned char dma_separate_rx: 1; unsigned char max_dma_support; }; @@ -293,8 +295,12 @@ struct mtk_i2c { /* set in i2c probe */ void __iomem *base; /* i2c base addr */ - void __iomem *pdmabase; /* dma base address*/ + void __iomem *pdmabase; /* dma base address (TX channel) */ + void __iomem *pdmabase_rx; /* RX dma base; aliases pdmabase + * when dma_separate_rx is 0 + */ struct clk_bulk_data clocks[I2C_MT65XX_CLK_MAX]; /* clocks for i2c */ + struct reset_control *reset; bool have_pmic; /* can use i2c pins from PMIC */ bool use_push_pull; /* IO config push-pull mode */ @@ -1007,6 +1013,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, u8 *dma_wr_buf = NULL; dma_addr_t rpaddr = 0; dma_addr_t wpaddr = 0; + void __iomem *rxbase = i2c->pdmabase_rx; + unsigned int rx_mem_off = i2c->dev_comp->dma_separate_rx ? + OFFSET_TX_MEM_ADDR : OFFSET_RX_MEM_ADDR; + unsigned int rx_len_off = i2c->dev_comp->dma_separate_rx ? + OFFSET_TX_LEN : OFFSET_RX_LEN; + unsigned int rx_4g_off = i2c->dev_comp->dma_separate_rx ? + OFFSET_TX_4G_MODE : OFFSET_RX_4G_MODE; int ret; i2c->irq_stat = 0; @@ -1085,8 +1098,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, /* Prepare buffer data to start transfer */ if (i2c->op == I2C_MASTER_RD) { - writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG); - writel(I2C_DMA_CON_RX | dma_sync, i2c->pdmabase + OFFSET_CON); + writel(I2C_DMA_INT_FLAG_NONE, rxbase + OFFSET_INT_FLAG); + writel(I2C_DMA_CON_RX | dma_sync, rxbase + OFFSET_CON); dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1); if (!dma_rd_buf) @@ -1102,11 +1115,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, if (i2c->dev_comp->max_dma_support > 32) { reg_4g_mode = upper_32_bits(rpaddr); - writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE); + writel(reg_4g_mode, rxbase + rx_4g_off); } - writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR); - writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN); + writel((u32)rpaddr, rxbase + rx_mem_off); + writel(msgs->len, rxbase + rx_len_off); } else if (i2c->op == I2C_MASTER_WR) { writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG); writel(I2C_DMA_CON_TX | dma_sync, i2c->pdmabase + OFFSET_CON); @@ -1174,16 +1187,28 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE); reg_4g_mode = upper_32_bits(rpaddr); - writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE); + writel(reg_4g_mode, rxbase + rx_4g_off); } writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR); - writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR); + writel((u32)rpaddr, rxbase + rx_mem_off); writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN); - writel((msgs + 1)->len, i2c->pdmabase + OFFSET_RX_LEN); + writel((msgs + 1)->len, rxbase + rx_len_off); + + if (i2c->dev_comp->dma_separate_rx) + writel(I2C_DMA_CON_RX, rxbase + OFFSET_CON); } - writel(I2C_DMA_START_EN, i2c->pdmabase + OFFSET_EN); + if (i2c->op == I2C_MASTER_RD) { + writel(I2C_DMA_START_EN, rxbase + OFFSET_EN); + } else if (i2c->op == I2C_MASTER_WR) { + writel(I2C_DMA_START_EN, i2c->pdmabase + OFFSET_EN); + } else { + /* I2C_MASTER_WRRD */ + writel(I2C_DMA_START_EN, i2c->pdmabase + OFFSET_EN); + if (i2c->dev_comp->dma_separate_rx) + writel(I2C_DMA_START_EN, rxbase + OFFSET_EN); + } if (!i2c->auto_restart) { start_reg = I2C_TRANSAC_START; @@ -1258,7 +1283,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap, i2c->auto_restart = i2c->dev_comp->auto_restart; /* checking if we can skip restart and optimize using WRRD mode */ - if (i2c->auto_restart && num == 2) { + if (num == 2) { if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) && msgs[0].addr == msgs[1].addr) { i2c->auto_restart = 0; @@ -1382,6 +1407,14 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c) return 0; } +static int mtk_i2c_reset(struct mtk_i2c *i2c) +{ + if (!i2c->reset) + return 0; + + return reset_control_reset(i2c->reset); +} + static int mtk_i2c_probe(struct platform_device *pdev) { int ret = 0; @@ -1407,6 +1440,22 @@ static int mtk_i2c_probe(struct platform_device *pdev) init_completion(&i2c->msg_complete); i2c->dev_comp = of_device_get_match_data(&pdev->dev); + + i2c->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, + "reset"); + if (IS_ERR(i2c->reset)) { + dev_err(&pdev->dev, "cannot get reset\n"); + return PTR_ERR(i2c->reset); + } + + if (i2c->dev_comp->dma_separate_rx) { + i2c->pdmabase_rx = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(i2c->pdmabase_rx)) + return PTR_ERR(i2c->pdmabase_rx); + } else { + i2c->pdmabase_rx = i2c->pdmabase; + } + i2c->adap.dev.of_node = pdev->dev.of_node; i2c->dev = &pdev->dev; i2c->adap.dev.parent = &pdev->dev; @@ -1485,6 +1534,14 @@ static int mtk_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "clock enable failed!\n"); return ret; } + + ret = mtk_i2c_reset(i2c); + if (ret) { + dev_err(&pdev->dev, "reset failed!\n"); + clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); + return ret; + } + mtk_i2c_init_hw(i2c); clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); @@ -1542,6 +1599,13 @@ static int mtk_i2c_resume_noirq(struct device *dev) return ret; } + ret = mtk_i2c_reset(i2c); + if (ret) { + dev_err(dev, "reset failed!\n"); + clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); + return ret; + } + mtk_i2c_init_hw(i2c); clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a9dedbb8eb461d..89464d8b460019 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1144,6 +1144,17 @@ config MCP3911 This driver can also be built as a module. If so, the module will be called mcp3911. +config MEDIATEK_MT6320_AUXADC + tristate "MediaTek MT6320 PMIC AUXADC driver" + depends on MFD_MT6397 + help + Say yes here to enable support for MediaTek MT6320 PMIC Auxiliary ADC. + This driver provides multiple channels for system monitoring, + such as battery voltage, PMIC temperature, and others. + + This driver can also be built as a module. If so, the module will be + called mt6320-auxadc. + config MEDIATEK_MT6359_AUXADC tristate "MediaTek MT6359 PMIC AUXADC driver" depends on MFD_MT6397 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 097357d146baf4..e54a78a86de649 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o obj-$(CONFIG_MCP3564) += mcp3564.o obj-$(CONFIG_MCP3911) += mcp3911.o +obj-$(CONFIG_MEDIATEK_MT6320_AUXADC) += mt6320-auxadc.o obj-$(CONFIG_MEDIATEK_MT6359_AUXADC) += mt6359-auxadc.o obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o diff --git a/drivers/iio/adc/mt6320-auxadc.c b/drivers/iio/adc/mt6320-auxadc.c new file mode 100644 index 00000000000000..bfe49ea031b47e --- /dev/null +++ b/drivers/iio/adc/mt6320-auxadc.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MediaTek MT6320 PMIC AUXADC + * + * Copyright (c) 2026 Akari Tsuyukusa + * + * MT6320 AUXADC programming model based on the MT6589 downstream + * PMIC implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MT6320_AUXADC_AVG_NUM GENMASK(6, 4) +#define MT6320_AUXADC_BUF_PWD_ON BIT(3) +#define MT6320_AUXADC_BUF_PWD_B BIT(1) + +#define MT6320_AUXADC_CHSEL GENMASK(10, 7) +#define MT6320_AUXADC_START BIT(0) + +#define MT6320_AUXADC_READY BIT(15) +#define MT6320_AUXADC_DATA GENMASK(9, 0) + +#define MT6320_AUXADC_VBUF_EN BIT(4) +#define MT6320_AUXADC_VBUF_BYP BIT(2) +#define MT6320_AUXADC_VBUF_CALEN BIT(0) + +#define MT6320_CHR_BATON_TDET_EN BIT(2) + +#define MT6320_AUXADC_AVG_NUM_VALUE 0x3 +#define MT6320_AUXADC_SPL_NUM_TEMP 0x1e + +#define MT6320_ACCDET_AUXADC_ENABLE 0x10b0 + +#define MT6320_AUXADC_FULL_SCALE_MV 1200 +#define MT6320_AUXADC_RESOLUTION 1024 + +#define MTK_PMIC_IIO_CHAN(_name, _chan) \ +{ \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .datasheet_name = __stringify(_name), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ +} + +#define MT6320_AUXADC_BATSNS 0 +#define MT6320_AUXADC_ISENSE 1 +#define MT6320_AUXADC_VCDT 2 +#define MT6320_AUXADC_BAT_TEMP 3 +#define MT6320_AUXADC_CHIP_TEMP 4 +#define MT6320_AUXADC_ACCDET 5 + +static const struct iio_chan_spec mt6320_auxadc_channels[] = { + MTK_PMIC_IIO_CHAN(batsns, MT6320_AUXADC_BATSNS), + MTK_PMIC_IIO_CHAN(isense, MT6320_AUXADC_ISENSE), + MTK_PMIC_IIO_CHAN(vcdt, MT6320_AUXADC_VCDT), + MTK_PMIC_IIO_CHAN(bat_temp, MT6320_AUXADC_BAT_TEMP), + MTK_PMIC_IIO_CHAN(chip_temp, MT6320_AUXADC_CHIP_TEMP), + MTK_PMIC_IIO_CHAN(accdet, MT6320_AUXADC_ACCDET), +}; + +struct mt6320_auxadc { + struct regmap *regmap; + struct mutex lock; +}; + +static unsigned int mt6320_auxadc_hw_channel(unsigned int channel) +{ + /* + * The downstream PMIC implementation selects channel 0 when + * reading the ISENSE path, while routing the source through + * the channel-0 mux. + */ + return channel == MT6320_AUXADC_ISENSE ? MT6320_AUXADC_BATSNS : + channel; +} + +static unsigned int mt6320_auxadc_result_reg(unsigned int channel) +{ + /* + * Raw conversion status/data is available in AUXADC_ADC0..ADC7. + * The trim=1 path used by the downstream driver reads the + * corresponding trimmed result from AUXADC_ADC11..ADC18. + */ + return MT6320_AUXADC_ADC11 + channel * 2; +} + +static int mt6320_auxadc_prepare(struct mt6320_auxadc *auxadc, + unsigned int channel, + unsigned int *hw_channel) +{ + struct regmap *map = auxadc->regmap; + int ret; + + *hw_channel = mt6320_auxadc_hw_channel(channel); + + if (channel == MT6320_AUXADC_ISENSE) { + ret = regmap_set_bits(map, MT6320_AUXADC_CON14, + BIT(2) | BIT(0)); + if (ret) + return ret; + } + + ret = regmap_update_bits(map, MT6320_AUXADC_CON1, + MT6320_AUXADC_CHSEL, + FIELD_PREP(MT6320_AUXADC_CHSEL, + *hw_channel)); + if (ret) + return ret; + + ret = regmap_update_bits(map, MT6320_AUXADC_CON0, + MT6320_AUXADC_AVG_NUM, + FIELD_PREP(MT6320_AUXADC_AVG_NUM, + MT6320_AUXADC_AVG_NUM_VALUE)); + if (ret) + return ret; + + switch (channel) { + case MT6320_AUXADC_BAT_TEMP: + ret = regmap_set_bits(map, MT6320_AUXADC_CON0, + MT6320_AUXADC_BUF_PWD_ON | + MT6320_AUXADC_BUF_PWD_B); + if (ret) + return ret; + + ret = regmap_set_bits(map, MT6320_CHR_CON7, + MT6320_CHR_BATON_TDET_EN); + if (ret) + return ret; + + msleep(20); + break; + + case MT6320_AUXADC_CHIP_TEMP: + /* + * Match PMIC_IMM_GetOneChannelValue(..., 4, ..., 2): + * enable VBUF, disable bypass, select the PMIC-temperature + * calibration path and increase the sample count. + */ + ret = regmap_update_bits(map, MT6320_AUXADC_CON12, + MT6320_AUXADC_VBUF_EN | + MT6320_AUXADC_VBUF_BYP | + MT6320_AUXADC_VBUF_CALEN, + MT6320_AUXADC_VBUF_EN); + if (ret) + return ret; + + ret = regmap_update_bits(map, MT6320_AUXADC_CON0, + GENMASK(11, 7), + FIELD_PREP(GENMASK(11, 7), + MT6320_AUXADC_SPL_NUM_TEMP)); + if (ret) + return ret; + + msleep(1); + break; + + case MT6320_AUXADC_ACCDET: + ret = regmap_write(map, MT6320_ACCDET_CON0, + MT6320_ACCDET_AUXADC_ENABLE); + if (ret) + return ret; + break; + } + + return 0; +} + +static int mt6320_auxadc_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct mt6320_auxadc *auxadc = iio_priv(indio_dev); + struct regmap *map = auxadc->regmap; + unsigned int hw_channel; + unsigned int status_reg; + unsigned int result_reg; + unsigned int regval; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + /* + * MT6320 AUXADC has a 1.2V full-scale range and + * 10-bit conversion result. + */ + *val = MT6320_AUXADC_FULL_SCALE_MV; + *val2 = MT6320_AUXADC_RESOLUTION; + + return IIO_VAL_FRACTIONAL; + + case IIO_CHAN_INFO_RAW: + break; + + default: + return -EINVAL; + } + + guard(mutex)(&auxadc->lock); + + ret = mt6320_auxadc_prepare(auxadc, chan->channel, &hw_channel); + if (ret) + return ret; + + status_reg = MT6320_AUXADC_ADC0 + hw_channel * 2; + result_reg = mt6320_auxadc_result_reg(hw_channel); + + /* + * Match the downstream sequence: + * + * START = 0 + * START = 1 + * delay 50 us + * wait for the raw channel ready bit + * read the trimmed result + */ + ret = regmap_clear_bits(map, MT6320_AUXADC_CON1, + MT6320_AUXADC_START); + if (ret) + return ret; + + ret = regmap_set_bits(map, MT6320_AUXADC_CON1, + MT6320_AUXADC_START); + if (ret) + return ret; + + fsleep(50); + + ret = regmap_read_poll_timeout(map, status_reg, regval, + regval & MT6320_AUXADC_READY, + 10, 10000); + if (ret) + goto stop; + + ret = regmap_read(map, result_reg, ®val); + if (ret) + goto stop; + + *val = FIELD_GET(MT6320_AUXADC_DATA, regval); + +stop: + /* + * Unlike the downstream implementation, clear START when the + * conversion is finished so a failed read cannot leave the + * conversion request asserted indefinitely. + */ + if (regmap_clear_bits(map, MT6320_AUXADC_CON1, + MT6320_AUXADC_START) && !ret) + ret = -EIO; + + if (ret) + return ret; + + return IIO_VAL_INT; +} + +static const struct iio_info mt6320_auxadc_iio_info = { + .read_raw = mt6320_auxadc_read_raw, +}; + +static int mt6320_auxadc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mt6320_auxadc *auxadc; + struct regmap *regmap; + struct iio_dev *iio; + + regmap = dev_get_regmap(dev->parent->parent, NULL); + if (!regmap) + return dev_err_probe(dev, -ENODEV, + "failed to get regmap\n"); + + iio = devm_iio_device_alloc(dev, sizeof(*auxadc)); + if (!iio) + return -ENOMEM; + + auxadc = iio_priv(iio); + auxadc->regmap = regmap; + mutex_init(&auxadc->lock); + + iio->name = "mt6320-auxadc"; + iio->info = &mt6320_auxadc_iio_info; + iio->modes = INDIO_DIRECT_MODE; + iio->channels = mt6320_auxadc_channels; + iio->num_channels = ARRAY_SIZE(mt6320_auxadc_channels); + + return devm_iio_device_register(dev, iio); +} + +static const struct of_device_id mt6320_auxadc_of_match[] = { + { .compatible = "mediatek,mt6320-auxadc" }, + { } +}; +MODULE_DEVICE_TABLE(of, mt6320_auxadc_of_match); + +static struct platform_driver mt6320_auxadc_driver = { + .driver = { + .name = "mt6320-auxadc", + .of_match_table = mt6320_auxadc_of_match, + }, + .probe = mt6320_auxadc_probe, +}; +module_platform_driver(mt6320_auxadc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MediaTek MT6320 PMIC AUXADC Driver"); diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index fe9e3ece3fdae1..24bd498f79be85 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -313,6 +313,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, static const struct of_device_id mt6577_auxadc_of_match[] = { { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat }, { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat }, + { .compatible = "mediatek,mt6589-auxadc", .data = &mt8173_compat }, { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat }, { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat }, { .compatible = "mediatek,mt8186-auxadc", .data = &mt8186_compat }, diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index eff33e456c70d7..91f541ad899326 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -65,10 +65,11 @@ config AL3010 config AL3320A tristate "AL3320A ambient light sensor" + select REGMAP_I2C depends on I2C help Say Y here if you want to build a driver for the Dyna Image AL3320A - ambient light sensor. + or AL3320B ambient light sensor. To compile this driver as a module, choose M here: the module will be called al3320a. diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c index 63f5a85912fc9a..3447436222580c 100644 --- a/drivers/iio/light/al3320a.c +++ b/drivers/iio/light/al3320a.c @@ -39,13 +39,12 @@ #define AL3320A_CONFIG_DISABLE 0x00 #define AL3320A_CONFIG_ENABLE 0x01 -#define AL3320A_GAIN_MASK GENMASK(2, 1) - /* chip params default values */ #define AL3320A_DEFAULT_MEAN_TIME 4 #define AL3320A_DEFAULT_WAIT_TIME 0 /* no waiting */ #define AL3320A_SCALE_AVAILABLE "0.512 0.128 0.032 0.01" +#define AL3320B_SCALE_AVAILABLE "1.53 0.512 0.38 0.128 0.096 0.032 0.03 0.01" enum al3320a_range { AL3320A_RANGE_1, /* 33.28 Klx */ @@ -58,6 +57,54 @@ static const int al3320a_scales[][2] = { {0, 512000}, {0, 128000}, {0, 32000}, {0, 10000} }; +static const int al3320b_scales[][2] = { + {1, 530000}, {0, 512000}, {0, 380000}, {0, 128000}, + {0, 96000}, {0, 32000}, {0, 30000}, {0, 10000} +}; + +static const u8 al3320a_scale_regs[] = { + 0x00, 0x02, 0x04, 0x06 +}; + +static const u8 al3320b_scale_regs[] = { + 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07 +}; + +struct al3320_variant { + const char *name; + const int (*scales)[2]; + const u8 *scale_regs; + const char *scale_available; + unsigned int num_scales; + unsigned int default_scale; + u8 scale_mask; + u8 mean_time; +}; + +static const struct al3320_variant al3320a_variant = { + .name = "al3320a", + .scales = al3320a_scales, + .scale_regs = al3320a_scale_regs, + .scale_available = AL3320A_SCALE_AVAILABLE, + .num_scales = ARRAY_SIZE(al3320a_scales), + .default_scale = AL3320A_RANGE_3, + .scale_mask = GENMASK(2, 1), + .mean_time = AL3320A_DEFAULT_MEAN_TIME, +}; + +static const struct al3320_variant al3320b_variant = { + .name = "al3320b", + .scales = al3320b_scales, + .scale_regs = al3320b_scale_regs, + .scale_available = AL3320B_SCALE_AVAILABLE, + .num_scales = ARRAY_SIZE(al3320b_scales), + /* Stock AL3320B programs 0x07 = 0x04 by default. */ + .default_scale = 4, + .scale_mask = GENMASK(2, 0), + .mean_time = 0x0f, +}; + static const struct regmap_config al3320a_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -66,6 +113,7 @@ static const struct regmap_config al3320a_regmap_config = { struct al3320a_data { struct regmap *regmap; + const struct al3320_variant *variant; }; static const struct iio_chan_spec al3320a_channels[] = { @@ -76,10 +124,21 @@ static const struct iio_chan_spec al3320a_channels[] = { } }; -static IIO_CONST_ATTR(in_illuminance_scale_available, AL3320A_SCALE_AVAILABLE); +static ssize_t al3320a_show_scale_available(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct al3320a_data *data = iio_priv(indio_dev); + + return sysfs_emit(buf, "%s\n", data->variant->scale_available); +} + +static DEVICE_ATTR(in_illuminance_scale_available, 0444, + al3320a_show_scale_available, NULL); static struct attribute *al3320a_attributes[] = { - &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, + &dev_attr_in_illuminance_scale_available.attr, NULL, }; @@ -106,6 +165,7 @@ static void al3320a_set_pwr_off(void *_data) static int al3320a_init(struct al3320a_data *data) { struct device *dev = regmap_get_device(data->regmap); + const struct al3320_variant *variant = data->variant; int ret; ret = al3320a_set_pwr_on(data); @@ -117,12 +177,12 @@ static int al3320a_init(struct al3320a_data *data) return ret; ret = regmap_write(data->regmap, AL3320A_REG_CONFIG_RANGE, - FIELD_PREP(AL3320A_GAIN_MASK, AL3320A_RANGE_3)); + variant->scale_regs[variant->default_scale]); if (ret) return ret; ret = regmap_write(data->regmap, AL3320A_REG_MEAN_TIME, - AL3320A_DEFAULT_MEAN_TIME); + variant->mean_time); if (ret) return ret; @@ -135,7 +195,10 @@ static int al3320a_read_raw(struct iio_dev *indio_dev, int *val2, long mask) { struct al3320a_data *data = iio_priv(indio_dev); - int ret, gain, raw; + const struct al3320_variant *variant = data->variant; + unsigned int i; + int ret, gain; + __le16 raw; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -144,11 +207,12 @@ static int al3320a_read_raw(struct iio_dev *indio_dev, * - low byte of output is stored at AL3320A_REG_DATA_LOW * - high byte of output is stored at AL3320A_REG_DATA_LOW + 1 */ - ret = regmap_read(data->regmap, AL3320A_REG_DATA_LOW, &raw); + ret = regmap_bulk_read(data->regmap, AL3320A_REG_DATA_LOW, + &raw, sizeof(raw)); if (ret) return ret; - *val = raw; + *val = le16_to_cpu(raw); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -156,11 +220,16 @@ static int al3320a_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - gain = FIELD_GET(AL3320A_GAIN_MASK, gain); - *val = al3320a_scales[gain][0]; - *val2 = al3320a_scales[gain][1]; + for (i = 0; i < variant->num_scales; i++) { + if ((gain & variant->scale_mask) != variant->scale_regs[i]) + continue; - return IIO_VAL_INT_PLUS_MICRO; + *val = variant->scales[i][0]; + *val2 = variant->scales[i][1]; + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; } return -EINVAL; } @@ -170,17 +239,18 @@ static int al3320a_write_raw(struct iio_dev *indio_dev, int val2, long mask) { struct al3320a_data *data = iio_priv(indio_dev); + const struct al3320_variant *variant = data->variant; unsigned int i; switch (mask) { case IIO_CHAN_INFO_SCALE: - for (i = 0; i < ARRAY_SIZE(al3320a_scales); i++) { - if (val != al3320a_scales[i][0] || - val2 != al3320a_scales[i][1]) + for (i = 0; i < variant->num_scales; i++) { + if (val != variant->scales[i][0] || + val2 != variant->scales[i][1]) continue; return regmap_write(data->regmap, AL3320A_REG_CONFIG_RANGE, - FIELD_PREP(AL3320A_GAIN_MASK, i)); + variant->scale_regs[i]); } break; } @@ -198,14 +268,20 @@ static int al3320a_probe(struct i2c_client *client) struct al3320a_data *data; struct device *dev = &client->dev; struct iio_dev *indio_dev; + const struct al3320_variant *variant; int ret; + variant = i2c_get_match_data(client); + if (!variant) + variant = &al3320a_variant; + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); + data->variant = variant; data->regmap = devm_regmap_init_i2c(client, &al3320a_regmap_config); if (IS_ERR(data->regmap)) @@ -213,7 +289,7 @@ static int al3320a_probe(struct i2c_client *client) "cannot allocate regmap\n"); indio_dev->info = &al3320a_info; - indio_dev->name = "al3320a"; + indio_dev->name = variant->name; indio_dev->channels = al3320a_channels; indio_dev->num_channels = ARRAY_SIZE(al3320a_channels); indio_dev->modes = INDIO_DIRECT_MODE; @@ -246,13 +322,15 @@ static DEFINE_SIMPLE_DEV_PM_OPS(al3320a_pm_ops, al3320a_suspend, al3320a_resume); static const struct i2c_device_id al3320a_id[] = { - { "al3320a" }, + { .name = "al3320a", .driver_data = (kernel_ulong_t)&al3320a_variant }, + { .name = "al3320b", .driver_data = (kernel_ulong_t)&al3320b_variant }, { } }; MODULE_DEVICE_TABLE(i2c, al3320a_id); static const struct of_device_id al3320a_of_match[] = { - { .compatible = "dynaimage,al3320a", }, + { .compatible = "dynaimage,al3320a", .data = &al3320a_variant }, + { .compatible = "dynaimage,al3320b", .data = &al3320b_variant }, { } }; MODULE_DEVICE_TABLE(of, al3320a_of_match); @@ -277,5 +355,5 @@ static struct i2c_driver al3320a_driver = { module_i2c_driver(al3320a_driver); MODULE_AUTHOR("Daniel Baluta "); -MODULE_DESCRIPTION("AL3320A Ambient Light Sensor driver"); +MODULE_DESCRIPTION("AL3320A/AL3320B Ambient Light Sensor driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c index c78d9f6d97c4f7..990f3256f71a24 100644 --- a/drivers/input/keyboard/mtk-pmic-keys.c +++ b/drivers/input/keyboard/mtk-pmic-keys.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -55,9 +56,24 @@ struct mtk_pmic_regs { const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT]; u32 pmic_rst_reg; u32 rst_lprst_mask; /* Long-press reset timeout bitmask */ + u32 homekey_puen_reg; + u32 homekey_puen_mask; bool key_release_irq; }; +static const struct mtk_pmic_regs mt6320_regs = { + .keys_regs[MTK_PMIC_PWRKEY_INDEX] = + MTK_PMIC_KEYS_REGS(MT6320_CHRSTATUS, + 0x8, MT6320_INT_RSV, 0x10, MTK_PMIC_PWRKEY_RST), + .keys_regs[MTK_PMIC_HOMEKEY_INDEX] = + MTK_PMIC_KEYS_REGS(MT6320_OCSTATUS2, + 0x10, MT6320_INT_RSV, 0x8, MTK_PMIC_HOMEKEY_RST), + .pmic_rst_reg = MT6320_TOP_RST_MISC, + .rst_lprst_mask = MTK_PMIC_RST_DU_MASK, + .homekey_puen_reg = MT6320_GPIO_SMT_CON3, + .homekey_puen_mask = BIT(8), +}; + static const struct mtk_pmic_regs mt6397_regs = { .keys_regs[MTK_PMIC_PWRKEY_INDEX] = MTK_PMIC_KEYS_REGS(MT6397_CHRSTATUS, @@ -299,6 +315,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend, static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = { { + .compatible = "mediatek,mt6320-keys", + .data = &mt6320_regs, + }, { .compatible = "mediatek,mt6397-keys", .data = &mt6397_regs, }, { @@ -363,6 +382,15 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev) return -EINVAL; } + if (mtk_pmic_regs->homekey_puen_reg) { + error = regmap_update_bits(keys->regmap, + mtk_pmic_regs->homekey_puen_reg, + mtk_pmic_regs->homekey_puen_mask, + mtk_pmic_regs->homekey_puen_mask); + if (error) + return error; + } + for_each_child_of_node_scoped(node, child) { keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index]; diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index ccd9338a44dbef..829473e797e39c 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -31,7 +31,6 @@ #define RMI4_PAGE_MASK 0xFF00 #define RMI_DEVICE_RESET_CMD 0x01 -#define DEFAULT_RESET_DELAY_MS 100 void rmi_free_function_list(struct rmi_device *rmi_dev) { @@ -809,6 +808,20 @@ int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx, return RMI_SCAN_DONE; } + if (pdata->initial_reset_control) { + u8 ctrl_buf = pdata->initial_reset_control; + u16 ctrl_addr = + pdt->page_start + pdt->control_base_addr; + + error = rmi_write_block(rmi_dev, ctrl_addr, &ctrl_buf, 1); + if (error) { + dev_err(&rmi_dev->dev, + "Initial reset control write failed. Code = %d.\n", + error); + return error; + } + } + rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Sending reset\n"); error = rmi_write_block(rmi_dev, cmd_addr, &cmd_buf, 1); if (error) { @@ -817,7 +830,8 @@ int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx, return error; } - mdelay(pdata->reset_delay_ms ?: DEFAULT_RESET_DELAY_MS); + mdelay(pdata->initial_reset_delay_ms ?: + pdata->reset_delay_ms ?: DEFAULT_RESET_DELAY_MS); return RMI_SCAN_DONE; } @@ -999,7 +1013,13 @@ static int rmi_driver_of_probe(struct device *dev, if (retval) return retval; - return 0; + retval = rmi_of_property_read_u32(dev, &pdata->initial_reset_control, + "syna,initial-reset-control", 1); + if (retval) + return retval; + + return rmi_of_property_read_u32(dev, &pdata->initial_reset_delay_ms, + "syna,initial-reset-delay-ms", 1); } #else static inline int rmi_driver_of_probe(struct device *dev, diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h index e84495caab1514..5af5a82128a7fe 100644 --- a/drivers/input/rmi4/rmi_driver.h +++ b/drivers/input/rmi4/rmi_driver.h @@ -16,6 +16,8 @@ #define SYNAPTICS_INPUT_DEVICE_NAME "Synaptics RMI4 Touch Sensor" #define SYNAPTICS_VENDOR_ID 0x06cb +#define DEFAULT_RESET_DELAY_MS 100 + #define GROUP(_attrs) { \ .attrs = _attrs, \ } diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c index 3c0c5fd4470275..a75289482f4a7d 100644 --- a/drivers/input/rmi4/rmi_i2c.c +++ b/drivers/input/rmi4/rmi_i2c.c @@ -4,6 +4,7 @@ * Copyright (c) 2011 Unixphere */ +#include #include #include #include @@ -26,7 +27,10 @@ * @tx_buf_size: Size of the buffer * * @supplies: Array of voltage regulators + * @reset_gpio: Reference to the reset GPIO * @startup_delay: Milliseconds to pause after powering up the regulators + * @reset_delay: Milliseconds to pause after resetting the device + * @reset_after_power_on: Pulse reset only after the regulators are enabled */ struct rmi_i2c_xport { struct rmi_transport_dev xport; @@ -39,7 +43,10 @@ struct rmi_i2c_xport { size_t tx_buf_size; struct regulator_bulk_data supplies[2]; + struct gpio_desc *reset_gpio; u32 startup_delay; + u32 reset_delay; + bool reset_after_power_on; }; #define RMI_PAGE_SELECT_REGISTER 0xff @@ -227,6 +234,20 @@ static int rmi_i2c_probe(struct i2c_client *client) return -ENODEV; } + rmi_i2c->reset_after_power_on = client->dev.of_node && + of_property_read_bool(client->dev.of_node, + "syna,reset-after-power-on"); + + rmi_i2c->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + rmi_i2c->reset_after_power_on ? + GPIOD_OUT_LOW : GPIOD_OUT_HIGH); + if (IS_ERR(rmi_i2c->reset_gpio)) { + error = PTR_ERR(rmi_i2c->reset_gpio); + dev_err(&client->dev, "failed to get reset GPIO: %d\n", error); + return error; + } + gpiod_set_consumer_name(rmi_i2c->reset_gpio, "rmi4 reset"); + rmi_i2c->supplies[0].supply = "vdd"; rmi_i2c->supplies[1].supply = "vio"; error = devm_regulator_bulk_get(&client->dev, @@ -251,6 +272,15 @@ static int rmi_i2c_probe(struct i2c_client *client) msleep(rmi_i2c->startup_delay); + if (rmi_i2c->reset_gpio) { + of_property_read_u32(client->dev.of_node, "syna,reset-delay-ms", + &rmi_i2c->reset_delay); + gpiod_set_value_cansleep(rmi_i2c->reset_gpio, 1); + usleep_range(10000, 20000); + gpiod_set_value_cansleep(rmi_i2c->reset_gpio, 0); + msleep(rmi_i2c->reset_delay ?: DEFAULT_RESET_DELAY_MS); + } + rmi_i2c->client = client; mutex_init(&rmi_i2c->page_mutex); diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c index 8c684756d5fc25..2de4344fc5b132 100644 --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c @@ -1859,6 +1859,7 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv) } static struct clk_bulk_data mtk_jpeg_clocks[] = { + { .id = "jpgenc-smi" }, { .id = "jpgenc" }, }; @@ -1933,6 +1934,10 @@ static const struct of_device_id mtk_jpeg_match[] = { .compatible = "mediatek,mt2701-jpgdec", .data = &mt8173_jpeg_drvdata, }, + { + .compatible = "mediatek,mt6589-jpgdec", + .data = &mt8173_jpeg_drvdata, + }, { .compatible = "mediatek,mtk-jpgenc", .data = &mtk_jpeg_drvdata, diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index aaeba8ab211e97..4b144e2b511b5f 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -37,6 +37,7 @@ #define SMI_DUMMY 0x444 /* SMI LARB */ +#define SMI_LARB_STAT 0x0 #define SMI_LARB_SLP_CON 0xc #define SLP_PROT_EN BIT(0) #define SLP_PROT_RDY BIT(16) @@ -48,9 +49,23 @@ #define SMI_LARB_SW_FLAG 0x40 #define SMI_LARB_SW_FLAG_1 0x1 +/* mt6589, mt8135 */ +#define SMI_LARB_BWFILTER_EN_V1 0x2c + +/* mt2601, mt6572, mt6571, mt6582, mt6592, mt8127 */ +#define SMI_LARB_BWFILTER_EN_V2 0x60 + +#define SMI_LARB_OSTD_CTRL_EN 0x64 + #define SMI_LARB_OSTDL_PORT 0x200 #define SMI_LARB_OSTDL_PORTx(id) (SMI_LARB_OSTDL_PORT + (((id) & 0x1f) << 2)) +/* mt6589 */ +#define SMI_LARB_SHARE_EN 0x210 +#define SMI_LARB_ROUTE_SEL 0x220 + +#define SMI_LARB_FIFO_STAT0 0x600 + /* Below are about mmu enable registers, they are different in SoCs */ /* gen1: mt2701 */ #define REG_SMI_SECUR_CON_BASE 0x5c0 @@ -92,6 +107,8 @@ #define MTK_SMI_FLAG_SW_FLAG BIT(1) #define MTK_SMI_FLAG_SLEEP_CTL BIT(2) #define MTK_SMI_FLAG_CFG_PORT_SEC_CTL BIT(3) +#define MTK_SMI_FLAG_BW_CALIBRATE BIT(4) +#define MTK_SMI_FLAG_BWFILTER_REG_V2 BIT(5) #define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x))) struct mtk_smi_reg_pair { @@ -100,6 +117,7 @@ struct mtk_smi_reg_pair { }; enum mtk_smi_type { + MTK_SMI_GEN0, MTK_SMI_GEN1, MTK_SMI_GEN2, /* gen2 smi common */ MTK_SMI_GEN2_SUB_COMM, /* gen2 smi sub common */ @@ -141,10 +159,8 @@ struct mtk_smi { unsigned int clk_num; struct clk_bulk_data clks[MTK_SMI_CLK_NR_MAX]; struct clk *clk_async; /*only needed by mt2701*/ - union { - void __iomem *smi_ao_base; /* only for gen1 */ - void __iomem *base; /* only for gen2 */ - }; + void __iomem *smi_ao_base; + void __iomem *base; struct device *smi_common_dev; /* for sub common */ const struct mtk_smi_common_plat *plat; }; @@ -188,6 +204,103 @@ static const struct component_ops mtk_smi_larb_component_ops = { .unbind = mtk_smi_larb_unbind, }; +static int mtk_smi_larb_config_port_gen0(struct device *dev) +{ + struct mtk_smi_larb *larb = dev_get_drvdata(dev); + const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen; + struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev); + const u8 *larbostd = larb_gen->ostd ? larb_gen->ostd[larb->larbid] : + NULL; + int i, m4u_port_id, larb_port_num, offset; + u32 sec_con_val, reg_val, tmp; + int ret; + + m4u_port_id = larb_gen->port_in_larb[larb->larbid]; + larb_port_num = larb_gen->port_in_larb[larb->larbid + 1] - m4u_port_id; + + /* gen 1 part */ + for (i = 0; i < larb_port_num; i++, m4u_port_id++) { + if (*larb->mmu & BIT(i)) { + sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id); + } else { + continue; + } + + reg_val = readl(common->smi_ao_base + + REG_SMI_SECUR_CON_ADDR(m4u_port_id)); + reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id); + reg_val |= sec_con_val; + reg_val |= SMI_SECUR_CON_VAL_DOMAIN(m4u_port_id); + writel(reg_val, common->smi_ao_base + + REG_SMI_SECUR_CON_ADDR(m4u_port_id)); + } + + /* gen 2 part */ + for (i = 0; i < SMI_LARB_PORT_NR_MAX && larbostd && !!larbostd[i]; i++) + writel_relaxed(larbostd[i], + larb->base + SMI_LARB_OSTDL_PORTx(i)); + + /* some gen 0 SoCs need BW calibration */ + if (MTK_SMI_CAPS(larb_gen->flags_general, MTK_SMI_FLAG_BW_CALIBRATE)) { + if (MTK_SMI_CAPS(larb_gen->flags_general, + MTK_SMI_FLAG_BWFILTER_REG_V2)) + offset = SMI_LARB_BWFILTER_EN_V2; + else + offset = SMI_LARB_BWFILTER_EN_V1; + + reg_val = readl_relaxed(larb->base + SMI_LARB_STAT); + if (!reg_val) { + writel_relaxed(0xffffffff, + larb->base + offset); + + ret = readl_poll_timeout( + larb->base + SMI_LARB_FIFO_STAT0, tmp, + tmp == 0xaaaa, 500, 64 * 500); + if (ret) + dev_warn(dev, + "BW limiter calibration timeout\n"); + + writel_relaxed(0, larb->base + offset); + writel_relaxed(0xffffffff, + larb->base + offset); + } + } + + return 0; +} + +static int mtk_smi_larb_config_port_mt6589(struct device *dev) +{ + struct mtk_smi_larb *larb = dev_get_drvdata(dev); + int ret; + + /* Execute the common Gen0 port configuration first */ + ret = mtk_smi_larb_config_port_gen0(dev); + if (ret) + return ret; + + /* + * MT6589 requires additional LARB-local settings: + * - Disable share for all ports + * - Route specific ports to EMI instead of MCI + */ + writel_relaxed(0x0, larb->base + SMI_LARB_SHARE_EN); + + switch (larb->larbid) { + case 2: + writel_relaxed(0x1e, larb->base + SMI_LARB_ROUTE_SEL); + break; + case 4: + writel_relaxed(0xffffffff, larb->base + SMI_LARB_ROUTE_SEL); + break; + default: + writel_relaxed(0x0, larb->base + SMI_LARB_ROUTE_SEL); + break; + } + + return 0; +} + static int mtk_smi_larb_config_port_gen1(struct device *dev) { struct mtk_smi_larb *larb = dev_get_drvdata(dev); @@ -283,6 +396,8 @@ static int mtk_smi_larb_config_port_gen2_general(struct device *dev) return 0; } + + static const u8 mtk_smi_larb_mt6893_ostd[][SMI_LARB_PORT_NR_MAX] = { [0] = {0x2, 0x6, 0x2, 0x2, 0x2, 0x28, 0x18, 0x18, 0x1, 0x1, 0x1, 0x8, 0x8, 0x1, 0x3f}, @@ -491,6 +606,12 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = { .larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */ }; +static const struct mtk_smi_larb_gen mtk_smi_larb_mt6589 = { + .port_in_larb = { 0, 10, 17, 29, 44 ,56 }, + .config_port = mtk_smi_larb_config_port_mt6589, + .flags_general = MTK_SMI_FLAG_BW_CALIBRATE, +}; + static const struct mtk_smi_larb_gen mtk_smi_larb_mt6779 = { .config_port = mtk_smi_larb_config_port_gen2_general, .larb_direct_to_common_mask = @@ -548,6 +669,7 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = { static const struct of_device_id mtk_smi_larb_of_ids[] = { {.compatible = "mediatek,mt2701-smi-larb", .data = &mtk_smi_larb_mt2701}, {.compatible = "mediatek,mt2712-smi-larb", .data = &mtk_smi_larb_mt2712}, + {.compatible = "mediatek,mt6589-smi-larb", .data = &mtk_smi_larb_mt6589}, {.compatible = "mediatek,mt6779-smi-larb", .data = &mtk_smi_larb_mt6779}, {.compatible = "mediatek,mt6795-smi-larb", .data = &mtk_smi_larb_mt8173}, {.compatible = "mediatek,mt6893-smi-larb", .data = &mtk_smi_larb_mt6893}, @@ -739,6 +861,10 @@ static struct platform_driver mtk_smi_larb_driver = { } }; +static const struct mtk_smi_reg_pair mtk_smi_common_mt6589_init[SMI_COMMON_INIT_REGS_NR] = { + {0x200, 0x24}, /* SMI_L1LEN */ +}; + static const struct mtk_smi_reg_pair mtk_smi_common_mt6795_init[SMI_COMMON_INIT_REGS_NR] = { {SMI_L1_ARB, 0x1b}, {SMI_M4U_TH, 0xce810c85}, @@ -763,6 +889,13 @@ static const struct mtk_smi_common_plat mtk_smi_common_gen2 = { .type = MTK_SMI_GEN2, }; +static const struct mtk_smi_common_plat mtk_smi_common_mt6589 = { + .type = MTK_SMI_GEN0, + .init = mtk_smi_common_mt6589_init, + /* LARB0→MMU0, LARB1→MMU1, LARB2→MMU0, LARB3→MMU1, LARB4→MMU1 */ + .bus_sel = 0x110, +}; + static const struct mtk_smi_common_plat mtk_smi_common_mt6779 = { .type = MTK_SMI_GEN2, .has_gals = true, @@ -843,6 +976,7 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8365 = { static const struct of_device_id mtk_smi_common_of_ids[] = { {.compatible = "mediatek,mt2701-smi-common", .data = &mtk_smi_common_gen1}, {.compatible = "mediatek,mt2712-smi-common", .data = &mtk_smi_common_gen2}, + {.compatible = "mediatek,mt6589-smi-common", .data = &mtk_smi_common_mt6589}, {.compatible = "mediatek,mt6779-smi-common", .data = &mtk_smi_common_mt6779}, {.compatible = "mediatek,mt6795-smi-common", .data = &mtk_smi_common_mt6795}, {.compatible = "mediatek,mt6893-smi-common", .data = &mtk_smi_common_mt6893}, @@ -883,31 +1017,42 @@ static int mtk_smi_common_probe(struct platform_device *pdev) if (ret) return ret; - /* - * for mtk smi gen 1, we need to get the ao(always on) base to config - * m4u port, and we need to enable the aync clock for transform the smi - * clock into emi clock domain, but for mtk smi gen2, there's no smi ao - * base. - */ - if (common->plat->type == MTK_SMI_GEN1) { - common->smi_ao_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(common->smi_ao_base)) - return PTR_ERR(common->smi_ao_base); - - common->clk_async = devm_clk_get_enabled(dev, "async"); - if (IS_ERR(common->clk_async)) - return PTR_ERR(common->clk_async); - } else { - common->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(common->base)) - return PTR_ERR(common->base); - } - - /* link its smi-common if this is smi-sub-common */ - if (common->plat->type == MTK_SMI_GEN2_SUB_COMM) { - ret = mtk_smi_device_link_common(dev, &common->smi_common_dev); - if (ret < 0) - return ret; + switch (common->plat->type) { + case MTK_SMI_GEN0: + /* + * gen 0 uses 2 mmio ranges: ao base for iommu configuration, + * and ext base for ostd, fifo and bw limiter setup + */ + common->smi_ao_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(common->smi_ao_base)) + return PTR_ERR(common->smi_ao_base); + common->base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(common->base)) + return PTR_ERR(common->base); + break; + case MTK_SMI_GEN1: + /* + * gen 1 needs async clock to transform the smi clock to the + * emi clock domain + */ + common->smi_ao_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(common->smi_ao_base)) + return PTR_ERR(common->smi_ao_base); + common->clk_async = devm_clk_get_enabled(dev, "async"); + if (IS_ERR(common->clk_async)) + return PTR_ERR(common->clk_async); + break; + case MTK_SMI_GEN2: + common->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(common->base)) + return PTR_ERR(common->base); + break; + case MTK_SMI_GEN2_SUB_COMM: + /* link its smi-common if this is smi-sub-common */ + ret = mtk_smi_device_link_common(dev, &common->smi_common_dev); + if (ret < 0) + return ret; + break; } pm_runtime_enable(dev); @@ -936,13 +1081,15 @@ static int __maybe_unused mtk_smi_common_resume(struct device *dev) if (ret) return ret; - if (common->plat->type != MTK_SMI_GEN2) + if (common->plat->type != MTK_SMI_GEN0 && common->plat->type != MTK_SMI_GEN2) return 0; for (i = 0; i < SMI_COMMON_INIT_REGS_NR && init && init[i].offset; i++) writel_relaxed(init[i].value, common->base + init[i].offset); - writel(bus_sel, common->base + SMI_BUS_SEL); + if (common->plat->bus_sel) + writel(bus_sel, common->base + SMI_BUS_SEL); + return 0; } diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 1bdacda9a933f2..929b747e3a6498 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +29,9 @@ #include #include +#define MT6320_RTC_BASE 0xe000 +#define MT6320_RTC_SIZE 0x3f + #define MT6323_RTC_BASE 0x8000 #define MT6323_RTC_SIZE 0x40 @@ -45,6 +50,15 @@ #define MT6323_PWRC_BASE 0x8000 #define MT6323_PWRC_SIZE 0x40 +static const struct resource mt6320_rtc_resources[] = { + DEFINE_RES_MEM(MT6320_RTC_BASE, MT6320_RTC_SIZE), + DEFINE_RES_IRQ(MT6320_IRQ_RTC), +}; + +static const struct resource mt6320_pwrc_resources[] = { + DEFINE_RES_MEM(MT6320_RTC_BASE, MT6320_RTC_SIZE), +}; + static const struct resource mt6323_rtc_resources[] = { DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE), DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC), @@ -70,6 +84,11 @@ static const struct resource mt6397_rtc_resources[] = { DEFINE_RES_IRQ(MT6397_IRQ_RTC), }; +static const struct resource mt6320_keys_resources[] = { + DEFINE_RES_IRQ_NAMED(MT6320_IRQ_PWRKEY, "powerkey"), + DEFINE_RES_IRQ_NAMED(MT6320_IRQ_HOMEKEY, "homekey"), +}; + static const struct resource mt6358_keys_resources[] = { DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY, "powerkey"), DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY, "homekey"), @@ -77,6 +96,10 @@ static const struct resource mt6358_keys_resources[] = { DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY_R, "homekey_r"), }; +static const struct resource mt6320_accdet_resources[] = { + DEFINE_RES_IRQ_NAMED(MT6320_IRQ_ACCDET, "accdet_irq"), +}; + static const struct resource mt6359_keys_resources[] = { DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY, "powerkey"), DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY, "homekey"), @@ -123,6 +146,48 @@ static const struct resource mt6323_pwrc_resources[] = { DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE), }; +static const struct mfd_cell mt6320_devs[] = { + { + .name = "mt6320-rtc", + .num_resources = ARRAY_SIZE(mt6320_rtc_resources), + .resources = mt6320_rtc_resources, + .of_compatible = "mediatek,mt6320-rtc", + }, { + .name = "mt6320-regulator", + .of_compatible = "mediatek,mt6320-regulator", + }, { + .name = "mt6320-clk", + .of_compatible = "mediatek,mt6320-clk", + }, { + .name = "mt6320-pinctrl", + .of_compatible = "mediatek,mt6320-pinctrl", + }, { + .name = "mt6320-keys", + .num_resources = ARRAY_SIZE(mt6320_keys_resources), + .resources = mt6320_keys_resources, + .of_compatible = "mediatek,mt6320-keys", + }, { + .name = "mt6320-pwrc", + .num_resources = ARRAY_SIZE(mt6320_pwrc_resources), + .resources = mt6320_pwrc_resources, + .of_compatible = "mediatek,mt6320-pwrc", + }, { + .name = "mt6320-auxadc", + .of_compatible = "mediatek,mt6320-auxadc", + }, { + .name = "mt6320-efuse", + .of_compatible = "mediatek,mt6320-efuse", + }, { + .name = "mt6320-accdet", + .num_resources = ARRAY_SIZE(mt6320_accdet_resources), + .resources = mt6320_accdet_resources, + .of_compatible = "mediatek,mt6320-accdet", + }, { + .name = "mt6320-sound", + .of_compatible = "mediatek,mt6320-sound", + }, +}; + static const struct mfd_cell mt6323_devs[] = { { .name = "mt6323-rtc", @@ -287,6 +352,14 @@ struct chip_data { int (*irq_init)(struct mt6397_chip *chip); }; +static const struct chip_data mt6320_core = { + .cid_addr = MT6320_CID, + .cid_shift = 0, + .cells = mt6320_devs, + .cell_size = ARRAY_SIZE(mt6320_devs), + .irq_init = mt6397_irq_init, +}; + static const struct chip_data mt6323_core = { .cid_addr = MT6323_CID, .cid_shift = 0, @@ -399,6 +472,9 @@ static int mt6397_probe(struct platform_device *pdev) static const struct of_device_id mt6397_of_match[] = { { + .compatible = "mediatek,mt6320", + .data = &mt6320_core, + }, { .compatible = "mediatek,mt6323", .data = &mt6323_core, }, { diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c index 5d2e5459f74449..190a546a9f6322 100644 --- a/drivers/mfd/mt6397-irq.c +++ b/drivers/mfd/mt6397-irq.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -176,6 +178,12 @@ int mt6397_irq_init(struct mt6397_chip *chip) mutex_init(&chip->irqlock); switch (chip->chip_id) { + case MT6320_CHIP_ID: + chip->int_con[0] = MT6320_INT_CON0; + chip->int_con[1] = MT6320_INT_CON1; + chip->int_status[0] = MT6320_INT_STATUS0; + chip->int_status[1] = MT6320_INT_STATUS1; + break; case MT6323_CHIP_ID: chip->int_con[0] = MT6323_INT_CON0; chip->int_con[1] = MT6323_INT_CON1; diff --git a/drivers/mtd/nand/ecc-mtk.c b/drivers/mtd/nand/ecc-mtk.c index c75bb8b80cc1e1..cf82246615bb2b 100644 --- a/drivers/mtd/nand/ecc-mtk.c +++ b/drivers/mtd/nand/ecc-mtk.c @@ -41,6 +41,7 @@ #define ECC_CTL_REG(op) ((op) == ECC_ENCODE ? ECC_ENCCON : ECC_DECCON) #define ECC_ERRMASK_MT7622 GENMASK(4, 0) +#define ECC_ERRMASK_MT6589 GENMASK(4, 0) #define ECC_ERRMASK_MT2701 GENMASK(5, 0) #define ECC_ERRMASK_MT2712 GENMASK(6, 0) @@ -83,6 +84,10 @@ static const u8 ecc_strength_mt7622[] = { 4, 6, 8, 10, 12 }; +static const u8 ecc_strength_mt6589[] = { + 4, 6, 8, 10, 12 +}; + static const u8 ecc_strength_mt7986[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 }; @@ -123,6 +128,15 @@ static int mt7622_ecc_regs[] = { [ECC_DECIRQ_STA] = 0x144, }; +static int mt6589_ecc_regs[] = { + [ECC_ENCPAR00] = 0x10, + [ECC_ENCIRQ_EN] = 0x30, + [ECC_ENCIRQ_STA] = 0x34, + [ECC_DECDONE] = 0x11c, + [ECC_DECIRQ_EN] = 0x140, + [ECC_DECIRQ_STA] = 0x144, +}; + static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, enum mtk_ecc_operation op) { @@ -469,6 +483,17 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { .pg_irq_sel = 0, }; +static const struct mtk_ecc_caps mtk_ecc_caps_mt6589 = { + .err_mask = ECC_ERRMASK_MT6589, + .err_shift = 5, + .ecc_strength = ecc_strength_mt6589, + .ecc_regs = mt6589_ecc_regs, + .num_ecc_strength = ARRAY_SIZE(ecc_strength_mt6589), + .ecc_mode_shift = 4, + .parity_bits = 13, + .pg_irq_sel = 0, +}; + static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { .err_mask = ECC_ERRMASK_MT2712, .err_shift = 8, @@ -506,6 +531,9 @@ static const struct of_device_id mtk_ecc_dt_match[] = { { .compatible = "mediatek,mt2701-ecc", .data = &mtk_ecc_caps_mt2701, + }, { + .compatible = "mediatek,mt6589-ecc", + .data = &mtk_ecc_caps_mt6589, }, { .compatible = "mediatek,mt2712-ecc", .data = &mtk_ecc_caps_mt2712, diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 21c7e110274693..f0f1804b52a2e6 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -102,6 +102,8 @@ struct mtk_nfc_caps { const u8 *spare_size; u8 num_spare_size; u8 pageformat_spare_shift; + bool pageformat_sec_sel_512; + u8 pageformat_init; u8 nfi_clk_div; u8 max_sector; u32 max_sector_size; @@ -166,6 +168,10 @@ static const u8 spare_size_mt2701[] = { 16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 63, 64 }; +static const u8 spare_size_mt6589[] = { + 16, 26, 27, 28 +}; + static const u8 spare_size_mt2712[] = { 16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 61, 63, 64, 67, 74 @@ -321,31 +327,38 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd) struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip); struct mtk_nfc *nfc = nand_get_controller_data(chip); u32 fmt, spare, i; + u32 sec_sel_512; if (!mtd->writesize) return 0; + if (mtd->writesize > + nfc->caps->max_sector * nfc->caps->max_sector_size) + return -EINVAL; + spare = mtk_nand->spare_per_sector; + sec_sel_512 = nfc->caps->pageformat_sec_sel_512 ? + PAGEFMT_SEC_SEL_512 : 0; switch (mtd->writesize) { case 512: - fmt = PAGEFMT_512_2K | PAGEFMT_SEC_SEL_512; + fmt = PAGEFMT_512_2K | sec_sel_512; break; case KB(2): if (chip->ecc.size == 512) - fmt = PAGEFMT_2K_4K | PAGEFMT_SEC_SEL_512; + fmt = PAGEFMT_2K_4K | sec_sel_512; else fmt = PAGEFMT_512_2K; break; case KB(4): if (chip->ecc.size == 512) - fmt = PAGEFMT_4K_8K | PAGEFMT_SEC_SEL_512; + fmt = PAGEFMT_4K_8K | sec_sel_512; else fmt = PAGEFMT_2K_4K; break; case KB(8): if (chip->ecc.size == 512) - fmt = PAGEFMT_8K_16K | PAGEFMT_SEC_SEL_512; + fmt = PAGEFMT_8K_16K | sec_sel_512; else fmt = PAGEFMT_4K_8K; break; @@ -1093,7 +1106,7 @@ static inline void mtk_nfc_hw_init(struct mtk_nfc *nfc) * 0 : poll the status of the busy/ready signal after [7:4]*16 cycles. */ nfi_writew(nfc, 0xf1, NFI_CNRNB); - nfi_writel(nfc, PAGEFMT_8K_16K, NFI_PAGEFMT); + nfi_writel(nfc, nfc->caps->pageformat_init, NFI_PAGEFMT); mtk_nfc_hw_reset(nfc); @@ -1466,15 +1479,36 @@ static const struct mtk_nfc_caps mtk_nfc_caps_mt2701 = { .spare_size = spare_size_mt2701, .num_spare_size = 16, .pageformat_spare_shift = 4, + .pageformat_sec_sel_512 = true, + .pageformat_init = PAGEFMT_8K_16K, .nfi_clk_div = 1, .max_sector = 16, .max_sector_size = 1024, }; +/* + * The MT6589 NFI is an earlier revision of the MT2701 one: same page + * format register layout (spare shift 4, FDM at bits 8/12), same + * spare per sector choices (16/26/27/28) and the same 512 byte + * sectors, as programmed by the downstream mt6589 mtk_nand.c. + */ +static const struct mtk_nfc_caps mtk_nfc_caps_mt6589 = { + .spare_size = spare_size_mt6589, + .num_spare_size = ARRAY_SIZE(spare_size_mt6589), + .pageformat_spare_shift = 4, + .pageformat_sec_sel_512 = false, + .pageformat_init = PAGEFMT_512_2K, + .nfi_clk_div = 1, + .max_sector = 8, + .max_sector_size = 512, +}; + static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = { .spare_size = spare_size_mt2712, .num_spare_size = 19, .pageformat_spare_shift = 16, + .pageformat_sec_sel_512 = true, + .pageformat_init = PAGEFMT_8K_16K, .nfi_clk_div = 2, .max_sector = 16, .max_sector_size = 1024, @@ -1484,6 +1518,8 @@ static const struct mtk_nfc_caps mtk_nfc_caps_mt7622 = { .spare_size = spare_size_mt7622, .num_spare_size = 4, .pageformat_spare_shift = 4, + .pageformat_sec_sel_512 = true, + .pageformat_init = PAGEFMT_8K_16K, .nfi_clk_div = 1, .max_sector = 8, .max_sector_size = 512, @@ -1493,6 +1529,9 @@ static const struct of_device_id mtk_nfc_id_table[] = { { .compatible = "mediatek,mt2701-nfc", .data = &mtk_nfc_caps_mt2701, + }, { + .compatible = "mediatek,mt6589-nfc", + .data = &mtk_nfc_caps_mt6589, }, { .compatible = "mediatek,mt2712-nfc", .data = &mtk_nfc_caps_mt2712, diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 74ddbd0f79b0ec..c4d69dd6019e9e 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -227,6 +227,13 @@ config NVMEM_MTK_EFUSE This driver can also be built as a module. If so, the module will be called efuse-mtk. +config NVMEM_MT6320_EFUSE + tristate "MediaTek MT6320 PMIC EFUSE support" + depends on MFD_MT6397 + help + This is a driver to access the one-time-programmable array in + the MediaTek MT6320 PMIC, e.g. battery calibration data. + config NVMEM_MXS_OCOTP tristate "Freescale MXS On-Chip OTP Memory Support" depends on ARCH_MXS || COMPILE_TEST diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index 7252b8ec88d469..58872b90d5fe5f 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_NVMEM_MICROCHIP_OTPC) += nvmem-microchip-otpc.o nvmem-microchip-otpc-y := microchip-otpc.o obj-$(CONFIG_NVMEM_MTK_EFUSE) += nvmem_mtk-efuse.o nvmem_mtk-efuse-y := mtk-efuse.o +obj-$(CONFIG_NVMEM_MT6320_EFUSE) += mt6320-efuse.o obj-$(CONFIG_NVMEM_MXS_OCOTP) += nvmem-mxs-ocotp.o nvmem-mxs-ocotp-y := mxs-ocotp.o obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o diff --git a/drivers/nvmem/mt6320-efuse.c b/drivers/nvmem/mt6320-efuse.c new file mode 100644 index 00000000000000..741e828e1611bd --- /dev/null +++ b/drivers/nvmem/mt6320-efuse.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MediaTek MT6320 PMIC eFuse NVMEM driver + * + * Copyright (c) 2026 Akari Tsuyukusa + * + * The MT6320 exposes 192 bits of eFuse data through the EFUSE_DOUT registers. + * The downstream preloader reads this latched DOUT window directly when + * applying PMIC trimming, so Linux must not start another software read + * transaction through EFUSE_CONx. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MT6320_EFUSE_NUM_WORDS 12 +#define MT6320_EFUSE_SIZE (MT6320_EFUSE_NUM_WORDS * sizeof(u16)) +#define MT6320_EFUSE_DOUT_BASE MT6320_EFUSE_DOUT_0_15 + +static int mt6320_efuse_read(void *context, unsigned int off, + void *data, size_t len) +{ + struct regmap *regmap = context; + u16 *buf = data; + unsigned int val; + size_t i; + int ret; + + if (!len || (off & 1) || (len & 1) || + off > MT6320_EFUSE_SIZE || len > MT6320_EFUSE_SIZE - off) + return -EINVAL; + + /* PWRAP is a register bus, not a linear memory window: read each word. */ + for (i = 0; i < len / sizeof(*buf); i++) { + ret = regmap_read(regmap, + MT6320_EFUSE_DOUT_BASE + off + i * sizeof(*buf), + &val); + if (ret) + return ret; + + buf[i] = val; + } + + return 0; +} + +static int mt6320_efuse_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mt6397_chip *pmic = dev_get_drvdata(dev->parent); + struct nvmem_device *nvmem; + struct nvmem_config config = { + .name = "mt6320-efuse", + .owner = THIS_MODULE, + .stride = 2, + .word_size = 2, + .size = MT6320_EFUSE_SIZE, + .reg_read = mt6320_efuse_read, + }; + + if (!pmic || !pmic->regmap) + return dev_err_probe(dev, -ENODEV, "failed to get PMIC regmap\n"); + + config.dev = dev; + config.priv = pmic->regmap; + + nvmem = devm_nvmem_register(dev, &config); + if (IS_ERR(nvmem)) + return dev_err_probe(dev, PTR_ERR(nvmem), + "failed to register nvmem\n"); + + return 0; +} + +static const struct of_device_id mt6320_efuse_of_match[] = { + { .compatible = "mediatek,mt6320-efuse" }, + { } +}; +MODULE_DEVICE_TABLE(of, mt6320_efuse_of_match); + +static struct platform_driver mt6320_efuse_driver = { + .driver = { + .name = "mt6320-efuse", + .of_match_table = mt6320_efuse_of_match, + }, + .probe = mt6320_efuse_probe, +}; +module_platform_driver(mt6320_efuse_driver); + +MODULE_AUTHOR("Akari Tsuyukusa "); +MODULE_DESCRIPTION("MediaTek MT6320 PMIC eFuse driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c index af953e1d923023..ca4dc4ad2676a7 100644 --- a/drivers/nvmem/mtk-efuse.c +++ b/drivers/nvmem/mtk-efuse.c @@ -14,10 +14,12 @@ struct mtk_efuse_pdata { bool uses_post_processing; + bool aligned_read; }; struct mtk_efuse_priv { void __iomem *base; + const struct mtk_efuse_pdata *data; }; static int mtk_reg_read(void *context, @@ -28,6 +30,20 @@ static int mtk_reg_read(void *context, u8 *val = _val; int i; + if (priv->data->aligned_read) { + u32 pos, align, shift; + + for (i = 0; i < bytes; i++, val++) { + pos = reg + i; + align = pos & ~3; + shift = (pos & 3) * 8; + + *val = (readl(priv->base + align) >> shift) & 0xff; + } + + return 0; + } + for (i = 0; i < bytes; i++, val++) *val = readb(addr + i); @@ -67,7 +83,6 @@ static int mtk_efuse_probe(struct platform_device *pdev) struct nvmem_device *nvmem; struct nvmem_config econfig = {}; struct mtk_efuse_priv *priv; - const struct mtk_efuse_pdata *pdata; struct platform_device *socinfo; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -78,7 +93,8 @@ static int mtk_efuse_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - pdata = device_get_match_data(dev); + priv->data = device_get_match_data(dev); + econfig.add_legacy_fixed_of_cells = true; econfig.stride = 1; econfig.word_size = 1; @@ -86,7 +102,7 @@ static int mtk_efuse_probe(struct platform_device *pdev) econfig.size = resource_size(res); econfig.priv = priv; econfig.dev = dev; - if (pdata->uses_post_processing) + if (priv->data->uses_post_processing) econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; nvmem = devm_nvmem_register(dev, &econfig); if (IS_ERR(nvmem)) @@ -101,6 +117,11 @@ static int mtk_efuse_probe(struct platform_device *pdev) return 0; } +static const struct mtk_efuse_pdata mtk_mt6572_efuse_pdata = { + .uses_post_processing = false, + .aligned_read = true, +}; + static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = { .uses_post_processing = true, }; @@ -110,6 +131,7 @@ static const struct mtk_efuse_pdata mtk_efuse_pdata = { }; static const struct of_device_id mtk_efuse_of_match[] = { + { .compatible = "mediatek,mt6572-efuse", .data = &mtk_mt6572_efuse_pdata }, { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata }, { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata }, { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata }, diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile index 1b8088df71e845..73f2614a17ea12 100644 --- a/drivers/phy/mediatek/Makefile +++ b/drivers/phy/mediatek/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o obj-$(CONFIG_PHY_MTK_MIPI_CSI_0_5) += phy-mtk-mipi-csi-0-5.o phy-mtk-mipi-dsi-drv-y := phy-mtk-mipi-dsi.o +phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt6589.o phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8173.o phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8183.o obj-$(CONFIG_PHY_MTK_MIPI_DSI) += phy-mtk-mipi-dsi-drv.o diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi-mt6589.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi-mt6589.c new file mode 100644 index 00000000000000..5a0a4432838606 --- /dev/null +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi-mt6589.c @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek MT6589 MIPI D-PHY driver + * + * Copyright (c) 2026 MediaTek Inc. + * Based on downstream mt6589 dsi_drv.c + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "phy-mtk-io.h" +#include "phy-mtk-mipi-dsi.h" + +/* MT6589 MIPI TX PHY registers (offsets relative to PHY base) */ +#define MIPITX_DSI_CON 0x00 +#define MIPITX_DSI_LANE0 0x04 +#define MIPITX_DSI_LANE1 0x08 +#define MIPITX_DSI_LANE2 0x0c +#define MIPITX_DSI_LANE3 0x10 +#define MIPITX_DSI_CLK_LANE 0x14 +#define MIPITX_DSI_TOP_CON 0x40 +#define MIPITX_DSI_BG_CON 0x44 +#define MIPITX_DSI_PLL_CON0 0x50 +#define MIPITX_DSI_PLL_PWR 0x60 +#define MIPITX_DSI_SW_CTRL 0x80 +#define MIPITX_DSI_SW_CTRL_CON0 0x84 +#define MIPITX_DSI_SW_CTRL_CON1 0x88 + +/* PLL configuration entry: raw register values from downstream pll_config[] */ +struct mt6589_pll_config { + u8 txdiv0; /* TXDIV0 field (2 bits) */ + u8 txdiv1; /* TXDIV1 field (2 bits) */ + u8 fbk_sel; /* FBK_SEL (2 bits) */ + u8 fbk_div; /* FBK_DIV (7 bits) */ + u8 pre_div; /* PRE_DIV (2 bits) */ + u8 rg_br; /* RG_BR (2 bits) */ + u8 rg_bc; /* RG_BC (2 bits) */ + u8 rg_bir; /* RG_BIR (4 bits) */ + u8 rg_bic; /* RG_BIC (4 bits) */ + u8 rg_bp; /* RG_BP (4 bits) */ +}; + +/* + * PLL configuration table (50 entries) taken from MT6589 downstream. + * Each entry corresponds to a pre‑defined output frequency. + */ +static const struct mt6589_pll_config pll_config[] = { + {1,1,1,0x1E,1,2,3,8,4,0xC}, + {1,1,1,0x0F,0,2,2,4,1,0xC}, + {1,1,1,0x20,1,2,3,9,4,0xC}, + {1,1,1,0x10,0,2,2,4,1,0xC}, + {1,1,1,0x22,1,2,3,9,4,0xC}, + {1,1,1,0x11,0,2,2,4,1,0xC}, + {1,1,1,0x24,1,2,3,0xA,5,0xC}, + {1,1,1,0x12,0,2,2,5,2,0xC}, + {1,1,1,0x26,1,2,3,0xA,4,0xC}, + {1,1,1,0x13,0,2,2,5,2,0xC}, + {1,1,1,0x28,1,2,3,0xA,4,0xC}, + {1,1,1,0x14,0,2,2,5,2,0xC}, + {1,1,1,0x2A,1,2,3,0xB,5,0xC}, + {1,1,1,0x15,0,2,2,6,2,0xC}, + {1,1,1,0x2C,1,2,3,0xB,5,0xC}, + {1,1,1,0x16,0,2,2,6,2,0xC}, + {1,1,1,0x2E,1,2,3,0xC,5,0xC}, + {1,1,1,0x17,0,2,2,6,2,0xC}, + {1,1,1,0x30,1,2,3,0xD,5,0xC}, + {1,1,1,0x18,0,2,2,6,2,0xC}, + {1,1,1,0x32,1,2,3,0xE,6,0xC}, + {1,1,1,0x19,0,2,2,6,2,0xC}, + {1,1,1,0x34,1,1,3,0x7,6,0x6}, + {1,1,1,0x1A,0,2,2,7,2,0xC}, + {1,1,1,0x36,1,1,3,0x7,7,0x6}, + {1,0,0,0x1B,0,2,2,5,2,0x8}, + {1,0,0,0x38,1,2,2,0xA,5,0x8}, + {1,0,1,0x1C,1,2,2,0xA,5,0x8}, + {1,0,1,0x3A,3,1,3,5,3,0x8}, + {1,0,1,0x0E,0,2,2,5,2,0x9}, + {1,0,1,0x3C,3,1,3,5,3,0x8}, + {1,0,1,0x1E,1,1,2,5,5,0x4}, + {1,0,1,0x3E,3,1,3,5,3,0x8}, + {1,0,1,0x0F,0,2,2,5,2,0xA}, + {1,0,1,0x40,3,1,3,5,3,0x8}, + {1,0,1,0x20,1,1,2,6,5,0x4}, + {1,0,1,0x42,3,1,3,6,3,0x8}, + {1,0,1,0x10,0,2,2,6,2,0xA}, + {1,0,1,0x44,3,1,3,6,3,0x8}, + {1,0,1,0x22,1,1,2,6,6,0x4}, + {1,0,1,0x46,3,1,3,6,4,0x8}, + {1,0,1,0x11,0,2,2,5,2,0xA}, + {1,0,1,0x48,3,1,3,6,4,0x8}, + {1,0,1,0x24,1,1,2,6,6,0x4}, + {1,0,1,0x4A,3,1,3,7,4,0x8}, + {1,0,1,0x12,0,2,2,5,2,0xC}, + {1,0,1,0x4C,3,1,3,7,4,0x8}, + {1,0,1,0x26,1,1,2,7,6,0x4}, + {1,0,1,0x4E,3,1,3,7,4,0x8}, + {1,0,1,0x13,0,2,2,5,2,0xC}, +}; + +/* Convert raw divider field to actual division factor */ +static u8 div_factor(u8 raw) +{ + switch (raw) { + case 0: return 1; + case 1: return 2; + case 2: + case 3: return 4; + default: return 4; + } +} + +/* Calculate the MIPI lane data rate (Hz) produced by a PLL configuration */ +static unsigned long mt6589_pll_rate(const struct mt6589_pll_config *cfg) +{ + unsigned int fbk = cfg->fbk_div + 1; + unsigned int fbk_sel = div_factor(cfg->fbk_sel); + unsigned int pre = div_factor(cfg->pre_div); + unsigned int div1 = div_factor(cfg->txdiv0); + unsigned int div2 = div_factor(cfg->txdiv1); + /* + * Lane data rate [Mbps] = 26 * (fbk_div + 1) * fbk_sel * 2 / + * (txdiv0 * txdiv1 * pre_div) + * + * The *2 accounts for DDR (differential) signalling: each clock edge + * carries one bit, so the full bit rate is twice the PLL output clock. + * The downstream LCM_DSI_6589_PLL_CLOCK_* enum values (201.5, 208 ...) + * are HS clock frequencies (half the bit rate); the full lane data rates + * produced by this table are 403, 416 ... Mbps. + */ + unsigned int mbps = 26 * fbk * fbk_sel * 2 / (div1 * div2 * pre); + + return mbps * 1000000UL; +} + +/* Find the table entry whose output rate is closest to the target */ +static const struct mt6589_pll_config *mt6589_pll_find_closest(unsigned long rate_hz) +{ + unsigned long best_diff = ULONG_MAX; + const struct mt6589_pll_config *best = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(pll_config); i++) { + unsigned long r = mt6589_pll_rate(&pll_config[i]); + unsigned long diff = r > rate_hz ? r - rate_hz : rate_hz - r; + + if (diff < best_diff) { + best_diff = diff; + best = &pll_config[i]; + } + } + return best; +} + +/* Program the PLL dividers and analog tuning values */ +static void mt6589_mipi_tx_set_pll(struct mtk_mipi_tx *mipi_tx, + const struct mt6589_pll_config *cfg) +{ + void __iomem *base = mipi_tx->regs; + u32 val; + + /* Assemble PLL_CON0 value without PLL_EN (bit0) */ + val = (cfg->rg_br << 30) | + (cfg->rg_bc << 28) | + (cfg->rg_bp << 24) | + (cfg->rg_bir << 20) | + (cfg->rg_bic << 16) | + (cfg->txdiv1 << 14) | + (cfg->txdiv0 << 12) | + (cfg->fbk_sel << 10) | + (cfg->pre_div << 8) | + (cfg->fbk_div << 1); + + writel(val, base + MIPITX_DSI_PLL_CON0); + /* Now enable the PLL */ + val |= BIT(0); + writel(val, base + MIPITX_DSI_PLL_CON0); +} + +/* --- Clock operations for the PLL --- */ + +static int mt6589_mipi_tx_pll_prepare(struct clk_hw *hw) +{ + struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); + void __iomem *base = mipi_tx->regs; + const struct mt6589_pll_config *cfg; + + cfg = mt6589_pll_find_closest(mipi_tx->data_rate); + if (!cfg) + return -EINVAL; + + dev_dbg(mipi_tx->dev, "PLL prepare: target %lu Hz, selected entry rate %lu Hz\n", + (unsigned long)mipi_tx->data_rate, + (unsigned long)mt6589_pll_rate(cfg)); + + /* Keep the analog PHY under software control while initializing it. */ + mtk_phy_set_bits(base + MIPITX_DSI_SW_CTRL, BIT(0)); + + /* Step 1: Enable bandgap and LDO core */ + mtk_phy_update_bits(base + MIPITX_DSI_BG_CON, 0x3, 0x3); + mtk_phy_update_bits(base + MIPITX_DSI_CON, 0x3, 0x3); + usleep_range(1000, 1100); + usleep_range(1000, 1100); + + /* Step 2: PLL power-up sequence. */ + mtk_phy_update_bits(base + MIPITX_DSI_PLL_PWR, 0x600, 0x400); + mt6589_mipi_tx_set_pll(mipi_tx, cfg); + usleep_range(1000, 1100); + mtk_phy_update_bits(base + MIPITX_DSI_PLL_PWR, 0x600, 0x600); + usleep_range(1000, 1100); + + return 0; +} + +static void mt6589_mipi_tx_pll_unprepare(struct clk_hw *hw) +{ + struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); + void __iomem *base = mipi_tx->regs; + + dev_dbg(mipi_tx->dev, "PLL unprepare\n"); + + /* Make sure the analog block remains under software control. */ + mtk_phy_set_bits(base + MIPITX_DSI_SW_CTRL, BIT(0)); + + /* Power down the PLL block first. */ + mtk_phy_update_bits(base + MIPITX_DSI_PLL_PWR, 0x600, 0); + + /* Restore default divider settings. */ + mtk_phy_update_bits(base + MIPITX_DSI_PLL_CON0, 0xF0FE, 0x26); + + /* Disable PLL */ + mtk_phy_clear_bits(base + MIPITX_DSI_PLL_CON0, BIT(0)); + usleep_range(1000, 1100); + + /* Power down analog blocks. */ + mtk_phy_update_bits(base + MIPITX_DSI_CON, 0x3, 0); + mtk_phy_update_bits(base + MIPITX_DSI_BG_CON, 0x3, 0); + usleep_range(1000, 1100); +} + +static int mt6589_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); + + dev_dbg(mipi_tx->dev, "set rate: %lu Hz\n", rate); + mipi_tx->data_rate = rate; + return 0; +} + +static unsigned long mt6589_mipi_tx_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); + return mipi_tx->data_rate; +} + +static int mt6589_mipi_tx_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + req->rate = clamp_val(req->rate, 50000000, 1250000000); + return 0; +} + +static const struct clk_ops mt6589_mipi_tx_pll_ops = { + .prepare = mt6589_mipi_tx_pll_prepare, + .unprepare = mt6589_mipi_tx_pll_unprepare, + .set_rate = mt6589_mipi_tx_pll_set_rate, + .recalc_rate = mt6589_mipi_tx_pll_recalc_rate, + .determine_rate = mt6589_mipi_tx_pll_determine_rate, +}; + +/* --- PHY signal enable / disable --- */ + +static void mt6589_mipi_tx_power_on_signal(struct phy *phy) +{ + struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); + void __iomem *base = mipi_tx->regs; + + /* Enable LDO output on all data lanes and clock lane */ + mtk_phy_set_bits(base + MIPITX_DSI_LANE0, BIT(0)); + mtk_phy_set_bits(base + MIPITX_DSI_LANE1, BIT(0)); + mtk_phy_set_bits(base + MIPITX_DSI_LANE2, BIT(0)); + mtk_phy_set_bits(base + MIPITX_DSI_LANE3, BIT(0)); + mtk_phy_set_bits(base + MIPITX_DSI_CLK_LANE, BIT(0)); + + /* Enable HS bias */ + mtk_phy_set_bits(base + MIPITX_DSI_TOP_CON, BIT(1)); + usleep_range(1000, 1100); + + /* Clear the downstream TOP_CON bit 11. */ + mtk_phy_clear_bits(base + MIPITX_DSI_TOP_CON, BIT(11)); + + /* Set DP/DN to mark-1 state: first 0x200, then 0x600 */ + writel(0x200, base + MIPITX_DSI_SW_CTRL_CON0); + usleep_range(1000, 1100); + writel(0x600, base + MIPITX_DSI_SW_CTRL_CON0); + usleep_range(1000, 1100); + + /* Return control to DSI host */ + writel(0, base + MIPITX_DSI_SW_CTRL); +} + +static void mt6589_mipi_tx_power_off_signal(struct phy *phy) +{ + struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); + void __iomem *base = mipi_tx->regs; + + /* Clear the software-controlled lane state first. */ + writel(0, base + MIPITX_DSI_SW_CTRL_CON0); + writel(0, base + MIPITX_DSI_SW_CTRL_CON1); + + /* Take software control. */ + writel(1, base + MIPITX_DSI_SW_CTRL); + + /* Match downstream shutdown ordering. */ + mtk_phy_set_bits(base + MIPITX_DSI_TOP_CON, BIT(11)); + + /* Disable all lane LDOs */ + mtk_phy_clear_bits(base + MIPITX_DSI_LANE0, BIT(0)); + mtk_phy_clear_bits(base + MIPITX_DSI_LANE1, BIT(0)); + mtk_phy_clear_bits(base + MIPITX_DSI_LANE2, BIT(0)); + mtk_phy_clear_bits(base + MIPITX_DSI_LANE3, BIT(0)); + mtk_phy_clear_bits(base + MIPITX_DSI_CLK_LANE, BIT(0)); + + /* Disable HS bias */ + mtk_phy_clear_bits(base + MIPITX_DSI_TOP_CON, BIT(1)); + usleep_range(1000, 1100); +} + +/* Platform data exported for binding */ +const struct mtk_mipitx_data mt6589_mipitx_data = { + .mppll_preserve = 0, /* not required? */ + .mipi_tx_clk_ops = &mt6589_mipi_tx_pll_ops, + .mipi_tx_enable_signal = mt6589_mipi_tx_power_on_signal, + .mipi_tx_disable_signal = mt6589_mipi_tx_power_off_signal, +}; +EXPORT_SYMBOL_GPL(mt6589_mipitx_data); + +MODULE_DESCRIPTION("MediaTek MT6589 MIPI TX PHY driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c index 065ea626093aaa..d34f46bdec0efd 100644 --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c @@ -181,6 +181,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) static const struct of_device_id mtk_mipi_tx_match[] = { { .compatible = "mediatek,mt2701-mipi-tx", .data = &mt2701_mipitx_data }, + { .compatible = "mediatek,mt6589-mipi-tx", .data = &mt6589_mipitx_data }, { .compatible = "mediatek,mt8173-mipi-tx", .data = &mt8173_mipitx_data }, { .compatible = "mediatek,mt8183-mipi-tx", .data = &mt8183_mipitx_data }, { /* sentinel */ } diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.h b/drivers/phy/mediatek/phy-mtk-mipi-dsi.h index 5d4876f1dc9509..6589557b258f6c 100644 --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.h +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.h @@ -40,6 +40,7 @@ unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate); extern const struct mtk_mipitx_data mt2701_mipitx_data; +extern const struct mtk_mipitx_data mt6589_mipitx_data; extern const struct mtk_mipitx_data mt8173_mipitx_data; extern const struct mtk_mipitx_data mt8183_mipitx_data; diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index acf5065295072c..67a764be3cecff 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -73,6 +73,9 @@ #define PA6_RG_U2_DISCTH GENMASK(7, 4) #define PA6_RG_U2_SQTH GENMASK(3, 0) +#define U3P_USBPHYACR3 0x01c +#define PA3_RG_USB20_PUPD_BIST_EN BIT(12) + #define U3P_U2PHYACR4 0x020 #define P2C_RG_USB20_GPIO_CTL BIT(9) #define P2C_USB20_GPIO_MODE BIT(8) @@ -87,6 +90,7 @@ #define P2R_RG_U2PLL_FRA_EN BIT(3) #define U3D_U2PHYDCR0 0x060 +#define P2C_RG_USB20_PLL_STABLE BIT(25) #define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24) #define U3P_U2PHYDTM0 0x068 @@ -291,6 +295,8 @@ struct mtk_phy_pdata { bool avoid_rx_sen_degradation; bool sw_pll_48m_to_26m; bool sw_efuse_supported; + /* MT6589 specific wordarounds */ + bool need_mt6589_workaround; u8 slew_ref_clock_mhz; u8 slew_rate_coefficient; enum mtk_phy_version version; @@ -339,6 +345,7 @@ struct mtk_phy_instance { struct mtk_tphy { struct device *dev; void __iomem *sif_base; /* only shared sif */ + void __iomem *legacy_fm_base; /* legacy FM block (e.g., MT6589) */ const struct mtk_phy_pdata *pdata; struct mtk_phy_instance **phys; int nphys; @@ -864,6 +871,37 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy, dev_dbg(tphy->dev, "%s(%d)\n", __func__, index); } +static void mt6589_u2_phy_recover(struct mtk_tphy *tphy, + struct mtk_phy_instance *instance) +{ + struct u2phy_banks *u2_banks = &instance->u2_banks; + void __iomem *com = u2_banks->com; + + /* PUPD_BIST_EN clear (PMIC charger detection) */ + mtk_phy_clear_bits(com + U3P_USBPHYACR3, PA3_RG_USB20_PUPD_BIST_EN); + + /* Clear UART force and normal bits to ensure USB function */ + mtk_phy_clear_bits(com + U3P_U2PHYDTM0, P2C_FORCE_UART_EN); + mtk_phy_clear_bits(com + U3P_U2PHYDTM1, P2C_RG_UART_EN); + + /* Release force suspendm */ + mtk_phy_clear_bits(com + U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM); + + /* Clear all previously forced pull/termination/xcvr settings */ + mtk_phy_clear_bits(com + U3P_U2PHYDTM0, + P2C_RG_DMPULLDOWN | P2C_RG_DPPULLDOWN | + P2C_RG_XCVRSEL | P2C_RG_TERMSEL | P2C_RG_DATAIN | + P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | + P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | + P2C_FORCE_TERMSEL | P2C_FORCE_SUSPENDM); + + /* BC1.2 disable, OTG VBUS comparator enable */ + mtk_phy_clear_bits(com + U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN); + mtk_phy_set_bits(com + U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN); + + udelay(800); +} + static void u2_phy_instance_power_on(struct mtk_tphy *tphy, struct mtk_phy_instance *instance) { @@ -878,14 +916,61 @@ static void u2_phy_instance_power_on(struct mtk_tphy *tphy, mtk_phy_clear_bits(com + U3P_U2PHYDTM1, P2C_RG_SESSEND); + if (tphy->pdata->need_mt6589_workaround) + mt6589_u2_phy_recover(tphy, instance); + if (tphy->pdata->avoid_rx_sen_degradation && index) { mtk_phy_set_bits(com + U3D_U2PHYDCR0, P2C_RG_SIF_U2PLL_FORCE_ON); mtk_phy_set_bits(com + U3P_U2PHYDTM0, P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM); } + dev_dbg(tphy->dev, "%s(%d)\n", __func__, index); } +static void mt6589_u2_phy_savecurrent(struct mtk_tphy *tphy, + struct mtk_phy_instance *instance) +{ + struct u2phy_banks *u2_banks = &instance->u2_banks; + void __iomem *com = u2_banks->com; + + /* Ensure UART off */ + mtk_phy_clear_bits(com + U3P_U2PHYDTM0, P2C_FORCE_UART_EN); + mtk_phy_clear_bits(com + U3P_U2PHYDTM1, P2C_RG_UART_EN); + + /* Release force suspendm briefly to configure pulldowns */ + mtk_phy_clear_bits(com + U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM); + + /* Set DP/DM pulldowns, XCVRSEL=01, TERMSEL=1, clear DATAIN */ + u32 tm0 = readl(com + U3P_U2PHYDTM0); + tm0 |= P2C_RG_DMPULLDOWN | P2C_RG_DPPULLDOWN; + tm0 &= ~P2C_RG_XCVRSEL; + tm0 |= FIELD_PREP(P2C_RG_XCVRSEL, 1); /* 01 */ + tm0 |= P2C_RG_TERMSEL; + tm0 &= ~P2C_RG_DATAIN; + writel(tm0, com + U3P_U2PHYDTM0); + + /* Force DP/DM pulldown, XCVRSEL, TERMSEL, DATAIN */ + mtk_phy_set_bits(com + U3P_U2PHYDTM0, + P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | + P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | + P2C_FORCE_TERMSEL); + + /* Disable BC1.2 and OTG VBUS comparator */ + mtk_phy_clear_bits(com + U3P_USBPHYACR6, + PA6_RG_U2_BC11_SW_EN | PA6_RG_U2_OTG_VBUSCMP_EN); + + udelay(800); + + /* Set PLL stable bit (U3D_U2PHYDCR0 bit25) */ + mtk_phy_set_bits(com + U3D_U2PHYDCR0, P2C_RG_USB20_PLL_STABLE); + udelay(1); + + /* Assert force suspendm to enter low power */ + mtk_phy_set_bits(com + U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM); + udelay(1); +} + static void u2_phy_instance_power_off(struct mtk_tphy *tphy, struct mtk_phy_instance *instance) { @@ -906,6 +991,9 @@ static void u2_phy_instance_power_off(struct mtk_tphy *tphy, mtk_phy_clear_bits(com + U3D_U2PHYDCR0, P2C_RG_SIF_U2PLL_FORCE_ON); } + if (tphy->pdata->need_mt6589_workaround) + mt6589_u2_phy_savecurrent(tphy, instance); + dev_dbg(tphy->dev, "%s(%d)\n", __func__, index); } @@ -1077,7 +1165,10 @@ static void phy_v1_banks_init(struct mtk_tphy *tphy, switch (instance->type) { case PHY_TYPE_USB2: u2_banks->misc = NULL; - u2_banks->fmreg = tphy->sif_base + SSUSB_SIFSLV_V1_U2FREQ; + if (tphy->legacy_fm_base) + u2_banks->fmreg = tphy->legacy_fm_base; + else + u2_banks->fmreg = tphy->sif_base + SSUSB_SIFSLV_V1_U2FREQ; u2_banks->com = instance->port_base + SSUSB_SIFSLV_V1_U2PHY_COM; break; case PHY_TYPE_USB3: @@ -1538,6 +1629,13 @@ static const struct mtk_phy_pdata tphy_v3_pdata = { .version = MTK_PHY_V3, }; +static const struct mtk_phy_pdata mt6589_pdata = { + .slew_ref_clock_mhz = 48, + .slew_rate_coefficient = 22, + .need_mt6589_workaround = true, + .version = MTK_PHY_V1, +}; + static const struct mtk_phy_pdata mt8173_pdata = { .avoid_rx_sen_degradation = true, .slew_ref_clock_mhz = 26, @@ -1554,6 +1652,7 @@ static const struct mtk_phy_pdata mt8195_pdata = { static const struct of_device_id mtk_tphy_id_table[] = { { .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata }, { .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata }, + { .compatible = "mediatek,mt6589-tphy", .data = &mt6589_pdata }, { .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata }, { .compatible = "mediatek,mt8195-tphy", .data = &mt8195_pdata }, { .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata }, @@ -1568,7 +1667,7 @@ static int mtk_tphy_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct phy_provider *provider; - struct resource *sif_res; + struct resource *sif_res, *fm_res; struct mtk_tphy *tphy; struct resource res; int port, ret; @@ -1601,6 +1700,13 @@ static int mtk_tphy_probe(struct platform_device *pdev) } } + fm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "legacy-fm"); + if (fm_res) { + tphy->legacy_fm_base = devm_ioremap_resource(dev, fm_res); + if (IS_ERR(tphy->legacy_fm_base)) + return PTR_ERR(tphy->legacy_fm_base); + } + /* Optional properties for slew calibration variation */ ret = device_property_read_u32(dev, "mediatek,src-ref-clk-mhz", &tphy->src_ref_clk); if (ret) diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 4819617d936836..7df3e98342925d 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -97,6 +97,13 @@ config PINCTRL_MT2701 default MACH_MT2701 select PINCTRL_MTK +config PINCTRL_MT6589 + tristate "MediaTek MT6589 pin control" + depends on MACH_MT6589 || COMPILE_TEST + depends on OF + default MACH_MT6589 + select PINCTRL_MTK_PARIS + config PINCTRL_MT7623 bool "MediaTek MT7623 pin control with generic binding" depends on MACH_MT7623 || COMPILE_TEST @@ -322,6 +329,13 @@ config PINCTRL_MT8516 select PINCTRL_MTK # For PMIC +config PINCTRL_MT6320 + bool "MediaTek MT6320 pin control" + depends on MFD_MT6397 || COMPILE_TEST + depends on OF + default MFD_MT6397 + select PINCTRL_MTK + config PINCTRL_MT6397 bool "MediaTek MT6397 pin control" depends on MFD_MT6397 || COMPILE_TEST diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index ae765bd999657c..4f305a2c15fa8b 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_RT305X) += pinctrl-rt305x.o obj-$(CONFIG_PINCTRL_RT3883) += pinctrl-rt3883.o obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o obj-$(CONFIG_PINCTRL_MT2712) += pinctrl-mt2712.o +obj-$(CONFIG_PINCTRL_MT6589) += pinctrl-mt6589.o obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o obj-$(CONFIG_PINCTRL_MT6765) += pinctrl-mt6765.o @@ -42,4 +43,5 @@ obj-$(CONFIG_PINCTRL_MT8195) += pinctrl-mt8195.o obj-$(CONFIG_PINCTRL_MT8196) += pinctrl-mt8196.o obj-$(CONFIG_PINCTRL_MT8365) += pinctrl-mt8365.o obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o +obj-$(CONFIG_PINCTRL_MT6320) += pinctrl-mt6320.o obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6320.c b/drivers/pinctrl/mediatek/pinctrl-mt6320.c new file mode 100644 index 00000000000000..319190676ad4f4 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mt6320.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Hongzhou.Yang + * + * Copyright (c) 2026 Akari Tsuyukusa + * + * MediaTek MT6320 PMIC Pinctrl Driver based on pinctrl-mt6397.c + */ + +#include +#include +#include +#include +#include +#include + +#include "pinctrl-mtk-common.h" +#include "pinctrl-mtk-mt6320.h" + +#define MT6320_PIN_REG_BASE 0xc000 + +static const struct mtk_pinctrl_devdata mt6320_pinctrl_data = { + .pins = mtk_pins_mt6320, + .npins = ARRAY_SIZE(mtk_pins_mt6320), + .dir_offset = (MT6320_PIN_REG_BASE + 0x000), + .ies_offset = MTK_PINCTRL_NOT_SUPPORT, + .smt_offset = MTK_PINCTRL_NOT_SUPPORT, + .pullen_offset = (MT6320_PIN_REG_BASE + 0x020), + .pullsel_offset = (MT6320_PIN_REG_BASE + 0x040), + .dout_offset = (MT6320_PIN_REG_BASE + 0x080), + .din_offset = (MT6320_PIN_REG_BASE + 0x0a0), + .pinmux_offset = (MT6320_PIN_REG_BASE + 0x0c0), + .type1_start = 49, + .type1_end = 49, + .port_shf = 3, + .port_mask = 0x3, + .port_align = 2, + .mode_mask = 0xf, + .mode_per_reg = 5, + .mode_shf = 4, +}; + +static int mt6320_pinctrl_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6320; + + mt6320 = dev_get_drvdata(pdev->dev.parent); + return mtk_pctrl_init(pdev, &mt6320_pinctrl_data, mt6320->regmap); +} + +static const struct of_device_id mt6320_pctrl_match[] = { + { .compatible = "mediatek,mt6320-pinctrl", }, + { }, +}; + +static struct platform_driver mtk_pinctrl_driver = { + .probe = mt6320_pinctrl_probe, + .driver = { + .name = "mediatek-mt6320-pinctrl", + .of_match_table = mt6320_pctrl_match, + }, +}; + +builtin_platform_driver(mtk_pinctrl_driver); diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6589.c b/drivers/pinctrl/mediatek/pinctrl-mt6589.c new file mode 100644 index 00000000000000..3d5b2af5b7ddc7 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mt6589.c @@ -0,0 +1,657 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) Akari Tsuyukusa + */ + +#include "pinctrl-paris.h" +#include "pinctrl-mtk-mt6589.h" + +/* GPIO0 */ +#define DRV_CON0 0x0500 +#define DRV_CON1 0x0510 +#define DRV_CON2 0x0520 +#define DRV_CON3 0x0530 +#define DRV_CON4 0x0540 +#define DRV_CON5 0x0550 + +/* GPIO1 */ +#define DRV_CON6 0x0560 +#define DRV_CON7 0x0570 +#define DRV_CON8 0x0580 +#define DRV_CON9 0x0590 + +/* GPIO0 */ +#define DRV_CON10 0x05a0 +#define DRV_CON11 0x05b0 +#define DRV_CON12 0x05c0 + +/* for 2nd base */ +#define PINS_FIELD1(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \ + PIN_FIELD_CALC(_s_pin, _e_pin, 1, _s_addr, _x_addrs, _s_bit, \ + _x_bits, 32, 1) + +/* all R0 are in one register */ +#define PIN_FIELD_R0(_bit, _pin) \ + PIN_FIELD_CALC(_pin, _pin, 0, 0x04f0, 0x0, _bit, 1, 32, 1) + +/* + * MT6589's Drive/Slew Rate register + * + * E2, E4, E8, E16: Drive + * SR: Slew Rate + * DM: Dummy + * MSB <-> LSB + * + * DRV_GRP1: SR E8 E4 DM : 4/8/12/16mA + * DRV_GRP3: SR E4 E2 DM : 2/4/6/8mA + * DRV_GRP4: SR E8 E4 E2 : 2/4/6/8/10/12/14/16mA + * DRV_GRP5: SR E16 E8 E4 : 4/8/12/16/20/24/28/32mA + */ + +#define PIN_FIELD_SR(_pin, _offset, _bit, _base) \ + PIN_FIELD_CALC(_pin, _pin, _base, _offset, 0x0, _bit, 1, 32, 1) + +#define PINS_FIELD_SR(_pin_s, _pin_e, _offset, _bit, _base) \ + PIN_FIELD_CALC(_pin_s, _pin_e, _base, _offset, 0x0, _bit, 1, 32, 1) + +#define PIN_FIELD_DRV(_pin, _offset, _bit, _base) \ + PIN_FIELD_CALC(_pin, _pin, _base, _offset, 0x0, _bit, 3, 32, 1) + +#define PINS_FIELD_DRV(_pin_s, _pin_e, _offset, _bit, _base) \ + PIN_FIELD_CALC(_pin_s, _pin_e, _base, _offset, 0x0, _bit, 3, 32, 1) + +static const struct mtk_pin_field_calc mt6589_pin_mode_range[] = { + PIN_FIELD_CALC(0, 43, 0, 0x0c00, 0x10, 0, 3, 15, 0), + PIN_FIELD_CALC(44, 46, 0, 0x0980, 0x10, 0, 4, 16, 0), + PIN_FIELD_CALC(47, 49, 0, 0x09a0, 0x10, 0, 4, 16, 0), + PIN_FIELD_CALC(50, 231, 0, 0x0ca0, 0x10, 0, 3, 15, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_dir_range[] = { + PIN_FIELD_CALC(0, 231, 0, 0x0000, 0x10, 0, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_di_range[] = { + PIN_FIELD_CALC(0, 231, 0, 0x0a00, 0x10, 0, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_do_range[] = { + PIN_FIELD_CALC(0, 231, 0, 0x0800, 0x10, 0, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_sr_range[] = { + /* MSDC0_DAT 7 to 4 */ + PINS_FIELD_SR(0, 3, DRV_CON0, 3, 0), + + /* MSDC0_RSTB */ + PIN_FIELD_SR(4, DRV_CON0, 11, 0), + + /* MSDC0_CMD */ + PIN_FIELD_SR(5, DRV_CON0, 7, 0), + + /* MSDC0_CLK */ + PIN_FIELD_SR(6, DRV_CON12, 15, 0), + + /* MSDC0_DAT 3 to 0 */ + PINS_FIELD_SR(7, 10, DRV_CON0, 3, 0), + + /* NFI */ + PINS_FIELD_SR(11, 17, DRV_CON0, 15, 0), + + /* NLD 0 to 15 */ + PINS_FIELD_SR(18, 25, DRV_CON0, 19, 0), + PINS_FIELD_SR(26, 33, DRV_CON0, 23, 0), + + /* EINT 0 to 4 */ + PIN_FIELD_SR(34, DRV_CON0, 27, 0), + PIN_FIELD_SR(35, DRV_CON0, 31, 0), + PIN_FIELD_SR(36, DRV_CON1, 3, 0), + PIN_FIELD_SR(37, DRV_CON1, 7, 0), + PIN_FIELD_SR(38, DRV_CON1, 11, 0), + + /* SPI0 */ + PINS_FIELD_SR(39, 43, DRV_CON1, 15, 0), + + /* SIM */ + PINS_FIELD_SR(44, 49, DRV_CON1, 19, 0), + + /* ADC */ + PINS_FIELD_SR(50, 52, DRV_CON1, 23, 0), + + /* DAC */ + PINS_FIELD_SR(53, 55, DRV_CON1, 27, 0), + + /* RTC32K_CK */ + /* + PIN_FIELD_SR(56, , , 0), // no drive? + */ + + /* IDDIG */ + PIN_FIELD_SR(57, DRV_CON1, 31, 0), + + /* WATCHDOG */ + PIN_FIELD_SR(58, DRV_CON2, 3, 0), + + /* SRCLKENA */ + PIN_FIELD_SR(59, DRV_CON2, 7, 0), + + /* SRCVOLTEN */ + PIN_FIELD_SR(60, DRV_CON2, 11, 0), + + /* JTAG */ + PINS_FIELD_SR(61, 66, DRV_CON3, 3, 0), + + /* UR2 */ + PIN_FIELD_SR(69, DRV_CON3, 7, 0), + PIN_FIELD_SR(70, DRV_CON3, 11, 0), + PIN_FIELD_SR(71, DRV_CON3, 15, 0), + PIN_FIELD_SR(72, DRV_CON3, 19, 0), + + /* PWM 1 to 4 */ + PIN_FIELD_SR(73, DRV_CON3, 23, 0), + PIN_FIELD_SR(74, DRV_CON3, 27, 0), + PIN_FIELD_SR(75, DRV_CON3, 31, 0), + PIN_FIELD_SR(76, DRV_CON4, 3, 0), + + /* UR1 */ + PIN_FIELD_SR(77, DRV_CON4, 7, 0), + PIN_FIELD_SR(78, DRV_CON4, 11, 0), + PIN_FIELD_SR(79, DRV_CON4, 15, 0), + PIN_FIELD_SR(80, DRV_CON4, 19, 0), + + /* UR4 */ + PIN_FIELD_SR(81, DRV_CON4, 23, 0), + PIN_FIELD_SR(82, DRV_CON4, 27, 0), + + /* BPI1B */ + PINS_FIELD_SR(83, 99, DRV_CON5, 15, 0), + + /* VM 1, 0 */ + PINS_FIELD_SR(100, 101, DRV_CON5, 15, 0), + + /* BSI 1 */ + PINS_FIELD_SR(102, 104, DRV_CON5, 19, 0), + + /* TXBPI1 */ + PIN_FIELD_SR(105, DRV_CON5, 23, 0), + + /* EXT_CLK_EN */ + PIN_FIELD_SR(106, DRV_CON4, 31, 0), + + /* SRCLKENA2 */ + PIN_FIELD_SR(107, DRV_CON5, 3, 0), + + /* BSI1A */ + PINS_FIELD_SR(108, 112, DRV_CON5, 7, 0), + + /* BSI1C */ + PINS_FIELD_SR(113, 114, DRV_CON5, 11, 0), + + /* EINT10_AUXIN2, EINT11_AUXIN3, EINT16_AUXIN3 */ + PIN_FIELD_SR(115, DRV_CON6, 3, 1), + PIN_FIELD_SR(116, DRV_CON6, 7, 1), + PIN_FIELD_SR(117, DRV_CON6, 11, 1), + + /* I2S */ + PINS_FIELD_SR(120, 123, DRV_CON6, 15, 1), + + /* EINT 5 to 9 */ + PIN_FIELD_SR(124, DRV_CON6, 19, 1), + PIN_FIELD_SR(125, DRV_CON6, 23, 1), + PIN_FIELD_SR(126, DRV_CON6, 27, 1), + PIN_FIELD_SR(127, DRV_CON6, 31, 1), + PIN_FIELD_SR(128, DRV_CON7, 3, 1), + + /* DISP_PWM */ + PIN_FIELD_SR(129, DRV_CON7, 31, 1), + + /* LPTE/MSDC4_DAT0, LRSTB/MSDC4_DAT1 */ + PINS_FIELD_SR(130, 131, DRV_CON8, 23, 1), + + /* LPCE1B, LPCE0B */ + PIN_FIELD_SR(132, DRV_CON8, 31, 1), + PIN_FIELD_SR(133, DRV_CON9, 3, 1), + + /* SPI1 / MSDC4 */ + PINS_FIELD_SR(134, 137, DRV_CON8, 23, 1), + + /* LCD / MSDC4 */ + PIN_FIELD_SR(138, DRV_CON8, 23, 1), + PIN_FIELD_SR(139, DRV_CON8, 3, 1), + PIN_FIELD_SR(140, DRV_CON8, 23, 1), + PIN_FIELD_SR(141, DRV_CON7, 19, 1), + PIN_FIELD_SR(142, DRV_CON7, 23, 1), + + /* DPI */ + PINS_FIELD_SR(143, 146, DRV_CON9, 11, 1), + PINS_FIELD_SR(147, 154, DRV_CON9, 15, 1), + PINS_FIELD_SR(155, 162, DRV_CON9, 19, 1), + PINS_FIELD_SR(163, 170, DRV_CON9, 23, 1), + + /* MSDC1_INSI, MSDC2_INSI */ + PIN_FIELD_SR(171, DRV_CON9, 27, 1), + PIN_FIELD_SR(172, DRV_CON10, 3, 0), + + /* MSDC2 */ + PIN_FIELD_SR(173, DRV_CON10, 7, 0), + PINS_FIELD_SR(174, 175, DRV_CON10, 11, 0), + PIN_FIELD_SR(176, DRV_CON10, 15, 0), + PIN_FIELD_SR(177, DRV_CON12, 23, 0), + PINS_FIELD_SR(178, 179, DRV_CON10, 11, 0), + + /* MSDC1 */ + PINS_FIELD_SR(180, 181, DRV_CON10, 23, 0), + PIN_FIELD_SR(182, DRV_CON10, 19, 0), + PIN_FIELD_SR(183, DRV_CON10, 27, 0), + PIN_FIELD_SR(184, DRV_CON12, 19, 0), + PINS_FIELD_SR(185, 186, DRV_CON10, 23, 0), + + /* CMPCLK, CMMCLK, CMRST, CMPDN, CMFLASH */ + PIN_FIELD_SR(209, DRV_CON11, 3, 0), + PIN_FIELD_SR(210, DRV_CON11, 7, 0), + PIN_FIELD_SR(211, DRV_CON11, 11, 0), + PIN_FIELD_SR(212, DRV_CON11, 15, 0), + PIN_FIELD_SR(213, DRV_CON11, 19, 0), + + /* SRCLKENAI */ + PIN_FIELD_SR(218, DRV_CON11, 23, 0), + + /* UR3 */ + PIN_FIELD_SR(219, DRV_CON11, 27, 0), + PIN_FIELD_SR(220, DRV_CON11, 31, 0), + + /* PCM0 */ + PINS_FIELD_SR(221, 225, DRV_CON12, 3, 0), + + /* MSDC3 */ + PINS_FIELD_SR(226, 227, DRV_CON12, 7, 0), + PIN_FIELD_SR(228, DRV_CON12, 11, 0), + PIN_FIELD_SR(229, DRV_CON12, 27, 0), + PINS_FIELD_SR(230, 231, DRV_CON12, 7, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_smt_range[] = { + PIN_FIELD_CALC(0, 113, 0, 0x0300, 0x10, 0, 1, 16, 0), + PIN_FIELD_CALC(114, 169, 1, 0x0370, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(170, 231, 0, 0x03a0, 0x10, 10, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_drv_range[] = { + /* MSDC0_DAT 7 to 4 */ + PINS_FIELD_DRV(0, 3, DRV_CON0, 0, 0), + + /* MSDC0_RSTB */ + PIN_FIELD_DRV(4, DRV_CON0, 8, 0), + + /* MSDC0_CMD */ + PIN_FIELD_DRV(5, DRV_CON0, 4, 0), + + /* MSDC0_CLK */ + PIN_FIELD_DRV(6, DRV_CON12, 12, 0), + + /* MSDC0_DAT 3 to 0 */ + PINS_FIELD_DRV(7, 10, DRV_CON0, 0, 0), + + /* NFI */ + PINS_FIELD_DRV(11, 17, DRV_CON0, 12, 0), + + /* NLD 0 to 15 */ + PINS_FIELD_DRV(18, 25, DRV_CON0, 16, 0), + PINS_FIELD_DRV(26, 33, DRV_CON0, 20, 0), + + /* EINT 0 to 4 */ + PIN_FIELD_DRV(34, DRV_CON0, 24, 0), + PIN_FIELD_DRV(35, DRV_CON0, 28, 0), + PIN_FIELD_DRV(36, DRV_CON1, 0, 0), + PIN_FIELD_DRV(37, DRV_CON1, 4, 0), + PIN_FIELD_DRV(38, DRV_CON1, 8, 0), + + /* SPI0 */ + PINS_FIELD_DRV(39, 43, DRV_CON1, 12, 0), + + /* SIM */ + PINS_FIELD_DRV(44, 49, DRV_CON1, 16, 0), + + /* ADC */ + PINS_FIELD_DRV(50, 52, DRV_CON1, 20, 0), + + /* DAC */ + PINS_FIELD_DRV(53, 55, DRV_CON1, 24, 0), + + /* RTC32K_CK */ + /* + PIN_FIELD_DRV(56, , , 0), // no drive? + */ + + /* IDDIG */ + PIN_FIELD_DRV(57, DRV_CON1, 28, 0), + + /* WATCHDOG */ + PIN_FIELD_DRV(58, DRV_CON2, 0, 0), + + /* SRCLKENA */ + PIN_FIELD_DRV(59, DRV_CON2, 4, 0), + + /* SRCVOLTEN */ + PIN_FIELD_DRV(60, DRV_CON2, 8, 0), + + /* JTAG */ + PINS_FIELD_DRV(61, 66, DRV_CON3, 0, 0), + + /* UR2 */ + PIN_FIELD_DRV(69, DRV_CON3, 4, 0), + PIN_FIELD_DRV(70, DRV_CON3, 8, 0), + PIN_FIELD_DRV(71, DRV_CON3, 12, 0), + PIN_FIELD_DRV(72, DRV_CON3, 16, 0), + + /* PWM 1 to 4 */ + PIN_FIELD_DRV(73, DRV_CON3, 20, 0), + PIN_FIELD_DRV(74, DRV_CON3, 24, 0), + PIN_FIELD_DRV(75, DRV_CON3, 28, 0), + PIN_FIELD_DRV(76, DRV_CON4, 0, 0), + + /* UR1 */ + PIN_FIELD_DRV(77, DRV_CON4, 4, 0), + PIN_FIELD_DRV(78, DRV_CON4, 8, 0), + PIN_FIELD_DRV(79, DRV_CON4, 12, 0), + PIN_FIELD_DRV(80, DRV_CON4, 16, 0), + + /* UR4 */ + PIN_FIELD_DRV(81, DRV_CON4, 20, 0), + PIN_FIELD_DRV(82, DRV_CON4, 24, 0), + + /* BPI1B */ + PINS_FIELD_DRV(83, 99, DRV_CON5, 12, 0), + + /* VM 1, 0 */ + PINS_FIELD_DRV(100, 101, DRV_CON5, 12, 0), + + /* BSI 1 */ + PINS_FIELD_DRV(102, 104, DRV_CON5, 16, 0), + + /* TXBPI1 */ + PIN_FIELD_DRV(105, DRV_CON5, 20, 0), + + /* EXT_CLK_EN */ + PIN_FIELD_DRV(106, DRV_CON4, 28, 0), + + /* SRCLKENA2 */ + PIN_FIELD_DRV(107, DRV_CON5, 0, 0), + + /* BSI1A */ + PINS_FIELD_DRV(108, 112, DRV_CON5, 4, 0), + + /* BSI1C */ + PINS_FIELD_DRV(113, 114, DRV_CON5, 8, 0), + + /* EINT10_AUXIN2, EINT11_AUXIN3, EINT16_AUXIN3 */ + PIN_FIELD_DRV(115, DRV_CON6, 0, 1), + PIN_FIELD_DRV(116, DRV_CON6, 4, 1), + PIN_FIELD_DRV(117, DRV_CON6, 8, 1), + + /* I2S */ + PINS_FIELD_DRV(120, 123, DRV_CON6, 12, 1), + + /* EINT 5 to 9 */ + PIN_FIELD_DRV(124, DRV_CON6, 16, 1), + PIN_FIELD_DRV(125, DRV_CON6, 20, 1), + PIN_FIELD_DRV(126, DRV_CON6, 24, 1), + PIN_FIELD_DRV(127, DRV_CON6, 28, 1), + PIN_FIELD_DRV(128, DRV_CON7, 0, 1), + + /* DISP_PWM */ + PIN_FIELD_DRV(129, DRV_CON7, 28, 1), + + /* LPTE/MSDC4_DAT0, LRSTB/MSDC4_DAT1 */ + PINS_FIELD_DRV(130, 131, DRV_CON8, 20, 1), + + /* LPCE1B, LPCE0B */ + PIN_FIELD_DRV(132, DRV_CON8, 28, 1), + PIN_FIELD_DRV(133, DRV_CON9, 0, 1), + + /* SPI1 / MSDC4 */ + PINS_FIELD_DRV(134, 137, DRV_CON8, 20, 1), + + /* LCD / MSDC4 */ + PIN_FIELD_DRV(138, DRV_CON8, 20, 1), + PIN_FIELD_DRV(139, DRV_CON8, 0, 1), + PIN_FIELD_DRV(140, DRV_CON8, 20, 1), + PIN_FIELD_DRV(141, DRV_CON7, 16, 1), + PIN_FIELD_DRV(142, DRV_CON7, 20, 1), + + /* DPI */ + PINS_FIELD_DRV(143, 146, DRV_CON9, 8, 1), + PINS_FIELD_DRV(147, 154, DRV_CON9, 12, 1), + PINS_FIELD_DRV(155, 162, DRV_CON9, 16, 1), + PINS_FIELD_DRV(163, 170, DRV_CON9, 20, 1), + + /* MSDC1_INSI, MSDC2_INSI */ + PIN_FIELD_DRV(171, DRV_CON9, 24, 1), + PIN_FIELD_DRV(172, DRV_CON10, 0, 0), + + /* MSDC2 */ + PIN_FIELD_DRV(173, DRV_CON10, 4, 0), + PINS_FIELD_DRV(174, 175, DRV_CON10, 8, 0), + PIN_FIELD_DRV(176, DRV_CON10, 12, 0), + PIN_FIELD_DRV(177, DRV_CON12, 20, 0), + PINS_FIELD_DRV(178, 179, DRV_CON10, 8, 0), + + /* MSDC1 */ + PINS_FIELD_DRV(180, 181, DRV_CON10, 20, 0), + PIN_FIELD_DRV(182, DRV_CON10, 16, 0), + PIN_FIELD_DRV(183, DRV_CON10, 24, 0), + PIN_FIELD_DRV(184, DRV_CON12, 16, 0), + PINS_FIELD_DRV(185, 186, DRV_CON10, 20, 0), + + /* CMPCLK, CMMCLK, CMRST, CMPDN, CMFLASH */ + PIN_FIELD_DRV(209, DRV_CON11, 0, 0), + PIN_FIELD_DRV(210, DRV_CON11, 4, 0), + PIN_FIELD_DRV(211, DRV_CON11, 8, 0), + PIN_FIELD_DRV(212, DRV_CON11, 12, 0), + PIN_FIELD_DRV(213, DRV_CON11, 16, 0), + + /* SRCLKENAI */ + PIN_FIELD_DRV(218, DRV_CON11, 20, 0), + + /* UR3 */ + PIN_FIELD_DRV(219, DRV_CON11, 24, 0), + PIN_FIELD_DRV(220, DRV_CON11, 28, 0), + + /* PCM0 */ + PINS_FIELD_DRV(221, 225, DRV_CON12, 0, 0), + + /* MSDC3 */ + PINS_FIELD_DRV(226, 227, DRV_CON12, 4, 0), + PIN_FIELD_DRV(228, DRV_CON12, 8, 0), + PIN_FIELD_DRV(229, DRV_CON12, 24, 0), + PINS_FIELD_DRV(230, 231, DRV_CON12, 4, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_r0_range[] = { + PIN_FIELD_R0(9, 0), + PIN_FIELD_R0(8, 1), + PIN_FIELD_R0(7, 2), + PIN_FIELD_R0(6, 3), + PIN_FIELD_R0(1, 5), + PIN_FIELD_R0(0, 6), + PIN_FIELD_R0(5, 7), + PIN_FIELD_R0(4, 8), + PIN_FIELD_R0(3, 9), + PIN_FIELD_R0(2, 10), + + PIN_FIELD_R0(18, 130), + PIN_FIELD_R0(19, 131), + PIN_FIELD_R0(23, 134), + PIN_FIELD_R0(24, 135), + PIN_FIELD_R0(25, 136), + PIN_FIELD_R0(22, 137), + PIN_FIELD_R0(20, 138), + PIN_FIELD_R0(16, 139), + PIN_FIELD_R0(21, 140), + PIN_FIELD_R0(17, 141), + + PIN_FIELD_R0(14, 226), + PIN_FIELD_R0(15, 227), + PIN_FIELD_R0(11, 228), + PIN_FIELD_R0(10, 229), + PIN_FIELD_R0(13, 230), + PIN_FIELD_R0(12, 231), +}; + +static const struct mtk_pin_field_calc mt6589_pin_r1_range[] = { + PIN_FIELD_CALC(0, 3, 0, 0x0200, 0x10, 0, 1, 16, 0), + PIN_FIELD_CALC(5, 10, 0, 0x0200, 0x10, 5, 1, 16, 0), + PIN_FIELD_CALC(130, 131, 1, 0x0280, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(134, 141, 1, 0x0280, 0x10, 6, 1, 16, 0), + PIN_FIELD_CALC(226, 231, 0, 0x02e0, 0x10, 2, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_pupd_range[] = { + PIN_FIELD_CALC(0, 3, 0, 0x0400, 0x10, 0, 1, 16, 0), + PIN_FIELD_CALC(5, 10, 0, 0x0400, 0x10, 5, 1, 16, 0), + PIN_FIELD_CALC(130, 131, 1, 0x0480, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(134, 141, 1, 0x0480, 0x10, 6, 1, 16, 0), + PIN_FIELD_CALC(226, 231, 0, 0x04e0, 0x10, 2, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_ies_range[] = { + PIN_FIELD_CALC(0, 113, 0, 0x0100, 0x10, 0, 1, 16, 0), + PIN_FIELD_CALC(114, 169, 1, 0x0170, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(170, 231, 0, 0x01a0, 0x10, 10, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_pullen_range[] = { + PIN_FIELD_CALC(4, 4, 0, 0x0200, 0x10, 4, 1, 16, 0), + PIN_FIELD_CALC(11, 43, 0, 0x0200, 0x10, 11, 1, 16, 0), + PIN_FIELD_CALC(44, 46, 0, 0x0990, 0x0, 4, 1, 16, 0), + PIN_FIELD_CALC(47, 49, 0, 0x09b0, 0x0, 4, 1, 16, 0), + PIN_FIELD_CALC(50, 113, 0, 0x0230, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(114, 129, 1, 0x0270, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(132, 133, 1, 0x0280, 0x10, 4, 1, 16, 0), + PIN_FIELD_CALC(142, 169, 1, 0x0280, 0x10, 14, 1, 16, 0), + PIN_FIELD_CALC(170, 225, 0, 0x02a0, 0x10, 10, 1, 16, 0), +}; + +static const struct mtk_pin_field_calc mt6589_pin_pullsel_range[] = { + PIN_FIELD_CALC(4, 4, 0, 0x0400, 0x10, 4, 1, 16, 0), + PIN_FIELD_CALC(11, 43, 0, 0x0400, 0x10, 11, 1, 16, 0), + PIN_FIELD_CALC(44, 46, 0, 0x0990, 0x0, 8, 1, 16, 0), + PIN_FIELD_CALC(47, 49, 0, 0x09b0, 0x0, 8, 1, 16, 0), + PIN_FIELD_CALC(50, 113, 0, 0x0430, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(114, 129, 1, 0x0470, 0x10, 2, 1, 16, 0), + PIN_FIELD_CALC(132, 133, 1, 0x0480, 0x10, 4, 1, 16, 0), + PIN_FIELD_CALC(142, 169, 1, 0x0480, 0x10, 14, 1, 16, 0), + PIN_FIELD_CALC(170, 225, 0, 0x04a0, 0x10, 10, 1, 16, 0), +}; + +static const struct mtk_pin_reg_calc mt6589_reg_cals[PINCTRL_PIN_REG_MAX] = { + [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt6589_pin_mode_range), + [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt6589_pin_dir_range), + [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt6589_pin_di_range), + [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt6589_pin_do_range), + [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt6589_pin_sr_range), + [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt6589_pin_smt_range), + [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt6589_pin_drv_range), + [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt6589_pin_r0_range), + [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt6589_pin_r1_range), + [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt6589_pin_pupd_range), + [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt6589_pin_ies_range), + [PINCTRL_PIN_REG_PULLEN] = MTK_RANGE(mt6589_pin_pullen_range), + [PINCTRL_PIN_REG_PULLSEL] = MTK_RANGE(mt6589_pin_pullsel_range), +}; + +static const unsigned int mt6589_pull_type[] = { + [0 ... 3] = MTK_PULL_PUPD_R1R0_TYPE, + [4] = MTK_PULL_PULLSEL_TYPE, + [5 ... 10] = MTK_PULL_PUPD_R1R0_TYPE, + [11 ... 129] = MTK_PULL_PULLSEL_TYPE, + [130 ... 131] = MTK_PULL_PUPD_R1R0_TYPE, + [132 ... 133] = MTK_PULL_PULLSEL_TYPE, + [134 ... 141] = MTK_PULL_PUPD_R1R0_TYPE, + [142 ... 225] = MTK_PULL_PULLSEL_TYPE, + [226 ... 231] = MTK_PULL_PUPD_R1R0_TYPE, +}; + +/* + * MT6589 PUPD polarity differs from the generic PUPD/R1/R0 helpers: + * 1 selects pull-up and 0 selects pull-down. + */ +static int mt6589_pinconf_bias_set_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + if (mt6589_pull_type[desc->number] & MTK_PULL_PUPD_R1R0_TYPE) + pullup = !pullup; + + return mtk_pinconf_bias_set_combo(hw, desc, pullup, arg); +} + +static int mt6589_pinconf_bias_get_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *arg) +{ + int err; + + err = mtk_pinconf_bias_get_combo(hw, desc, pullup, arg); + if (err) + return err; + + if (mt6589_pull_type[desc->number] & MTK_PULL_PUPD_R1R0_TYPE) + *pullup = !*pullup; + + return 0; +} + +static const char * const mt6589_pinctrl_register_base_names[] = { + "gpio", "gpio1", +}; + +static const struct mtk_eint_hw mt6589_eint_hw = { + .port_mask = 7, + .ports = 6, + .ap_num = 192, + .db_cnt = 16, + .db_time = debounce_time_mt6795, +}; + +static const struct mtk_pin_soc mt6589_pinctrl_data = { + .reg_cal = mt6589_reg_cals, + .pins = mtk_pins_mt6589, + .npins = ARRAY_SIZE(mtk_pins_mt6589), + .ngrps = ARRAY_SIZE(mtk_pins_mt6589), + .nfuncs = 8, + .eint_hw = &mt6589_eint_hw, + .gpio_m = 0, + .base_names = mt6589_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt6589_pinctrl_register_base_names), + .bias_set_combo = mt6589_pinconf_bias_set_combo, + .bias_get_combo = mt6589_pinconf_bias_get_combo, + .drive_set = mtk_pinconf_drive_set_rev1, + .drive_get = mtk_pinconf_drive_get_rev1, + .adv_pull_set = mtk_pinconf_adv_pull_set, + .adv_pull_get = mtk_pinconf_adv_pull_get, + .pull_type = mt6589_pull_type, +}; + +static const struct of_device_id mt6589_pinctrl_match[] = { + { .compatible = "mediatek,mt6589-pinctrl", .data = &mt6589_pinctrl_data }, + {}, +}; +MODULE_DEVICE_TABLE(of, mt6589_pinctrl_match); + +static struct platform_driver mt6589_pinctrl_driver = { + .probe = mtk_paris_pinctrl_probe, + .driver = { + .name = "mediatek-mt6589-pinctrl", + .of_match_table = mt6589_pinctrl_match, + }, +}; + +static int __init mt6589_pinctrl_init(void) +{ + return platform_driver_register(&mt6589_pinctrl_driver); +} +arch_initcall(mt6589_pinctrl_init); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MediaTek MT6589 Pinctrl Driver"); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index 4918d38abfc29d..c9ed8203532f0d 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -43,6 +43,7 @@ static const struct mtk_drive_desc mtk_drive[] = { [DRV_GRP2] = { 2, 8, 2, 1 }, [DRV_GRP3] = { 2, 8, 2, 2 }, [DRV_GRP4] = { 2, 16, 2, 1 }, + [DRV_GRP5] = { 4, 32, 4, 1 }, }; static void mtk_w32(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 val) @@ -236,14 +237,23 @@ EXPORT_SYMBOL_GPL(mtk_hw_get_value); static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n) { const struct mtk_pin_desc *desc; - int i = 0; + int i, err, value; desc = (const struct mtk_pin_desc *)hw->soc->pins; - while (i < hw->soc->npins) { + /* If there's a pin muxed to this EINT, use it */ + for (i = 0; i < hw->soc->npins; i++) { + if (desc[i].eint.eint_n == eint_n) { + err = mtk_hw_get_value(hw, &desc[i], + PINCTRL_PIN_REG_MODE, &value); + if (!err && value == desc[i].eint.eint_m) + return desc[i].number; + } + } + + for (i = 0; i < hw->soc->npins; i++) { if (desc[i].eint.eint_n == eint_n) return desc[i].number; - i++; } return EINT_NA; @@ -1149,13 +1159,13 @@ int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw, * 10K on & 50K (75K) on, when (R0, R1) = (1, 1) */ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, arg & 1); - if (err) - return 0; + if (err != -ENOTSUPP) + return err; err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, !!(arg & 2)); - if (err) - return 0; + if (err != -ENOTSUPP) + return err; arg = pullup ? 0 : 1; @@ -1169,6 +1179,10 @@ int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw, err = hw->soc->bias_set(hw, desc, pullup); if (err) return err; + } else if (hw->soc->bias_set_combo) { + err = hw->soc->bias_set_combo(hw, desc, pullup, arg); + if (err) + return err; } else { err = mtk_pinconf_bias_set_rev1(hw, desc, pullup); if (err) @@ -1184,6 +1198,7 @@ int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, u32 *val) { + u32 current_pullup, current_enable; u32 t, t2; int err; @@ -1197,6 +1212,20 @@ int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw, err = hw->soc->bias_get(hw, desc, pullup, val); if (err) return err; + return 0; + } else if (hw->soc->bias_get_combo) { + err = hw->soc->bias_get_combo(hw, desc, + ¤t_pullup, + ¤t_enable); + if (err) + return err; + + if (current_enable == MTK_DISABLE || + !!current_pullup != pullup) + return -EINVAL; + + *val = current_enable; + return 0; } else { return -ENOTSUPP; } diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h index fa7c0ed4934648..f3aaebdcfcf080 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h @@ -104,6 +104,7 @@ enum { DRV_GRP2, DRV_GRP3, DRV_GRP4, + DRV_GRP5, DRV_GRP_MAX, }; diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6320.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6320.h new file mode 100644 index 00000000000000..695dfff7a104e1 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6320.h @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ + +#ifndef __PINCTRL_MTK_MT6320_H +#define __PINCTRL_MTK_MT6320_H + +#include +#include "pinctrl-mtk-common.h" + +static const struct mtk_desc_pin mtk_pins_mt6320[] = { + MTK_PIN(PINCTRL_PIN(0, "INT"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO0"), + MTK_FUNCTION(1, "INT") + ), + MTK_PIN(PINCTRL_PIN(1, "SRCVOLTEN"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO1"), + MTK_FUNCTION(1, "SRCVOLTEN") + ), + MTK_PIN(PINCTRL_PIN(2, "SRCLKEN_PERI"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO2"), + MTK_FUNCTION(1, "SRCLKEN_PERI") + ), + MTK_PIN(PINCTRL_PIN(3, "SRCLKEN_MD2"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO3"), + MTK_FUNCTION(1, "SRCLKEN_MD2") + ), + MTK_PIN(PINCTRL_PIN(4, "RTC_32K1V8"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO4"), + MTK_FUNCTION(1, "RTC_32K1V8") + ), + MTK_PIN(PINCTRL_PIN(5, "WRAP_EVENT"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO5"), + MTK_FUNCTION(1, "WRAP_EVENT") + ), + MTK_PIN(PINCTRL_PIN(6, "SPI_CLK"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO6"), + MTK_FUNCTION(1, "SPI_CLK") + ), + MTK_PIN(PINCTRL_PIN(7, "SPI_CSN"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO7"), + MTK_FUNCTION(1, "SPI_CSN") + ), + MTK_PIN(PINCTRL_PIN(8, "SPI_MOSI"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO8"), + MTK_FUNCTION(1, "SPI_MOSI") + ), + MTK_PIN(PINCTRL_PIN(9, "SPI_MISO"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO9"), + MTK_FUNCTION(1, "SPI_MISO") + ), + MTK_PIN(PINCTRL_PIN(10, "ADC_CK"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO10"), + MTK_FUNCTION(1, "ADC_CK") + ), + MTK_PIN(PINCTRL_PIN(11, "ADC_WS"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO11"), + MTK_FUNCTION(1, "ADC_WS") + ), + MTK_PIN(PINCTRL_PIN(12, "ADC_DAT"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO12"), + MTK_FUNCTION(1, "ADC_DAT") + ), + MTK_PIN(PINCTRL_PIN(13, "DAC_CK"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO13"), + MTK_FUNCTION(1, "DAC_CK") + ), + MTK_PIN(PINCTRL_PIN(14, "DAC_WS"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO14"), + MTK_FUNCTION(1, "DAC_WS") + ), + MTK_PIN(PINCTRL_PIN(15, "DAC_DAT"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO15"), + MTK_FUNCTION(1, "DAC_DAT") + ), + MTK_PIN(PINCTRL_PIN(16, "COL0_USBDL"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 10), + MTK_FUNCTION(0, "GPIO16"), + MTK_FUNCTION(1, "COL0_USBDL"), + MTK_FUNCTION(2, "EINT10"), + MTK_FUNCTION(3, "PWM1_3X") + ), + MTK_PIN(PINCTRL_PIN(17, "COL1"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 11), + MTK_FUNCTION(0, "GPIO17"), + MTK_FUNCTION(1, "COL1"), + MTK_FUNCTION(2, "EINT11"), + MTK_FUNCTION(3, "SCL0_2X") + ), + MTK_PIN(PINCTRL_PIN(18, "COL2"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 12), + MTK_FUNCTION(0, "GPIO18"), + MTK_FUNCTION(1, "COL2"), + MTK_FUNCTION(2, "EINT12"), + MTK_FUNCTION(3, "SDA0_2X") + ), + MTK_PIN(PINCTRL_PIN(19, "COL3"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 13), + MTK_FUNCTION(0, "GPIO19"), + MTK_FUNCTION(1, "COL3"), + MTK_FUNCTION(2, "EINT13"), + MTK_FUNCTION(3, "SCL1_2X") + ), + MTK_PIN(PINCTRL_PIN(20, "COL4"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 14), + MTK_FUNCTION(0, "GPIO20"), + MTK_FUNCTION(1, "COL4"), + MTK_FUNCTION(2, "EINT14"), + MTK_FUNCTION(3, "SDA1_2X") + ), + MTK_PIN(PINCTRL_PIN(21, "COL5"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 15), + MTK_FUNCTION(0, "GPIO21"), + MTK_FUNCTION(1, "COL5"), + MTK_FUNCTION(2, "EINT15"), + MTK_FUNCTION(3, "SCL2_2X") + ), + MTK_PIN(PINCTRL_PIN(22, "COL6"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 16), + MTK_FUNCTION(0, "GPIO22"), + MTK_FUNCTION(1, "COL6"), + MTK_FUNCTION(2, "EINT16"), + MTK_FUNCTION(3, "SDA2_2X"), + MTK_FUNCTION(4, "GPIO32K_0"), + MTK_FUNCTION(5, "GPIO26M_0") + ), + MTK_PIN(PINCTRL_PIN(23, "COL7"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 17), + MTK_FUNCTION(0, "GPIO23"), + MTK_FUNCTION(1, "COL7"), + MTK_FUNCTION(2, "EINT17"), + MTK_FUNCTION(3, "PWM2_3X"), + MTK_FUNCTION(4, "GPIO32K_1"), + MTK_FUNCTION(5, "GPIO26M_1") + ), + MTK_PIN(PINCTRL_PIN(24, "ROW0"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 18), + MTK_FUNCTION(0, "GPIO24"), + MTK_FUNCTION(1, "ROW0"), + MTK_FUNCTION(2, "EINT18"), + MTK_FUNCTION(3, "SCL0_3X") + ), + MTK_PIN(PINCTRL_PIN(25, "ROW1"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 19), + MTK_FUNCTION(0, "GPIO25"), + MTK_FUNCTION(1, "ROW1"), + MTK_FUNCTION(2, "EINT19"), + MTK_FUNCTION(3, "SDA0_3X") + ), + MTK_PIN(PINCTRL_PIN(26, "ROW2"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 20), + MTK_FUNCTION(0, "GPIO26"), + MTK_FUNCTION(1, "ROW2"), + MTK_FUNCTION(2, "EINT20"), + MTK_FUNCTION(3, "SCL1_3X") + ), + MTK_PIN(PINCTRL_PIN(27, "ROW3"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 21), + MTK_FUNCTION(0, "GPIO27"), + MTK_FUNCTION(1, "ROW3"), + MTK_FUNCTION(2, "EINT21"), + MTK_FUNCTION(3, "SDA1_3X") + ), + MTK_PIN(PINCTRL_PIN(28, "ROW4"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 22), + MTK_FUNCTION(0, "GPIO28"), + MTK_FUNCTION(1, "ROW4"), + MTK_FUNCTION(2, "EINT22"), + MTK_FUNCTION(3, "SCL2_3X") + ), + MTK_PIN(PINCTRL_PIN(29, "ROW5"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 23), + MTK_FUNCTION(0, "GPIO29"), + MTK_FUNCTION(1, "ROW5"), + MTK_FUNCTION(2, "EINT23"), + MTK_FUNCTION(3, "SDA2_3X") + ), + MTK_PIN(PINCTRL_PIN(30, "ROW6"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 24), + MTK_FUNCTION(0, "GPIO30"), + MTK_FUNCTION(1, "ROW6"), + MTK_FUNCTION(2, "EINT24"), + MTK_FUNCTION(3, "PWM3_3X"), + MTK_FUNCTION(4, "GPIO32K_2"), + MTK_FUNCTION(5, "GPIO26M_2") + ), + MTK_PIN(PINCTRL_PIN(31, "ROW7"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 3), + MTK_FUNCTION(0, "GPIO31"), + MTK_FUNCTION(1, "ROW7"), + MTK_FUNCTION(2, "EINT3"), + MTK_FUNCTION(4, "GPIO32K_3"), + MTK_FUNCTION(5, "GPIO26M_3") + ), + MTK_PIN(PINCTRL_PIN(32, "PWM1"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 4), + MTK_FUNCTION(0, "GPIO32"), + MTK_FUNCTION(1, "PWM1"), + MTK_FUNCTION(2, "EINT4"), + MTK_FUNCTION(4, "GPIO32K_4"), + MTK_FUNCTION(5, "GPIO26M_4") + ), + MTK_PIN(PINCTRL_PIN(33, "PWM2"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 5), + MTK_FUNCTION(0, "GPIO33"), + MTK_FUNCTION(1, "PWM2"), + MTK_FUNCTION(2, "EINT5"), + MTK_FUNCTION(4, "GPIO32K_5"), + MTK_FUNCTION(5, "GPIO26M_5") + ), + MTK_PIN(PINCTRL_PIN(34, "PWM3"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 6), + MTK_FUNCTION(0, "GPIO34"), + MTK_FUNCTION(1, "PWM3"), + MTK_FUNCTION(2, "EINT6"), + MTK_FUNCTION(3, "COL0"), + MTK_FUNCTION(4, "GPIO32K_6"), + MTK_FUNCTION(5, "GPIO26M_6") + ), + MTK_PIN(PINCTRL_PIN(35, "SCL0"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 7), + MTK_FUNCTION(0, "GPIO35"), + MTK_FUNCTION(1, "SCL0"), + MTK_FUNCTION(2, "EINT7"), + MTK_FUNCTION(3, "PWM1_2X") + ), + MTK_PIN(PINCTRL_PIN(36, "SDA0"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 8), + MTK_FUNCTION(0, "GPIO36"), + MTK_FUNCTION(1, "SDA0"), + MTK_FUNCTION(2, "EINT8") + ), + MTK_PIN(PINCTRL_PIN(37, "SCL1"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 9), + MTK_FUNCTION(0, "GPIO37"), + MTK_FUNCTION(1, "SCL1"), + MTK_FUNCTION(2, "EINT9"), + MTK_FUNCTION(3, "PWM2_2X") + ), + MTK_PIN(PINCTRL_PIN(38, "SDA1"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 0), + MTK_FUNCTION(0, "GPIO38"), + MTK_FUNCTION(1, "SDA1"), + MTK_FUNCTION(2, "EINT0") + ), + MTK_PIN(PINCTRL_PIN(39, "SCL2"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 1), + MTK_FUNCTION(0, "GPIO39"), + MTK_FUNCTION(1, "SCL2"), + MTK_FUNCTION(2, "EINT1"), + MTK_FUNCTION(3, "PWM3_2X") + ), + MTK_PIN(PINCTRL_PIN(40, "SDA2"), + NULL, "mt6320", + MTK_EINT_FUNCTION(2, 2), + MTK_FUNCTION(0, "GPIO40"), + MTK_FUNCTION(1, "SDA2"), + MTK_FUNCTION(2, "EINT2") + ), + MTK_PIN(PINCTRL_PIN(41, "SIM1_AP_SCLK"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO41"), + MTK_FUNCTION(1, "SIM1_AP_SCLK") + ), + MTK_PIN(PINCTRL_PIN(42, "SIM1_AP_SRST"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO42"), + MTK_FUNCTION(1, "SIM1_AP_SRST") + ), + MTK_PIN(PINCTRL_PIN(43, "SIM2_AP_SCLK"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO43"), + MTK_FUNCTION(1, "SIM2_AP_SCLK") + ), + MTK_PIN(PINCTRL_PIN(44, "SIM2_AP_SRST"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO44"), + MTK_FUNCTION(1, "SIM2_AP_SRST") + ), + MTK_PIN(PINCTRL_PIN(45, "SIMLS1_SCLK"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO45"), + MTK_FUNCTION(1, "SIMLS1_SCLK") + ), + MTK_PIN(PINCTRL_PIN(46, "SIMLS1_SRST"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO46"), + MTK_FUNCTION(1, "SIMLS1_SRST") + ), + MTK_PIN(PINCTRL_PIN(47, "SIMLS2_SCLK"), + NULL, "mt6320", + MTK_EINT_FUNCTION(5, 10), + MTK_FUNCTION(0, "GPIO47"), + MTK_FUNCTION(1, "SIMLS2_SCLK"), + MTK_FUNCTION(5, "EINT10") + ), + MTK_PIN(PINCTRL_PIN(48, "SIMLS2_SRST"), + NULL, "mt6320", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO48"), + MTK_FUNCTION(1, "SIMLS2_SRST") + ), +}; + +#endif /* __PINCTRL_MTK_MT6320_H */ diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6589.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6589.h new file mode 100644 index 00000000000000..df570f4afdb1b2 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6589.h @@ -0,0 +1,2576 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ + +#ifndef __PINCTRL_MTK_MT6589_H +#define __PINCTRL_MTK_MT6589_H + +#include "pinctrl-mtk-common-v2.h" +#include "pinctrl-paris.h" + +static const struct mtk_pin_desc mtk_pins_mt6589[] = { + MTK_PIN( + 0, "MSDC0_DAT7", + MTK_EINT_FUNCTION(2, 49), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO0"), + MTK_FUNCTION(1, "MSDC0_DAT7"), + MTK_FUNCTION(2, "EINT49"), + MTK_FUNCTION(3, "I2SOUT_DAT"), + MTK_FUNCTION(4, "DAC_DAT_OUT"), + MTK_FUNCTION(5, "PCM1_DO"), + MTK_FUNCTION(6, "SPI1_MO"), + MTK_FUNCTION(7, "NALE") + ), + MTK_PIN( + 1, "MSDC0_DAT6", + MTK_EINT_FUNCTION(2, 48), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO1"), + MTK_FUNCTION(1, "MSDC0_DAT6"), + MTK_FUNCTION(2, "EINT48"), + MTK_FUNCTION(3, "I2SIN_WS"), + MTK_FUNCTION(4, "DAC_WS"), + MTK_FUNCTION(5, "PCM1_WS"), + MTK_FUNCTION(6, "SPI1_CSN"), + MTK_FUNCTION(7, "NCLE") + ), + MTK_PIN( + 2, "MSDC0_DAT5", + MTK_EINT_FUNCTION(2, 47), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO2"), + MTK_FUNCTION(1, "MSDC0_DAT5"), + MTK_FUNCTION(2, "EINT47"), + MTK_FUNCTION(3, "I2SIN_CK"), + MTK_FUNCTION(4, "DAC_CK"), + MTK_FUNCTION(5, "PCM1_CK"), + MTK_FUNCTION(6, "SPI1_CLK"), + MTK_FUNCTION(7, "NLD4") + ), + MTK_PIN( + 3, "MSDC0_DAT4", + MTK_EINT_FUNCTION(2, 46), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO3"), + MTK_FUNCTION(1, "MSDC0_DAT4"), + MTK_FUNCTION(2, "EINT46"), + MTK_FUNCTION(6, "LSCE1B_2X"), + MTK_FUNCTION(7, "NLD5") + ), + MTK_PIN( + 4, "MSDC0_RSTB", + MTK_EINT_FUNCTION(2, 50), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO4"), + MTK_FUNCTION(1, "MSDC0_RSTB"), + MTK_FUNCTION(2, "EINT50"), + MTK_FUNCTION(3, "I2SIN_DAT"), + MTK_FUNCTION(5, "PCM1_DI"), + MTK_FUNCTION(6, "SPI1_MI"), + MTK_FUNCTION(7, "NLD10") + ), + MTK_PIN( + 5, "MSDC0_CMD", + MTK_EINT_FUNCTION(2, 41), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO5"), + MTK_FUNCTION(1, "MSDC0_CMD"), + MTK_FUNCTION(2, "EINT41"), + MTK_FUNCTION(6, "LRSTB_2X"), + MTK_FUNCTION(7, "NRNB") + ), + MTK_PIN( + 6, "MSDC0_CLK", + MTK_EINT_FUNCTION(2, 40), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO6"), + MTK_FUNCTION(1, "MSDC0_CLK"), + MTK_FUNCTION(2, "EINT40"), + MTK_FUNCTION(6, "LPTE"), + MTK_FUNCTION(7, "NREB") + ), + MTK_PIN( + 7, "MSDC0_DAT3", + MTK_EINT_FUNCTION(2, 45), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO7"), + MTK_FUNCTION(1, "MSDC0_DAT3"), + MTK_FUNCTION(2, "EINT45"), + MTK_FUNCTION(6, "LSCE0B_2X"), + MTK_FUNCTION(7, "NLD7") + ), + MTK_PIN( + 8, "MSDC0_DAT2", + MTK_EINT_FUNCTION(2, 44), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO8"), + MTK_FUNCTION(1, "MSDC0_DAT2"), + MTK_FUNCTION(2, "EINT44"), + MTK_FUNCTION(6, "LSA0_2X"), + MTK_FUNCTION(7, "NLD14") + ), + MTK_PIN( + 9, "MSDC0_DAT1", + MTK_EINT_FUNCTION(2, 43), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO9"), + MTK_FUNCTION(1, "MSDC0_DAT1"), + MTK_FUNCTION(2, "EINT43"), + MTK_FUNCTION(6, "LSCK_2X"), + MTK_FUNCTION(7, "NLD11") + ), + MTK_PIN( + 10, "MSDC0_DAT0", + MTK_EINT_FUNCTION(2, 42), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO10"), + MTK_FUNCTION(1, "MSDC0_DAT0"), + MTK_FUNCTION(2, "EINT42"), + MTK_FUNCTION(6, "LSDA_2X") + ), + MTK_PIN( + 11, "NCEB0", + MTK_EINT_FUNCTION(2, 139), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO11"), + MTK_FUNCTION(1, "NCEB0"), + MTK_FUNCTION(2, "EINT139"), + MTK_FUNCTION(7, "TESTA_OUT4") + ), + MTK_PIN( + 12, "NCEB1", + MTK_EINT_FUNCTION(2, 140), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO12"), + MTK_FUNCTION(1, "NCEB1"), + MTK_FUNCTION(2, "EINT140"), + MTK_FUNCTION(4, "MD1_GPS_SYNC"), + MTK_FUNCTION(5, "MD2_GPS_SYNC"), + MTK_FUNCTION(6, "USB_DRVVBUS"), + MTK_FUNCTION(7, "TESTA_OUT5") + ), + MTK_PIN( + 13, "NRNB", + MTK_EINT_FUNCTION(2, 141), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO13"), + MTK_FUNCTION(1, "NRNB"), + MTK_FUNCTION(2, "EINT141"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[0]"), + MTK_FUNCTION(7, "TESTA_OUT6") + ), + MTK_PIN( + 14, "NCLE", + MTK_EINT_FUNCTION(2, 142), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO14"), + MTK_FUNCTION(1, "NCLE"), + MTK_FUNCTION(2, "EINT142"), + MTK_FUNCTION(3, "DPI1_CK_1X"), + MTK_FUNCTION(4, "CM2PDN_1X"), + MTK_FUNCTION(6, "NALE"), + MTK_FUNCTION(7, "TESTA_OUT7") + ), + MTK_PIN( + 15, "NALE", + MTK_EINT_FUNCTION(2, 143), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO15"), + MTK_FUNCTION(1, "NALE"), + MTK_FUNCTION(2, "EINT143"), + MTK_FUNCTION(3, "DPI1_DE_1X"), + MTK_FUNCTION(4, "CM2MCLK_1X"), + MTK_FUNCTION(5, "IRDA_RXD"), + MTK_FUNCTION(6, "NCLE"), + MTK_FUNCTION(7, "TESTA_OUT8") + ), + MTK_PIN( + 16, "NREB", + MTK_EINT_FUNCTION(2, 144), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO16"), + MTK_FUNCTION(1, "NREB"), + MTK_FUNCTION(2, "EINT144"), + MTK_FUNCTION(3, "DPI1_HSYNC_1X"), + MTK_FUNCTION(4, "CM2RST_1X"), + MTK_FUNCTION(5, "IRDA_TXD"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[1]"), + MTK_FUNCTION(7, "TESTA_OUT9") + ), + MTK_PIN( + 17, "NWEB", + MTK_EINT_FUNCTION(2, 145), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO17"), + MTK_FUNCTION(1, "NWEB"), + MTK_FUNCTION(2, "EINT145"), + MTK_FUNCTION(3, "DPI1_VSYNC_1X"), + MTK_FUNCTION(4, "CM2PCLK_1X"), + MTK_FUNCTION(5, "IRDA_PDN"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[2]"), + MTK_FUNCTION(7, "TESTA_OUT10") + ), + MTK_PIN( + 18, "NLD0", + MTK_EINT_FUNCTION(2, 146), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO18"), + MTK_FUNCTION(1, "NLD0"), + MTK_FUNCTION(2, "EINT146"), + MTK_FUNCTION(3, "DPI1_D_1X[0]"), + MTK_FUNCTION(4, "CM2DAT_1X[0]"), + MTK_FUNCTION(5, "I2SIN_CK"), + MTK_FUNCTION(6, "DAC_CK"), + MTK_FUNCTION(7, "TESTA_OUT11") + ), + MTK_PIN( + 19, "NLD1", + MTK_EINT_FUNCTION(2, 147), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO19"), + MTK_FUNCTION(1, "NLD1"), + MTK_FUNCTION(2, "EINT147"), + MTK_FUNCTION(3, "DPI1_D_1X[1]"), + MTK_FUNCTION(4, "CM2DAT_1X[1]"), + MTK_FUNCTION(5, "I2SIN_WS"), + MTK_FUNCTION(6, "DAC_WS"), + MTK_FUNCTION(7, "TESTA_OUT12") + ), + MTK_PIN( + 20, "NLD2", + MTK_EINT_FUNCTION(2, 148), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO20"), + MTK_FUNCTION(1, "NLD2"), + MTK_FUNCTION(2, "EINT148"), + MTK_FUNCTION(3, "DPI1_D_1X[2]"), + MTK_FUNCTION(4, "CM2DAT_1X[2]"), + MTK_FUNCTION(5, "I2SOUT_DAT"), + MTK_FUNCTION(6, "DAC_DAT_OUT"), + MTK_FUNCTION(7, "TESTA_OUT13") + ), + MTK_PIN( + 21, "NLD3", + MTK_EINT_FUNCTION(2, 149), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO21"), + MTK_FUNCTION(1, "NLD3"), + MTK_FUNCTION(2, "EINT149"), + MTK_FUNCTION(3, "DPI1_D_1X[3]"), + MTK_FUNCTION(4, "CM2DAT_1X[3]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[3]"), + MTK_FUNCTION(7, "TESTA_OUT14") + ), + MTK_PIN( + 22, "NLD4", + MTK_EINT_FUNCTION(2, 150), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO22"), + MTK_FUNCTION(1, "NLD4"), + MTK_FUNCTION(2, "EINT150"), + MTK_FUNCTION(3, "DPI1_D_1X[4]"), + MTK_FUNCTION(4, "CM2DAT_1X[4]"), + MTK_FUNCTION(5, "MD1_DAI_RX_GPIO"), + MTK_FUNCTION(6, "MD2_DAI_RX_GPIO"), + MTK_FUNCTION(7, "TESTA_OUT15") + ), + MTK_PIN( + 23, "NLD5", + MTK_EINT_FUNCTION(2, 151), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO23"), + MTK_FUNCTION(1, "NLD5"), + MTK_FUNCTION(2, "EINT151"), + MTK_FUNCTION(3, "DPI1_D_1X[5]"), + MTK_FUNCTION(4, "CM2DAT_1X[5]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[4]"), + MTK_FUNCTION(7, "TESTA_OUT16") + ), + MTK_PIN( + 24, "NLD6", + MTK_EINT_FUNCTION(2, 152), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO24"), + MTK_FUNCTION(1, "NLD6"), + MTK_FUNCTION(2, "EINT152"), + MTK_FUNCTION(3, "DPI1_D_1X[6]"), + MTK_FUNCTION(4, "CM2DAT_1X[6]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[5]"), + MTK_FUNCTION(7, "TESTA_OUT17") + ), + MTK_PIN( + 25, "NLD7", + MTK_EINT_FUNCTION(2, 153), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO25"), + MTK_FUNCTION(1, "NLD7"), + MTK_FUNCTION(2, "EINT153"), + MTK_FUNCTION(3, "DPI1_D_1X[7]"), + MTK_FUNCTION(4, "CM2DAT_1X[7]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[6]"), + MTK_FUNCTION(7, "TESTA_OUT18") + ), + MTK_PIN( + 26, "NLD8", + MTK_EINT_FUNCTION(2, 154), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO26"), + MTK_FUNCTION(1, "NLD8"), + MTK_FUNCTION(2, "EINT154"), + MTK_FUNCTION(3, "DPI1_D_1X[8]"), + MTK_FUNCTION(4, "CM2DAT_1X[8]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[7]"), + MTK_FUNCTION(7, "TESTA_OUT19") + ), + MTK_PIN( + 27, "NLD9", + MTK_EINT_FUNCTION(2, 155), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO27"), + MTK_FUNCTION(1, "NLD9"), + MTK_FUNCTION(2, "EINT155"), + MTK_FUNCTION(3, "DPI1_D_1X[9]"), + MTK_FUNCTION(4, "CM2DAT_1X[9]"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[8]"), + MTK_FUNCTION(7, "TESTA_OUT20") + ), + MTK_PIN( + 28, "NLD10", + MTK_EINT_FUNCTION(2, 156), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO28"), + MTK_FUNCTION(1, "NLD10"), + MTK_FUNCTION(2, "EINT156"), + MTK_FUNCTION(3, "DPI1_D_1X[10]"), + MTK_FUNCTION(4, "CM2VSYNC_1X"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[9]"), + MTK_FUNCTION(7, "TESTA_OUT21") + ), + MTK_PIN( + 29, "NLD11", + MTK_EINT_FUNCTION(2, 157), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO29"), + MTK_FUNCTION(1, "NLD11"), + MTK_FUNCTION(2, "EINT157"), + MTK_FUNCTION(3, "DPI1_D_1X[11]"), + MTK_FUNCTION(4, "CM2HSYNC_1X"), + MTK_FUNCTION(5, "PWM3"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[10]"), + MTK_FUNCTION(7, "TESTA_OUT22") + ), + MTK_PIN( + 30, "NLD12", + MTK_EINT_FUNCTION(2, 158), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO30"), + MTK_FUNCTION(1, "NLD12"), + MTK_FUNCTION(2, "EINT158"), + MTK_FUNCTION(3, "I2SIN_CK"), + MTK_FUNCTION(4, "DAC_CK"), + MTK_FUNCTION(5, "PCM1_CK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[11]"), + MTK_FUNCTION(7, "TESTA_OUT23") + ), + MTK_PIN( + 31, "NLD13", + MTK_EINT_FUNCTION(2, 159), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO31"), + MTK_FUNCTION(1, "NLD13"), + MTK_FUNCTION(2, "EINT159"), + MTK_FUNCTION(3, "I2SIN_WS"), + MTK_FUNCTION(4, "DAC_WS"), + MTK_FUNCTION(5, "PCM1_WS"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[12]"), + MTK_FUNCTION(7, "TESTA_OUT24") + ), + MTK_PIN( + 32, "NLD14", + MTK_EINT_FUNCTION(2, 160), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO32"), + MTK_FUNCTION(1, "NLD14"), + MTK_FUNCTION(2, "EINT160"), + MTK_FUNCTION(3, "I2SOUT_DAT"), + MTK_FUNCTION(4, "DAC_DAT_OUT"), + MTK_FUNCTION(5, "PCM1_DO"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[13]"), + MTK_FUNCTION(7, "TESTA_OUT25") + ), + MTK_PIN( + 33, "NLD15", + MTK_EINT_FUNCTION(2, 161), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO33"), + MTK_FUNCTION(1, "NLD15"), + MTK_FUNCTION(2, "EINT161"), + MTK_FUNCTION(3, "DISP_PWM"), + MTK_FUNCTION(4, "PWM4"), + MTK_FUNCTION(5, "PCM1_DI"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[14]"), + MTK_FUNCTION(7, "TESTA_OUT26") + ), + MTK_PIN( + 34, "EINT0", + MTK_EINT_FUNCTION(1, 0), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO34"), + MTK_FUNCTION(1, "EINT0"), + MTK_FUNCTION(2, "PWM1"), + MTK_FUNCTION(3, "CLKM0"), + MTK_FUNCTION(5, "MD2_UTXD"), + MTK_FUNCTION(6, "MD1_EINT1"), + MTK_FUNCTION(7, "USB_SCL") + ), + MTK_PIN( + 35, "EINT1", + MTK_EINT_FUNCTION(1, 1), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO35"), + MTK_FUNCTION(1, "EINT1"), + MTK_FUNCTION(2, "PWM2"), + MTK_FUNCTION(3, "CLKM1"), + MTK_FUNCTION(5, "MD2_URXD"), + MTK_FUNCTION(6, "MD1_EINT2"), + MTK_FUNCTION(7, "USB_SDA") + ), + MTK_PIN( + 36, "EINT2", + MTK_EINT_FUNCTION(1, 2), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO36"), + MTK_FUNCTION(1, "EINT2"), + MTK_FUNCTION(2, "PWM3"), + MTK_FUNCTION(3, "CLKM2"), + MTK_FUNCTION(4, "SRCLKENAI2"), + MTK_FUNCTION(6, "MD1_EINT3") + ), + MTK_PIN( + 37, "EINT3", + MTK_EINT_FUNCTION(1, 3), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO37"), + MTK_FUNCTION(1, "EINT3"), + MTK_FUNCTION(6, "MD1_EINT5"), + MTK_FUNCTION(7, "EXT_26M_CK") + ), + MTK_PIN( + 38, "EINT4", + MTK_EINT_FUNCTION(1, 4), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO38"), + MTK_FUNCTION(1, "EINT4"), + MTK_FUNCTION(2, "PWM4"), + MTK_FUNCTION(3, "MD1_GPS_SYNC"), + MTK_FUNCTION(4, "MD2_GPS_SYNC"), + MTK_FUNCTION(5, "USB_DRVVBUS"), + MTK_FUNCTION(6, "MD1_EINT4") + ), + MTK_PIN( + 39, "PWRAP_SPIDI", + MTK_EINT_FUNCTION(2, 29), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO39"), + MTK_FUNCTION(1, "PWRAP_SPIDI"), + MTK_FUNCTION(2, "EINT29") + ), + MTK_PIN( + 40, "PWRAP_SPIDO", + MTK_EINT_FUNCTION(2, 28), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO40"), + MTK_FUNCTION(1, "PWRAP_SPIDO"), + MTK_FUNCTION(2, "EINT28") + ), + MTK_PIN( + 41, "PWRAP_SPICS_B_I", + MTK_EINT_FUNCTION(2, 27), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO41"), + MTK_FUNCTION(1, "PWRAP_SPICS_B_I"), + MTK_FUNCTION(2, "EINT27") + ), + MTK_PIN( + 42, "PWRAP_SPICK_I", + MTK_EINT_FUNCTION(2, 26), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO42"), + MTK_FUNCTION(1, "PWRAP_SPICK_I"), + MTK_FUNCTION(2, "EINT26") + ), + MTK_PIN( + 43, "PWRAP_EVENT_IN", + MTK_EINT_FUNCTION(2, 25), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO43"), + MTK_FUNCTION(1, "PWRAP_EVENT_IN"), + MTK_FUNCTION(2, "EINT25") + ), + MTK_PIN( + 44, "MD1_SIM1_SCLK", + MTK_EINT_FUNCTION(2, 30), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO44"), + MTK_FUNCTION(1, "MD1_SIM1_SCLK"), + MTK_FUNCTION(2, "EINT30"), + MTK_FUNCTION(3, "MD1_SIM2_SCLK"), + MTK_FUNCTION(4, "MD2_SIM1_SCLK"), + MTK_FUNCTION(5, "MD2_SIM2_SCLK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[15]") + ), + MTK_PIN( + 45, "MD1_SIM1_SRST", + MTK_EINT_FUNCTION(2, 31), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO45"), + MTK_FUNCTION(1, "MD1_SIM1_SRST"), + MTK_FUNCTION(2, "EINT31"), + MTK_FUNCTION(3, "MD1_SIM2_SRST"), + MTK_FUNCTION(4, "MD2_SIM1_SRST"), + MTK_FUNCTION(5, "MD2_SIM2_SRST"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[16]") + ), + MTK_PIN( + 46, "MD1_SIM1_SDAT", + MTK_EINT_FUNCTION(2, 32), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO46"), + MTK_FUNCTION(1, "MD1_SIM1_SDAT"), + MTK_FUNCTION(2, "EINT32"), + MTK_FUNCTION(3, "MD1_SIM2_SDAT"), + MTK_FUNCTION(4, "MD2_SIM1_SDAT"), + MTK_FUNCTION(5, "MD2_SIM2_SDAT"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[17]") + ), + MTK_PIN( + 47, "MD1_SIM2_SCLK", + MTK_EINT_FUNCTION(2, 33), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO47"), + MTK_FUNCTION(1, "MD1_SIM2_SCLK"), + MTK_FUNCTION(2, "EINT33"), + MTK_FUNCTION(3, "MD1_SIM1_SCLK"), + MTK_FUNCTION(4, "MD2_SIM2_SCLK"), + MTK_FUNCTION(5, "MD2_SIM1_SCLK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[18]") + ), + MTK_PIN( + 48, "MD1_SIM2_SRST", + MTK_EINT_FUNCTION(2, 34), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO48"), + MTK_FUNCTION(1, "MD1_SIM2_SRST"), + MTK_FUNCTION(2, "EINT34"), + MTK_FUNCTION(3, "MD1_SIM1_SRST"), + MTK_FUNCTION(4, "MD2_SIM2_SRST"), + MTK_FUNCTION(5, "MD2_SIM1_SRST"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[19]") + ), + MTK_PIN( + 49, "MD1_SIM2_SDAT", + MTK_EINT_FUNCTION(2, 35), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO49"), + MTK_FUNCTION(1, "MD1_SIM2_SDAT"), + MTK_FUNCTION(2, "EINT35"), + MTK_FUNCTION(3, "MD1_SIM1_SDAT"), + MTK_FUNCTION(4, "MD2_SIM2_SDAT"), + MTK_FUNCTION(5, "MD2_SIM1_SDAT"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[20]") + ), + MTK_PIN( + 50, "ADC_CK", + MTK_EINT_FUNCTION(2, 19), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO50"), + MTK_FUNCTION(1, "ADC_CK"), + MTK_FUNCTION(2, "EINT19") + ), + MTK_PIN( + 51, "ADC_WS", + MTK_EINT_FUNCTION(2, 21), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO51"), + MTK_FUNCTION(1, "ADC_WS"), + MTK_FUNCTION(2, "EINT21") + ), + MTK_PIN( + 52, "ADC_DAT_IN", + MTK_EINT_FUNCTION(2, 20), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO52"), + MTK_FUNCTION(1, "ADC_DAT_IN"), + MTK_FUNCTION(2, "EINT20") + ), + MTK_PIN( + 53, "DAC_CK", + MTK_EINT_FUNCTION(2, 22), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO53"), + MTK_FUNCTION(1, "DAC_CK"), + MTK_FUNCTION(2, "EINT22") + ), + MTK_PIN( + 54, "DAC_WS", + MTK_EINT_FUNCTION(2, 24), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO54"), + MTK_FUNCTION(1, "DAC_WS"), + MTK_FUNCTION(2, "EINT24") + ), + MTK_PIN( + 55, "DAC_DAT_OUT", + MTK_EINT_FUNCTION(2, 23), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO55"), + MTK_FUNCTION(1, "DAC_DAT_OUT"), + MTK_FUNCTION(2, "EINT23") + ), + MTK_PIN( + 56, "RTC32K_CK", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_FIXED, /* maybe */ + MTK_FUNCTION(0, "GPIO56"), + MTK_FUNCTION(1, "RTC32K_CK") + ), + MTK_PIN( + 57, "IDDIG", + MTK_EINT_FUNCTION(2, 34), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO57"), + MTK_FUNCTION(1, "IDDIG"), + MTK_FUNCTION(2, "EINT34") + ), + MTK_PIN( + 58, "WATCHDOG", + MTK_EINT_FUNCTION(2, 36), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO58"), + MTK_FUNCTION(1, "WATCHDOG"), + MTK_FUNCTION(2, "EINT36") + ), + MTK_PIN( + 59, "SRCLKENA", + MTK_EINT_FUNCTION(2, 38), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO59"), + MTK_FUNCTION(1, "SRCLKENA"), + MTK_FUNCTION(2, "EINT38") + ), + MTK_PIN( + 60, "SRCVOLTEN", + MTK_EINT_FUNCTION(2, 37), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO60"), + MTK_FUNCTION(1, "SRCVOLTEN"), + MTK_FUNCTION(2, "EINT37") + ), + MTK_PIN( + 61, "JTCK", + MTK_EINT_FUNCTION(2, 188), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO61"), + MTK_FUNCTION(1, "JTCK"), + MTK_FUNCTION(2, "EINT188"), + MTK_FUNCTION(3, "DSP1_ICK"), + MTK_FUNCTION(7, "MD2_TCK_PAD") + ), + MTK_PIN( + 62, "JTDO", + MTK_EINT_FUNCTION(2, 190), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO62"), + MTK_FUNCTION(1, "JTDO"), + MTK_FUNCTION(2, "EINT190"), + MTK_FUNCTION(3, "DSP2_IMS"), + MTK_FUNCTION(7, "MD2_TDO_PAD") + ), + MTK_PIN( + 63, "JTRST_B", + MTK_EINT_FUNCTION(2, 0), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO63"), + MTK_FUNCTION(1, "JTRST_B"), + MTK_FUNCTION(2, "EINT0"), + MTK_FUNCTION(3, "DSP2_ICK"), + MTK_FUNCTION(7, "MD2_NTRST_PAD") + ), + MTK_PIN( + 64, "JTDI", + MTK_EINT_FUNCTION(2, 189), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO64"), + MTK_FUNCTION(1, "JTDI"), + MTK_FUNCTION(2, "EINT189"), + MTK_FUNCTION(3, "DSP1_IMS"), + MTK_FUNCTION(7, "MD2_TDI_PAD") + ), + MTK_PIN( + 65, "JRTCK", + MTK_EINT_FUNCTION(2, 187), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO65"), + MTK_FUNCTION(1, "JRTCK"), + MTK_FUNCTION(2, "EINT187"), + MTK_FUNCTION(3, "DSP1_ID"), + MTK_FUNCTION(7, "MD2_RTCK_PAD") + ), + MTK_PIN( + 66, "JTMS", + MTK_EINT_FUNCTION(2, 191), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO66"), + MTK_FUNCTION(1, "JTMS"), + MTK_FUNCTION(2, "EINT191"), + MTK_FUNCTION(3, "DSP2_ID"), + MTK_FUNCTION(7, "MD2_TMS_PAD") + ), + MTK_PIN( + 67, "SDA3", + MTK_EINT_FUNCTION(2, 97), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO67"), + MTK_FUNCTION(1, "SDA3"), + MTK_FUNCTION(2, "EINT97"), + MTK_FUNCTION(7, "A_FUNC_DIN[13]") + ), + MTK_PIN( + 68, "SCL3", + MTK_EINT_FUNCTION(2, 96), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO68"), + MTK_FUNCTION(1, "SCL3"), + MTK_FUNCTION(2, "EINT96"), + MTK_FUNCTION(3, "CLKM6"), + MTK_FUNCTION(4, "PWM6"), + MTK_FUNCTION(7, "A_FUNC_DIN[14]") + ), + MTK_PIN( + 69, "URXD2", + MTK_EINT_FUNCTION(2, 83), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO69"), + MTK_FUNCTION(1, "URXD2"), + MTK_FUNCTION(2, "EINT83"), + MTK_FUNCTION(3, "BSI2_CLK"), + MTK_FUNCTION(4, "MD1_URXD"), + MTK_FUNCTION(5, "CLKM3"), + MTK_FUNCTION(6, "UTXD2"), + MTK_FUNCTION(7, "MD1_EINT4") + ), + MTK_PIN( + 70, "UTXD2", + MTK_EINT_FUNCTION(2, 82), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO70"), + MTK_FUNCTION(1, "UTXD2"), + MTK_FUNCTION(2, "EINT82"), + MTK_FUNCTION(3, "BSI2_CS"), + MTK_FUNCTION(4, "MD1_UTXD"), + MTK_FUNCTION(5, "CLKM2"), + MTK_FUNCTION(6, "URXD2"), + MTK_FUNCTION(7, "MD1_EINT3") + ), + MTK_PIN( + 71, "UCTS2", + MTK_EINT_FUNCTION(2, 84), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO71"), + MTK_FUNCTION(1, "UCTS2"), + MTK_FUNCTION(2, "EINT84"), + MTK_FUNCTION(3, "BSI2_DATA0"), + MTK_FUNCTION(4, "MD2_UTXD"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(6, "URTS2"), + MTK_FUNCTION(7, "MD2_EINT1") + ), + MTK_PIN( + 72, "URTS2", + MTK_EINT_FUNCTION(2, 85), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO72"), + MTK_FUNCTION(1, "URTS2"), + MTK_FUNCTION(2, "EINT85"), + MTK_FUNCTION(3, "BSI2_DATA1"), + MTK_FUNCTION(4, "MD2_URXD"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(6, "UCTS2"), + MTK_FUNCTION(7, "MD2_EINT2") + ), + MTK_PIN( + 73, "PWM1", + MTK_EINT_FUNCTION(2, 73), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO73"), + MTK_FUNCTION(1, "PWM1"), + MTK_FUNCTION(2, "EINT73"), + MTK_FUNCTION(3, "MD1_GPS_SYNC"), + MTK_FUNCTION(4, "MD2_GPS_SYNC"), + MTK_FUNCTION(5, "USB_DRVVBUS"), + MTK_FUNCTION(6, "DISP_PWM"), + MTK_FUNCTION(7, "MD2_TCK_PAD") + ), + MTK_PIN( + 74, "PWM2", + MTK_EINT_FUNCTION(2, 74), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO74"), + MTK_FUNCTION(1, "PWM2"), + MTK_FUNCTION(2, "EINT74"), + MTK_FUNCTION(3, "BPI2_BUS11"), + MTK_FUNCTION(4, "PWM5"), + MTK_FUNCTION(5, "URXD2"), + MTK_FUNCTION(6, "DISP_PWM"), + MTK_FUNCTION(7, "MD2_RTCK_PAD") + ), + MTK_PIN( + 75, "PWM3", + MTK_EINT_FUNCTION(2, 75), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO75"), + MTK_FUNCTION(1, "PWM3"), + MTK_FUNCTION(2, "EINT75"), + MTK_FUNCTION(3, "BPI2_BUS12"), + MTK_FUNCTION(4, "PWM6"), + MTK_FUNCTION(5, "UTXD2"), + MTK_FUNCTION(6, "DISP_PWM"), + MTK_FUNCTION(7, "MD2_NTRST_PAD") + ), + MTK_PIN( + 76, "PWM4", + MTK_EINT_FUNCTION(2, 76), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO76"), + MTK_FUNCTION(1, "PWM4"), + MTK_FUNCTION(2, "EINT76"), + MTK_FUNCTION(3, "BPI2_BUS13"), + MTK_FUNCTION(4, "PWM7"), + MTK_FUNCTION(6, "DISP_PWM"), + MTK_FUNCTION(7, "MD2_TMS_PAD") + ), + MTK_PIN( + 77, "URXD1", + MTK_EINT_FUNCTION(2, 79), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO77"), + MTK_FUNCTION(1, "URXD1"), + MTK_FUNCTION(2, "EINT79"), + MTK_FUNCTION(3, "URXD4"), + MTK_FUNCTION(4, "MD1_URXD"), + MTK_FUNCTION(5, "MD2_URXD"), + MTK_FUNCTION(6, "UTXD1"), + MTK_FUNCTION(7, "MD2_TDO_PAD") + ), + MTK_PIN( + 78, "UTXD1", + MTK_EINT_FUNCTION(2, 78), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO78"), + MTK_FUNCTION(1, "UTXD1"), + MTK_FUNCTION(2, "EINT78"), + MTK_FUNCTION(3, "UTXD4"), + MTK_FUNCTION(4, "MD1_UTXD"), + MTK_FUNCTION(5, "MD2_UTXD"), + MTK_FUNCTION(6, "URXD1"), + MTK_FUNCTION(7, "MD2_TDI_PAD") + ), + MTK_PIN( + 79, "UCTS1", + MTK_EINT_FUNCTION(2, 80), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO79"), + MTK_FUNCTION(1, "UCTS1"), + MTK_FUNCTION(2, "EINT80"), + MTK_FUNCTION(3, "DUAL_BPI1_BUS14"), + MTK_FUNCTION(4, "MD1_UTXD"), + MTK_FUNCTION(5, "CLKM0"), + MTK_FUNCTION(6, "URTS1"), + MTK_FUNCTION(7, "MD1_EINT1") + ), + MTK_PIN( + 80, "URTS1", + MTK_EINT_FUNCTION(2, 81), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO80"), + MTK_FUNCTION(1, "URTS1"), + MTK_FUNCTION(2, "EINT81"), + MTK_FUNCTION(3, "DUAL_BPI1_BUS15"), + MTK_FUNCTION(4, "MD1_URXD"), + MTK_FUNCTION(5, "CLKM1"), + MTK_FUNCTION(6, "UCTS1"), + MTK_FUNCTION(7, "MD1_EINT2") + ), + MTK_PIN( + 81, "URXD4", + MTK_EINT_FUNCTION(2, 89), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO81"), + MTK_FUNCTION(1, "URXD4"), + MTK_FUNCTION(2, "EINT89"), + MTK_FUNCTION(3, "URXD1"), + MTK_FUNCTION(4, "MD1_URXD"), + MTK_FUNCTION(5, "MD2_URXD"), + MTK_FUNCTION(6, "UTXD4"), + MTK_FUNCTION(7, "MD2_EINT5") + ), + MTK_PIN( + 82, "UTXD4", + MTK_EINT_FUNCTION(2, 88), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO82"), + MTK_FUNCTION(1, "UTXD4"), + MTK_FUNCTION(2, "EINT88"), + MTK_FUNCTION(3, "UTXD1"), + MTK_FUNCTION(4, "MD1_UTXD"), + MTK_FUNCTION(5, "MD2_UTXD"), + MTK_FUNCTION(6, "URXD4"), + MTK_FUNCTION(7, "MD1_EINT5") + ), + MTK_PIN( + 83, "DUAL_BPI1_BUS0", + MTK_EINT_FUNCTION(2, 1), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO83"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS0"), + MTK_FUNCTION(2, "EINT1"), + MTK_FUNCTION(3, "BPI2_BUS0"), + MTK_FUNCTION(5, "USB_TEST_IO[0]"), + MTK_FUNCTION(7, "A_FUNC_DIN[31]") + ), + MTK_PIN( + 84, "DUAL_BPI1_BUS1", + MTK_EINT_FUNCTION(2, 2), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO84"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS1"), + MTK_FUNCTION(2, "EINT2"), + MTK_FUNCTION(3, "BPI2_BUS1"), + MTK_FUNCTION(5, "USB_TEST_IO[1]"), + MTK_FUNCTION(7, "A_FUNC_DIN[30]") + ), + MTK_PIN( + 85, "DUAL_BPI1_BUS2", + MTK_EINT_FUNCTION(2, 3), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO85"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS2"), + MTK_FUNCTION(2, "EINT3"), + MTK_FUNCTION(3, "BPI2_BUS2"), + MTK_FUNCTION(5, "USB_TEST_IO[2]"), + MTK_FUNCTION(7, "A_FUNC_DIN[29]") + ), + MTK_PIN( + 86, "DUAL_BPI1_BUS3", + MTK_EINT_FUNCTION(2, 4), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO86"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS3"), + MTK_FUNCTION(2, "EINT4"), + MTK_FUNCTION(3, "BPI2_BUS3"), + MTK_FUNCTION(5, "USB_TEST_IO[3]"), + MTK_FUNCTION(7, "A_FUNC_DIN[28]") + ), + MTK_PIN( + 87, "DUAL_BPI1_BUS4", + MTK_EINT_FUNCTION(2, 5), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO87"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS4"), + MTK_FUNCTION(2, "EINT5"), + MTK_FUNCTION(3, "BPI2_BUS4"), + MTK_FUNCTION(5, "USB_TEST_IO[4]"), + MTK_FUNCTION(7, "A_FUNC_DIN[27]") + ), + MTK_PIN( + 88, "DUAL_BPI1_BUS5", + MTK_EINT_FUNCTION(2, 6), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO88"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS5"), + MTK_FUNCTION(2, "EINT6"), + MTK_FUNCTION(3, "BPI2_BUS5"), + MTK_FUNCTION(5, "USB_TEST_IO[5]"), + MTK_FUNCTION(7, "A_FUNC_DIN[26]") + ), + MTK_PIN( + 89, "DUAL_BPI1_BUS6", + MTK_EINT_FUNCTION(2, 7), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO89"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS6"), + MTK_FUNCTION(2, "EINT7"), + MTK_FUNCTION(3, "BPI2_BUS6"), + MTK_FUNCTION(5, "USB_TEST_IO[6]"), + MTK_FUNCTION(7, "A_FUNC_DIN[25]") + ), + MTK_PIN( + 90, "DUAL_BPI1_BUS7", + MTK_EINT_FUNCTION(2, 8), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO90"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS7"), + MTK_FUNCTION(2, "EINT8"), + MTK_FUNCTION(3, "MD1_GPS_SYNC"), + MTK_FUNCTION(4, "MD2_GPS_SYNC"), + MTK_FUNCTION(5, "USB_TEST_IO[7]"), + MTK_FUNCTION(6, "USB_DRVVBUS"), + MTK_FUNCTION(7, "A_FUNC_DIN[24]") + ), + MTK_PIN( + 91, "DUAL_BPI1_BUS8", + MTK_EINT_FUNCTION(2, 9), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO91"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS8"), + MTK_FUNCTION(2, "EINT9"), + MTK_FUNCTION(3, "DUAL_BPI1_BUS14"), + MTK_FUNCTION(5, "USB_TEST_IO[8]"), + MTK_FUNCTION(7, "A_FUNC_DIN[23]") + ), + MTK_PIN( + 92, "DUAL_BPI1_BUS9", + MTK_EINT_FUNCTION(2, 10), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO92"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS9"), + MTK_FUNCTION(2, "EINT10"), + MTK_FUNCTION(3, "DUAL_BPI1_BUS15"), + MTK_FUNCTION(5, "USB_TEST_IO[9]"), + MTK_FUNCTION(7, "A_FUNC_DIN[22]") + ), + MTK_PIN( + 93, "DUAL_BPI1_BUS10", + MTK_EINT_FUNCTION(2, 11), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO93"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS10"), + MTK_FUNCTION(2, "EINT11"), + MTK_FUNCTION(5, "USB_TEST_IO[10]"), + MTK_FUNCTION(7, "A_FUNC_DIN[21]") + ), + MTK_PIN( + 94, "DUAL_BPI1_BUS11", + MTK_EINT_FUNCTION(2, 12), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO94"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS11"), + MTK_FUNCTION(2, "EINT12"), + MTK_FUNCTION(3, "BPI2_BUS11"), + MTK_FUNCTION(5, "USB_TEST_IO[11]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[7]") + ), + MTK_PIN( + 95, "DUAL_BPI1_BUS12", + MTK_EINT_FUNCTION(2, 13), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO95"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS12"), + MTK_FUNCTION(2, "EINT13"), + MTK_FUNCTION(3, "BPI2_BUS12"), + MTK_FUNCTION(5, "USB_TEST_IO[12]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[6]") + ), + MTK_PIN( + 96, "DUAL_BPI1_BUS13", + MTK_EINT_FUNCTION(2, 14), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO96"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS13"), + MTK_FUNCTION(2, "EINT14"), + MTK_FUNCTION(3, "BPI2_BUS13"), + MTK_FUNCTION(5, "USB_TEST_IO[13]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[5]") + ), + MTK_PIN( + 97, "DUAL_BPI1_BUS14", + MTK_EINT_FUNCTION(2, 15), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO97"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS14"), + MTK_FUNCTION(2, "EINT15"), + MTK_FUNCTION(3, "BPI2_BUS16"), + MTK_FUNCTION(5, "USB_TEST_IO[14]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[4]") + ), + MTK_PIN( + 98, "DUAL_BPI1_BUS17", + MTK_EINT_FUNCTION(2, 16), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO98"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS17"), + MTK_FUNCTION(2, "EINT16"), + MTK_FUNCTION(3, "BPI2_BUS17"), + MTK_FUNCTION(5, "USB_TEST_IO[15]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[3]") + ), + MTK_PIN( + 99, "DUAL_BPI1_BUS15", + MTK_EINT_FUNCTION(2, 17), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO99"), + MTK_FUNCTION(1, "DUAL_BPI1_BUS15"), + MTK_FUNCTION(2, "EINT17"), + MTK_FUNCTION(3, "BPI2_BUS18"), + MTK_FUNCTION(5, "USB_TEST_IO[16]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[2]") + ), + MTK_PIN( + 100, "VM1", + MTK_EINT_FUNCTION(2, 19), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO100"), + MTK_FUNCTION(1, "VM1"), + MTK_FUNCTION(2, "EINT19"), + MTK_FUNCTION(5, "USB_TEST_IO[17]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[0]") + ), + MTK_PIN( + 101, "VM0", + MTK_EINT_FUNCTION(2, 18), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO101"), + MTK_FUNCTION(1, "VM0"), + MTK_FUNCTION(2, "EINT18"), + MTK_FUNCTION(5, "USB_TEST_IO[18]"), + MTK_FUNCTION(7, "A_FUNC_DOUT[1]") + ), + MTK_PIN( + 102, "BSI1B_CS0", + MTK_EINT_FUNCTION(2, 26), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO102"), + MTK_FUNCTION(1, "BSI1B_CS0"), + MTK_FUNCTION(2, "EINT26"), + MTK_FUNCTION(5, "USB_TEST_IO[19]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[21]") + ), + MTK_PIN( + 103, "BSI1B_DATA0", + MTK_EINT_FUNCTION(2, 27), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO103"), + MTK_FUNCTION(1, "BSI1B_DATA0"), + MTK_FUNCTION(2, "EINT27"), + MTK_FUNCTION(5, "USB_TEST_IO[20]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[22]") + ), + MTK_PIN( + 104, "BSI1B_CLK", + MTK_EINT_FUNCTION(2, 25), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO104"), + MTK_FUNCTION(1, "BSI1B_CLK"), + MTK_FUNCTION(2, "EINT25"), + MTK_FUNCTION(5, "USB_TEST_IO[21]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[23]") + ), + MTK_PIN( + 105, "TXBPI1", + MTK_EINT_FUNCTION(2, 30), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO105"), + MTK_FUNCTION(1, "TXBPI1"), + MTK_FUNCTION(2, "EINT30") + ), + MTK_PIN( + 106, "EXT_CLK_EN", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO106"), + MTK_FUNCTION(1, "EXT_CLK_EN") + ), + MTK_PIN( + 107, "SRCLKENA2", + MTK_EINT_FUNCTION(2, 39), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO107"), + MTK_FUNCTION(1, "SRCLKENA2"), + MTK_FUNCTION(2, "EINT39") + ), + MTK_PIN( + 108, "BSI1A_CS0", + MTK_EINT_FUNCTION(2, 21), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO108"), + MTK_FUNCTION(1, "BSI1A_CS0"), + MTK_FUNCTION(2, "EINT21"), + MTK_FUNCTION(3, "BSI2_CS"), + MTK_FUNCTION(5, "USB_TEST_IO[22]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[24]") + ), + MTK_PIN( + 109, "BSI1A_DATA2", + MTK_EINT_FUNCTION(2, 24), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO109"), + MTK_FUNCTION(1, "BSI1A_DATA2"), + MTK_FUNCTION(2, "EINT24"), + MTK_FUNCTION(5, "USB_TEST_IO[23]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[25]") + ), + MTK_PIN( + 110, "BSI1A_DATA1", + MTK_EINT_FUNCTION(2, 23), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO110"), + MTK_FUNCTION(1, "BSI1A_DATA1"), + MTK_FUNCTION(2, "EINT23"), + MTK_FUNCTION(3, "BSI2_DATA1"), + MTK_FUNCTION(5, "USB_TEST_IO[24]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[26]") + ), + MTK_PIN( + 111, "BSI1A_DATA0", + MTK_EINT_FUNCTION(2, 22), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO111"), + MTK_FUNCTION(1, "BSI1A_DATA0"), + MTK_FUNCTION(2, "EINT22"), + MTK_FUNCTION(3, "BSI2_DATA0"), + MTK_FUNCTION(5, "USB_TEST_IO[25]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[27]") + ), + MTK_PIN( + 112, "BSI1A_CLK", + MTK_EINT_FUNCTION(2, 20), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO112"), + MTK_FUNCTION(1, "BSI1A_CLK"), + MTK_FUNCTION(2, "EINT20"), + MTK_FUNCTION(3, "BSI2_CLK"), + MTK_FUNCTION(5, "USB_TEST_IO[26]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[28]") + ), + MTK_PIN( + 113, "BSI1C_DATA", + MTK_EINT_FUNCTION(2, 29), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO113"), + MTK_FUNCTION(1, "BSI1C_DATA"), + MTK_FUNCTION(2, "EINT29"), + MTK_FUNCTION(3, "MD1_GPS_SYNC"), + MTK_FUNCTION(4, "MD2_GPS_SYNC"), + MTK_FUNCTION(5, "USB_TEST_IO[27]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[29]"), + MTK_FUNCTION(7, "USB_DRVVBUS") + ), + MTK_PIN( + 114, "BSI1C_CLK", + MTK_EINT_FUNCTION(2, 28), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO114"), + MTK_FUNCTION(1, "BSI1C_CLK"), + MTK_FUNCTION(2, "EINT28"), + MTK_FUNCTION(5, "USB_TEST_IO[28]"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[30]") + ), + MTK_PIN( + 115, "EINT10", + MTK_EINT_FUNCTION(1, 10), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO115"), + MTK_FUNCTION(1, "EINT10"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[31]") + ), + MTK_PIN( + 116, "EINT11", + MTK_EINT_FUNCTION(1, 11), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO116"), + MTK_FUNCTION(1, "EINT11"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[32]") + ), + MTK_PIN( + 117, "EINT16", + MTK_EINT_FUNCTION(1, 16), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO117"), + MTK_FUNCTION(1, "EINT16"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[33]") + ), + MTK_PIN( + 118, "SDA0", + MTK_EINT_FUNCTION(2, 91), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO118"), + MTK_FUNCTION(1, "SDA0"), + MTK_FUNCTION(2, "EINT91"), + MTK_FUNCTION(3, "CLKM1"), + MTK_FUNCTION(4, "PWM1"), + MTK_FUNCTION(7, "A_FUNC_DIN[19]") + ), + MTK_PIN( + 119, "SCL0", + MTK_EINT_FUNCTION(2, 90), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO119"), + MTK_FUNCTION(1, "SCL0"), + MTK_FUNCTION(2, "EINT90"), + MTK_FUNCTION(3, "CLKM0"), + MTK_FUNCTION(4, "DISP_PWM"), + MTK_FUNCTION(7, "A_FUNC_DIN[20]") + ), + MTK_PIN( + 120, "I2SIN_CK", + MTK_EINT_FUNCTION(2, 10), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO120"), + MTK_FUNCTION(1, "I2SIN_CK"), + MTK_FUNCTION(2, "EINT10"), + MTK_FUNCTION(3, "DAC_CK"), + MTK_FUNCTION(4, "PCM1_CK"), + MTK_FUNCTION(5, "DSP1_ICK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[34]") + ), + MTK_PIN( + 121, "I2SIN_WS", + MTK_EINT_FUNCTION(2, 13), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO121"), + MTK_FUNCTION(1, "I2SIN_WS"), + MTK_FUNCTION(2, "EINT13"), + MTK_FUNCTION(3, "DAC_WS"), + MTK_FUNCTION(4, "PCM1_WS"), + MTK_FUNCTION(5, "DSP1_ID"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[35]") + ), + MTK_PIN( + 122, "I2SIN_DAT", + MTK_EINT_FUNCTION(2, 11), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO122"), + MTK_FUNCTION(1, "I2SIN_DAT"), + MTK_FUNCTION(2, "EINT11"), + MTK_FUNCTION(4, "PCM1_DI"), + MTK_FUNCTION(5, "DSP1_IMS"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[36]") + ), + MTK_PIN( + 123, "I2SOUT_DAT", + MTK_EINT_FUNCTION(2, 12), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO123"), + MTK_FUNCTION(1, "I2SOUT_DAT"), + MTK_FUNCTION(2, "EINT12"), + MTK_FUNCTION(3, "DAC_DAT_OUT"), + MTK_FUNCTION(4, "PCM1_DO"), + MTK_FUNCTION(5, "MD2_EINT5"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[37]") + ), + MTK_PIN( + 124, "EINT5", + MTK_EINT_FUNCTION(1, 5), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO124"), + MTK_FUNCTION(1, "EINT5"), + MTK_FUNCTION(2, "PWM5"), + MTK_FUNCTION(3, "CLKM3"), + MTK_FUNCTION(4, "MD1_UTXD"), + MTK_FUNCTION(5, "MD2_EINT1"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[38]") + ), + MTK_PIN( + 125, "EINT6", + MTK_EINT_FUNCTION(1, 6), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO125"), + MTK_FUNCTION(1, "EINT6"), + MTK_FUNCTION(2, "PWM6"), + MTK_FUNCTION(3, "CLKM4"), + MTK_FUNCTION(4, "MD1_URXD"), + MTK_FUNCTION(5, "MD2_EINT2"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[39]") + ), + MTK_PIN( + 126, "EINT7", + MTK_EINT_FUNCTION(1, 7), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO126"), + MTK_FUNCTION(1, "EINT7"), + MTK_FUNCTION(2, "PWM7"), + MTK_FUNCTION(3, "CLKM5"), + MTK_FUNCTION(4, "SRCLKENAI2"), + MTK_FUNCTION(5, "MD2_EINT3"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[40]") + ), + MTK_PIN( + 127, "EINT8", + MTK_EINT_FUNCTION(1, 8), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO127"), + MTK_FUNCTION(1, "EINT8"), + MTK_FUNCTION(2, "DISP_PWM"), + MTK_FUNCTION(3, "CLKM6"), + MTK_FUNCTION(5, "MD2_EINT4"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[41]"), + MTK_FUNCTION(7, "EXT_FRAME_SYNC") + ), + MTK_PIN( + 128, "EINT9", + MTK_EINT_FUNCTION(1, 9), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO128"), + MTK_FUNCTION(1, "EINT9"), + MTK_FUNCTION(3, "MD1_GPS_SYNC"), + MTK_FUNCTION(4, "MD2_GPS_SYNC"), + MTK_FUNCTION(5, "USB_DRVVBUS"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[42]") + ), + MTK_PIN( + 129, "DISP_PWM", + MTK_EINT_FUNCTION(2, 77), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO129"), + MTK_FUNCTION(1, "DISP_PWM"), + MTK_FUNCTION(2, "EINT77"), + MTK_FUNCTION(3, "LSDI"), + MTK_FUNCTION(4, "PWM1"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[43]"), + MTK_FUNCTION(7, "PWM3") + ), + MTK_PIN( + 130, "MSDC4_DAT0", + MTK_EINT_FUNCTION(2, 133), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO130"), + MTK_FUNCTION(1, "MSDC4_DAT0"), + MTK_FUNCTION(2, "EINT133"), + MTK_FUNCTION(4, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "USB_DRVVBUS"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[46]"), + MTK_FUNCTION(7, "LPTE") + ), + MTK_PIN( + 131, "MSDC4_DAT1", + MTK_EINT_FUNCTION(2, 134), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO131"), + MTK_FUNCTION(1, "MSDC4_DAT1"), + MTK_FUNCTION(2, "EINT134"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[47]"), + MTK_FUNCTION(7, "LRSTB_1X") + ), + MTK_PIN( + 132, "LPCE1B", + MTK_EINT_FUNCTION(2, 127), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO132"), + MTK_FUNCTION(1, "LPCE1B"), + MTK_FUNCTION(2, "EINT127"), + MTK_FUNCTION(3, "DPI1_HSYNC_2X"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[44]") + ), + MTK_PIN( + 133, "LPCE0B", + MTK_EINT_FUNCTION(2, 126), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO133"), + MTK_FUNCTION(1, "LPCE0B"), + MTK_FUNCTION(2, "EINT126"), + MTK_FUNCTION(3, "DPI1_VSYNC_2X"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[45]") + ), + MTK_PIN( + 134, "MSDC4_DAT5", + MTK_EINT_FUNCTION(2, 136), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO134"), + MTK_FUNCTION(1, "MSDC4_DAT5"), + MTK_FUNCTION(2, "EINT136"), + MTK_FUNCTION(3, "I2SIN_WS"), + MTK_FUNCTION(4, "DAC_WS"), + MTK_FUNCTION(5, "PCM1_WS"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[48]"), + MTK_FUNCTION(7, "SPI1_CSN") + ), + MTK_PIN( + 135, "MSDC4_DAT6", + MTK_EINT_FUNCTION(2, 137), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO135"), + MTK_FUNCTION(1, "MSDC4_DAT6"), + MTK_FUNCTION(2, "EINT137"), + MTK_FUNCTION(3, "I2SOUT_DAT"), + MTK_FUNCTION(4, "DAC_DAT_OUT"), + MTK_FUNCTION(5, "PCM1_DO"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[49]"), + MTK_FUNCTION(7, "SPI1_MO") + ), + MTK_PIN( + 136, "MSDC4_DAT7", + MTK_EINT_FUNCTION(2, 138), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO136"), + MTK_FUNCTION(1, "MSDC4_DAT7"), + MTK_FUNCTION(2, "EINT138"), + MTK_FUNCTION(3, "I2SIN_DAT"), + MTK_FUNCTION(5, "PCM1_DI"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[50]"), + MTK_FUNCTION(7, "SPI1_MI") + ), + MTK_PIN( + 137, "MSDC4_DAT4", + MTK_EINT_FUNCTION(2, 135), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO137"), + MTK_FUNCTION(1, "MSDC4_DAT4"), + MTK_FUNCTION(2, "EINT135"), + MTK_FUNCTION(3, "I2SIN_CK"), + MTK_FUNCTION(4, "DAC_CK"), + MTK_FUNCTION(5, "PCM1_CK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[51]"), + MTK_FUNCTION(7, "SPI1_CLK") + ), + MTK_PIN( + 138, "MSDC4_DAT2", + MTK_EINT_FUNCTION(2, 131), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO138"), + MTK_FUNCTION(1, "MSDC4_DAT2"), + MTK_FUNCTION(2, "EINT131"), + MTK_FUNCTION(3, "I2SIN_WS"), + MTK_FUNCTION(4, "CM2PDN_2X"), + MTK_FUNCTION(5, "DAC_WS"), + MTK_FUNCTION(6, "PCM1_WS"), + MTK_FUNCTION(7, "LSCE0B_1X") + ), + MTK_PIN( + 139, "MSDC4_CLK", + MTK_EINT_FUNCTION(2, 129), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO139"), + MTK_FUNCTION(1, "MSDC4_CLK"), + MTK_FUNCTION(2, "EINT129"), + MTK_FUNCTION(3, "DPI1_CK_2X"), + MTK_FUNCTION(4, "CM2PCLK_2X"), + MTK_FUNCTION(5, "PWM4"), + MTK_FUNCTION(6, "PCM1_DI"), + MTK_FUNCTION(7, "LSCK_1X") + ), + MTK_PIN( + 140, "MSDC4_DAT3", + MTK_EINT_FUNCTION(2, 132), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO140"), + MTK_FUNCTION(1, "MSDC4_DAT3"), + MTK_FUNCTION(2, "EINT132"), + MTK_FUNCTION(3, "I2SOUT_DAT"), + MTK_FUNCTION(4, "CM2RST_2X"), + MTK_FUNCTION(5, "DAC_DAT_OUT"), + MTK_FUNCTION(6, "PCM1_DO"), + MTK_FUNCTION(7, "LSCE1B_1X") + ), + MTK_PIN( + 141, "MSDC4_CMD", + MTK_EINT_FUNCTION(2, 128), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO141"), + MTK_FUNCTION(1, "MSDC4_CMD"), + MTK_FUNCTION(2, "EINT128"), + MTK_FUNCTION(3, "DPI1_DE_2X"), + MTK_FUNCTION(4, "MD1_GPS_SYNC"), + MTK_FUNCTION(5, "PWM3"), + MTK_FUNCTION(6, "MD2_GPS_SYNC"), + MTK_FUNCTION(7, "LSDA_1X") + ), + MTK_PIN( + 142, "MSDC4_RSTB", + MTK_EINT_FUNCTION(2, 130), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO142"), + MTK_FUNCTION(1, "MSDC4_RSTB"), + MTK_FUNCTION(2, "EINT130"), + MTK_FUNCTION(3, "I2SIN_CK"), + MTK_FUNCTION(4, "CM2MCLK_2X"), + MTK_FUNCTION(5, "DAC_CK"), + MTK_FUNCTION(6, "PCM1_CK"), + MTK_FUNCTION(7, "LSA0_1X") + ), + MTK_PIN( + 143, "DPI0_VSYNC", + MTK_EINT_FUNCTION(2, 98), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO143"), + MTK_FUNCTION(1, "DPI0_VSYNC"), + MTK_FUNCTION(2, "EINT98"), + MTK_FUNCTION(3, "I2SIN_CK"), + MTK_FUNCTION(4, "DAC_CK"), + MTK_FUNCTION(5, "PCM1_CK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[52]"), + MTK_FUNCTION(7, "TESTB_OUT8") + ), + MTK_PIN( + 144, "DPI0_HSYNC", + MTK_EINT_FUNCTION(2, 99), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO144"), + MTK_FUNCTION(1, "DPI0_HSYNC"), + MTK_FUNCTION(2, "EINT99"), + MTK_FUNCTION(3, "I2SIN_WS"), + MTK_FUNCTION(4, "DAC_WS"), + MTK_FUNCTION(5, "PCM1_WS"), + MTK_FUNCTION(6, "IRDA_RXD"), + MTK_FUNCTION(7, "TESTB_OUT9") + ), + MTK_PIN( + 145, "DPI0_DE", + MTK_EINT_FUNCTION(2, 100), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO145"), + MTK_FUNCTION(1, "DPI0_DE"), + MTK_FUNCTION(2, "EINT100"), + MTK_FUNCTION(3, "I2SOUT_DAT"), + MTK_FUNCTION(4, "DAC_DAT_OUT"), + MTK_FUNCTION(5, "PCM1_DO"), + MTK_FUNCTION(6, "IRDA_TXD"), + MTK_FUNCTION(7, "TESTB_OUT10") + ), + MTK_PIN( + 146, "DPI0_CK", + MTK_EINT_FUNCTION(2, 101), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO146"), + MTK_FUNCTION(1, "DPI0_CK"), + MTK_FUNCTION(2, "EINT101"), + MTK_FUNCTION(3, "I2SIN_DAT"), + MTK_FUNCTION(5, "PCM1_DI"), + MTK_FUNCTION(6, "IRDA_PDN"), + MTK_FUNCTION(7, "TESTB_OUT11") + ), + MTK_PIN( + 147, "DPI0_B0", + MTK_EINT_FUNCTION(2, 102), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO147"), + MTK_FUNCTION(1, "DPI0_B0"), + MTK_FUNCTION(2, "EINT102"), + MTK_FUNCTION(4, "SCL0"), + MTK_FUNCTION(5, "DISP_PWM"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[57]"), + MTK_FUNCTION(7, "TESTB_OUT12") + ), + MTK_PIN( + 148, "DPI0_B1", + MTK_EINT_FUNCTION(2, 103), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO148"), + MTK_FUNCTION(1, "DPI0_B1"), + MTK_FUNCTION(2, "EINT103"), + MTK_FUNCTION(3, "CLKM0"), + MTK_FUNCTION(4, "SDA0"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[58]"), + MTK_FUNCTION(7, "TESTB_OUT13") + ), + MTK_PIN( + 149, "DPI0_B2", + MTK_EINT_FUNCTION(2, 104), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO149"), + MTK_FUNCTION(1, "DPI0_B2"), + MTK_FUNCTION(2, "EINT104"), + MTK_FUNCTION(3, "CLKM1"), + MTK_FUNCTION(4, "SCL1"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[59]"), + MTK_FUNCTION(7, "TESTB_OUT14") + ), + MTK_PIN( + 150, "DPI0_B3", + MTK_EINT_FUNCTION(2, 105), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO150"), + MTK_FUNCTION(1, "DPI0_B3"), + MTK_FUNCTION(2, "EINT105"), + MTK_FUNCTION(3, "CLKM2"), + MTK_FUNCTION(4, "SDA1"), + MTK_FUNCTION(5, "PWM3"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[60]"), + MTK_FUNCTION(7, "TESTB_OUT15") + ), + MTK_PIN( + 151, "DPI0_B4", + MTK_EINT_FUNCTION(2, 106), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO151"), + MTK_FUNCTION(1, "DPI0_B4"), + MTK_FUNCTION(2, "EINT106"), + MTK_FUNCTION(3, "CLKM3"), + MTK_FUNCTION(4, "SCL2"), + MTK_FUNCTION(5, "PWM4"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[61]"), + MTK_FUNCTION(7, "TESTB_OUT16") + ), + MTK_PIN( + 152, "DPI0_B5", + MTK_EINT_FUNCTION(2, 107), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO152"), + MTK_FUNCTION(1, "DPI0_B5"), + MTK_FUNCTION(2, "EINT107"), + MTK_FUNCTION(3, "CLKM4"), + MTK_FUNCTION(4, "SDA2"), + MTK_FUNCTION(5, "PWM5"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[62]"), + MTK_FUNCTION(7, "TESTB_OUT17") + ), + MTK_PIN( + 153, "DPI0_B6", + MTK_EINT_FUNCTION(2, 108), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO153"), + MTK_FUNCTION(1, "DPI0_B6"), + MTK_FUNCTION(2, "EINT108"), + MTK_FUNCTION(3, "CLKM5"), + MTK_FUNCTION(4, "SCL3"), + MTK_FUNCTION(5, "PWM6"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[63]"), + MTK_FUNCTION(7, "TESTB_OUT18") + ), + MTK_PIN( + 154, "DPI0_B7", + MTK_EINT_FUNCTION(2, 109), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO154"), + MTK_FUNCTION(1, "DPI0_B7"), + MTK_FUNCTION(2, "EINT109"), + MTK_FUNCTION(3, "CLKM6"), + MTK_FUNCTION(4, "SDA3"), + MTK_FUNCTION(5, "PWM7"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[0]"), + MTK_FUNCTION(7, "TESTB_OUT19") + ), + MTK_PIN( + 155, "DPI0_G0", + MTK_EINT_FUNCTION(2, 110), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO155"), + MTK_FUNCTION(1, "DPI0_G0"), + MTK_FUNCTION(2, "EINT110"), + MTK_FUNCTION(5, "DSP1_ID"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[1]"), + MTK_FUNCTION(7, "TESTB_OUT20") + ), + MTK_PIN( + 156, "DPI0_G1", + MTK_EINT_FUNCTION(2, 111), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO156"), + MTK_FUNCTION(1, "DPI0_G1"), + MTK_FUNCTION(2, "EINT111"), + MTK_FUNCTION(5, "DSP1_ICK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[56]"), + MTK_FUNCTION(7, "TESTB_OUT21") + ), + MTK_PIN( + 157, "DPI0_G2", + MTK_EINT_FUNCTION(2, 112), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO157"), + MTK_FUNCTION(1, "DPI0_G2"), + MTK_FUNCTION(2, "EINT112"), + MTK_FUNCTION(5, "DSP1_IMS"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[2]"), + MTK_FUNCTION(7, "TESTB_OUT22") + ), + MTK_PIN( + 158, "DPI0_G3", + MTK_EINT_FUNCTION(2, 113), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO158"), + MTK_FUNCTION(1, "DPI0_G3"), + MTK_FUNCTION(2, "EINT113"), + MTK_FUNCTION(5, "DSP2_IMS"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[3]"), + MTK_FUNCTION(7, "TESTB_OUT23") + ), + MTK_PIN( + 159, "DPI0_G4", + MTK_EINT_FUNCTION(2, 114), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO159"), + MTK_FUNCTION(1, "DPI0_G4"), + MTK_FUNCTION(2, "EINT114"), + MTK_FUNCTION(3, "DPI1_D_2X[0]"), + MTK_FUNCTION(4, "CM2DAT_2X[0]"), + MTK_FUNCTION(5, "DSP2_ID"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[53]"), + MTK_FUNCTION(7, "TESTB_OUT24") + ), + MTK_PIN( + 160, "DPI0_G5", + MTK_EINT_FUNCTION(2, 115), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO160"), + MTK_FUNCTION(1, "DPI0_G5"), + MTK_FUNCTION(2, "EINT115"), + MTK_FUNCTION(3, "DPI1_D_2X[1]"), + MTK_FUNCTION(4, "CM2DAT_2X[1]"), + MTK_FUNCTION(5, "DSP2_ICK"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[54]"), + MTK_FUNCTION(7, "TESTB_OUT25") + ), + MTK_PIN( + 161, "DPI0_G6", + MTK_EINT_FUNCTION(2, 116), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO161"), + MTK_FUNCTION(1, "DPI0_G6"), + MTK_FUNCTION(2, "EINT116"), + MTK_FUNCTION(3, "DPI1_D_2X[2]"), + MTK_FUNCTION(4, "CM2DAT_2X[2]"), + MTK_FUNCTION(5, "MD2_RTCK_PAD"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[4]"), + MTK_FUNCTION(7, "TESTB_OUT26") + ), + MTK_PIN( + 162, "DPI0_G7", + MTK_EINT_FUNCTION(2, 117), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO162"), + MTK_FUNCTION(1, "DPI0_G7"), + MTK_FUNCTION(2, "EINT117"), + MTK_FUNCTION(3, "DPI1_D_2X[3]"), + MTK_FUNCTION(4, "CM2DAT_2X[3]"), + MTK_FUNCTION(5, "MD2_TCK_PAD"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[5]"), + MTK_FUNCTION(7, "TESTB_OUT27") + ), + MTK_PIN( + 163, "DPI0_R0", + MTK_EINT_FUNCTION(2, 118), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO163"), + MTK_FUNCTION(1, "DPI0_R0"), + MTK_FUNCTION(2, "EINT118"), + MTK_FUNCTION(3, "DPI1_D_2X[4]"), + MTK_FUNCTION(4, "CM2DAT_2X[4]"), + MTK_FUNCTION(5, "MD2_TDI_PAD"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[6]"), + MTK_FUNCTION(7, "TESTB_OUT28") + ), + MTK_PIN( + 164, "DPI0_R1", + MTK_EINT_FUNCTION(2, 119), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO164"), + MTK_FUNCTION(1, "DPI0_R1"), + MTK_FUNCTION(2, "EINT119"), + MTK_FUNCTION(3, "DPI1_D_2X[5]"), + MTK_FUNCTION(4, "CM2DAT_2X[5]"), + MTK_FUNCTION(5, "MD2_TDO_PAD"), + MTK_FUNCTION(6, "MD1_PLL_A_FUNC_DOUT[7]"), + MTK_FUNCTION(7, "TESTB_OUT29") + ), + MTK_PIN( + 165, "DPI0_R2", + MTK_EINT_FUNCTION(2, 120), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO165"), + MTK_FUNCTION(1, "DPI0_R2"), + MTK_FUNCTION(2, "EINT120"), + MTK_FUNCTION(3, "DPI1_D_2X[6]"), + MTK_FUNCTION(4, "CM2DAT_2X[6]"), + MTK_FUNCTION(5, "MD2_TMS_PAD"), + MTK_FUNCTION(7, "TESTB_OUT30") + ), + MTK_PIN( + 166, "DPI0_R3", + MTK_EINT_FUNCTION(2, 121), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO166"), + MTK_FUNCTION(1, "DPI0_R3"), + MTK_FUNCTION(2, "EINT121"), + MTK_FUNCTION(3, "DPI1_D_2X[7]"), + MTK_FUNCTION(4, "CM2DAT_2X[7]"), + MTK_FUNCTION(5, "MD2_NTRST_PAD"), + MTK_FUNCTION(6, "MD_ABB_AFUNC_D[55]"), + MTK_FUNCTION(7, "TESTB_OUT31") + ), + MTK_PIN( + 167, "DPI0_R4", + MTK_EINT_FUNCTION(2, 122), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO167"), + MTK_FUNCTION(1, "DPI0_R4"), + MTK_FUNCTION(2, "EINT122"), + MTK_FUNCTION(3, "DPI1_D_2X[8]"), + MTK_FUNCTION(4, "CM2DAT_2X[8]"), + MTK_FUNCTION(7, "TESTA_OUT0") + ), + MTK_PIN( + 168, "DPI0_R5", + MTK_EINT_FUNCTION(2, 123), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO168"), + MTK_FUNCTION(1, "DPI0_R5"), + MTK_FUNCTION(2, "EINT123"), + MTK_FUNCTION(3, "DPI1_D_2X[9]"), + MTK_FUNCTION(4, "CM2DAT_2X[9]"), + MTK_FUNCTION(5, "MD1_DAI_RX_GPIO"), + MTK_FUNCTION(6, "MD2_DAI_RX_GPIO"), + MTK_FUNCTION(7, "TESTA_OUT1") + ), + MTK_PIN( + 169, "DPI0_R6", + MTK_EINT_FUNCTION(2, 124), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO169"), + MTK_FUNCTION(1, "DPI0_R6"), + MTK_FUNCTION(2, "EINT124"), + MTK_FUNCTION(3, "DPI1_D_2X[10]"), + MTK_FUNCTION(4, "CM2VSYNC_2X"), + MTK_FUNCTION(7, "TESTA_OUT2") + ), + MTK_PIN( + 170, "DPI0_R7", + MTK_EINT_FUNCTION(2, 125), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO170"), + MTK_FUNCTION(1, "DPI0_R7"), + MTK_FUNCTION(2, "EINT125"), + MTK_FUNCTION(3, "DPI1_D_2X[11]"), + MTK_FUNCTION(4, "CM2HSYNC_2X"), + MTK_FUNCTION(7, "TESTA_OUT3") + ), + MTK_PIN( + 171, "MSDC1_INSI", + MTK_EINT_FUNCTION(2, 57), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO171"), + MTK_FUNCTION(1, "MSDC1_INSI"), + MTK_FUNCTION(2, "EINT57"), + MTK_FUNCTION(3, "SCL5"), + MTK_FUNCTION(4, "PWM6"), + MTK_FUNCTION(5, "CLKM5"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[0]"), + MTK_FUNCTION(7, "TESTB_OUT6") + ), + MTK_PIN( + 172, "MSDC2_INSI", + MTK_EINT_FUNCTION(2, 65), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO172"), + MTK_FUNCTION(1, "MSDC2_INSI"), + MTK_FUNCTION(2, "EINT65"), + MTK_FUNCTION(3, "BPI2_BUS6"), + MTK_FUNCTION(7, "A_FUNC_DIN[6]") + ), + MTK_PIN( + 173, "MSDC2_SDWPI", + MTK_EINT_FUNCTION(2, 66), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO173"), + MTK_FUNCTION(1, "MSDC2_SDWPI"), + MTK_FUNCTION(2, "EINT66"), + MTK_FUNCTION(3, "BPI2_BUS17"), + MTK_FUNCTION(4, "DUAL_BPI1_BUS14"), + MTK_FUNCTION(5, "DUAL_BPI1_BUS15"), + MTK_FUNCTION(7, "A_FUNC_DIN[5]") + ), + MTK_PIN( + 174, "MSDC2_DAT2", + MTK_EINT_FUNCTION(2, 63), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO174"), + MTK_FUNCTION(1, "MSDC2_DAT2"), + MTK_FUNCTION(2, "EINT63"), + MTK_FUNCTION(3, "BPI2_BUS4"), + MTK_FUNCTION(4, "DSP2_IMS"), + MTK_FUNCTION(7, "A_FUNC_DIN[8]") + ), + MTK_PIN( + 175, "MSDC2_DAT3", + MTK_EINT_FUNCTION(2, 64), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO175"), + MTK_FUNCTION(1, "MSDC2_DAT3"), + MTK_FUNCTION(2, "EINT64"), + MTK_FUNCTION(3, "BPI2_BUS5"), + MTK_FUNCTION(4, "DSP2_ID"), + MTK_FUNCTION(7, "A_FUNC_DIN[7]") + ), + MTK_PIN( + 176, "MSDC2_CMD", + MTK_EINT_FUNCTION(2, 60), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO176"), + MTK_FUNCTION(1, "MSDC2_CMD"), + MTK_FUNCTION(2, "EINT60"), + MTK_FUNCTION(3, "BPI2_BUS1"), + MTK_FUNCTION(4, "DSP1_IMS"), + MTK_FUNCTION(5, "PCM1_WS"), + MTK_FUNCTION(7, "A_FUNC_DIN[11]") + ), + MTK_PIN( + 177, "MSDC2_CLK", + MTK_EINT_FUNCTION(2, 59), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO177"), + MTK_FUNCTION(1, "MSDC2_CLK"), + MTK_FUNCTION(2, "EINT59"), + MTK_FUNCTION(3, "BPI2_BUS0"), + MTK_FUNCTION(4, "DSP1_ICK"), + MTK_FUNCTION(5, "PCM1_CK"), + MTK_FUNCTION(7, "A_FUNC_DIN[12]") + ), + MTK_PIN( + 178, "MSDC2_DAT1", + MTK_EINT_FUNCTION(2, 62), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO178"), + MTK_FUNCTION(1, "MSDC2_DAT1"), + MTK_FUNCTION(2, "EINT62"), + MTK_FUNCTION(3, "BPI2_BUS3"), + MTK_FUNCTION(4, "DSP2_ICK"), + MTK_FUNCTION(5, "PCM1_DO"), + MTK_FUNCTION(7, "A_FUNC_DIN[9]") + ), + MTK_PIN( + 179, "MSDC2_DAT0", + MTK_EINT_FUNCTION(2, 61), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO179"), + MTK_FUNCTION(1, "MSDC2_DAT0"), + MTK_FUNCTION(2, "EINT61"), + MTK_FUNCTION(3, "BPI2_BUS2"), + MTK_FUNCTION(4, "DSP1_ID"), + MTK_FUNCTION(5, "PCM1_DI"), + MTK_FUNCTION(7, "A_FUNC_DIN[10]") + ), + MTK_PIN( + 180, "MSDC1_DAT0", + MTK_EINT_FUNCTION(2, 53), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO180"), + MTK_FUNCTION(1, "MSDC1_DAT0"), + MTK_FUNCTION(2, "EINT53"), + MTK_FUNCTION(3, "SCL1"), + MTK_FUNCTION(4, "PWM2"), + MTK_FUNCTION(5, "CLKM1"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[1]"), + MTK_FUNCTION(7, "TESTB_OUT2") + ), + MTK_PIN( + 181, "MSDC1_DAT1", + MTK_EINT_FUNCTION(2, 54), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO181"), + MTK_FUNCTION(1, "MSDC1_DAT1"), + MTK_FUNCTION(2, "EINT54"), + MTK_FUNCTION(3, "SDA1"), + MTK_FUNCTION(4, "PWM3"), + MTK_FUNCTION(5, "CLKM2"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[2]"), + MTK_FUNCTION(7, "TESTB_OUT3") + ), + MTK_PIN( + 182, "MSDC1_SDWPI", + MTK_EINT_FUNCTION(2, 58), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO182"), + MTK_FUNCTION(1, "MSDC1_SDWPI"), + MTK_FUNCTION(2, "EINT58"), + MTK_FUNCTION(3, "SDA5"), + MTK_FUNCTION(4, "PWM7"), + MTK_FUNCTION(5, "CLKM6"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[3]"), + MTK_FUNCTION(7, "TESTB_OUT7") + ), + MTK_PIN( + 183, "MSDC1_CMD", + MTK_EINT_FUNCTION(2, 52), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO183"), + MTK_FUNCTION(1, "MSDC1_CMD"), + MTK_FUNCTION(2, "EINT52"), + MTK_FUNCTION(3, "SDA0"), + MTK_FUNCTION(4, "PWM1"), + MTK_FUNCTION(5, "CLKM0"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[4]"), + MTK_FUNCTION(7, "TESTB_OUT1") + ), + MTK_PIN( + 184, "MSDC1_CLK", + MTK_EINT_FUNCTION(2, 51), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO184"), + MTK_FUNCTION(1, "MSDC1_CLK"), + MTK_FUNCTION(2, "EINT51"), + MTK_FUNCTION(3, "SCL0"), + MTK_FUNCTION(4, "DISP_PWM"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[5]"), + MTK_FUNCTION(7, "TESTB_OUT0") + ), + MTK_PIN( + 185, "MSDC1_DAT2", + MTK_EINT_FUNCTION(2, 55), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO185"), + MTK_FUNCTION(1, "MSDC1_DAT2"), + MTK_FUNCTION(2, "EINT55"), + MTK_FUNCTION(3, "SCL4"), + MTK_FUNCTION(4, "PWM4"), + MTK_FUNCTION(5, "CLKM3"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[6]"), + MTK_FUNCTION(7, "TESTB_OUT4") + ), + MTK_PIN( + 186, "MSDC1_DAT3", + MTK_EINT_FUNCTION(2, 56), + DRV_GRP5, + MTK_FUNCTION(0, "GPIO186"), + MTK_FUNCTION(1, "MSDC1_DAT3"), + MTK_FUNCTION(2, "EINT56"), + MTK_FUNCTION(3, "SDA4"), + MTK_FUNCTION(4, "PWM5"), + MTK_FUNCTION(5, "CLKM4"), + MTK_FUNCTION(6, "MD2_PLL_A_FUNC_DOUT[7]"), + MTK_FUNCTION(7, "TESTB_OUT5") + ), + MTK_PIN( + 187, "GPIO187", + MTK_EINT_FUNCTION(2, 36), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO187"), + MTK_FUNCTION(2, "EINT36") + ), + MTK_PIN( + 188, "GPIO188", + MTK_EINT_FUNCTION(2, 35), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO188"), + MTK_FUNCTION(2, "EINT35") + ), + MTK_PIN( + 189, "GPIO189", + MTK_EINT_FUNCTION(2, 169), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO189"), + MTK_FUNCTION(2, "EINT169") + ), + MTK_PIN( + 190, "GPIO190", + MTK_EINT_FUNCTION(2, 168), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO190"), + MTK_FUNCTION(2, "EINT168") + ), + MTK_PIN( + 191, "GPIO191", + MTK_EINT_FUNCTION(2, 163), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO191"), + MTK_FUNCTION(2, "EINT163") + ), + MTK_PIN( + 192, "GPIO192", + MTK_EINT_FUNCTION(2, 162), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO192"), + MTK_FUNCTION(2, "EINT162") + ), + MTK_PIN( + 193, "GPIO193", + MTK_EINT_FUNCTION(2, 167), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO193"), + MTK_FUNCTION(2, "EINT167") + ), + MTK_PIN( + 194, "GPIO194", + MTK_EINT_FUNCTION(2, 166), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO194"), + MTK_FUNCTION(2, "EINT166") + ), + MTK_PIN( + 195, "GPIO195", + MTK_EINT_FUNCTION(2, 165), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO195"), + MTK_FUNCTION(2, "EINT165") + ), + MTK_PIN( + 196, "GPIO196", + MTK_EINT_FUNCTION(2, 164), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO196"), + MTK_FUNCTION(2, "EINT164") + ), + MTK_PIN( + 197, "CMDAT6", + MTK_EINT_FUNCTION(2, 175), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO197"), + MTK_FUNCTION(1, "CMDAT6"), + MTK_FUNCTION(2, "EINT175") + ), + MTK_PIN( + 198, "CMDAT7", + MTK_EINT_FUNCTION(2, 174), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO198"), + MTK_FUNCTION(1, "CMDAT7"), + MTK_FUNCTION(2, "EINT174") + ), + MTK_PIN( + 199, "CMDAT8", + MTK_EINT_FUNCTION(2, 171), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO199"), + MTK_FUNCTION(1, "CMDAT8"), + MTK_FUNCTION(2, "EINT171") + ), + MTK_PIN( + 200, "CMDAT9", + MTK_EINT_FUNCTION(2, 170), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO200"), + MTK_FUNCTION(1, "CMDAT9"), + MTK_FUNCTION(2, "EINT170") + ), + MTK_PIN( + 201, "CMHSYNC", + MTK_EINT_FUNCTION(2, 173), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO201"), + MTK_FUNCTION(1, "CMHSYNC"), + MTK_FUNCTION(2, "EINT173") + ), + MTK_PIN( + 202, "CMVSYNC", + MTK_EINT_FUNCTION(2, 172), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO202"), + MTK_FUNCTION(1, "CMVSYNC"), + MTK_FUNCTION(2, "EINT172") + ), + MTK_PIN( + 203, "CMDAT2", + MTK_EINT_FUNCTION(2, 181), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO203"), + MTK_FUNCTION(1, "CMDAT2"), + MTK_FUNCTION(2, "EINT181"), + MTK_FUNCTION(3, "CMCSD2") + ), + MTK_PIN( + 204, "CMDAT3", + MTK_EINT_FUNCTION(2, 180), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO204"), + MTK_FUNCTION(1, "CMDAT3"), + MTK_FUNCTION(2, "EINT180"), + MTK_FUNCTION(3, "CMCSD3") + ), + MTK_PIN( + 205, "CMDAT4", + MTK_EINT_FUNCTION(2, 177), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO205"), + MTK_FUNCTION(1, "CMDAT4"), + MTK_FUNCTION(2, "EINT177") + ), + MTK_PIN( + 206, "CMDAT5", + MTK_EINT_FUNCTION(2, 176), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO206"), + MTK_FUNCTION(1, "CMDAT5"), + MTK_FUNCTION(2, "EINT176") + ), + MTK_PIN( + 207, "CMDAT0", + MTK_EINT_FUNCTION(2, 179), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO207"), + MTK_FUNCTION(1, "CMDAT0"), + MTK_FUNCTION(2, "EINT179"), + MTK_FUNCTION(3, "CMCSD0") + ), + MTK_PIN( + 208, "CMDAT1", + MTK_EINT_FUNCTION(2, 178), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO208"), + MTK_FUNCTION(1, "CMDAT1"), + MTK_FUNCTION(2, "EINT178"), + MTK_FUNCTION(3, "CMCSD1") + ), + MTK_PIN( + 209, "CMPCLK", + MTK_EINT_FUNCTION(2, 182), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO209"), + MTK_FUNCTION(1, "CMPCLK"), + MTK_FUNCTION(2, "EINT182"), + MTK_FUNCTION(3, "CMCSK"), + MTK_FUNCTION(4, "CM2MCLK_4X"), + MTK_FUNCTION(5, "TS_AUXADC_SEL[3]"), + MTK_FUNCTION(7, "TESTA_OUT27") + ), + MTK_PIN( + 210, "CMMCLK", + MTK_EINT_FUNCTION(2, 183), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO210"), + MTK_FUNCTION(1, "CMMCLK"), + MTK_FUNCTION(2, "EINT183"), + MTK_FUNCTION(5, "TS_AUXADC_SEL[2]"), + MTK_FUNCTION(7, "TESTA_OUT28") + ), + MTK_PIN( + 211, "CMRST", + MTK_EINT_FUNCTION(2, 185), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO211"), + MTK_FUNCTION(1, "CMRST"), + MTK_FUNCTION(2, "EINT185"), + MTK_FUNCTION(5, "TS_AUXADC_SEL[1]"), + MTK_FUNCTION(7, "TESTA_OUT30") + ), + MTK_PIN( + 212, "CMPDN", + MTK_EINT_FUNCTION(2, 184), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO212"), + MTK_FUNCTION(1, "CMPDN"), + MTK_FUNCTION(2, "EINT184"), + MTK_FUNCTION(5, "TS_AUXADC_SEL[0]"), + MTK_FUNCTION(7, "TESTA_OUT29") + ), + MTK_PIN( + 213, "CMFLASH", + MTK_EINT_FUNCTION(2, 186), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO213"), + MTK_FUNCTION(1, "CMFLASH"), + MTK_FUNCTION(2, "EINT186"), + MTK_FUNCTION(3, "CM2MCLK_3X"), + MTK_FUNCTION(7, "TESTA_OUT31") + ), + MTK_PIN( + 214, "SDA1", + MTK_EINT_FUNCTION(2, 93), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO214"), + MTK_FUNCTION(1, "SDA1"), + MTK_FUNCTION(2, "EINT93"), + MTK_FUNCTION(3, "CLKM3"), + MTK_FUNCTION(4, "PWM3"), + MTK_FUNCTION(5, "TS_AUX_SCLK_PWDB"), + MTK_FUNCTION(7, "A_FUNC_DIN[17]") + ), + MTK_PIN( + 215, "SCL1", + MTK_EINT_FUNCTION(2, 92), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO215"), + MTK_FUNCTION(1, "SCL1"), + MTK_FUNCTION(2, "EINT92"), + MTK_FUNCTION(3, "CLKM2"), + MTK_FUNCTION(4, "PWM2"), + MTK_FUNCTION(5, "TS_AUX_DIN"), + MTK_FUNCTION(7, "A_FUNC_DIN[18]") + ), + MTK_PIN( + 216, "SDA2", + MTK_EINT_FUNCTION(2, 95), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO216"), + MTK_FUNCTION(1, "SDA2"), + MTK_FUNCTION(2, "EINT95"), + MTK_FUNCTION(3, "CLKM5"), + MTK_FUNCTION(4, "PWM5"), + MTK_FUNCTION(5, "TS_AUX_PWDB"), + MTK_FUNCTION(7, "A_FUNC_DIN[15]") + ), + MTK_PIN( + 217, "SCL2", + MTK_EINT_FUNCTION(2, 94), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO217"), + MTK_FUNCTION(1, "SCL2"), + MTK_FUNCTION(2, "EINT94"), + MTK_FUNCTION(3, "CLKM4"), + MTK_FUNCTION(4, "PWM4"), + MTK_FUNCTION(5, "TS_AUXADC_TEST_CK"), + MTK_FUNCTION(7, "A_FUNC_DIN[16]") + ), + MTK_PIN( + 218, "SRCLKENAI", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO218"), + MTK_FUNCTION(1, "SRCLKENAI") + ), + MTK_PIN( + 219, "URXD3", + MTK_EINT_FUNCTION(2, 87), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO219"), + MTK_FUNCTION(1, "URXD3"), + MTK_FUNCTION(2, "EINT87"), + MTK_FUNCTION(3, "UTXD3"), + MTK_FUNCTION(4, "MD2_URXD"), + MTK_FUNCTION(5, "TS_AUX_ST"), + MTK_FUNCTION(6, "PWM4"), + MTK_FUNCTION(7, "MD2_EINT4") + ), + MTK_PIN( + 220, "UTXD3", + MTK_EINT_FUNCTION(2, 86), + DRV_GRP1, + MTK_FUNCTION(0, "GPIO220"), + MTK_FUNCTION(1, "UTXD3"), + MTK_FUNCTION(2, "EINT86"), + MTK_FUNCTION(3, "URXD3"), + MTK_FUNCTION(4, "MD2_UTXD"), + MTK_FUNCTION(5, "TS_AUX_CS_B"), + MTK_FUNCTION(6, "PWM3"), + MTK_FUNCTION(7, "MD2_EINT3") + ), + MTK_PIN( + 221, "MRG_I2S_PCM_CLK", + MTK_EINT_FUNCTION(2, 14), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO221"), + MTK_FUNCTION(1, "MRG_I2S_PCM_CLK"), + MTK_FUNCTION(2, "EINT14"), + MTK_FUNCTION(3, "I2SIN_CK"), + MTK_FUNCTION(4, "PCM0_CK"), + MTK_FUNCTION(5, "DSP2_ICK"), + MTK_FUNCTION(6, "IMG_TEST_CK"), + MTK_FUNCTION(7, "USB_SCL") + ), + MTK_PIN( + 222, "MRG_I2S_PCM_SYNC", + MTK_EINT_FUNCTION(2, 16), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO222"), + MTK_FUNCTION(1, "MRG_I2S_PCM_SYNC"), + MTK_FUNCTION(2, "EINT16"), + MTK_FUNCTION(3, "I2SIN_WS"), + MTK_FUNCTION(4, "PCM0_WS"), + MTK_FUNCTION(6, "DISP_TEST_CK") + ), + MTK_PIN( + 223, "MRG_I2S_PCM_RX", + MTK_EINT_FUNCTION(2, 15), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO223"), + MTK_FUNCTION(1, "MRG_I2S_PCM_RX"), + MTK_FUNCTION(2, "EINT15"), + MTK_FUNCTION(3, "I2SIN_DAT"), + MTK_FUNCTION(4, "PCM0_DI"), + MTK_FUNCTION(5, "DSP2_ID"), + MTK_FUNCTION(6, "MFG_TEST_CK"), + MTK_FUNCTION(7, "USB_SDA") + ), + MTK_PIN( + 224, "MRG_I2S_PCM_TX", + MTK_EINT_FUNCTION(2, 17), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO224"), + MTK_FUNCTION(1, "MRG_I2S_PCM_TX"), + MTK_FUNCTION(2, "EINT17"), + MTK_FUNCTION(3, "I2SOUT_DAT"), + MTK_FUNCTION(4, "PCM0_DO"), + MTK_FUNCTION(6, "VDEC_TEST_CK") + ), + MTK_PIN( + 225, "MD1_DAI_RX_GPIO", + MTK_EINT_FUNCTION(2, 18), + DRV_GRP3, + MTK_FUNCTION(0, "GPIO225"), + MTK_FUNCTION(1, "MD1_DAI_RX_GPIO"), + MTK_FUNCTION(2, "EINT18"), + MTK_FUNCTION(3, "BT_SYNC"), + MTK_FUNCTION(4, "MD2_DAI_RX_GPIO"), + MTK_FUNCTION(5, "DSP2_IMS"), + MTK_FUNCTION(6, "VENC_TEST_CK") + ), + MTK_PIN( + 226, "MSDC3_DAT2", + MTK_EINT_FUNCTION(2, 71), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO226"), + MTK_FUNCTION(1, "MSDC3_DAT2"), + MTK_FUNCTION(2, "EINT71"), + MTK_FUNCTION(3, "SCL6"), + MTK_FUNCTION(4, "PWM5"), + MTK_FUNCTION(5, "CLKM4"), + MTK_FUNCTION(7, "A_FUNC_DIN[0]") + ), + MTK_PIN( + 227, "MSDC3_DAT3", + MTK_EINT_FUNCTION(2, 72), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO227"), + MTK_FUNCTION(1, "MSDC3_DAT3"), + MTK_FUNCTION(2, "EINT72"), + MTK_FUNCTION(3, "SDA6"), + MTK_FUNCTION(4, "PWM6"), + MTK_FUNCTION(5, "CLKM5"), + MTK_FUNCTION(7, "A_FUNC_CK") + ), + MTK_PIN( + 228, "MSDC3_CMD", + MTK_EINT_FUNCTION(2, 68), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO228"), + MTK_FUNCTION(1, "MSDC3_CMD"), + MTK_FUNCTION(2, "EINT68"), + MTK_FUNCTION(3, "SDA2"), + MTK_FUNCTION(4, "PWM2"), + MTK_FUNCTION(5, "CLKM1"), + MTK_FUNCTION(7, "A_FUNC_DIN[3]") + ), + MTK_PIN( + 229, "MSDC3_CLK", + MTK_EINT_FUNCTION(2, 67), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO229"), + MTK_FUNCTION(1, "MSDC3_CLK"), + MTK_FUNCTION(2, "EINT67"), + MTK_FUNCTION(3, "SCL2"), + MTK_FUNCTION(4, "PWM1"), + MTK_FUNCTION(5, "CLKM0"), + MTK_FUNCTION(7, "A_FUNC_DIN[4]") + ), + MTK_PIN( + 230, "MSDC3_DAT1", + MTK_EINT_FUNCTION(2, 70), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO230"), + MTK_FUNCTION(1, "MSDC3_DAT1"), + MTK_FUNCTION(2, "EINT70"), + MTK_FUNCTION(3, "SDA3"), + MTK_FUNCTION(4, "PWM4"), + MTK_FUNCTION(5, "CLKM3"), + MTK_FUNCTION(7, "A_FUNC_DIN[1]") + ), + MTK_PIN( + 231, "MSDC3_DAT0", + MTK_EINT_FUNCTION(2, 69), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO231"), + MTK_FUNCTION(1, "MSDC3_DAT0"), + MTK_FUNCTION(2, "EINT69"), + MTK_FUNCTION(3, "SCL3"), + MTK_FUNCTION(4, "PWM3"), + MTK_FUNCTION(5, "CLKM2"), + MTK_FUNCTION(7, "A_FUNC_DIN[2]") + ), +}; + +#endif /* __PINCTRL_MTK_MT6589_H */ diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 6bf37d8085fae5..d6e753be9ce7f5 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -106,9 +106,20 @@ static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, { struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); const struct mtk_pin_desc *desc; + int mux; desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; + /* + * If EINT is available and the GPIO is already set to the EINT, + * don't re-mux to the default value. + */ + if (desc->eint.eint_m != NO_EINT_SUPPORT) { + if (!mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_MODE, &mux) && + mux == desc->eint.eint_m) + return 0; + } + return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, hw->soc->gpio_m); } diff --git a/drivers/pmdomain/mediatek/mt6589-pm-domains.h b/drivers/pmdomain/mediatek/mt6589-pm-domains.h new file mode 100644 index 00000000000000..dea93a6aabf7ec --- /dev/null +++ b/drivers/pmdomain/mediatek/mt6589-pm-domains.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MT6589_PM_DOMAINS_H +#define __SOC_MEDIATEK_MT6589_PM_DOMAINS_H + +#include "mtk-pm-domains.h" +#include + +/* + * MT6589 power domain support + */ + +#define MT6589_BUS_PROT_INFRA_SI0_CTL(_mask) \ + _BUS_PROT(INFRA, _mask, 0x0200, 0x0200, 0, 0, \ + BUS_PROT_REG_UPDATE | \ + BUS_PROT_INVERTED | \ + BUS_PROT_IGNORE_CLR_ACK) + +static const struct scpsys_domain_data scpsys_domain_data_mt6589[] = { + [MT6589_POWER_DOMAIN_MD1] = { + .name = "md1", + .sta_mask = PWR_STATUS_MD1, + .ctl_offs = SPM_MD1_PWR_CON, + .sram_pdn_bits = BIT(8), + .sram_pdn_ack_bits = 0, + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, + .bp_cfg = { + BUS_PROT_INFRA_UPDATE_TOPAXI(0x5300), + }, + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_MD2] = { + .name = "md2", + .sta_mask = PWR_STATUS_CONN, + .ctl_offs = SPM_CONN_PWR_CON, + .sram_pdn_bits = BIT(8), + .sram_pdn_ack_bits = 0, + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, + .bp_cfg = { + BUS_PROT_INFRA_UPDATE_TOPAXI(0xac00), + }, + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_DPY] = { + .name = "dpy", + .sta_mask = PWR_STATUS_DDRPHY, + .ctl_offs = 0x0240, + .caps = MTK_SCPD_ALWAYS_ON, + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_DIS] = { + .name = "dis", + .sta_mask = PWR_STATUS_DISP, + .ctl_offs = SPM_DIS_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_MFG] = { + .name = "mfg", + .sta_mask = PWR_STATUS_MFG, + .ctl_offs = SPM_MFG_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = BIT(12), + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, + .bp_cfg = { + BUS_PROT_INFRA_UPDATE_TOPAXI(0x0020), + MT6589_BUS_PROT_INFRA_SI0_CTL(0x0400), + }, + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_ISP] = { + .name = "isp", + .sta_mask = PWR_STATUS_ISP, + .ctl_offs = SPM_ISP_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_IFR] = { + .name = "ifr", + .sta_mask = PWR_STATUS_INFRASYS, + .ctl_offs = 0x0234, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .caps = MTK_SCPD_ALWAYS_ON, + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_VEN] = { + .name = "ven", + .sta_mask = BIT(7), + .ctl_offs = SPM_VEN_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, + [MT6589_POWER_DOMAIN_VDE] = { + .name = "vde", + .sta_mask = BIT(8), + .ctl_offs = SPM_VDE_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + .caps = MTK_SCPD_KEEP_DEFAULT_OFF, + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, + }, +}; + +static const struct scpsys_soc_data mt6589_scpsys_data = { + .domains_data = scpsys_domain_data_mt6589, + .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6589), +}; + +#endif /* __SOC_MEDIATEK_MT6589_PM_DOMAINS_H */ diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c index e1cfd42234734f..f8589bc5423eab 100644 --- a/drivers/pmdomain/mediatek/mtk-pm-domains.c +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c @@ -18,6 +18,7 @@ #include #include +#include "mt6589-pm-domains.h" #include "mt6735-pm-domains.h" #include "mt6795-pm-domains.h" #include "mt6893-pm-domains.h" @@ -48,7 +49,6 @@ #define PWR_CLK_DIS_BIT BIT(4) #define PWR_SRAM_CLKISO_BIT BIT(5) #define PWR_SRAM_ISOINT_B_BIT BIT(6) - #define PWR_RTFF_SAVE BIT(24) #define PWR_RTFF_NRESTORE BIT(25) #define PWR_RTFF_CLK_DIS BIT(26) @@ -1144,6 +1144,10 @@ static int scpsys_get_bus_protection(struct device *dev, struct scpsys *scpsys) } static const struct of_device_id scpsys_of_match[] = { + { + .compatible = "mediatek,mt6589-power-controller", + .data = &mt6589_scpsys_data, + }, { .compatible = "mediatek,mt6735-power-controller", .data = &mt6735_scpsys_data, @@ -1246,6 +1250,12 @@ static int scpsys_probe(struct platform_device *pdev) return PTR_ERR(scpsys->base); } + /* PROJECT_CODE magic value and enable bit */ + ret = regmap_write(scpsys->base, SPM_POWERON_CONFIG_SET, + (SPM_PROJECT_CODE << 16) | BIT(0)); + if (ret) + return dev_err_probe(dev, ret, "failed to enable SPM\n"); + if (of_find_property(np, "access-controllers", NULL)) ret = scpsys_get_bus_protection(dev, scpsys); else diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h index a5dca24cbc2f5e..09643ba184c30a 100644 --- a/drivers/pmdomain/mediatek/mtk-pm-domains.h +++ b/drivers/pmdomain/mediatek/mtk-pm-domains.h @@ -21,6 +21,17 @@ (_scpd)->data->caps & (_x) : \ (_scpd)->hwv_data->caps & (_x)) +#define PWR_RST_B_BIT BIT(0) +#define PWR_ISO_BIT BIT(1) +#define PWR_ON_BIT BIT(2) +#define PWR_ON_2ND_BIT BIT(3) +#define PWR_CLK_DIS_BIT BIT(4) +#define PWR_SRAM_CLKISO_BIT BIT(5) +#define PWR_SRAM_ISOINT_B_BIT BIT(6) + +#define SPM_POWERON_CONFIG_SET 0x0000 +#define SPM_PROJECT_CODE 0x0b16 + #define SPM_VDE_PWR_CON 0x0210 #define SPM_MFG_PWR_CON 0x0214 #define SPM_VEN_PWR_CON 0x0230 @@ -38,10 +49,12 @@ #define SPM_PWR_STATUS_2ND 0x0610 #define PWR_STATUS_MD1 BIT(0) +#define PWR_STATUS_DDRPHY BIT(2) #define PWR_STATUS_CONN BIT(1) #define PWR_STATUS_DISP BIT(3) #define PWR_STATUS_MFG BIT(4) #define PWR_STATUS_ISP BIT(5) +#define PWR_STATUS_INFRASYS BIT(6) #define PWR_STATUS_VDEC BIT(7) #define PWR_STATUS_VENC_LT BIT(20) #define PWR_STATUS_VENC BIT(21) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 55da91bacc3e63..ded841b6e10144 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -245,6 +245,8 @@ struct bq24190_dev_info { u8 ss_reg; u8 watchdog; const struct bq24190_chip_info *info; + unsigned int poll_interval; /* ms, 0 = IRQ mode */ + struct delayed_work poll_work; }; struct bq24190_chip_info { @@ -1840,6 +1842,27 @@ static void bq24190_check_status(struct bq24190_dev_info *bdi) dev_dbg(bdi->dev, "ss_reg: 0x%02x, f_reg: 0x%02x\n", ss_reg, f_reg); } +static void bq24190_poll_work(struct work_struct *work) +{ + struct bq24190_dev_info *bdi = + container_of(work, struct bq24190_dev_info, poll_work.work); + int error; + + error = pm_runtime_resume_and_get(bdi->dev); + if (error < 0) { + dev_warn(bdi->dev, "poll: pm_runtime_get failed: %d\n", error); + goto reschedule; + } + + bq24190_check_status(bdi); + pm_runtime_put_autosuspend(bdi->dev); + +reschedule: + if (bdi->poll_interval > 0) + schedule_delayed_work(&bdi->poll_work, + msecs_to_jiffies(bdi->poll_interval)); +} + static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) { struct bq24190_dev_info *bdi = data; @@ -2088,6 +2111,7 @@ static int bq24190_probe(struct i2c_client *client) bdi->charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST; bdi->f_reg = 0; bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ + bdi->poll_interval = 0; /* interrupt mode */ ret = devm_delayed_work_autocancel(dev, &bdi->input_current_limit_work, bq24190_input_current_limit_work); @@ -2096,11 +2120,6 @@ static int bq24190_probe(struct i2c_client *client) i2c_set_clientdata(client, bdi); - if (client->irq <= 0) { - dev_err(dev, "Can't get irq info\n"); - return -EINVAL; - } - bdi->edev = devm_extcon_dev_allocate(dev, bq24190_usb_extcon_cable); if (IS_ERR(bdi->edev)) return PTR_ERR(bdi->edev); @@ -2166,21 +2185,36 @@ static int bq24190_probe(struct i2c_client *client) bdi->initialized = true; - ret = devm_request_threaded_irq(dev, client->irq, NULL, - bq24190_irq_handler_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "bq24190-charger", bdi); - if (ret < 0) { - dev_err(dev, "Can't set up irq handler\n"); - goto out_charger; + if (client->irq <= 0) { + if (device_property_read_u32(dev, "poll-interval", + &bdi->poll_interval) == 0 && + bdi->poll_interval > 0) { + dev_info(dev, "using polling mode, interval %u ms\n", + bdi->poll_interval); + INIT_DELAYED_WORK(&bdi->poll_work, bq24190_poll_work); + schedule_delayed_work(&bdi->poll_work, + msecs_to_jiffies(bdi->poll_interval)); + } else { + dev_err(dev, "No IRQ and no poll-interval specified\n"); + ret = -EINVAL; + goto out_charger; + } + } else { + ret = devm_request_threaded_irq(dev, client->irq, NULL, + bq24190_irq_handler_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "bq24190-charger", bdi); + if (ret < 0) { + dev_err(dev, "Can't set up irq handler\n"); + goto out_charger; + } + enable_irq_wake(client->irq); } ret = bq24190_register_vbus_regulator(bdi); if (ret < 0) goto out_charger; - enable_irq_wake(client->irq); - pm_runtime_put_autosuspend(dev); return 0; @@ -2202,6 +2236,8 @@ static void bq24190_remove(struct i2c_client *client) struct bq24190_dev_info *bdi = i2c_get_clientdata(client); int error; + cancel_delayed_work_sync(&bdi->poll_work); + error = pm_runtime_resume_and_get(bdi->dev); if (error < 0) dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error); @@ -2222,6 +2258,10 @@ static void bq24190_shutdown(struct i2c_client *client) /* Turn off 5V boost regulator on shutdown */ bdi->info->set_otg_vbus(bdi, false); + + /* Ensure poll work is not rescheduled */ + bdi->poll_interval = 0; + cancel_delayed_work_sync(&bdi->poll_work); } static __maybe_unused int bq24190_runtime_suspend(struct device *dev) @@ -2293,6 +2333,10 @@ static __maybe_unused int bq24190_pm_resume(struct device *dev) pm_runtime_put_autosuspend(bdi->dev); } + if (bdi->poll_interval > 0) + schedule_delayed_work(&bdi->poll_work, + msecs_to_jiffies(bdi->poll_interval)); + /* Things may have changed while suspended so alert upper layer */ power_supply_changed(bdi->charger); if (bdi->battery) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 6f3147518376a0..ed234f7000f1a3 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -504,6 +504,11 @@ config PWM_MICROCHIP_CORE To compile this driver as a module, choose M here: the module will be called pwm-microchip-core. +config PWM_MT6589_DISP + tristate "MediaTek MT6589 display PWM driver" + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on HAS_IOMEM + config PWM_MTK_DISP tristate "MediaTek display PWM driver" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 0dc0d2b69025db..d38e28bdcbae1a 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_PWM_MC33XS2410) += pwm-mc33xs2410.o obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o obj-$(CONFIG_PWM_MESON) += pwm-meson.o obj-$(CONFIG_PWM_MICROCHIP_CORE) += pwm-microchip-core.o +obj-$(CONFIG_PWM_MT6589_DISP) += pwm-mt6589-disp.o obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o obj-$(CONFIG_PWM_MXS) += pwm-mxs.o obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o diff --git a/drivers/pwm/pwm-mt6589-disp.c b/drivers/pwm/pwm-mt6589-disp.c new file mode 100644 index 00000000000000..10269e666601bb --- /dev/null +++ b/drivers/pwm/pwm-mt6589-disp.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek MT6589 Display BLS PWM Driver + * + * Copyright (c) 2026 Akari Tsuyukusa + * + * The MT6589 BLS (Backlight Scaler) module provides a PWM generator + * for LCD backlight control, integrated with gamma correction LUTs, + * PWM output LUTs, dithering, and histogram-based auto-brightness. + * This driver exposes only the PWM functionality; the other features + * are set up once during probe and then left in their default states. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offsets (relative to BLS base address) */ +#define BLS_EN 0x0000 +#define BLS_RST 0x0004 +#define BLS_BLS_SETTING 0x0008 +#define BLS_HIS_SETTING 0x000C +#define BLS_INTEN 0x0010 +#define BLS_INTSTA 0x0014 +#define BLS_SRC_SIZE 0x0018 +#define BLS_HIS_PROT 0x001C +#define BLS_GAIN 0x0020 +#define BLS_DISTORT_POINT 0x0024 +#define BLS_GAIN_SETTING 0x0028 +#define BLS_GAMMA_SETTING 0x0030 +#define BLS_GAMMA_BOUNDARY 0x0034 +#define BLS_LUT_UPDATE 0x0038 +#define BLS_PWM_LUT_SEL 0x003C +#define BLS_MAXCLR_LIMIT 0x0040 +#define BLS_PRE_DIST_THD 0x0044 +#define BLS_DIST_THD_NORM 0x0048 +#define BLS_DIST_THD_DARK 0x004C +#define BLS_DIST_THD_BRIGHT 0x0050 +#define BLS_DIST_THD_TEXT 0x0054 +#define BLS_DS_SETTING 0x0058 +#define BLS_BS_SETTING 0x005C +#define BLS_TS_SETTING0 0x0060 +#define BLS_TS_SETTING1 0x0064 +#define BLS_SC_DIFF_THD 0x0068 +#define BLS_SC_BIN_THD 0x006C +#define BLS_FAST_IIR_XCOEFF 0x0070 +#define BLS_FAST_IIR_YCOEFF 0x0074 +#define BLS_SLOW_IIR_XCOEFF 0x0078 +#define BLS_SLOW_IIR_YCOEFF 0x007C +#define BLS_PWM_DUTY 0x0080 +#define BLS_PWM_DUTY_GAIN 0x0084 +#define BLS_PATTERN 0x0088 +#define BLS_PWM_CON 0x0090 +/* + * PWM period is determined by PWM_H_DURATION, PWM_L_DURATION, + * and PWM_G_DURATION registers. These are left at their reset values + * for now, as downstream does not modify them. If the backlight + * frequency needs to be adjusted, set these registers accordingly. + */ +#define PWM_H_DURATION 0x0094 +#define PWM_L_DURATION 0x0098 +#define PWM_G_DURATION 0x009C +#define PWM_SEND_DATA0 0x00A0 +#define PWM_SEND_DATA1 0x00A4 +#define PWM_WAVE_NUM 0x00A8 +#define PWM_DATA_WIDTH 0x00AC +#define PWM_THRESH 0x00B0 +#define PWM_SEND_WAVENUM 0x00B4 + +/* Gamma LUT / IGAMMA LUT / PWM LUT base offsets */ +#define BLS_GAMMA_LUT(n) (0x0400 + 4 * (n)) /* n=0..255 */ +#define BLS_IGAMMA_LUT(n) (0x0800 + 4 * (n)) /* n=0..255 */ +#define BLS_PWM_LUT(n) (0x0C00 + 4 * (n)) /* n=0..32 */ + +/* Dither registers */ +#define BLS_DITHER(n) (0x0E00 + 4 * (n)) /* n=0..17 */ + +/* BLS_EN bit definitions */ +#define BLS_EN_PWM_ONLY BIT(31) /* Enable PWM, others off */ + +/* BLS_PWM_DUTY format */ +#define PWM_DUTY_MIN_LEVEL BIT(19) /* Lower bound (fixed to 1) */ +#define PWM_MAX_LEVEL 255 /* Maximum duty value */ + +/* Default PWM divider value (from downstream) */ +#define PWM_DEFAULT_DIV 0x24 + +struct mt6589_bls_pwm { + void __iomem *base; + struct clk *clk_main; + unsigned int max_level; + bool clk_enabled; +}; + +static inline struct mt6589_bls_pwm *to_mt6589_bls_pwm(struct pwm_chip *chip) +{ + return pwmchip_get_drvdata(chip); +} + +/* + * Convert PWM duty cycle (in ns) to a brightness level (0..max_level). + * The period is expected to be constant and provided by the consumer + * (e.g., pwm-backlight). We simply scale duty_cycle to the [0, max_level] + * range. + */ +static unsigned int duty_to_level(const struct pwm_state *state, + unsigned int max_level) +{ + u64 level; + + if (!state->enabled || state->duty_cycle == 0) + return 0; + + level = mul_u64_u64_div_u64(state->duty_cycle, max_level, state->period); + if (level > max_level) + level = max_level; + + return (unsigned int)level; +} + +/* Initialize Gamma LUT with identity (1:1) mapping */ +static void mt6589_bls_gamma_init(struct mt6589_bls_pwm *bls) +{ + unsigned int i; + u32 val; + + /* Gamma table: 256 entries, 10-bit per component, packed as + * {R[9:0], G[9:0], B[9:0]} => bits 29..20, 19..10, 9..0. + * Identity mapping: entry[i] = (i << 2) so that 255 -> 1020. + */ + for (i = 0; i < 256; i++) { + val = ((i << 2) & 0x3FF) << 20 | /* Red */ + ((i << 2) & 0x3FF) << 10 | /* Green */ + ((i << 2) & 0x3FF); /* Blue */ + writel(val, bls->base + BLS_GAMMA_LUT(i)); + } + + /* Last point (index 256) boundary register */ + val = (0x3FF << 20) | + (0x3FF << 10) | + 0x3FF; + writel(val, bls->base + BLS_GAMMA_BOUNDARY); + + /* Enable gamma table (bit 0 of BLS_GAMMA_SETTING) */ + writel(0x00000001, bls->base + BLS_GAMMA_SETTING); +} + +/* Configure dithering registers with downstream magic values */ +static void mt6589_bls_dither_init(struct mt6589_bls_pwm *bls) +{ + /* Values taken from MT6589 downstream ddp_bls.c */ + writel(0x00000001, bls->base + BLS_DITHER(0)); + writel(0x00000000, bls->base + BLS_DITHER(6)); + writel(0x00000222, bls->base + BLS_DITHER(13)); + writel(0x00000000, bls->base + BLS_DITHER(14)); + writel(0x22220001, bls->base + BLS_DITHER(15)); + writel(0x22222222, bls->base + BLS_DITHER(16)); + writel(0x00000000, bls->base + BLS_DITHER(17)); +} + +static int mt6589_bls_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct mt6589_bls_pwm *bls = to_mt6589_bls_pwm(chip); + unsigned int level; + u32 reg; + int ret; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; + + if (state->enabled) { + if (!bls->clk_enabled) { + ret = clk_prepare_enable(bls->clk_main); + if (ret) + return ret; + + bls->clk_enabled = true; + } + + level = duty_to_level(state, bls->max_level); + + if (!level) + reg = 0; + else + reg = PWM_DUTY_MIN_LEVEL | (level & 0x3FF); + + writel(reg, bls->base + BLS_PWM_DUTY); + + /* Enable PWM (only PWM, keep BLS engine off) */ + writel(BLS_EN_PWM_ONLY, bls->base + BLS_EN); + } else { + /* Disable PWM output */ + writel(0x0, bls->base + BLS_EN); + + if (bls->clk_enabled) { + clk_disable_unprepare(bls->clk_main); + bls->clk_enabled = false; + } + } + + return 0; +} + +static const struct pwm_ops mt6589_bls_pwm_ops = { + .apply = mt6589_bls_pwm_apply, +}; + +static int mt6589_bls_pwm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pwm_chip *chip; + struct mt6589_bls_pwm *bls; + int ret; + + chip = devm_pwmchip_alloc(dev, 1, sizeof(*bls)); + if (IS_ERR(chip)) + return PTR_ERR(chip); + bls = to_mt6589_bls_pwm(chip); + + bls->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(bls->base)) + return PTR_ERR(bls->base); + + bls->clk_main = devm_clk_get(dev, "main"); + if (IS_ERR(bls->clk_main)) + return dev_err_probe(dev, PTR_ERR(bls->clk_main), + "failed to get clock\n"); + + bls->max_level = PWM_MAX_LEVEL; /* hardcoded, matches downstream default */ + + /* Enable clocks for initialization */ + ret = clk_prepare_enable(bls->clk_main); + if (ret) + return ret; + + /* Reset the BLS module (optional, downstream does this) */ + writel(0x0, bls->base + BLS_RST); /* release reset */ + + /* Set source size (unknown, use default 0, ) */ + writel(0x0, bls->base + BLS_SRC_SIZE); + + /* Initialize PWM control: clock divider, idle level high */ + writel(0x00050000 | PWM_DEFAULT_DIV, bls->base + BLS_PWM_CON); + + /* Duty gain = 1.0 (0x100 = 256/256) */ + writel(0x00000100, bls->base + BLS_PWM_DUTY_GAIN); + + /* Disable BLS processing, keep only PWM enabled eventually */ + writel(0x0, bls->base + BLS_BLS_SETTING); + + /* Enable PWM-only mode */ + writel(BLS_EN_PWM_ONLY, bls->base + BLS_EN); + + /* Initialize gamma LUT (identity) */ + mt6589_bls_gamma_init(bls); + + /* Initialize dithering */ + mt6589_bls_dither_init(bls); + + /* Disable interrupts (they are enabled by default?) */ + writel(0x0, bls->base + BLS_INTEN); + + /* + * BLS_HIS_SETTING: + * bit1: Histogram_Mode = 1 (histogram of input data, w/o inverse gamma) + * bit0: Histogram_Auto_Clear = 1 (auto-clear histogram at frame start) + * We do not use the histogram engine, but keep downstream default. + */ + writel(0x00000003, bls->base + BLS_HIS_SETTING); + + /* Disable BLS module for now, it will be enabled on first apply */ + writel(0x0, bls->base + BLS_EN); + + clk_disable_unprepare(bls->clk_main); + + chip->ops = &mt6589_bls_pwm_ops; + + ret = devm_pwmchip_add(dev, chip); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to add PWM chip\n"); + + return 0; +} + +static const struct of_device_id mt6589_bls_pwm_of_match[] = { + { .compatible = "mediatek,mt6589-disp-pwm" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mt6589_bls_pwm_of_match); + +static struct platform_driver mt6589_bls_pwm_driver = { + .probe = mt6589_bls_pwm_probe, + .driver = { + .name = "mt6589-disp-pwm", + .of_match_table = mt6589_bls_pwm_of_match, + }, +}; +module_platform_driver(mt6589_bls_pwm_driver); + +MODULE_AUTHOR("Akari Tsuyukusa"); +MODULE_DESCRIPTION("MediaTek MT6589 Display BLS PWM Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 87554ab92801df..a912e3658eb75e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -910,6 +910,15 @@ config REGULATOR_MT6316 This driver supports the control of different power rails of device through regulator interface. +config REGULATOR_MT6320 + tristate "MediaTek MT6320 PMIC" + depends on MFD_MT6397 + help + Say y here to select this option to enable the power regulator of + MediaTek MT6320 PMIC. + This driver supports the control of different power rails of device + through regulator interface. + config REGULATOR_MT6323 tristate "MediaTek MT6323 PMIC" depends on MFD_MT6397 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 35639f3115fd03..b7c8773b918382 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o obj-$(CONFIG_REGULATOR_MT6315) += mt6316-regulator.o +obj-$(CONFIG_REGULATOR_MT6320) += mt6320-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o diff --git a/drivers/regulator/mt6320-regulator.c b/drivers/regulator/mt6320-regulator.c new file mode 100644 index 00000000000000..69eb726dbb7213 --- /dev/null +++ b/drivers/regulator/mt6320-regulator.c @@ -0,0 +1,746 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 Akari Tsuyukusa + * + * based on mt6320-regulator.c + * Copyright (c) 2016 MediaTek Inc. + * Author: Chen Zhong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * LDO LP_SEL (BIT(0) in enable_reg): + * 0 = Normal mode (default) + * 1 = Low Power / PFM mode + */ +#define MT6320_LDO_MODE_NORMAL 0 +#define MT6320_LDO_MODE_LP 1 + +/* + * BUCK MODESET (BIT(8) in CON2): + * 0 = Auto PFM/PWM mode (normal operation, light-load power saving) + * 1 = Forced PWM mode (heavy load, fast response) + * + * Follows the same convention as MT6397: + * REGULATOR_MODE_FAST → Forced PWM → MODESET=1 + * REGULATOR_MODE_NORMAL → Auto PFM → MODESET=0 + * + * This matches the downstream GPU driver usage: + * upmu_set_rg_vrf18_2_modeset(1) // GPU active: force PWM for stable voltage + * upmu_set_rg_vrf18_2_modeset(0) // GPU idle: return to auto PFM + */ +#define MT6320_BUCK_MODE_AUTO 0 /* REGULATOR_MODE_NORMAL */ +#define MT6320_BUCK_MODE_FORCE_PWM 1 /* REGULATOR_MODE_FAST */ + +/* + * MT6320 regulators' information + * + * @desc: standard fields of regulator description. + * @qi: Mask for query enable signal status of regulators. + * BUCKs: BIT(13) within CON7. LDOs: BIT(15) within enable_reg. + * @vselon_reg: CON10 — BUCK voltage register used in HW-control mode. + * @vselctrl_reg: CON5 — selects SW vs HW voltage control for BUCKs. + * @vselctrl_mask: BIT(1) — VOSEL_CTRL bit in vselctrl_reg (all BUCKs). + * @modeset_reg: Register for Normal/Low-Power mode selection. + * @modeset_mask: Mask for the mode bit in modeset_reg. + */ +struct mt6320_regulator_info { + struct regulator_desc desc; + u32 qi; + u32 vselon_reg; + u32 vselctrl_reg; + u32 vselctrl_mask; + u32 modeset_reg; + u32 modeset_mask; +}; + +/* + * BUCK register map (all addresses confirmed from upmu_hw.h CON definitions) + * -------------------------------------------------------------------------- + * CON2 CON5 CON7 CON9 CON10 + * modeset vselctrl enable+status vosel_sw voselon + * VPROC 0x020A 0x0210 0x0214 0x0218 0x021A + * VSRAM 0x0230 0x0236 0x023A 0x023E 0x0240 + * VCORE 0x025C 0x0262 0x0266 0x026A 0x026C + * VM 0x0282 0x0288 0x028C 0x0290 0x0292 + * VIO18 0x0304 0x030A 0x030E 0x0312 0x0314 + * VPA 0x032A 0x0330 0x0334 0x0338 0x033A + * VRF18 0x0354 0x035A 0x035E 0x0362 0x0364 + * VRF18_2 0x037E 0x0384 0x0388 0x038C 0x038E + * + * CON7 dual purpose: EN=BIT(0) (enable), qi=BIT(13) (HW status readback) + * CON5: VOSEL_CTRL=BIT(1) + * CON2: MODESET=BIT(8) (confirmed from PMIC_RG_Vxxx_MODESET_SHIFT=8) + * + * LDO register map (all confirmed from upmu_hw.h + upmu_common.c) + * ---------------------------------------------------------------- + * enable_reg = ANALDO_CONn or DIGLDO_CONn (see individual entries) + * EN bit = PMIC_RG_Vxxx_EN_SHIFT (each confirmed) + * modeset_reg = same as enable_reg (LP_SEL=BIT(0) in same register) + * vosel_reg = separate CON register per LDO + * vosel_mask = pre-shifted: raw_mask << shift + */ + +#define MT6320_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \ + vosel, vosel_mask, voselon, vosel_ctrl, modesetreg) \ +[MT6320_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6320_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6320_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = (max - min)/step + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(0), \ + .of_map_mode = mt6320_map_mode, \ + }, \ + .qi = BIT(13), \ + .vselon_reg = voselon, \ + .vselctrl_reg = vosel_ctrl, \ + .vselctrl_mask = BIT(1), \ + .modeset_reg = modesetreg, \ + .modeset_mask = BIT(8), \ +} + +/* + * MT6320_LDO — variable-voltage LDO with volt_table + * + * modeset_reg = enable_reg (LP_SEL=BIT(0) is in the same CON register as EN, + * confirmed for every LDO from upmu_common.c upmu_set_Vxxx_lp_sel()). + * modeset_mask = BIT(0). + */ +#define MT6320_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \ + vosel_mask) \ +[MT6320_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6320_volt_table_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6320_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + }, \ + .qi = BIT(15), \ + .modeset_reg = enreg, \ + .modeset_mask = BIT(0), \ +} + +/* + * MT6320_REG_FIXED — fixed-voltage LDO + * + * Same LP_SEL=BIT(0) logic as MT6320_LDO. + * VTCXO_1 and VRTC have no LP_SEL in upmu_common.c; + * those two use modeset_reg=0/modeset_mask=0 via MT6320_REG_FIXED_NOLP. + */ +#define MT6320_REG_FIXED(match, vreg, enreg, enbit, volt) \ +[MT6320_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6320_volt_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6320_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + .min_uV = volt, \ + }, \ + .qi = BIT(15), \ + .modeset_reg = enreg, \ + .modeset_mask = BIT(0), \ +} + +#define MT6320_REG_FIXED_NOLP(match, vreg, enreg, enbit, volt) \ +[MT6320_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6320_volt_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6320_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + .min_uV = volt, \ + }, \ + .qi = BIT(15), \ + .modeset_reg = 0, \ + .modeset_mask = 0, \ +} + +/* + * BUCK voltage ranges + * ------------------- + * All vosel masks confirmed from PMIC_Vxxx_VOSEL_MASK in upmu_hw.h. + * Base voltages confirmed by back-calculating from real hardware readings. + * + * buck_volt_range1: 700 mV, 6.25 mV/step, 7-bit (mask=0x7F) + * VPROC: vosel=0x50 -> 700+80*6.25=1200 mV ✓ (real: 1200 mV) + * VSRAM: vosel=0x5A -> 700+90*6.25=1262.5 mV ✓ (real: 1262 mV, display truncated) + * VCORE: vosel=0x38 -> 700+56*6.25=1050 mV ✓ (real: 1050 mV) + * VM: vosel=0x52 -> 700+82*6.25=1212.5 mV ✓ (real: 1212 mV, display truncated) + * Applies to: VPROC, VSRAM, VCORE, VM + * + * buck_volt_range2: 500 mV, 50 mV/step, 6-bit (mask=0x3F) + * VPA: vosel=0 -> 500 mV ✓ (real: 500 mV = minimum) + * Applies to: VPA + * + * buck_volt_range3: 1500 mV, 20 mV/step, 5-bit (mask=0x1F) + * Confirmed from show_BUCK_VIO18_VOLTAGE() in pmic_mt6320.c: + * ret_value = 1500 + (reg_val * 20) + * Cross-check: real reading=1800 mV -> reg_val=(1800-1500)/20=15=0x0F ✓ + * Range: 1500 mV (vosel=0x00) to 2120 mV (vosel=0x1F) + * Applies to: VIO18 + * + * buck_volt_range4: 1050 mV, 25 mV/step, 5-bit (mask=0x1F) + * Confirmed by pmic_vrf18_2_usage_protection() in pmic_mt6320.c: + * gpu_status_bit=1 -> val=0x1F -> 1050 + 31*25 = 1825 mV (RF mode) ✓ + * gpu_status_bit=0 -> val=0x04 -> 1050 + 4*25 = 1150 mV (GPU OD mode) + * vosel=0x00 gives 1050 mV (GPU OD minimum per datasheet). + * VRF18 (1st RF) shares the same CON9 structure; it always operates at + * vosel=0x1F=1825 mV and never uses GPU OD mode. + * Applies to: VRF18, VRF18_2 + */ +static const struct linear_range buck_volt_range1[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250), +}; + +static const struct linear_range buck_volt_range2[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), +}; + +static const struct linear_range buck_volt_range3[] = { + REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000), +}; + +static const struct linear_range buck_volt_range4[] = { + REGULATOR_LINEAR_RANGE(1050000, 0, 0x1f, 25000), +}; + +/* + * LDO voltage tables + * ------------------ + * All tables confirmed from dct_pmic_XXX_sel() in pmic_mt6320.c. + * Real hardware readings are noted where available. + * + * ldo_volt_table1: VMC — vosel BIT(4) + * Real: 3300 mV (vosel=1) + */ +static const unsigned int ldo_volt_table1[] = { + 1800000, 3300000, +}; + +/* + * ldo_volt_table2: VMCH, VEMC_3V3 — vosel BIT(7) + * Real: VMCH=3300 mV (vosel=1), VEMC_3V3=3300 mV (vosel=1) + */ +static const unsigned int ldo_volt_table2[] = { + 3000000, 3300000, +}; + +/* + * ldo_volt_table3: VEMC_1V8, VGP1-VGP6, VSIM1, VSIM2, VIBR — vosel [7:5] + * Real: VGP1=2800, VGP2=2800, VGP3=2800, VGP4=2800, VGP5=2800, VGP6=1800, + * VSIM1=1200, VSIM2=1200, VIBR=2800, VEMC_1V8=1800 mV + */ +static const unsigned int ldo_volt_table3[] = { + 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000, +}; + +/* + * ldo_volt_table4: VAST — vosel [14:13] (descending) + * Real: 1200 mV (vosel=0) + */ +static const unsigned int ldo_volt_table4[] = { + 1200000, 1100000, 1000000, 900000, +}; + +/* + * ldo_volt_table5: VRF28_1, VRF28_2, VTCXO_2 — vosel BIT(3) + * Real: VRF28_1=2800, VRF28_2=1800, VTCXO_2=2800 mV + * Note: datasheet lists VRF28_1/2 output as 2.85 V; downstream and real + * hardware show 2800 mV for vosel=1. Using 2850 mV as per datasheet spec. + */ +static const unsigned int ldo_volt_table5[] = { + 1800000, 2850000, +}; + +/* + * ldo_volt_table6: VA — vosel BIT(6) + * Real: 1800 mV (vosel=0) + */ +static const unsigned int ldo_volt_table6[] = { + 1800000, 2500000, +}; + +/* + * ldo_volt_table7: VCAMA — vosel [7:6] = 0xC0 + * Real: 2800 mV (vosel=3) + */ +static const unsigned int ldo_volt_table7[] = { + 1500000, 1800000, 2500000, 2800000, +}; + +static int mt6320_get_status(struct regulator_dev *rdev) +{ + int ret; + u32 regval; + struct mt6320_regulator_info *info = rdev_get_drvdata(rdev); + + ret = regmap_read(rdev->regmap, info->desc.enable_reg, ®val); + if (ret != 0) { + dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret); + return ret; + } + + return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF; +} + +static unsigned int mt6320_map_mode(unsigned int mode) +{ + switch (mode) { + case MT6320_BUCK_MODE_AUTO: + return REGULATOR_MODE_NORMAL; + case MT6320_BUCK_MODE_FORCE_PWM: + return REGULATOR_MODE_FAST; + default: + return REGULATOR_MODE_INVALID; + } +} + +static int mt6320_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + int ret; + unsigned int val; + struct mt6320_regulator_info *info = rdev_get_drvdata(rdev); + + switch (mode) { + case REGULATOR_MODE_FAST: + /* Force PWM: heavy load, stable voltage (e.g. GPU active) */ + val = MT6320_BUCK_MODE_FORCE_PWM; + break; + case REGULATOR_MODE_NORMAL: + /* Auto PFM: light load, power saving */ + val = MT6320_BUCK_MODE_AUTO; + break; + default: + return -EINVAL; + } + + val <<= ffs(info->modeset_mask) - 1; + + ret = regmap_update_bits(rdev->regmap, info->modeset_reg, + info->modeset_mask, val); + return ret; +} + +static unsigned int mt6320_buck_get_mode(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + struct mt6320_regulator_info *info = rdev_get_drvdata(rdev); + + ret = regmap_read(rdev->regmap, info->modeset_reg, &val); + if (ret < 0) + return ret; + + val &= info->modeset_mask; + val >>= ffs(info->modeset_mask) - 1; + + switch (val) { + case MT6320_BUCK_MODE_FORCE_PWM: + return REGULATOR_MODE_FAST; + case MT6320_BUCK_MODE_AUTO: + return REGULATOR_MODE_NORMAL; + default: + return -EINVAL; + } +} + +static int mt6320_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + int ret, val = 0; + struct mt6320_regulator_info *info = rdev_get_drvdata(rdev); + + if (!info->modeset_mask) { + dev_err(&rdev->dev, "regulator %s doesn't support set_mode\n", + info->desc.name); + return -EINVAL; + } + + switch (mode) { + case REGULATOR_MODE_STANDBY: + val = MT6320_LDO_MODE_LP; + break; + case REGULATOR_MODE_NORMAL: + val = MT6320_LDO_MODE_NORMAL; + break; + default: + return -EINVAL; + } + + val <<= ffs(info->modeset_mask) - 1; + + ret = regmap_update_bits(rdev->regmap, info->modeset_reg, + info->modeset_mask, val); + return ret; +} + +static unsigned int mt6320_ldo_get_mode(struct regulator_dev *rdev) +{ + unsigned int val; + unsigned int mode; + int ret; + struct mt6320_regulator_info *info = rdev_get_drvdata(rdev); + + if (!info->modeset_mask) { + dev_err(&rdev->dev, "regulator %s doesn't support get_mode\n", + info->desc.name); + return -EINVAL; + } + + ret = regmap_read(rdev->regmap, info->modeset_reg, &val); + if (ret < 0) + return ret; + + val &= info->modeset_mask; + val >>= ffs(info->modeset_mask) - 1; + + if (val & 0x1) + mode = REGULATOR_MODE_STANDBY; + else + mode = REGULATOR_MODE_NORMAL; + + return mode; +} + +static const struct regulator_ops mt6320_volt_range_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6320_get_status, + .set_mode = mt6320_buck_set_mode, + .get_mode = mt6320_buck_get_mode, +}; + +static const struct regulator_ops mt6320_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6320_get_status, + .set_mode = mt6320_ldo_set_mode, + .get_mode = mt6320_ldo_get_mode, +}; + +static const struct regulator_ops mt6320_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6320_get_status, + .set_mode = mt6320_ldo_set_mode, + .get_mode = mt6320_ldo_get_mode, +}; + +/* The array is indexed by id (MT6320_ID_XXX) */ +static struct mt6320_regulator_info mt6320_regulators[] = { + /* + * BUCKs + * ----- + * All addresses confirmed from upmu_hw.h VPROC_CONn etc. + * enable_reg = CON7 EN=BIT(0), qi=BIT(13) + * vselctrl = CON5 VOSEL_CTRL=BIT(1) + * vosel_sw = CON9 + * voselon = CON10 + * modeset = CON2 MODESET=BIT(8) + */ + + /* VPROC CPU 0.7-1.493 V (6.25 mV/step, mask=0x7F) */ + MT6320_BUCK("buck_vproc", VPROC, 700000, 1493750, 6250, + buck_volt_range1, + 0x0214, /* CON7: enable + status */ + 0x0218, 0x7f, /* CON9: vosel_sw */ + 0x021A, /* CON10: voselon */ + 0x0210, /* CON5: vselctrl */ + 0x020A), /* CON2: modeset */ + + /* VSRAM Memory 0.7-1.493 V (6.25 mV/step, mask=0x7F) */ + MT6320_BUCK("buck_vsram", VSRAM, 700000, 1493750, 6250, + buck_volt_range1, + 0x023A, 0x023E, 0x7f, 0x0240, 0x0236, 0x0230), + + /* VCORE MDSYS/Infra 0.7-1.493 V (6.25 mV/step, mask=0x7F) */ + MT6320_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250, + buck_volt_range1, + 0x0266, 0x026A, 0x7f, 0x026C, 0x0262, 0x025C), + + /* VM 1.2-1.493 V (6.25 mV/step, mask=0x7F) */ + MT6320_BUCK("buck_vm", VM, 700000, 1493750, 6250, + buck_volt_range1, + 0x028C, 0x0290, 0x7f, 0x0292, 0x0288, 0x0282), + + /* VIO18 IO App. 1.5-2.12 V (20 mV/step, mask=0x1F, real: vosel=0x0F=1800 mV) */ + MT6320_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000, + buck_volt_range3, + 0x030E, 0x0312, 0x1f, 0x0314, 0x030A, 0x0304), + + /* VPA 3GPA 0.5-3.65 V (50 mV/step, mask=0x3F) */ + MT6320_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, + buck_volt_range2, + 0x0334, 0x0338, 0x3f, 0x033A, 0x0330, 0x032A), + + /* VRF18 1st RF 1.825 V nominal (25 mV/step, mask=0x1F, vosel=0x1F=1825 mV) */ + MT6320_BUCK("buck_vrf18", VRF18, 1050000, 1825000, 25000, + buck_volt_range4, + 0x035E, 0x0362, 0x1f, 0x0364, 0x035A, 0x0354), + + /* + * VRF18_2 2nd RF / GPU OD (25 mV/step, mask=0x1F) + * vosel=0x1F -> 1825 mV (RF mode, confirmed from real hardware + usage_protection) + * vosel=0x04 -> 1150 mV (GPU OD mode, set by pmic_vrf18_2_usage_protection) + * vosel=0x00 -> 1050 mV (GPU OD minimum per datasheet) + */ + MT6320_BUCK("buck_vrf18_2", VRF18_2, 1050000, 1825000, 25000, + buck_volt_range4, + 0x0388, 0x038C, 0x1f, 0x038E, 0x0384, 0x037E), + + /* + * Analog LDOs + * ----------- + * enable_reg = ANALDO_CONn (confirmed from upmu_hw.h) + * EN bit = confirmed from PMIC_RG_Vxxx_EN_SHIFT + * LP_SEL = BIT(0) in same enable_reg (confirmed from upmu_common.c) + * vosel_reg = separate ANALDO_CONn + * vosel_mask = pre-shifted (raw_mask << shift) + * + * VRF28_1 / VRF28_2: datasheet 2.85 V; downstream uses same vosel + * encoding (0=1800/1=2850). Real hardware reads back 2800 mV for + * vosel=1 due to display truncation; 2850 mV is the correct spec value. + */ + + /* VRF28_1 MDSYS 1.8/2.85 V (ANALDO_CON0=0x0400, EN=BIT(12)) */ + MT6320_LDO("ldo_vrf28", VRF28, ldo_volt_table5, + 0x0400, 12, 0x0412, BIT(3)), + + /* + * VTCXO_1 MDSYS 2.8 V fixed (ANALDO_CON1=0x0402, EN=BIT(10)) + * No LP_SEL function in upmu_common.c for VTCXO_1 (ON_CTRL-managed). + */ + MT6320_REG_FIXED_NOLP("ldo_vtcxo", VTCXO, 0x0402, 10, 2800000), + + /* VA 1.8/2.5 V (ANALDO_CON2=0x0404, EN=BIT(14)) */ + MT6320_LDO("ldo_va", VA, ldo_volt_table6, + 0x0404, 14, 0x0410, BIT(6)), + + /* VA28 2.8 V fixed (ANALDO_CON3=0x0406, EN=BIT(14)) */ + MT6320_REG_FIXED("ldo_va28", VA28, 0x0406, 14, 2800000), + + /* VCAMA 1.5/1.8/2.5/2.8 V (ANALDO_CON4=0x0408, EN=BIT(15)) */ + MT6320_LDO("ldo_vcama", VCAMA, ldo_volt_table7, + 0x0408, 15, 0x0414, 0x3 << 6), + + /* VRF28_2 General 1.8/2.85 V (ANALDO_CON13=0x041A, EN=BIT(12)) */ + MT6320_LDO("ldo_vrf28_2", VRF28_2, ldo_volt_table5, + 0x041A, 12, 0x0418, BIT(3)), + + /* VTCXO_2 MDSYS 1.8/2.8 V (ANALDO_CON14=0x041C, EN=BIT(10)) */ + MT6320_LDO("ldo_vtcxo_2", VTCXO_2, ldo_volt_table5, + 0x041C, 10, 0x0416, BIT(3)), + + /* + * Digital LDOs + * ------------ + * enable_reg = DIGLDO_CONn (confirmed from upmu_hw.h) + * EN bit = confirmed from PMIC_RG_Vxxx_EN_SHIFT / PMIC_Vxxx_EN_SHIFT + * LP_SEL = BIT(0) in same enable_reg (confirmed from upmu_common.c) + * vosel_reg = separate DIGLDO_CONn + * vosel_mask = pre-shifted (raw_mask << shift) + */ + + /* VIO28 2.8 V fixed (DIGLDO_CON0=0x0420, EN=BIT(14)) */ + MT6320_REG_FIXED("ldo_vio28", VIO28, 0x0420, 14, 2800000), + + /* VUSB 3.3 V fixed (DIGLDO_CON2=0x0422, EN=BIT(14)) */ + MT6320_REG_FIXED("ldo_vusb", VUSB, 0x0422, 14, 3300000), + + /* VMC1 T-Card 1.8/3.3 V (DIGLDO_CON3=0x0424, EN=BIT(12)) */ + MT6320_LDO("ldo_vmc1", VMC1, ldo_volt_table1, + 0x0424, 12, 0x044A, BIT(4)), + + /* VMCH1 T-Card 3.0/3.3 V (DIGLDO_CON5=0x0426, EN=BIT(14)) */ + MT6320_LDO("ldo_vmch1", VMCH1, ldo_volt_table2, + 0x0426, 14, 0x044C, BIT(7)), + + /* VEMC_3V3 eMMC Core 3.0/3.3 V (DIGLDO_CON6=0x0428, EN=BIT(14)) */ + MT6320_LDO("ldo_vemc_3v3", VEMC_3V3, ldo_volt_table2, + 0x0428, 14, 0x044E, BIT(7)), + + /* VEMC_1V8 eMMC 1.2-3.3 V (DIGLDO_CON37=0x0462, EN=BIT(14)) */ + MT6320_LDO("ldo_vemc_1v8", VEMC_1V8, ldo_volt_table3, + 0x0462, 14, 0x0464, 0x7 << 5), + + /* VGP1 VCAMD 1.2-3.3 V (DIGLDO_CON7=0x042A, EN=BIT(15)) */ + MT6320_LDO("ldo_vgp1", VGP1, ldo_volt_table3, + 0x042A, 15, 0x0450, 0x7 << 5), + + /* VGP2 VCAM_IO 1.2-3.3 V (DIGLDO_CON8=0x042C, EN=BIT(15)) */ + MT6320_LDO("ldo_vgp2", VGP2, ldo_volt_table3, + 0x042C, 15, 0x0452, 0x7 << 5), + + /* VGP3 VCAM_AF 1.2-3.3 V (DIGLDO_CON9=0x042E, EN=BIT(15)) */ + MT6320_LDO("ldo_vgp3", VGP3, ldo_volt_table3, + 0x042E, 15, 0x0454, 0x7 << 5), + + /* VGP4 CTP/CMMB 1.2-3.3 V (DIGLDO_CON10=0x0430, EN=BIT(15)) */ + MT6320_LDO("ldo_vgp4", VGP4, ldo_volt_table3, + 0x0430, 15, 0x0456, 0x7 << 5), + + /* VGP5 CTP/CMMB 1.2-3.3 V (DIGLDO_CON11=0x0432, EN=BIT(15)) */ + MT6320_LDO("ldo_vgp5", VGP5, ldo_volt_table3, + 0x0432, 15, 0x0458, 0x7 << 5), + + /* VGP6 CTP/CMMB 1.2-3.3 V (DIGLDO_CON12=0x0434, EN=BIT(15)) */ + MT6320_LDO("ldo_vgp6", VGP6, ldo_volt_table3, + 0x0434, 15, 0x045A, 0x7 << 5), + + /* VSIM1 1.2-3.3 V (DIGLDO_CON13=0x0436, EN=BIT(15)) */ + MT6320_LDO("ldo_vsim1", VSIM1, ldo_volt_table3, + 0x0436, 15, 0x045C, 0x7 << 5), + + /* VSIM2 1.2-3.3 V (DIGLDO_CON14=0x0438, EN=BIT(15)) */ + MT6320_LDO("ldo_vsim2", VSIM2, ldo_volt_table3, + 0x0438, 15, 0x045E, 0x7 << 5), + + /* VIBR Vibrator 1.2-3.3 V (DIGLDO_CON39=0x0466, EN=BIT(15)) */ + MT6320_LDO("ldo_vibr", VIBR, ldo_volt_table3, + 0x0466, 15, 0x0468, 0x7 << 5), + + /* + * VRTC RTC Block 2.8 V fixed (DIGLDO_CON15=0x043A, EN=BIT(8)) + * No LP_SEL function in upmu_common.c for VRTC. + */ + MT6320_REG_FIXED_NOLP("ldo_vrtc", VRTC, 0x043A, 8, 2800000), + + /* + * VAST MT6168 0.9-1.2 V (DIGLDO_CON20=0x0444, EN=BIT(12)) + * enable_reg and vosel_reg share the same address (DIGLDO_CON20). + * LP_SEL=BIT(0) also in DIGLDO_CON20. + */ + MT6320_LDO("ldo_vast", VAST, ldo_volt_table4, + 0x0444, 12, 0x0444, 0x3 << 13), +}; + +static int mt6320_set_buck_vosel_reg(struct platform_device *pdev) +{ + struct mt6397_chip *mt6320 = dev_get_drvdata(pdev->dev.parent); + int i; + u32 regval; + + for (i = 0; i < MT6320_MAX_REGULATOR; i++) { + if (mt6320_regulators[i].vselctrl_reg) { + if (regmap_read(mt6320->regmap, + mt6320_regulators[i].vselctrl_reg, + ®val) < 0) { + dev_err(&pdev->dev, + "Failed to read buck ctrl\n"); + return -EIO; + } + + if (regval & mt6320_regulators[i].vselctrl_mask) { + mt6320_regulators[i].desc.vsel_reg = + mt6320_regulators[i].vselon_reg; + } + } + } + + return 0; +} + +static int mt6320_regulator_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6320 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = {}; + struct regulator_dev *rdev; + int i; + u32 reg_value; + + /* Query buck controller to select activated voltage register part */ + if (mt6320_set_buck_vosel_reg(pdev)) + return -EIO; + + /* Read PMIC chip revision */ + if (regmap_read(mt6320->regmap, MT6320_CID, ®_value) < 0) { + dev_err(&pdev->dev, "Failed to read Chip ID\n"); + return -EIO; + } + dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value); + + for (i = 0; i < MT6320_MAX_REGULATOR; i++) { + config.dev = &pdev->dev; + config.driver_data = &mt6320_regulators[i]; + config.regmap = mt6320->regmap; + rdev = devm_regulator_register(&pdev->dev, + &mt6320_regulators[i].desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s\n", + mt6320_regulators[i].desc.name); + return PTR_ERR(rdev); + } + } + return 0; +} + +static const struct platform_device_id mt6320_platform_ids[] = { + {"mt6320-regulator", 0}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6320_platform_ids); + +static struct platform_driver mt6320_regulator_driver = { + .driver = { + .name = "mt6320-regulator", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .probe = mt6320_regulator_probe, + .id_table = mt6320_platform_ids, +}; + +module_platform_driver(mt6320_regulator_driver); + +MODULE_AUTHOR("Akari Tsuyukusa "); +MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6320 PMIC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/mediatek/mt6589-dispsys.h b/drivers/soc/mediatek/mt6589-dispsys.h new file mode 100644 index 00000000000000..a219078fcbbeee --- /dev/null +++ b/drivers/soc/mediatek/mt6589-dispsys.h @@ -0,0 +1,347 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#ifndef __SOC_MEDIATEK_MT6589_DISPSYS_H +#define __SOC_MEDIATEK_MT6589_DISPSYS_H + +#include "mtk-mmsys.h" + +/* + * MT6589 DISPSYS_CONFIG + * + * The register block is described in the MT6589 datasheet, chapter 38 + * "Display Subsystem Configuration". DISPSYS_CONFIG is based at 0x14000000. + * + * Registers 0x020..0x05c are the display crossbar controls. MOUT_EN fields + * enable output ports and *_SEL fields select the input consumed by a block. + * Fixed datapath links do not need entries in the routing table below. + */ + +/* DISPSYS_CONFIG routing registers. */ +#define MT6589_DISP_SCL_MOUT_EN 0x020 +#define MT6589_DISP_OVL_MOUT_EN 0x024 +#define MT6589_DISP_COLOR_MOUT_EN 0x028 +#define MT6589_DISP_TDSHP_MOUT_EN 0x02c +#define MT6589_DISP_MOUT_RST 0x030 +#define MT6589_DISP_RDMA0_OUT_SEL 0x034 +#define MT6589_DISP_RDMA1_OUT_SEL 0x038 +#define MT6589_DISP_OVL_PQ_OUT_SEL 0x03c +#define MT6589_DISP_WDMA0_SEL 0x040 +#define MT6589_DISP_OVL_SEL 0x044 +#define MT6589_DISP_OVL_PQ_IN_SEL 0x048 +#define MT6589_DISP_COLOR_SEL 0x04c +#define MT6589_DISP_TDSHP_SEL 0x050 +#define MT6589_DISP_BLS_SEL 0x054 +#define MT6589_DISP_DBI_SEL 0x058 +#define MT6589_DISP_DPI0_SEL 0x05c +#define MT6589_DISP_MISC 0x060 + +/* DISPSYS software reset. */ +#define MT6589_DISP_SW_RST_B 0x140 +#define MT6589_DISP_NUM_RESETS 21 + +/* DISP_SCL_MOUT_EN: bits [3:0]. */ +#define MT6589_SCL_MOUT_EN_MASK GENMASK(3, 0) +#define MT6589_SCL_MOUT_EN_WDMA0 BIT(0) +#define MT6589_SCL_MOUT_EN_OVL BIT(1) +#define MT6589_SCL_MOUT_EN_COLOR BIT(2) +#define MT6589_SCL_MOUT_EN_TDSHP BIT(3) + +/* DISP_OVL_MOUT_EN: bits [3:0]. */ +#define MT6589_OVL_MOUT_EN_MASK GENMASK(3, 0) +#define MT6589_OVL_MOUT_EN_WDMA1 BIT(0) +#define MT6589_OVL_MOUT_EN_BLS BIT(1) +#define MT6589_OVL_MOUT_EN_COLOR BIT(2) +#define MT6589_OVL_MOUT_EN_TDSHP BIT(3) + +/* DISP_COLOR_MOUT_EN: bits [4:0]. */ +#define MT6589_COLOR_MOUT_EN_MASK GENMASK(4, 0) +#define MT6589_COLOR_MOUT_EN_OVL_PQ BIT(0) +#define MT6589_COLOR_MOUT_EN_TDSHP BIT(1) +#define MT6589_COLOR_MOUT_EN_WDMA0 BIT(2) +#define MT6589_COLOR_MOUT_EN_BLS BIT(3) +#define MT6589_COLOR_MOUT_EN_OVL BIT(4) + +/* DISP_TDSHP_MOUT_EN: bits [4:0]. */ +#define MT6589_TDSHP_MOUT_EN_MASK GENMASK(4, 0) +#define MT6589_TDSHP_MOUT_EN_OVL_PQ BIT(0) +#define MT6589_TDSHP_MOUT_EN_COLOR BIT(1) +#define MT6589_TDSHP_MOUT_EN_WDMA0 BIT(2) +#define MT6589_TDSHP_MOUT_EN_BLS BIT(3) +#define MT6589_TDSHP_MOUT_EN_OVL BIT(4) + +/* DISP_MOUT_RST: bits [3:0]. */ +#define MT6589_MOUT_RST_MASK GENMASK(3, 0) +#define MT6589_MOUT_RST_SCL BIT(0) +#define MT6589_MOUT_RST_OVL BIT(1) +#define MT6589_MOUT_RST_COLOR BIT(2) +#define MT6589_MOUT_RST_TDSHP BIT(3) + +/* DISP_RDMA0_OUT_SEL: 0 = DSI, 1 = DBI, 2 = DPI0. */ +#define MT6589_RDMA0_OUT_SEL_MASK GENMASK(1, 0) +#define MT6589_RDMA0_OUT_SEL_DSI 0x0 +#define MT6589_RDMA0_OUT_SEL_DBI 0x1 +#define MT6589_RDMA0_OUT_SEL_DPI0 0x2 + +/* DISP_RDMA1_OUT_SEL: 0 = DBI, 1 = DPI0, 2 = DPI1. */ +#define MT6589_RDMA1_OUT_SEL_MASK GENMASK(1, 0) +#define MT6589_RDMA1_OUT_SEL_DBI 0x0 +#define MT6589_RDMA1_OUT_SEL_DPI0 0x1 +#define MT6589_RDMA1_OUT_SEL_DPI1 0x2 + +/* DISP_OVL_PQ_OUT_SEL: 0 = COLOR, 1 = TDSHP. */ +#define MT6589_OVL_PQ_OUT_SEL_MASK BIT(0) +#define MT6589_OVL_PQ_OUT_SEL_COLOR 0x0 +#define MT6589_OVL_PQ_OUT_SEL_TDSHP 0x1 + +/* DISP_WDMA0_SEL: 0 = SCL, 1 = COLOR, 2 = TDSHP. */ +#define MT6589_WDMA0_SEL_MASK GENMASK(1, 0) +#define MT6589_WDMA0_SEL_SCL 0x0 +#define MT6589_WDMA0_SEL_COLOR 0x1 +#define MT6589_WDMA0_SEL_TDSHP 0x2 + +/* DISP_OVL_SEL: 0 = SCL, 1 = COLOR, 2 = TDSHP. */ +#define MT6589_OVL_SEL_MASK GENMASK(1, 0) +#define MT6589_OVL_SEL_SCL 0x0 +#define MT6589_OVL_SEL_COLOR 0x1 +#define MT6589_OVL_SEL_TDSHP 0x2 + +/* DISP_OVL_PQ_IN_SEL: 0 = COLOR, 1 = TDSHP. */ +#define MT6589_OVL_PQ_IN_SEL_MASK BIT(0) +#define MT6589_OVL_PQ_IN_SEL_COLOR 0x0 +#define MT6589_OVL_PQ_IN_SEL_TDSHP 0x1 + +/* DISP_COLOR_SEL: 0 = OVL pre-blend, 1 = OVL post-blend, 2 = TDSHP, 3 = SCL. */ +#define MT6589_COLOR_SEL_MASK GENMASK(1, 0) +#define MT6589_COLOR_SEL_OVL_PRE 0x0 +#define MT6589_COLOR_SEL_OVL_POST 0x1 +#define MT6589_COLOR_SEL_TDSHP 0x2 +#define MT6589_COLOR_SEL_SCL 0x3 + +/* DISP_TDSHP_SEL: 0 = OVL pre-blend, 1 = OVL post-blend, 2 = COLOR, 3 = SCL. */ +#define MT6589_TDSHP_SEL_MASK GENMASK(1, 0) +#define MT6589_TDSHP_SEL_OVL_PRE 0x0 +#define MT6589_TDSHP_SEL_OVL_POST 0x1 +#define MT6589_TDSHP_SEL_COLOR 0x2 +#define MT6589_TDSHP_SEL_SCL 0x3 + +/* DISP_BLS_SEL: 0 = OVL, 1 = COLOR, 2 = TDSHP. */ +#define MT6589_BLS_SEL_MASK GENMASK(1, 0) +#define MT6589_BLS_SEL_OVL 0x0 +#define MT6589_BLS_SEL_COLOR 0x1 +#define MT6589_BLS_SEL_TDSHP 0x2 + +/* DISP_DBI_SEL: 0 = RDMA0, 1 = RDMA1. */ +#define MT6589_DBI_SEL_MASK BIT(0) +#define MT6589_DBI_SEL_RDMA0 0x0 +#define MT6589_DBI_SEL_RDMA1 0x1 + +/* DISP_DPI0_SEL: 0 = RDMA0, 1 = RDMA1. */ +#define MT6589_DPI0_SEL_MASK BIT(0) +#define MT6589_DPI0_SEL_RDMA0 0x0 +#define MT6589_DPI0_SEL_RDMA1 0x1 + +/* DISP_MISC: DPI/DBI external IO mode controls. */ +#define MT6589_DISP_MISC_DPI0_MODE_EN BIT(0) +#define MT6589_DISP_MISC_DPI0_I2X_EN BIT(1) +#define MT6589_DISP_MISC_DPI0_EDGE_SEL BIT(2) +#define MT6589_DISP_MISC_DPI0_IO_SEL BIT(3) +#define MT6589_DISP_MISC_DPI1_MODE_EN BIT(4) +#define MT6589_DISP_MISC_DPI1_I2X_EN BIT(5) +#define MT6589_DISP_MISC_DPI1_EDGE_SEL BIT(6) +#define MT6589_DISP_MISC_DPI1_IO_EN BIT(7) +#define MT6589_DISP_MISC_DPI2_MODE_EN BIT(8) +#define MT6589_DISP_MISC_DPI2_I2X_EN BIT(9) +#define MT6589_DISP_MISC_DPI2_EDGE_SEL BIT(10) +#define MT6589_DISP_MISC_DPI2_IO_EN BIT(11) +#define MT6589_DISP_MISC_DBI_C_IO_SEL BIT(12) + +/* + * Routes used by the MT6589 display paths. When a connection needs both an + * output-port enable and an input selector, both registers are represented by + * separate entries with the same (from, to) pair. + * + * MOUT enables are actual output gates and are cleared on disconnect. Input + * selectors and DISP_MISC interface controls have no generic disconnected + * state, so preserve them rather than writing zero (which selects a valid + * input or changes the interface mode). + * + * The MT6589 datasheet path-debug registers show fixed links for ROT -> SCL, + * BLS -> RDMA0 and GAMMA -> RDMA1; those links therefore need no route entry. + */ +static const struct mtk_mmsys_routes mt6589_dispsys_routing_table[] = { + /* SCL -> WDMA0 */ + MMSYS_ROUTE(SCL, WDMA0, + MT6589_DISP_SCL_MOUT_EN, + MT6589_SCL_MOUT_EN_WDMA0, MT6589_SCL_MOUT_EN_WDMA0), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(SCL, WDMA0, + MT6589_DISP_WDMA0_SEL, + MT6589_WDMA0_SEL_MASK, MT6589_WDMA0_SEL_SCL), + + /* SCL -> OVL */ + MMSYS_ROUTE(SCL, OVL0, + MT6589_DISP_SCL_MOUT_EN, + MT6589_SCL_MOUT_EN_OVL, MT6589_SCL_MOUT_EN_OVL), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(SCL, OVL0, + MT6589_DISP_OVL_SEL, + MT6589_OVL_SEL_MASK, MT6589_OVL_SEL_SCL), + + /* SCL -> COLOR */ + MMSYS_ROUTE(SCL, COLOR0, + MT6589_DISP_SCL_MOUT_EN, + MT6589_SCL_MOUT_EN_COLOR, MT6589_SCL_MOUT_EN_COLOR), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(SCL, COLOR0, + MT6589_DISP_COLOR_SEL, + MT6589_COLOR_SEL_MASK, MT6589_COLOR_SEL_SCL), + + /* SCL -> TDSHP */ + MMSYS_ROUTE(SCL, TDSHP, + MT6589_DISP_SCL_MOUT_EN, + MT6589_SCL_MOUT_EN_TDSHP, MT6589_SCL_MOUT_EN_TDSHP), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(SCL, TDSHP, + MT6589_DISP_TDSHP_SEL, + MT6589_TDSHP_SEL_MASK, MT6589_TDSHP_SEL_SCL), + + /* OVL -> WDMA1 */ + MMSYS_ROUTE(OVL0, WDMA1, + MT6589_DISP_OVL_MOUT_EN, + MT6589_OVL_MOUT_EN_WDMA1, MT6589_OVL_MOUT_EN_WDMA1), + + /* OVL -> BLS */ + MMSYS_ROUTE(OVL0, BLS, + MT6589_DISP_OVL_MOUT_EN, + MT6589_OVL_MOUT_EN_BLS, MT6589_OVL_MOUT_EN_BLS), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(OVL0, BLS, + MT6589_DISP_BLS_SEL, + MT6589_BLS_SEL_MASK, MT6589_BLS_SEL_OVL), + + /* OVL -> COLOR */ + MMSYS_ROUTE(OVL0, COLOR0, + MT6589_DISP_OVL_MOUT_EN, + MT6589_OVL_MOUT_EN_COLOR, MT6589_OVL_MOUT_EN_COLOR), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(OVL0, COLOR0, + MT6589_DISP_COLOR_SEL, + MT6589_COLOR_SEL_MASK, MT6589_COLOR_SEL_OVL_POST), + + /* OVL -> TDSHP */ + MMSYS_ROUTE(OVL0, TDSHP, + MT6589_DISP_OVL_MOUT_EN, + MT6589_OVL_MOUT_EN_TDSHP, MT6589_OVL_MOUT_EN_TDSHP), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(OVL0, TDSHP, + MT6589_DISP_TDSHP_SEL, + MT6589_TDSHP_SEL_MASK, MT6589_TDSHP_SEL_OVL_POST), + + /* COLOR -> WDMA0 */ + MMSYS_ROUTE(COLOR0, WDMA0, + MT6589_DISP_COLOR_MOUT_EN, + MT6589_COLOR_MOUT_EN_WDMA0, MT6589_COLOR_MOUT_EN_WDMA0), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(COLOR0, WDMA0, + MT6589_DISP_WDMA0_SEL, + MT6589_WDMA0_SEL_MASK, MT6589_WDMA0_SEL_COLOR), + + /* COLOR -> OVL direct input */ + MMSYS_ROUTE(COLOR0, OVL0, + MT6589_DISP_COLOR_MOUT_EN, + MT6589_COLOR_MOUT_EN_OVL, MT6589_COLOR_MOUT_EN_OVL), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(COLOR0, OVL0, + MT6589_DISP_OVL_SEL, + MT6589_OVL_SEL_MASK, MT6589_OVL_SEL_COLOR), + + /* COLOR -> TDSHP */ + MMSYS_ROUTE(COLOR0, TDSHP, + MT6589_DISP_COLOR_MOUT_EN, + MT6589_COLOR_MOUT_EN_TDSHP, MT6589_COLOR_MOUT_EN_TDSHP), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(COLOR0, TDSHP, + MT6589_DISP_TDSHP_SEL, + MT6589_TDSHP_SEL_MASK, MT6589_TDSHP_SEL_COLOR), + + /* COLOR -> BLS */ + MMSYS_ROUTE(COLOR0, BLS, + MT6589_DISP_COLOR_MOUT_EN, + MT6589_COLOR_MOUT_EN_BLS, MT6589_COLOR_MOUT_EN_BLS), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(COLOR0, BLS, + MT6589_DISP_BLS_SEL, + MT6589_BLS_SEL_MASK, MT6589_BLS_SEL_COLOR), + + /* TDSHP -> WDMA0 */ + MMSYS_ROUTE(TDSHP, WDMA0, + MT6589_DISP_TDSHP_MOUT_EN, + MT6589_TDSHP_MOUT_EN_WDMA0, MT6589_TDSHP_MOUT_EN_WDMA0), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(TDSHP, WDMA0, + MT6589_DISP_WDMA0_SEL, + MT6589_WDMA0_SEL_MASK, MT6589_WDMA0_SEL_TDSHP), + + /* TDSHP -> COLOR */ + MMSYS_ROUTE(TDSHP, COLOR0, + MT6589_DISP_TDSHP_MOUT_EN, + MT6589_TDSHP_MOUT_EN_COLOR, MT6589_TDSHP_MOUT_EN_COLOR), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(TDSHP, COLOR0, + MT6589_DISP_COLOR_SEL, + MT6589_COLOR_SEL_MASK, MT6589_COLOR_SEL_TDSHP), + + /* TDSHP -> OVL direct input */ + MMSYS_ROUTE(TDSHP, OVL0, + MT6589_DISP_TDSHP_MOUT_EN, + MT6589_TDSHP_MOUT_EN_OVL, MT6589_TDSHP_MOUT_EN_OVL), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(TDSHP, OVL0, + MT6589_DISP_OVL_SEL, + MT6589_OVL_SEL_MASK, MT6589_OVL_SEL_TDSHP), + + /* TDSHP -> BLS */ + MMSYS_ROUTE(TDSHP, BLS, + MT6589_DISP_TDSHP_MOUT_EN, + MT6589_TDSHP_MOUT_EN_BLS, MT6589_TDSHP_MOUT_EN_BLS), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(TDSHP, BLS, + MT6589_DISP_BLS_SEL, + MT6589_BLS_SEL_MASK, MT6589_BLS_SEL_TDSHP), + + /* RDMA0 -> DSI */ + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA0, DSI0, + MT6589_DISP_RDMA0_OUT_SEL, + MT6589_RDMA0_OUT_SEL_MASK, MT6589_RDMA0_OUT_SEL_DSI), + + /* RDMA0 -> DBI */ + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA0, DBI0, + MT6589_DISP_RDMA0_OUT_SEL, + MT6589_RDMA0_OUT_SEL_MASK, MT6589_RDMA0_OUT_SEL_DBI), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA0, DBI0, + MT6589_DISP_DBI_SEL, + MT6589_DBI_SEL_MASK, MT6589_DBI_SEL_RDMA0), + + /* RDMA0 -> DPI0 */ + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA0, DPI0, + MT6589_DISP_RDMA0_OUT_SEL, + MT6589_RDMA0_OUT_SEL_MASK, MT6589_RDMA0_OUT_SEL_DPI0), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA0, DPI0, + MT6589_DISP_DPI0_SEL, + MT6589_DPI0_SEL_MASK, MT6589_DPI0_SEL_RDMA0), + + /* RDMA1 -> DBI */ + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA1, DBI0, + MT6589_DISP_RDMA1_OUT_SEL, + MT6589_RDMA1_OUT_SEL_MASK, MT6589_RDMA1_OUT_SEL_DBI), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA1, DBI0, + MT6589_DISP_DBI_SEL, + MT6589_DBI_SEL_MASK, MT6589_DBI_SEL_RDMA1), + + /* RDMA1 -> DPI0 */ + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA1, DPI0, + MT6589_DISP_RDMA1_OUT_SEL, + MT6589_RDMA1_OUT_SEL_MASK, MT6589_RDMA1_OUT_SEL_DPI0), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA1, DPI0, + MT6589_DISP_DPI0_SEL, + MT6589_DPI0_SEL_MASK, MT6589_DPI0_SEL_RDMA1), + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA1, DPI0, + MT6589_DISP_MISC, + MT6589_DISP_MISC_DPI0_MODE_EN, + MT6589_DISP_MISC_DPI0_MODE_EN), + + /* RDMA1 -> DPI1 */ + MMSYS_ROUTE_KEEP_ON_DISCONNECT(RDMA1, DPI1, + MT6589_DISP_RDMA1_OUT_SEL, + MT6589_RDMA1_OUT_SEL_MASK, MT6589_RDMA1_OUT_SEL_DPI1), +}; + +#endif /* __SOC_MEDIATEK_MT6589_DISPSYS_H */ diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index bb4639ca0b8cdc..4f6ed92419092b 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -14,6 +14,7 @@ #include #include "mtk-mmsys.h" +#include "mt6589-dispsys.h" #include "mt8167-mmsys.h" #include "mt8173-mmsys.h" #include "mt8183-mmsys.h" @@ -37,6 +38,14 @@ static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = { .num_routes = ARRAY_SIZE(mmsys_default_routing_table), }; +static const struct mtk_mmsys_driver_data mt6589_dispsys_driver_data = { + .clk_driver = "clk-mt6589-disp", + .routes = mt6589_dispsys_routing_table, + .num_routes = ARRAY_SIZE(mt6589_dispsys_routing_table), + .sw0_rst_offset = MT6589_DISP_SW_RST_B, + .num_resets = MT6589_DISP_NUM_RESETS, +}; + static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = { .clk_driver = "clk-mt6779-mm", }; @@ -209,7 +218,10 @@ void mtk_mmsys_ddp_disconnect(struct device *dev, for (i = 0; i < mmsys->data->num_routes; i++) if (cur == routes[i].from_comp && next == routes[i].to_comp) - mtk_mmsys_update_bits(mmsys, routes[i].addr, routes[i].mask, 0, NULL); + if (!(routes[i].flags & + MTK_MMSYS_ROUTE_F_KEEP_ON_DISCONNECT)) + mtk_mmsys_update_bits(mmsys, routes[i].addr, + routes[i].mask, 0, NULL); } EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect); @@ -458,6 +470,7 @@ static void mtk_mmsys_remove(struct platform_device *pdev) static const struct of_device_id of_match_mtk_mmsys[] = { { .compatible = "mediatek,mt2701-mmsys", .data = &mt2701_mmsys_driver_data }, { .compatible = "mediatek,mt2712-mmsys", .data = &mt2712_mmsys_driver_data }, + { .compatible = "mediatek,mt6589-dispsys", .data = &mt6589_dispsys_driver_data }, { .compatible = "mediatek,mt6779-mmsys", .data = &mt6779_mmsys_driver_data }, { .compatible = "mediatek,mt6795-mmsys", .data = &mt6795_mmsys_driver_data }, { .compatible = "mediatek,mt6797-mmsys", .data = &mt6797_mmsys_driver_data }, diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h index fe628d5f519861..e26debf3368ce5 100644 --- a/drivers/soc/mediatek/mtk-mmsys.h +++ b/drivers/soc/mediatek/mtk-mmsys.h @@ -80,26 +80,41 @@ #define MMSYS_RST_NR(bank, bit) (((bank) * 32) + (bit)) +/* + * Some input selectors have no disconnected encoding: writing zero selects + * a valid input. Keep their values when disconnecting a route. + */ +#define MTK_MMSYS_ROUTE_F_KEEP_ON_DISCONNECT (1U << 0) + /* * This macro adds a compile time check to make sure that the in/out * selection bit(s) fit in the register mask, similar to bitfield * macros, but this does not transform the value. */ -#define MMSYS_ROUTE(from, to, reg_addr, reg_mask, selection) \ +#define __MTK_MMSYS_ROUTE(from, to, reg_addr, reg_mask, selection, flags) \ { DDP_COMPONENT_##from, DDP_COMPONENT_##to, reg_addr, reg_mask, \ (__BUILD_BUG_ON_ZERO_MSG((reg_mask) == 0, "Invalid mask") + \ __BUILD_BUG_ON_ZERO_MSG(~(reg_mask) & (selection), \ #selection " does not fit in " \ #reg_mask) + \ - (selection)) \ + (selection)), (flags) \ } +#define MMSYS_ROUTE(from, to, reg_addr, reg_mask, selection) \ + __MTK_MMSYS_ROUTE(from, to, reg_addr, reg_mask, selection, 0) + +#define MMSYS_ROUTE_KEEP_ON_DISCONNECT(from, to, reg_addr, reg_mask, \ + selection) \ + __MTK_MMSYS_ROUTE(from, to, reg_addr, reg_mask, selection, \ + MTK_MMSYS_ROUTE_F_KEEP_ON_DISCONNECT) + struct mtk_mmsys_routes { u32 from_comp; u32 to_comp; u32 addr; u32 mask; u32 val; + u8 flags; }; /** diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 0bcd8582637550..0d9c23a94cba80 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -17,15 +17,31 @@ #define PWRAP_POLL_DELAY_US 10 #define PWRAP_POLL_TIMEOUT_US 10000 -#define PWRAP_MT8135_BRIDGE_IORD_ARB_EN 0x4 -#define PWRAP_MT8135_BRIDGE_WACS3_EN 0x10 -#define PWRAP_MT8135_BRIDGE_INIT_DONE3 0x14 -#define PWRAP_MT8135_BRIDGE_WACS4_EN 0x24 -#define PWRAP_MT8135_BRIDGE_INIT_DONE4 0x28 -#define PWRAP_MT8135_BRIDGE_INT_EN 0x38 -#define PWRAP_MT8135_BRIDGE_TIMER_EN 0x48 -#define PWRAP_MT8135_BRIDGE_WDT_UNIT 0x50 -#define PWRAP_MT8135_BRIDGE_WDT_SRC_EN 0x54 +/* MT6589 and MT8135 specific PWARP Bridge registers */ +#define PWRAP_BRIDGE_IARB_INIT 0x0 +#define PWRAP_BRIDGE_IORD_ARB_EN 0x4 +#define PWRAP_BRIDGE_IARB_STA0 0x8 +#define PWRAP_BRIDGE_IARB_STA1 0xc +#define PWRAP_BRIDGE_WACS3_EN 0x10 +#define PWRAP_BRIDGE_INIT_DONE3 0x14 +#define PWRAP_BRIDGE_WACS3_CMD 0x18 +#define PWRAP_BRIDGE_WACS3_RDATA 0x1c +#define PWRAP_BRIDGE_WACS3_VLDCLR 0x20 +#define PWRAP_BRIDGE_WACS4_EN 0x24 +#define PWRAP_BRIDGE_INIT_DONE4 0x28 +#define PWRAP_BRIDGE_WACS4_CMD 0x2c +#define PWRAP_BRIDGE_WACS4_RDATA 0x30 +#define PWRAP_BRIDGE_WACS4_VLDCLR 0x34 +#define PWRAP_BRIDGE_INT_EN 0x38 +#define PWRAP_BRIDGE_INT_FLG_RAW 0x3c +#define PWRAP_BRIDGE_INT_FLG 0x40 +#define PWRAP_BRIDGE_INT_CLR 0x44 +#define PWRAP_BRIDGE_TIMER_EN 0x48 +#define PWRAP_BRIDGE_TIMER_STA 0x4c +#define PWRAP_BRIDGE_WDT_UNIT 0x50 +#define PWRAP_BRIDGE_WDT_SRC_EN 0x54 +#define PWRAP_BRIDGE_WDT_FLG 0x58 +#define PWRAP_BRIDGE_DEBUG_INT_SEL 0x5c /* macro for wrapper status */ #define PWRAP_GET_WACS_RDATA(x) (((x) >> 0) & 0x0000ffff) @@ -100,6 +116,24 @@ enum dew_regs { PWRAP_DEW_CIPHER_MODE, PWRAP_DEW_CIPHER_SWRST, + /* MT6320 only regs */ + PWRAP_DEW_CIPHER_IV0, + PWRAP_DEW_CIPHER_IV1, + PWRAP_DEW_CIPHER_IV2, + PWRAP_DEW_CIPHER_IV3, + PWRAP_DEW_CIPHER_IV4, + PWRAP_DEW_CIPHER_IV5, + + /* MT6320 and MT6397 only regs */ + PWRAP_DEW_EVENT_OUT_EN, + PWRAP_DEW_EVENT_SRC_EN, + PWRAP_DEW_EVENT_SRC, + PWRAP_DEW_EVENT_FLAG, + PWRAP_DEW_MON_FLAG_SEL, + PWRAP_DEW_EVENT_TEST, + PWRAP_DEW_CIPHER_LOAD, + PWRAP_DEW_CIPHER_START, + /* MT6323 only regs */ PWRAP_DEW_CIPHER_EN, PWRAP_DEW_RDDMY_NO, @@ -142,16 +176,34 @@ enum dew_regs { PWRAP_DEW_RG_WDATA_MASK, PWRAP_DEW_RG_SPI_RECORD_CLR, PWRAP_DEW_RG_CMD_ALERT_CLR, +}; - /* MT6397 only regs */ - PWRAP_DEW_EVENT_OUT_EN, - PWRAP_DEW_EVENT_SRC_EN, - PWRAP_DEW_EVENT_SRC, - PWRAP_DEW_EVENT_FLAG, - PWRAP_DEW_MON_FLAG_SEL, - PWRAP_DEW_EVENT_TEST, - PWRAP_DEW_CIPHER_LOAD, - PWRAP_DEW_CIPHER_START, +static const u32 mt6320_regs[] = { + [PWRAP_DEW_EVENT_OUT_EN] = 0xbc00, + [PWRAP_DEW_DIO_EN] = 0xbc02, + [PWRAP_DEW_EVENT_SRC_EN] = 0xbc04, + [PWRAP_DEW_EVENT_SRC] = 0xbc06, + [PWRAP_DEW_EVENT_FLAG] = 0xbc08, + [PWRAP_DEW_READ_TEST] = 0xbc0a, + [PWRAP_DEW_WRITE_TEST] = 0xbc0c, + [PWRAP_DEW_CRC_EN] = 0xbc0e, + [PWRAP_DEW_CRC_VAL] = 0xbc10, + [PWRAP_DEW_MON_GRP_SEL] = 0xbc12, + [PWRAP_DEW_MON_FLAG_SEL] = 0xbc14, + [PWRAP_DEW_EVENT_TEST] = 0xbc16, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0xbc18, + [PWRAP_DEW_CIPHER_IV_SEL] = 0xbc1a, + [PWRAP_DEW_CIPHER_LOAD] = 0xbc1c, + [PWRAP_DEW_CIPHER_START] = 0xbc1e, + [PWRAP_DEW_CIPHER_RDY] = 0xbc20, + [PWRAP_DEW_CIPHER_MODE] = 0xbc22, + [PWRAP_DEW_CIPHER_SWRST] = 0xbc24, + [PWRAP_DEW_CIPHER_IV0] = 0xbc26, + [PWRAP_DEW_CIPHER_IV1] = 0xbc28, + [PWRAP_DEW_CIPHER_IV2] = 0xbc2a, + [PWRAP_DEW_CIPHER_IV3] = 0xbc2c, + [PWRAP_DEW_CIPHER_IV4] = 0xbc2e, + [PWRAP_DEW_CIPHER_IV5] = 0xbc30, }; static const u32 mt6323_regs[] = { @@ -386,6 +438,22 @@ enum pwrap_regs { PWRAP_EINT_STA1_ADR, PWRAP_SWINF_2_WDATA_31_0, PWRAP_SWINF_2_RDATA_31_0, + PWRAP_DVFS_ADR0, + PWRAP_DVFS_WDATA0, + PWRAP_DVFS_ADR1, + PWRAP_DVFS_WDATA1, + PWRAP_DVFS_ADR2, + PWRAP_DVFS_WDATA2, + PWRAP_DVFS_ADR3, + PWRAP_DVFS_WDATA3, + PWRAP_DVFS_ADR4, + PWRAP_DVFS_WDATA4, + PWRAP_DVFS_ADR5, + PWRAP_DVFS_WDATA5, + PWRAP_DVFS_ADR6, + PWRAP_DVFS_WDATA6, + PWRAP_DVFS_ADR7, + PWRAP_DVFS_WDATA7, /* MT2701 only regs */ PWRAP_ADC_CMD_ADDR, @@ -394,6 +462,24 @@ enum pwrap_regs { PWRAP_ADC_RDATA_ADDR1, PWRAP_ADC_RDATA_ADDR2, + /* MT6589 only regs */ + PWRAP_CIPHER_IV0, + PWRAP_CIPHER_IV1, + PWRAP_CIPHER_IV2, + + /* MT6589 and MT8135 only regs */ + PWRAP_CSHEXT, + PWRAP_EVENT_IN_EN, + PWRAP_EVENT_DST_EN, + PWRAP_RRARB_INIT, + PWRAP_RRARB_EN, + PWRAP_RRARB_STA0, + PWRAP_RRARB_STA1, + PWRAP_EVENT_STA, + PWRAP_EVENT_STACLR, + PWRAP_CIPHER_LOAD, + PWRAP_CIPHER_START, + /* MT7622 only regs */ PWRAP_STA, PWRAP_CLR, @@ -422,38 +508,9 @@ enum pwrap_regs { PWRAP_DVFS_STEP_CTRL2, PWRAP_SPI2_CTRL, - /* MT8135 only regs */ - PWRAP_CSHEXT, - PWRAP_EVENT_IN_EN, - PWRAP_EVENT_DST_EN, - PWRAP_RRARB_INIT, - PWRAP_RRARB_EN, - PWRAP_RRARB_STA0, - PWRAP_RRARB_STA1, - PWRAP_EVENT_STA, - PWRAP_EVENT_STACLR, - PWRAP_CIPHER_LOAD, - PWRAP_CIPHER_START, - /* MT8173 only regs */ PWRAP_RDDMY, PWRAP_SI_CK_CON, - PWRAP_DVFS_ADR0, - PWRAP_DVFS_WDATA0, - PWRAP_DVFS_ADR1, - PWRAP_DVFS_WDATA1, - PWRAP_DVFS_ADR2, - PWRAP_DVFS_WDATA2, - PWRAP_DVFS_ADR3, - PWRAP_DVFS_WDATA3, - PWRAP_DVFS_ADR4, - PWRAP_DVFS_WDATA4, - PWRAP_DVFS_ADR5, - PWRAP_DVFS_WDATA5, - PWRAP_DVFS_ADR6, - PWRAP_DVFS_WDATA6, - PWRAP_DVFS_ADR7, - PWRAP_DVFS_WDATA7, PWRAP_SPMINF_STA, PWRAP_CIPHER_EN, @@ -569,6 +626,98 @@ static const int mt2701_regs[] = { [PWRAP_ADC_RDATA_ADDR2] = 0x154, }; +static const int mt6589_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_SIDLY] = 0xc, + [PWRAP_CSHEXT] = 0x10, + [PWRAP_CSHEXT_WRITE] = 0x14, + [PWRAP_CSHEXT_READ] = 0x18, + [PWRAP_CSLEXT_START] = 0x1c, + [PWRAP_CSLEXT_END] = 0x20, + [PWRAP_STAUPD_PRD] = 0x24, + [PWRAP_STAUPD_GRPEN] = 0x28, + [PWRAP_STAUPD_MAN_TRIG] = 0x2c, + [PWRAP_STAUPD_STA] = 0x30, + [PWRAP_EVENT_IN_EN] = 0x34, + [PWRAP_EVENT_DST_EN] = 0x38, + [PWRAP_WRAP_STA] = 0x3c, + [PWRAP_RRARB_INIT] = 0x40, + [PWRAP_RRARB_EN] = 0x44, + [PWRAP_RRARB_STA0] = 0x48, + [PWRAP_RRARB_STA1] = 0x4c, + [PWRAP_HARB_INIT] = 0x50, + [PWRAP_HARB_HPRIO] = 0x54, + [PWRAP_HIPRIO_ARB_EN] = 0x58, + [PWRAP_HARB_STA0] = 0x5c, + [PWRAP_HARB_STA1] = 0x60, + [PWRAP_MAN_EN] = 0x64, + [PWRAP_MAN_CMD] = 0x68, + [PWRAP_MAN_RDATA] = 0x6c, + [PWRAP_MAN_VLDCLR] = 0x70, + [PWRAP_WACS0_EN] = 0x74, + [PWRAP_INIT_DONE0] = 0x78, + [PWRAP_WACS0_CMD] = 0x7c, + [PWRAP_WACS0_RDATA] = 0x80, + [PWRAP_WACS0_VLDCLR] = 0x84, + [PWRAP_WACS1_EN] = 0x88, + [PWRAP_INIT_DONE1] = 0x8c, + [PWRAP_WACS1_CMD] = 0x90, + [PWRAP_WACS1_RDATA] = 0x94, + [PWRAP_WACS1_VLDCLR] = 0x98, + [PWRAP_WACS2_EN] = 0x9c, + [PWRAP_INIT_DONE2] = 0xa0, + [PWRAP_WACS2_CMD] = 0xa4, + [PWRAP_WACS2_RDATA] = 0xa8, + [PWRAP_WACS2_VLDCLR] = 0xac, + [PWRAP_INT_EN] = 0xb0, + [PWRAP_INT_FLG_RAW] = 0xb4, + [PWRAP_INT_FLG] = 0xb8, + [PWRAP_INT_CLR] = 0xbc, + [PWRAP_SIG_ADR] = 0xc0, + [PWRAP_SIG_MODE] = 0xc4, + [PWRAP_SIG_VALUE] = 0xc8, + [PWRAP_SIG_ERRVAL] = 0xcc, + [PWRAP_CRC_EN] = 0xd0, + [PWRAP_EVENT_STA] = 0xd4, + [PWRAP_EVENT_STACLR] = 0xd8, + [PWRAP_TIMER_EN] = 0xdc, + [PWRAP_TIMER_STA] = 0xe0, + [PWRAP_WDT_UNIT] = 0xe4, + [PWRAP_WDT_SRC_EN] = 0xe8, + [PWRAP_WDT_FLG] = 0xec, + [PWRAP_DEBUG_INT_SEL] = 0xf0, + [PWRAP_DVFS_ADR0] = 0xf4, + [PWRAP_DVFS_WDATA0] = 0xf8, + [PWRAP_DVFS_ADR1] = 0xfc, + [PWRAP_DVFS_WDATA1] = 0x100, + [PWRAP_DVFS_ADR2] = 0x104, + [PWRAP_DVFS_WDATA2] = 0x108, + [PWRAP_DVFS_ADR3] = 0x10c, + [PWRAP_DVFS_WDATA3] = 0x110, + [PWRAP_DVFS_ADR4] = 0x114, + [PWRAP_DVFS_WDATA4] = 0x118, + [PWRAP_DVFS_ADR5] = 0x11c, + [PWRAP_DVFS_WDATA5] = 0x120, + [PWRAP_DVFS_ADR6] = 0x124, + [PWRAP_DVFS_WDATA6] = 0x128, + [PWRAP_DVFS_ADR7] = 0x12c, + [PWRAP_DVFS_WDATA7] = 0x130, + [PWRAP_CIPHER_KEY_SEL] = 0x134, + [PWRAP_CIPHER_IV_SEL] = 0x138, + [PWRAP_CIPHER_LOAD] = 0x13c, + [PWRAP_CIPHER_START] = 0x140, + [PWRAP_CIPHER_RDY] = 0x144, + [PWRAP_CIPHER_MODE] = 0x148, + [PWRAP_CIPHER_SWRST] = 0x14c, + [PWRAP_CIPHER_IV0] = 0x150, + [PWRAP_CIPHER_IV1] = 0x154, + [PWRAP_CIPHER_IV2] = 0x158, + [PWRAP_DCM_EN] = 0x15c, + [PWRAP_DCM_DBC_PRD] = 0x160, +}; + static const int mt6765_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -1301,6 +1450,7 @@ static const int mt8186_regs[] = { }; enum pmic_type { + PMIC_MT6320, PMIC_MT6323, PMIC_MT6331, PMIC_MT6332, @@ -1314,6 +1464,7 @@ enum pmic_type { enum pwrap_type { PWRAP_MT2701, + PWRAP_MT6589, PWRAP_MT6765, PWRAP_MT6779, PWRAP_MT6795, @@ -1750,6 +1901,7 @@ static int pwrap_common_init_reg_clock(struct pmic_wrapper *wrp) case PWRAP_MT8173: pwrap_init_chip_select_ext(wrp, 0, 4, 2, 2); break; + case PWRAP_MT6589: case PWRAP_MT8135: pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); pwrap_init_chip_select_ext(wrp, 0, 4, 0, 0); @@ -1834,6 +1986,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL); switch (wrp->master->type) { + case PWRAP_MT6589: case PWRAP_MT8135: pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD); pwrap_writel(wrp, 1, PWRAP_CIPHER_START); @@ -1866,6 +2019,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) pwrap_config_cipher(wrp, wrp->slave->comp_dew_regs); switch (wrp->slave->type) { + case PMIC_MT6320: case PMIC_MT6397: pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1); @@ -1960,13 +2114,13 @@ static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp) /* enable pwrap events and pwrap bridge in AP side */ pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN); pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN); - writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT); - writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN); - writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN); - writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN); + writel(0x7f, wrp->bridge_base + PWRAP_BRIDGE_IORD_ARB_EN); + writel(0x1, wrp->bridge_base + PWRAP_BRIDGE_WACS3_EN); + writel(0x1, wrp->bridge_base + PWRAP_BRIDGE_WACS4_EN); + writel(0x1, wrp->bridge_base + PWRAP_BRIDGE_WDT_UNIT); + writel(0xffff, wrp->bridge_base + PWRAP_BRIDGE_WDT_SRC_EN); + writel(0x1, wrp->bridge_base + PWRAP_BRIDGE_TIMER_EN); + writel(0x7ff, wrp->bridge_base + PWRAP_BRIDGE_INT_EN); /* enable PMIC event out and sources */ if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_EVENT_OUT_EN], @@ -2110,7 +2264,8 @@ static int pwrap_init(struct pmic_wrapper *wrp) return ret; } - if (wrp->master->type == PWRAP_MT8135) + if (wrp->master->type == PWRAP_MT8135 || + wrp->master->type == PWRAP_MT6589) pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN); pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN); @@ -2131,8 +2286,8 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_INIT_DONE1); if (HAS_CAP(wrp->master->caps, PWRAP_CAP_BRIDGE)) { - writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3); - writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4); + writel(1, wrp->bridge_base + PWRAP_BRIDGE_INIT_DONE3); + writel(1, wrp->bridge_base + PWRAP_BRIDGE_INIT_DONE4); } return 0; @@ -2186,6 +2341,14 @@ static const struct pwrap_slv_regops pwrap_regops32 = { .regmap = &pwrap_regmap_config32, }; +static const struct pwrap_slv_type pmic_mt6320 = { + .dew_regs = mt6320_regs, + .type = PMIC_MT6320, + .regops = &pwrap_regops16, + .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | + PWRAP_SLV_CAP_SECURITY, +}; + static const struct pwrap_slv_type pmic_mt6323 = { .dew_regs = mt6323_regs, .type = PMIC_MT6323, @@ -2248,6 +2411,7 @@ static const struct pwrap_slv_type pmic_mt6397 = { }; static const struct of_device_id of_slave_match_tbl[] = { + { .compatible = "mediatek,mt6320", .data = &pmic_mt6320 }, { .compatible = "mediatek,mt6323", .data = &pmic_mt6323 }, { .compatible = "mediatek,mt6331", .data = &pmic_mt6331 }, { .compatible = "mediatek,mt6351", .data = &pmic_mt6351 }, @@ -2277,6 +2441,19 @@ static const struct pmic_wrapper_type pwrap_mt2701 = { .init_soc_specific = pwrap_mt2701_init_soc_specific, }; +static const struct pmic_wrapper_type pwrap_mt6589 = { + .regs = mt6589_regs, + .type = PWRAP_MT6589, + .arb_en_all = 0x1ff, + .int_en_all = 0x7ffffffd, + .int1_en_all = 0, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .caps = PWRAP_CAP_BRIDGE | PWRAP_CAP_RESET | PWRAP_CAP_DCM, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = pwrap_mt8135_init_soc_specific, +}; + static const struct pmic_wrapper_type pwrap_mt6765 = { .regs = mt6765_regs, .type = PWRAP_MT6765, @@ -2446,6 +2623,7 @@ static const struct pmic_wrapper_type pwrap_mt8186 = { static const struct of_device_id of_pwrap_match_tbl[] = { { .compatible = "mediatek,mt2701-pwrap", .data = &pwrap_mt2701 }, + { .compatible = "mediatek,mt6589-pwrap", .data = &pwrap_mt6589 }, { .compatible = "mediatek,mt6765-pwrap", .data = &pwrap_mt6765 }, { .compatible = "mediatek,mt6779-pwrap", .data = &pwrap_mt6779 }, { .compatible = "mediatek,mt6795-pwrap", .data = &pwrap_mt6795 }, diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c index 9ee2e7283435ac..ddf202170854a4 100644 --- a/drivers/thermal/mediatek/auxadc_thermal.c +++ b/drivers/thermal/mediatek/auxadc_thermal.c @@ -180,6 +180,7 @@ enum { enum mtk_thermal_version { MTK_THERMAL_V1 = 1, + MTK_THERMAL_V1_5, MTK_THERMAL_V2, MTK_THERMAL_V3, }; @@ -189,6 +190,25 @@ enum mtk_thermal_version { #define MT2701_TS2 1 #define MT2701_TSABB 2 +/* MT6589 thermal sensors */ +#define MT6589_TS1 0 +#define MT6589_TSABB 1 + +/* AUXADC channel 11 is used for the temperature sensors */ +#define MT6589_TEMP_AUXADC_CHANNEL 11 + +/* The total number of temperature sensors in the MT6589 */ +#define MT6589_NUM_SENSORS 2 + +/* The number of sensing points per bank */ +#define MT6589_NUM_SENSORS_PER_ZONE 2 + +/* The number of controller in the MT6589 */ +#define MT6589_NUM_CONTROLLER 1 + +/* The calibration coefficient of sensor */ +#define MT6589_CALIBRATION 165 + /* AUXADC channel 11 is used for the temperature sensors */ #define MT2701_TEMP_AUXADC_CHANNEL 11 @@ -325,6 +345,7 @@ struct mtk_thermal_data { u32 apmixed_buffer_ctl_reg; u32 apmixed_buffer_ctl_mask; u32 apmixed_buffer_ctl_set; + int (*extract_efuse)(struct mtk_thermal *mt, u32 *buf); }; struct mtk_thermal { @@ -339,6 +360,7 @@ struct mtk_thermal { /* Calibration values */ s32 adc_ge; s32 adc_oe; + s32 adc_cali_base; s32 degc_cali; s32 o_slope; s32 o_slope_sign; @@ -350,6 +372,8 @@ struct mtk_thermal { int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); }; +static int mtk_thermal_extract_efuse_mt6589(struct mtk_thermal *mt, u32 *buf); + /* MT8183 thermal sensor data */ static const int mt8183_bank_data[MT8183_NUM_SENSORS] = { MT8183_TS1, MT8183_TS2, MT8183_TS3, MT8183_TS4, MT8183_TS5, MT8183_TSABB @@ -414,6 +438,26 @@ static const int mt2701_vts_index[MT2701_NUM_SENSORS] = { VTS1, VTS2, VTS3 }; +/* MT6589 thermal sensor data */ +static const int mt6589_bank_data[MT6589_NUM_SENSORS] = { + MT6589_TS1, MT6589_TSABB +}; + +static const int mt6589_msr[MT6589_NUM_SENSORS_PER_ZONE] = { + TEMP_MSR0, TEMP_MSR1 +}; + +static const int mt6589_adcpnp[MT6589_NUM_SENSORS_PER_ZONE] = { + TEMP_ADCPNP0, TEMP_ADCPNP1 +}; + +static const int mt6589_mux_values[MT6589_NUM_SENSORS] = { 0, 1 }; +static const int mt6589_tc_offset[MT6589_NUM_CONTROLLER] = { 0x0 }; + +static const int mt6589_vts_index[MT6589_NUM_SENSORS] = { + VTS1, VTSABB +}; + /* MT2712 thermal sensor data */ static const int mt2712_bank_data[MT2712_NUM_SENSORS] = { MT2712_TS1, MT2712_TS2, MT2712_TS3, MT2712_TS4 @@ -607,6 +651,33 @@ static const struct mtk_thermal_data mt2712_thermal_data = { .version = MTK_THERMAL_V1, }; +/* + * The MT6589 thermal controller has one bank, which can read up to + * three temperature sensors simultaneously. The MT6589 has a total of + * two temperature sensors: the CPU sensor (TS1) and the ABB sensor. + */ +static const struct mtk_thermal_data mt6589_thermal_data = { + .auxadc_channel = MT6589_TEMP_AUXADC_CHANNEL, + .num_banks = 1, + .num_sensors = MT6589_NUM_SENSORS, + .vts_index = mt6589_vts_index, + .cali_val = MT6589_CALIBRATION, + .num_controller = MT6589_NUM_CONTROLLER, + .controller_offset = mt6589_tc_offset, + .need_switch_bank = false, + .bank_data = { + { + .num_sensors = 2, + .sensors = mt6589_bank_data, + }, + }, + .msr = mt6589_msr, + .adcpnp = mt6589_adcpnp, + .sensor_mux_values = mt6589_mux_values, + .version = MTK_THERMAL_V1_5, + .extract_efuse = mtk_thermal_extract_efuse_mt6589, +}; + /* * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data * access. @@ -724,6 +795,42 @@ static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) return mt->degc_cali * 500 - tmp; } +/* + * raw_to_mcelsius_v1_5 - convert a raw ADC value to mcelsius on + * platforms whose calibration layout matches the MT6572/MT6589 one. + * The formula follows the downstream mt65xx thermal driver. + */ +static int raw_to_mcelsius_v1_5(struct mtk_thermal *mt, int sensno, s32 raw) +{ + s32 format_1; + s32 format_2; + s32 g_oe; + s32 g_gain; + s32 g_x_roomt; + s32 tmp; + + if (raw == 0) + return 0; + + raw &= 0xfff; + g_gain = 10000 + (((mt->adc_ge - mt->adc_cali_base) * 10000) >> 12); + g_oe = mt->adc_oe - mt->adc_cali_base; + format_1 = mt->vts[sensno] + 3350 - g_oe; + format_2 = (mt->degc_cali * 10) >> 1; + g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; + + tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; + tmp = tmp * 15 / 18; + + if (mt->o_slope_sign == 0) + tmp = (tmp * 100) / (165 + mt->o_slope); + else + tmp = (tmp * 100) / (165 - mt->o_slope); + + tmp = tmp - (tmp << 1); + return (format_2 + tmp) * 100; +} + static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) { s32 format_1; @@ -930,7 +1037,8 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, writel(auxadc_phys_base + AUXADC_CON1_CLR_V, controller_base + TEMP_ADCMUXADDR); - if (mt->conf->version == MTK_THERMAL_V1) { + if (mt->conf->version == MTK_THERMAL_V1 || + mt->conf->version == MTK_THERMAL_V1_5) { /* AHB address for pnp sensor mux selection */ writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, controller_base + TEMP_PNPMUXADDR); @@ -1070,6 +1178,40 @@ static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) return 0; } +/* + * MT6589 efuse layout: the thermal words live at efuse offsets 0x100, + * 0x104 and 0x108 (buf[0..2]). The ADC gain/offset are split over the + * second and third word and a corner flag selects the base used by the + * conversion formula. + */ +static int mtk_thermal_extract_efuse_mt6589(struct mtk_thermal *mt, u32 *buf) +{ + mt->adc_ge = ((buf[1] & 0xFF000000) >> 24) | + (((buf[2] & 0x000C0000) >> 18) << 8); + mt->adc_oe = ((buf[1] & 0x00FF0000) >> 16) | + (((buf[2] & 0x00030000) >> 16) << 8); + mt->adc_cali_base = (buf[2] & BIT(20)) ? 512 : 128; + + mt->vts[VTS1] = (buf[0] & 0x03FE0000) >> 17; + mt->vts[VTSABB] = (buf[1] & 0x0000FF80) >> 7; + + mt->degc_cali = (buf[0] & 0x0000007E) >> 1; + /* The MT6589 uses the TSMC slope table. */ + mt->o_slope = 0; + mt->o_slope_sign = 0; + + if (!(buf[0] & 0x00000001)) { + /* not calibrated, fall back to defaults */ + mt->adc_ge = 128; + mt->adc_oe = 128; + mt->degc_cali = 40; + mt->o_slope = 0; + mt->vts[VTSABB] = 272; + } + + return 0; +} + static int mtk_thermal_get_calibration_data(struct device *dev, struct mtk_thermal *mt) { @@ -1081,6 +1223,7 @@ static int mtk_thermal_get_calibration_data(struct device *dev, /* Start with default values */ mt->adc_ge = 512; mt->adc_oe = 512; + mt->adc_cali_base = 512; for (i = 0; i < mt->conf->num_sensors; i++) mt->vts[i] = 260; mt->degc_cali = 40; @@ -1110,6 +1253,9 @@ static int mtk_thermal_get_calibration_data(struct device *dev, case MTK_THERMAL_V1: ret = mtk_thermal_extract_efuse_v1(mt, buf); break; + case MTK_THERMAL_V1_5: + ret = mt->conf->extract_efuse(mt, buf); + break; case MTK_THERMAL_V2: ret = mtk_thermal_extract_efuse_v2(mt, buf); break; @@ -1145,6 +1291,10 @@ static const struct of_device_id mtk_thermal_of_match[] = { .compatible = "mediatek,mt2712-thermal", .data = (void *)&mt2712_thermal_data, }, + { + .compatible = "mediatek,mt6589-thermal", + .data = (void *)&mt6589_thermal_data, + }, { .compatible = "mediatek,mt7622-thermal", .data = (void *)&mt7622_thermal_data, @@ -1270,11 +1420,14 @@ static int mtk_thermal_probe(struct platform_device *pdev) mtk_thermal_turn_on_buffer(mt, apmixed_base); - if (mt->conf->version != MTK_THERMAL_V1) + if (mt->conf->version != MTK_THERMAL_V1 && + mt->conf->version != MTK_THERMAL_V1_5) mtk_thermal_release_periodic_ts(mt, auxadc_base); if (mt->conf->version == MTK_THERMAL_V1) mt->raw_to_mcelsius = raw_to_mcelsius_v1; + else if (mt->conf->version == MTK_THERMAL_V1_5) + mt->raw_to_mcelsius = raw_to_mcelsius_v1_5; else if (mt->conf->version == MTK_THERMAL_V2) mt->raw_to_mcelsius = raw_to_mcelsius_v2; else diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c index c6cbe718b1da2f..d72be4530194a3 100644 --- a/drivers/usb/musb/mediatek.c +++ b/drivers/usb/musb/mediatek.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "musb_core.h" #include "musb_dma.h" @@ -37,6 +39,9 @@ #define DMA_INTR_STATUS_MSK GENMASK(7, 0) #define DMA_INTR_UNMASK_SET_MSK GENMASK(31, 24) +#define MTK_MUSB_L1INT_MASK (TX_INT_STATUS | RX_INT_STATUS | \ + USBCOM_INT_STATUS | DMA_INT_STATUS) + #define MTK_MUSB_CLKS_NUM 3 struct mtk_glue { @@ -50,6 +55,8 @@ struct mtk_glue { struct clk_bulk_data clks[MTK_MUSB_CLKS_NUM]; enum usb_role role; struct usb_role_switch *role_sw; + struct regulator *vusb; + struct reset_control *rstc; }; static int mtk_musb_clks_get(struct mtk_glue *glue) @@ -68,30 +75,63 @@ static int mtk_otg_switch_set(struct mtk_glue *glue, enum usb_role role) struct musb *musb = glue->musb; u8 devctl = readb(musb->mregs + MUSB_DEVCTL); enum usb_role new_role; + int ret; if (role == glue->role) return 0; switch (role) { case USB_ROLE_HOST: + new_role = USB_ROLE_HOST; + if (glue->role == USB_ROLE_NONE) { + if (glue->vusb) { + ret = regulator_enable(glue->vusb); + if (ret) { + dev_err(glue->dev, "failed to enable vusb: %d\n", ret); + return ret; + } + } + } + musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; glue->phy_mode = PHY_MODE_USB_HOST; - new_role = USB_ROLE_HOST; - if (glue->role == USB_ROLE_NONE) - phy_power_on(glue->phy); + if (glue->role == USB_ROLE_NONE) { + ret = phy_power_on(glue->phy); + if (ret) { + if (glue->vusb) + regulator_disable(glue->vusb); + return ret; + } + } devctl |= MUSB_DEVCTL_SESSION; musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); MUSB_HST_MODE(musb); break; case USB_ROLE_DEVICE: - musb->xceiv->otg->state = OTG_STATE_B_IDLE; - glue->phy_mode = PHY_MODE_USB_DEVICE; new_role = USB_ROLE_DEVICE; devctl &= ~MUSB_DEVCTL_SESSION; musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - if (glue->role == USB_ROLE_NONE) - phy_power_on(glue->phy); + if (glue->role == USB_ROLE_NONE) { + if (glue->vusb) { + ret = regulator_enable(glue->vusb); + if (ret) { + dev_err(glue->dev, "failed to enable vusb: %d\n", ret); + return ret; + } + } + } + + musb->xceiv->otg->state = OTG_STATE_B_IDLE; + glue->phy_mode = PHY_MODE_USB_DEVICE; + if (glue->role == USB_ROLE_NONE) { + ret = phy_power_on(glue->phy); + if (ret) { + if (glue->vusb) + regulator_disable(glue->vusb); + return ret; + } + } MUSB_DEV_MODE(musb); break; @@ -100,8 +140,11 @@ static int mtk_otg_switch_set(struct mtk_glue *glue, enum usb_role role) new_role = USB_ROLE_NONE; devctl &= ~MUSB_DEVCTL_SESSION; musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - if (glue->role != USB_ROLE_NONE) + if (glue->role != USB_ROLE_NONE) { phy_power_off(glue->phy); + if (glue->vusb) + regulator_disable(glue->vusb); + } break; default: @@ -248,8 +291,7 @@ static int mtk_musb_set_mode(struct musb *musb, u8 mode) return -EINVAL; } - mtk_otg_switch_set(glue, new_role); - return 0; + return mtk_otg_switch_set(glue, new_role); } static int mtk_musb_init(struct musb *musb) @@ -288,8 +330,7 @@ static int mtk_musb_init(struct musb *musb) musb_writel(musb->mregs, MUSB_HSDMA_INTR, DMA_INTR_STATUS_MSK | DMA_INTR_UNMASK_SET_MSK); #endif - musb_writel(musb->mregs, USB_L1INTM, TX_INT_STATUS | RX_INT_STATUS | - USBCOM_INT_STATUS | DMA_INT_STATUS); + musb_writel(musb->mregs, USB_L1INTM, MTK_MUSB_L1INT_MASK); return 0; err_phy_power_on: @@ -300,6 +341,17 @@ static int mtk_musb_init(struct musb *musb) return ret; } +static void mtk_musb_enable(struct musb *musb) +{ + musb_writel(musb->mregs, USB_L1INTM, MTK_MUSB_L1INT_MASK); +} + +static void mtk_musb_disable(struct musb *musb) +{ + musb_writel(musb->mregs, USB_L1INTM, 0); + (void)musb_readl(musb->mregs, USB_L1INTM); +} + static u16 mtk_musb_get_toggle(struct musb_qh *qh, int is_out) { struct musb *musb = qh->hw_ep->musb; @@ -335,10 +387,17 @@ static int mtk_musb_exit(struct musb *musb) { struct device *dev = musb->controller; struct mtk_glue *glue = dev_get_drvdata(dev->parent); + int ret; - mtk_otg_switch_exit(glue); + if (musb->port_mode == MUSB_OTG) + mtk_otg_switch_exit(glue); phy_power_off(glue->phy); phy_exit(glue->phy); + + ret = reset_control_assert(glue->rstc); + if (ret) + dev_warn(glue->dev, "failed to assert USB reset: %d\n", ret); + clk_bulk_disable_unprepare(MTK_MUSB_CLKS_NUM, glue->clks); pm_runtime_put_sync(dev); @@ -349,6 +408,8 @@ static int mtk_musb_exit(struct musb *musb) static const struct musb_platform_ops mtk_musb_ops = { .quirks = MUSB_DMA_INVENTRA, .init = mtk_musb_init, + .enable = mtk_musb_enable, + .disable = mtk_musb_disable, .get_toggle = mtk_musb_get_toggle, .set_toggle = mtk_musb_set_toggle, .exit = mtk_musb_exit, @@ -424,6 +485,15 @@ static int mtk_musb_probe(struct platform_device *pdev) if (ret) return ret; + glue->rstc = devm_reset_control_get_optional_exclusive(dev, "hrst"); + if (IS_ERR(glue->rstc)) + return dev_err_probe(dev, PTR_ERR(glue->rstc), + "failed to get reset control\n"); + + ret = reset_control_reset(glue->rstc); + if (ret) + return dev_err_probe(dev, ret, "failed to reset usb ip\n"); + pdata->config = &mtk_musb_hdrc_config; pdata->platform_ops = &mtk_musb_ops; pdata->mode = usb_get_dr_mode(dev); @@ -456,6 +526,16 @@ static int mtk_musb_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(glue->phy), "fail to getting phy\n"); + glue->vusb = devm_regulator_get_optional(dev, "vusb"); + if (IS_ERR(glue->vusb)) { + ret = PTR_ERR(glue->vusb); + if (ret == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (ret != -ENODEV) + return dev_err_probe(dev, ret, "fail to getting vusb-supply\n"); + glue->vusb = NULL; + } + glue->usb_phy = usb_phy_generic_register(); if (IS_ERR(glue->usb_phy)) return dev_err_probe(dev, PTR_ERR(glue->usb_phy), diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 73ac25f53698f4..2556600fee2506 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2617,23 +2617,16 @@ static int musb_probe(struct platform_device *pdev) return musb_init_controller(dev, irq, base); } -static void musb_remove(struct platform_device *pdev) +static void musb_quiesce(struct musb *musb) { - struct device *dev = &pdev->dev; - struct musb *musb = dev_to_musb(dev); - unsigned long flags; + unsigned long flags; - /* this gets called on rmmod. - * - Host mode: host may still be active - * - Peripheral mode: peripheral is deactivated (or never-activated) - * - OTG mode: both roles are deactivated (or never-activated) - */ - musb_exit_debugfs(musb); + pm_runtime_get_sync(musb->controller); cancel_delayed_work_sync(&musb->irq_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); - pm_runtime_get_sync(musb->controller); + musb_host_cleanup(musb); musb_gadget_cleanup(musb); @@ -2642,19 +2635,58 @@ static void musb_remove(struct platform_device *pdev) musb_disable_interrupts(musb); musb_writeb(musb->mregs, MUSB_DEVCTL, 0); spin_unlock_irqrestore(&musb->lock, flags); - musb_platform_exit(musb); + timer_shutdown_sync(&musb->otg_timer); + + if (musb->nIrq >= 0) + synchronize_irq(musb->nIrq); +} + +static void musb_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct musb *musb = dev_to_musb(dev); + + /* this gets called on rmmod. + * - Host mode: host may still be active + * - Peripheral mode: peripheral is deactivated (or never-activated) + * - OTG mode: both roles are deactivated (or never-activated) + */ + musb_exit_debugfs(musb); + + musb_quiesce(musb); + + if (musb->dma_controller) { + musb_dma_controller_destroy(musb->dma_controller); + musb->dma_controller = NULL; + } + + musb_platform_exit(musb); pm_runtime_dont_use_autosuspend(musb->controller); pm_runtime_put_sync(musb->controller); pm_runtime_disable(musb->controller); musb_phy_callback = NULL; - if (musb->dma_controller) - musb_dma_controller_destroy(musb->dma_controller); usb_phy_shutdown(musb->xceiv); musb_free(musb); device_init_wakeup(dev, 0); } +static void musb_shutdown(struct platform_device *pdev) +{ + struct musb *musb = dev_to_musb(&pdev->dev); + + musb_quiesce(musb); + + if (musb->dma_controller) { + musb_dma_controller_destroy(musb->dma_controller); + musb->dma_controller = NULL; + } + + musb_platform_exit(musb); + musb_phy_callback = NULL; + usb_phy_shutdown(musb->xceiv); +} + #ifdef CONFIG_PM static void musb_save_context(struct musb *musb) @@ -2950,6 +2982,7 @@ static struct platform_driver musb_driver = { }, .probe = musb_probe, .remove = musb_remove, + .shutdown = musb_shutdown, }; module_platform_driver(musb_driver); diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 8c6c643fcb2ce2..2c9d801b7169cb 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -72,26 +72,26 @@ struct musb_dma_controller { }; static void dma_channel_release(struct dma_channel *channel); +static int dma_channel_abort(struct dma_channel *channel); static void dma_controller_stop(struct musb_dma_controller *controller) { - struct musb *musb = controller->private_data; struct dma_channel *channel; + void __iomem *mbase = controller->base; u8 bit; - if (controller->used_channels != 0) { - dev_err(musb->controller, - "Stopping DMA controller while channel active\n"); - - for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) { - if (controller->used_channels & (1 << bit)) { - channel = &controller->channel[bit].channel; - dma_channel_release(channel); + for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) { + channel = &controller->channel[bit].channel; - if (!controller->used_channels) - break; - } + if (controller->used_channels & (1 << bit)) { + dma_channel_abort(channel); + dma_channel_release(channel); } + + musb_writew(mbase, + MUSB_HSDMA_CHANNEL_OFFSET(bit, MUSB_HSDMA_CONTROL), 0); + musb_write_hsdma_addr(mbase, bit, 0); + musb_write_hsdma_count(mbase, bit, 0); } } diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 91d110646e16f7..e2783dee7707dc 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -64,6 +64,7 @@ #define DRV_NAME "mtk-wdt" #define DRV_VERSION "1.0" +#define MT6589_TOPRGU_SW_RST_NUM 12 #define MT7988_TOPRGU_SW_RST_NUM 24 static bool nowayout = WATCHDOG_NOWAYOUT; @@ -88,6 +89,10 @@ static const struct mtk_wdt_data mt2712_data = { .toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM, }; +static const struct mtk_wdt_data mt6589_data = { + .toprgu_sw_rst_num = MT6589_TOPRGU_SW_RST_NUM, +}; + static const struct mtk_wdt_data mt6735_data = { .toprgu_sw_rst_num = MT6735_TOPRGU_RST_NUM, }; @@ -493,7 +498,7 @@ static int mtk_wdt_resume(struct device *dev) static const struct of_device_id mtk_wdt_dt_ids[] = { { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, - { .compatible = "mediatek,mt6589-wdt" }, + { .compatible = "mediatek,mt6589-wdt", .data = &mt6589_data }, { .compatible = "mediatek,mt6735-wdt", .data = &mt6735_data }, { .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data }, { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data }, diff --git a/include/dt-bindings/clock/mediatek,mt6320-clk.h b/include/dt-bindings/clock/mediatek,mt6320-clk.h new file mode 100644 index 00000000000000..a4c560d129bd08 --- /dev/null +++ b/include/dt-bindings/clock/mediatek,mt6320-clk.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Flora Fu + * + * Author: Akari Tsuyukusa + */ + +#ifndef _DT_BINDINGS_CLK_MT6397_H +#define _DT_BINDINGS_CLK_MT6397_H + +#define MT6320_CLK_AUD26M 0 +#define MT6320_CLK_AUD13M 1 +#define MT6320_CLK_AUD26M_DIV64 2 +#define MT6320_CLK_SMPS24M 3 +#define MT6320_CLK_SMPS12M 4 +#define MT6320_CLK_SMPS6M 5 +#define MT6320_CLK_SMPS3M 6 +#define MT6320_CLK_SMPS2M 7 +#define MT6320_CLK_SMPS1M 8 +#define MT6320_CLK_PMU75K 9 +#define MT6320_CLK_PMU12M 10 +#define MT6320_CLK_FG32K 11 +#define MT6320_CLK_RTC32K 12 +#define MT6320_CLK_CHR1M 13 + +#define MT6320_TOPCKPDN_AUD_26M 14 +#define MT6320_TOPCKPDN_AUD_13M 15 +#define MT6320_TOPCKPDN_SPK_CK 16 +#define MT6320_TOPCKPDN_PWMOC_CK 17 +#define MT6320_TOPCKPDN_EFUSE_CK 18 +#define MT6320_TOPCKPDN_FGADC_CK 19 +#define MT6320_TOPCKPDN_FGADC_ANA_CK 20 +#define MT6320_TOPCKPDN_BST_DRV_1M_CK 21 +#define MT6320_TOPCKPDN_RTC_MCLK 22 +#define MT6320_TOPCKPDN_SPK_PWM_DIV 23 +#define MT6320_TOPCKPDN_SPK_DIV 24 +#define MT6320_TOPCKPDN_SMPS_CK_DIV2 25 +#define MT6320_TOPCKPDN_SMPS_CK_DIV 26 +#define MT6320_TOPCKPDN_AUXADC_CK 27 +#define MT6320_TOPCKPDN_ACCDET_CK 28 +#define MT6320_TOPCKPDN_STRUP_6M 29 +#define MT6320_TOPCKPDN2_RTC32K_1V8 30 +#define MT6320_TOPCKPDN2_FQMTR 31 +#define MT6320_TOPCKPDN2_STRUP_75K_CK 32 +#define MT6320_TOPCKPDN2_RTC_32K_CK 33 +#define MT6320_TOPCKPDN2_PCHR_32K_CK 34 +#define MT6320_TOPCKPDN2_LDOSTB_1M_CK 35 +#define MT6320_TOPCKPDN2_INTRP_CK 36 +#define MT6320_TOPCKPDN2_DRV_32K_CK 37 +#define MT6320_TOPCKPDN2_CHR1M_CK 38 +#define MT6320_TOPCKPDN2_BUCK_CK 39 +#define MT6320_TOPCKPDN2_BUCK_ANA_CK 40 +#define MT6320_TOPCKPDN2_BUCK32K 41 +#define MT6320_TOPCKPDN2_BUCK_1M_CK 42 +#define MT6320_TOPCKPDN2_STRUP_32K_CK 43 +#define MT6320_TOPCKPDN2_RTC_75K_CK 44 +#define MT6320_TOPCKPDN2_RSV_15 45 +#define MT6320_WRPCKPDN_I2C0 46 +#define MT6320_WRPCKPDN_I2C1 47 +#define MT6320_WRPCKPDN_I2C2 48 +#define MT6320_WRPCKPDN_PWM 49 +#define MT6320_WRPCKPDN_KP 50 +#define MT6320_WRPCKPDN_EINT 51 +#define MT6320_WRPCKPDN_32K 52 +#define MT6320_WRPCKPDN_WRP 53 +#define MT6320_CLK_MAX 54 + +#endif diff --git a/include/dt-bindings/clock/mediatek,mt6589-clk.h b/include/dt-bindings/clock/mediatek,mt6589-clk.h new file mode 100644 index 00000000000000..cfeff8b6ab9186 --- /dev/null +++ b/include/dt-bindings/clock/mediatek,mt6589-clk.h @@ -0,0 +1,296 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Author: Akari Tsuyukusa + */ + +#ifndef _DT_BINDINGS_CLK_MEDIATEK_MT6589_CLK_H +#define _DT_BINDINGS_CLK_MEDIATEK_MT6589_CLK_H + +/* APMIXEDSYS */ +#define CLK_APMIXED_ARMPLL 0 +#define CLK_APMIXED_MAINPLL 1 +#define CLK_APMIXED_UNIVPLL 2 +#define CLK_APMIXED_MMPLL 3 +#define CLK_APMIXED_ISPPLL 4 +#define CLK_APMIXED_MSDCPLL 5 +#define CLK_APMIXED_TVDPLL 6 +#define CLK_APMIXED_LVDSPLL 7 + +#define CLK_APMIXED_ARMPLL_1300M 8 + +#define CLK_APMIXED_MAINPLL_806M 9 +#define CLK_APMIXED_MAINPLL_537P3M 10 +#define CLK_APMIXED_MAINPLL_322P4M 11 +#define CLK_APMIXED_MAINPLL_230P3M 12 + +#define CLK_APMIXED_UNIVPLL_624M 13 +#define CLK_APMIXED_UNIVPLL_416M 14 +#define CLK_APMIXED_UNIVPLL_249P6M 15 +#define CLK_APMIXED_UNIVPLL_178P3M 16 +#define CLK_APMIXED_UNIVPLL_48M 17 +#define CLK_APMIXED_UNIVPLL_USB_48M 18 + +#define CLK_APMIXED_MMPLL_D2 19 +/* GPU: 476MHz */ +#define CLK_APMIXED_MMPLL_D3 20 +/* GPU: 286MHz */ +#define CLK_APMIXED_MMPLL_D5 21 +#define CLK_APMIXED_MMPLL_D7 22 + +#define CLK_APMIXED_ISPPLL_208M 23 + +#define CLK_APMIXED_MSDCPLL_208M 24 + +#define CLK_APMIXED_TVDPLL_148P5M 25 + +#define CLK_APMIXED_LVDSPLL_180M 26 + + +/* TOPCKGEN */ +#define CLK_TOP_CLK_NULL 0 + +#define CLK_TOP_CLKPH_MCK 1 +#define CLK_TOP_CPUM_TCK_IN 2 + +/* GPU: 403MHz */ +#define CLK_TOP_SYSPLL_D2 3 +/* MAINPLL / 3 / 2 = GPU: 268MHz */ +#define CLK_TOP_SYSPLL_D3 4 +#define CLK_TOP_SYSPLL_D3P5 5 +/* MAINPLL / 2 / 4 */ +#define CLK_TOP_SYSPLL_D4 6 +#define CLK_TOP_SYSPLL_D5 7 +/* MAINPLL /2 / 6 */ +#define CLK_TOP_SYSPLL_D6 8 +#define CLK_TOP_SYSPLL_D8 9 +#define CLK_TOP_SYSPLL_D10 10 +#define CLK_TOP_SYSPLL_D16 11 +#define CLK_TOP_SYSPLL_D24 12 + +#define CLK_TOP_UNIVPLL_D3 13 +/* UNIVPLL / 5 */ +#define CLK_TOP_UNIVPLL_D5 14 +#define CLK_TOP_UNIVPLL_D7 15 +#define CLK_TOP_UNIVPLL_D10 16 +#define CLK_TOP_UNIVPLL_D26 17 + +/* GPU: 312MHz */ +#define CLK_TOP_UNIVPLL1_D2 18 +/* GPU: 156MHz */ +#define CLK_TOP_UNIVPLL1_D4 19 +#define CLK_TOP_UNIVPLL1_D6 20 +#define CLK_TOP_UNIVPLL1_D8 21 +#define CLK_TOP_UNIVPLL1_D10 22 + +/* UNIVPLL / 3 / 2 */ +#define CLK_TOP_UNIVPLL2_D2 23 +/* unknown */ +#define CLK_TOP_UNIVPLL2_D4 24 +#define CLK_TOP_UNIVPLL2_D6 25 +#define CLK_TOP_UNIVPLL2_D8 26 + +/* GPU: 357MHz */ +#define CLK_TOP_MMPLL_D4 27 +/* GPU: 238MHz */ +#define CLK_TOP_MMPLL_D6 28 + +#define CLK_TOP_LVDSPLL 29 +#define CLK_TOP_LVDSPLL_D2 30 +#define CLK_TOP_LVDSPLL_D4 31 +#define CLK_TOP_LVDSPLL_D8 32 + +#define CLK_TOP_MEMPLL_MCK_D4 33 + +/* MUXs */ +/* CLK_CFG_0 */ +#define CLK_TOP_MUX_AXI 34 +#define CLK_TOP_MUX_SMI 35 +#define CLK_TOP_MUX_MFG 36 +#define CLK_TOP_MUX_IRDA 37 + +/* CLK_CFG_1 */ +#define CLK_TOP_MUX_CAM 38 +#define CLK_TOP_MUX_AUDINTBUS 39 +#define CLK_TOP_MUX_JPG 40 +#define CLK_TOP_MUX_DISP 41 + +/* CLK_CFG_2 */ +#define CLK_TOP_MUX_MSDC1 42 +#define CLK_TOP_MUX_MSDC2 43 +#define CLK_TOP_MUX_MSDC3 44 +#define CLK_TOP_MUX_MSDC4 45 + +/* CLK_CFG_3 */ +#define CLK_TOP_MUX_USB20 46 + +/* CLK_CFG_4 */ +#define CLK_TOP_MUX_HYD 47 +#define CLK_TOP_MUX_VENC 48 +#define CLK_TOP_MUX_SPI 49 +#define CLK_TOP_MUX_UART 50 + +/* CLK_CFG_6 */ +#define CLK_TOP_MUX_MEM 51 +#define CLK_TOP_MUX_CAMTG 52 +#define CLK_TOP_MUX_FD 53 +#define CLK_TOP_MUX_AUDIO 54 + +/* CLK_CFG_7 */ +#define CLK_TOP_MUX_FIX 55 +#define CLK_TOP_MUX_VDEC 56 +#define CLK_TOP_MUX_DPILVDS 57 + +/* CLK_CFG_8 */ +#define CLK_TOP_MUX_PMICSPI 58 +#define CLK_TOP_MUX_MSDC0 59 +#define CLK_TOP_MUX_SMI_MFG_AS 60 + +#define CLK_TOPCK_PMICSPI 61 + + +/* INFRACFG */ +#define CLK_INFRA_MUX1 0 + +#define CLK_INFRA_DBGCLK 1 +#define CLK_INFRA_SMI 2 +#define CLK_INFRA_SPI0 3 +#define CLK_INFRA_AUDIO 4 +#define CLK_INFRA_DEVAPC 5 +#define CLK_INFRA_MFGAXI 6 +#define CLK_INFRA_M4U 7 +#define CLK_INFRA_MD1MCUAXI 8 +#define CLK_INFRA_MD1HWMIXAXI 9 +#define CLK_INFRA_MD1AHB 10 +#define CLK_INFRA_MD2MCUAXI 11 +#define CLK_INFRA_MD2HWMIXAXI 12 +#define CLK_INFRA_MD2AHB 13 +#define CLK_INFRA_CPUM 14 +#define CLK_INFRA_KP 15 +#define CLK_INFRA_CCIF0 16 +#define CLK_INFRA_CCIF1 17 +#define CLK_INFRA_PMICSPI 18 +#define CLK_INFRA_PMICWRAP 19 + + +/* PERICFG */ +#define CLK_PERI0_NFI 0 +#define CLK_PERI0_THERM 1 +#define CLK_PERI0_PWM1 2 +#define CLK_PERI0_PWM2 3 +#define CLK_PERI0_PWM3 4 +#define CLK_PERI0_PWM4 5 +#define CLK_PERI0_PWM5 6 +#define CLK_PERI0_PWM6 7 +#define CLK_PERI0_PWM7 8 +#define CLK_PERI0_PWM 9 +#define CLK_PERI0_USB0 10 +#define CLK_PERI0_USB1 11 +#define CLK_PERI0_APDMA 12 +#define CLK_PERI0_MSDC0 13 +#define CLK_PERI0_MSDC1 14 +#define CLK_PERI0_MSDC2 15 +#define CLK_PERI0_MSDC3 16 +#define CLK_PERI0_MSDC4 17 +#define CLK_PERI0_APHIF 18 +#define CLK_PERI0_MDHIF 19 +#define CLK_PERI0_NLI 20 +#define CLK_PERI0_IRDA 21 +#define CLK_PERI0_UART0 22 +#define CLK_PERI0_UART1 23 +#define CLK_PERI0_UART2 24 +#define CLK_PERI0_UART3 25 +#define CLK_PERI0_I2C0 26 +#define CLK_PERI0_I2C1 27 +#define CLK_PERI0_I2C2 28 +#define CLK_PERI0_I2C3 29 +#define CLK_PERI0_I2C4 30 +#define CLK_PERI0_I2C5 31 + +#define CLK_PERI1_I2C6 32 +#define CLK_PERI1_PWRAP 33 +#define CLK_PERI1_AUXADC 34 +#define CLK_PERI1_SPI1 35 +#define CLK_PERI1_FHCTL 36 + +#define CLK_PERI_MUX_UART0 37 +#define CLK_PERI_MUX_UART1 38 +#define CLK_PERI_MUX_UART2 39 +#define CLK_PERI_MUX_UART3 40 + + +/* DISP */ +#define CLK_DISP0_LARB2_SMI 0 +#define CLK_DISP0_ROT_ENGINE 1 +#define CLK_DISP0_ROT_SMI 2 +#define CLK_DISP0_SCL 3 +#define CLK_DISP0_OVL_ENGINE 4 +#define CLK_DISP0_OVL_SMI 5 +#define CLK_DISP0_COLOR 6 +#define CLK_DISP0_2DSHP 7 +#define CLK_DISP0_BLS 8 +#define CLK_DISP0_WDMA0_ENGINE 9 +#define CLK_DISP0_WDMA0_SMI 10 +#define CLK_DISP0_WDMA1_ENGINE 11 +#define CLK_DISP0_WDMA1_SMI 12 +#define CLK_DISP0_RDMA0_ENGINE 13 +#define CLK_DISP0_RDMA0_SMI 14 +#define CLK_DISP0_RDMA0_OUTPUT 15 +#define CLK_DISP0_RDMA1_ENGINE 16 +#define CLK_DISP0_RDMA1_SMI 17 +#define CLK_DISP0_RDMA1_OUTPUT 18 +#define CLK_DISP0_GAMMA_ENGINE 19 +#define CLK_DISP0_GAMMA_PIXEL 20 +#define CLK_DISP0_CMDQ_ENGINE 21 +#define CLK_DISP0_CMDQ_SMI 22 +#define CLK_DISP0_G2D_ENGINE 23 +#define CLK_DISP0_G2D_SMI 24 + +#define CLK_DISP1_DBI_ENGINE 25 +#define CLK_DISP1_DBI_SMI 26 +#define CLK_DISP1_DBI_OUTPUT 27 +#define CLK_DISP1_DSI_ENGINE 28 +#define CLK_DISP1_DSI_DIGITAL 29 +#define CLK_DISP1_DSI_DIGITAL_LANE 30 +#define CLK_DISP1_DPI0 31 +#define CLK_DISP1_DPI1 32 +#define CLK_DISP1_LCD 33 +#define CLK_DISP1_SLCD 34 + + +/* IMG */ +#define CLK_IMAGE_LARB3_SMI 0 +#define CLK_IMAGE_LARB4_SMI 1 +#define CLK_IMAGE_COMMON_SMI 2 +#define CLK_IMAGE_CAM_SMI 3 +#define CLK_IMAGE_CAM_CAM 4 +#define CLK_IMAGE_SEN_TG 5 +#define CLK_IMAGE_SEN_CAM 6 +#define CLK_IMAGE_JPGD_SMI 7 +#define CLK_IMAGE_JPGD_JPG 8 +#define CLK_IMAGE_JPGE_SMI 9 +#define CLK_IMAGE_JPGE_JPG 10 +#define CLK_IMAGE_FPC 11 + + +/* MFG */ +#define CLK_MFG_AXI 0 +#define CLK_MFG_MEM 1 +#define CLK_MFG_G3D 2 +#define CLK_MFG_HYD 3 + + +/* AUD */ +#define CLK_AUDIO_AFE 0 +#define CLK_AUDIO_I2S 1 + + +/* VDEC */ +#define CLK_VDEC0_VDE 0 + +#define CLK_VDEC1_SMI 1 + + +/* VENC */ +#define CLK_VENC_VEN 0 + +#endif diff --git a/include/dt-bindings/memory/mt6589-larb-port.h b/include/dt-bindings/memory/mt6589-larb-port.h new file mode 100644 index 00000000000000..ae0acf225e13be --- /dev/null +++ b/include/dt-bindings/memory/mt6589-larb-port.h @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#ifndef _DT_BINDINGS_MEMORY_MT6589_LARB_PORT_H_ +#define _DT_BINDINGS_MEMORY_MT6589_LARB_PORT_H_ + +#define MT6589_LARB0_PORT_OFFSET 0 +#define MT6589_LARB1_PORT_OFFSET 10 +#define MT6589_LARB2_PORT_OFFSET 17 +#define MT6589_LARB3_PORT_OFFSET 29 +#define MT6589_LARB4_PORT_OFFSET 43 +#define MT6589_LARB5_PORT_OFFSET 53 + +#define MT6589_M4U_ID_LARB0(n) ((n) + MT6589_LARB0_PORT_OFFSET) +#define MT6589_M4U_ID_LARB1(n) ((n) + MT6589_LARB1_PORT_OFFSET) +#define MT6589_M4U_ID_LARB2(n) ((n) + MT6589_LARB2_PORT_OFFSET) +#define MT6589_M4U_ID_LARB3(n) ((n) + MT6589_LARB3_PORT_OFFSET) +#define MT6589_M4U_ID_LARB4(n) ((n) + MT6589_LARB4_PORT_OFFSET) +#define MT6589_M4U_ID_LARB5(n) ((n) + MT6589_LARB5_PORT_OFFSET) + +/* larb0 */ +#define MT6589_M4U_PORT_VENC_RCPU MT6589_M4U_ID_LARB0(0) +#define MT6589_M4U_PORT_VENC_REF_LUMA MT6589_M4U_ID_LARB0(1) +#define MT6589_M4U_PORT_VENC_REF_CHROMA MT6589_M4U_ID_LARB0(2) +#define MT6589_M4U_PORT_VENC_DB_READ MT6589_M4U_ID_LARB0(3) +#define MT6589_M4U_PORT_VENC_DB_WRITE MT6589_M4U_ID_LARB0(4) +#define MT6589_M4U_PORT_VENC_CUR_LUMA MT6589_M4U_ID_LARB0(5) +#define MT6589_M4U_PORT_VENC_CUR_CHROMA MT6589_M4U_ID_LARB0(6) +#define MT6589_M4U_PORT_VENC_RD_COMV MT6589_M4U_ID_LARB0(7) +#define MT6589_M4U_PORT_VENC_SV_COMV MT6589_M4U_ID_LARB0(8) +#define MT6589_M4U_PORT_VENC_BSDMA MT6589_M4U_ID_LARB0(9) + +/* larb1 */ +#define MT6589_M4U_PORT_HW_VDEC_MC_EXT MT6589_M4U_ID_LARB1(0) +#define MT6589_M4U_PORT_HW_VDEC_PP_EXT MT6589_M4U_ID_LARB1(1) +#define MT6589_M4U_PORT_HW_VDEC_AVC_MV_EXT MT6589_M4U_ID_LARB1(2) +#define MT6589_M4U_PORT_HW_VDEC_PRED_RD_EXT MT6589_M4U_ID_LARB1(3) +#define MT6589_M4U_PORT_HW_VDEC_PRED_WR_EXT MT6589_M4U_ID_LARB1(4) +#define MT6589_M4U_PORT_HW_VDEC_VLD_EXT MT6589_M4U_ID_LARB1(5) +#define MT6589_M4U_PORT_HW_VDEC_VLD2_EXT MT6589_M4U_ID_LARB1(6) + +/* larb2 */ +#define MT6589_M4U_PORT_ROT_EXT MT6589_M4U_ID_LARB2(0) +#define MT6589_M4U_PORT_OVL_CH0 MT6589_M4U_ID_LARB2(1) +#define MT6589_M4U_PORT_OVL_CH1 MT6589_M4U_ID_LARB2(2) +#define MT6589_M4U_PORT_OVL_CH2 MT6589_M4U_ID_LARB2(3) +#define MT6589_M4U_PORT_OVL_CH3 MT6589_M4U_ID_LARB2(4) +#define MT6589_M4U_PORT_WDMA0 MT6589_M4U_ID_LARB2(5) +#define MT6589_M4U_PORT_WDMA1 MT6589_M4U_ID_LARB2(6) +#define MT6589_M4U_PORT_RDMA0 MT6589_M4U_ID_LARB2(7) +#define MT6589_M4U_PORT_RDMA1 MT6589_M4U_ID_LARB2(8) +#define MT6589_M4U_PORT_CMDQ MT6589_M4U_ID_LARB2(9) +#define MT6589_M4U_PORT_DBI MT6589_M4U_ID_LARB2(10) +#define MT6589_M4U_PORT_G2D MT6589_M4U_ID_LARB2(11) + +/* larb3 */ +#define MT6589_M4U_PORT_JPGDEC_WDMA MT6589_M4U_ID_LARB3(0) +#define MT6589_M4U_PORT_JPGENC_RDMA MT6589_M4U_ID_LARB3(1) +#define MT6589_M4U_PORT_VIPI MT6589_M4U_ID_LARB3(2) +#define MT6589_M4U_PORT_IMGI MT6589_M4U_ID_LARB3(3) +#define MT6589_M4U_PORT_DISPO MT6589_M4U_ID_LARB3(4) +#define MT6589_M4U_PORT_DISPCO MT6589_M4U_ID_LARB3(5) +#define MT6589_M4U_PORT_DISPVO MT6589_M4U_ID_LARB3(6) +#define MT6589_M4U_PORT_VIDO MT6589_M4U_ID_LARB3(7) +#define MT6589_M4U_PORT_VIDCO MT6589_M4U_ID_LARB3(8) +#define MT6589_M4U_PORT_VIDVO MT6589_M4U_ID_LARB3(9) +#define MT6589_M4U_PORT_VIP2I MT6589_M4U_ID_LARB3(10) +#define MT6589_M4U_PORT_GDMA_SMI_WR MT6589_M4U_ID_LARB3(11) +#define MT6589_M4U_PORT_JPGDEC_BSDMA MT6589_M4U_ID_LARB3(12) +#define MT6589_M4U_PORT_JPGENC_BSDMA MT6589_M4U_ID_LARB3(13) + +/* larb4 */ +#define MT6589_M4U_PORT_GDMA_SMI_RD MT6589_M4U_ID_LARB4(0) +#define MT6589_M4U_PORT_IMGCI MT6589_M4U_ID_LARB4(1) +#define MT6589_M4U_PORT_IMGO MT6589_M4U_ID_LARB4(2) +#define MT6589_M4U_PORT_IMG2O MT6589_M4U_ID_LARB4(3) +#define MT6589_M4U_PORT_LSCI MT6589_M4U_ID_LARB4(4) +#define MT6589_M4U_PORT_FLKI MT6589_M4U_ID_LARB4(5) +#define MT6589_M4U_PORT_LCEI MT6589_M4U_ID_LARB4(6) +#define MT6589_M4U_PORT_LCSO MT6589_M4U_ID_LARB4(7) +#define MT6589_M4U_PORT_ESFKO MT6589_M4U_ID_LARB4(8) +#define MT6589_M4U_PORT_AAO MT6589_M4U_ID_LARB4(9) + +/* larb5 */ +/* xxx: is it really larb? */ +#define MT6589_M4U_PORT_AUDIO MT6589_M4U_ID_LARB5(0) + +#define MT6589_M4U_PORT_NR 54 + +#endif diff --git a/include/dt-bindings/pinctrl/mt6320-pinfunc.h b/include/dt-bindings/pinctrl/mt6320-pinfunc.h new file mode 100644 index 00000000000000..28d2aa43ac4b4f --- /dev/null +++ b/include/dt-bindings/pinctrl/mt6320-pinfunc.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __DTS_MT6320_PINFUNC_H +#define __DTS_MT6320_PINFUNC_H + +#include + + +#define MT6320_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define MT6320_GPIO0__FUNC_INT (MTK_PIN_NO(0) | 1) + +#define MT6320_GPIO1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define MT6320_GPIO1__FUNC_SRCVOLTEN (MTK_PIN_NO(1) | 1) + +#define MT6320_GPIO2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define MT6320_GPIO2__FUNC_SRCLKEN_PERI (MTK_PIN_NO(2) | 1) + +#define MT6320_GPIO3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define MT6320_GPIO3__FUNC_SRCLKEN_MD2 (MTK_PIN_NO(3) | 1) + +#define MT6320_GPIO4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define MT6320_GPIO4__FUNC_RTC_32K1V8 (MTK_PIN_NO(4) | 1) + +#define MT6320_GPIO5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define MT6320_GPIO5__FUNC_WRAP_EVENT (MTK_PIN_NO(5) | 1) + +#define MT6320_GPIO6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define MT6320_GPIO6__FUNC_SPI_CLK (MTK_PIN_NO(6) | 1) + +#define MT6320_GPIO7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define MT6320_GPIO7__FUNC_SPI_CSN (MTK_PIN_NO(7) | 1) + +#define MT6320_GPIO8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define MT6320_GPIO8__FUNC_SPI_MOSI (MTK_PIN_NO(8) | 1) + +#define MT6320_GPIO9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define MT6320_GPIO9__FUNC_SPI_MISO (MTK_PIN_NO(9) | 1) + +#define MT6320_GPIO10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define MT6320_GPIO10__FUNC_ADC_CK (MTK_PIN_NO(10) | 1) + +#define MT6320_GPIO11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define MT6320_GPIO11__FUNC_ADC_WS (MTK_PIN_NO(11) | 1) + +#define MT6320_GPIO12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define MT6320_GPIO12__FUNC_ADC_DAT (MTK_PIN_NO(12) | 1) + +#define MT6320_GPIO13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define MT6320_GPIO13__FUNC_DAC_CK (MTK_PIN_NO(13) | 1) + +#define MT6320_GPIO14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define MT6320_GPIO14__FUNC_DAC_WS (MTK_PIN_NO(14) | 1) + +#define MT6320_GPIO15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define MT6320_GPIO15__FUNC_DAC_DAT (MTK_PIN_NO(15) | 1) + +#define MT6320_GPIO16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0) +#define MT6320_GPIO16__FUNC_COL0_USBDL (MTK_PIN_NO(16) | 1) +#define MT6320_GPIO16__FUNC_EINT10 (MTK_PIN_NO(16) | 2) +#define MT6320_GPIO16__FUNC_PWM1_3X (MTK_PIN_NO(16) | 3) + +#define MT6320_GPIO17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0) +#define MT6320_GPIO17__FUNC_COL1 (MTK_PIN_NO(17) | 1) +#define MT6320_GPIO17__FUNC_EINT11 (MTK_PIN_NO(17) | 2) +#define MT6320_GPIO17__FUNC_SCL0_2X (MTK_PIN_NO(17) | 3) + +#define MT6320_GPIO18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define MT6320_GPIO18__FUNC_COL2 (MTK_PIN_NO(18) | 1) +#define MT6320_GPIO18__FUNC_EINT12 (MTK_PIN_NO(18) | 2) +#define MT6320_GPIO18__FUNC_SDA0_2X (MTK_PIN_NO(18) | 3) + +#define MT6320_GPIO19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define MT6320_GPIO19__FUNC_COL3 (MTK_PIN_NO(19) | 1) +#define MT6320_GPIO19__FUNC_EINT13 (MTK_PIN_NO(19) | 2) +#define MT6320_GPIO19__FUNC_SCL1_2X (MTK_PIN_NO(19) | 3) + +#define MT6320_GPIO20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define MT6320_GPIO20__FUNC_COL4 (MTK_PIN_NO(20) | 1) +#define MT6320_GPIO20__FUNC_EINT14 (MTK_PIN_NO(20) | 2) +#define MT6320_GPIO20__FUNC_SDA1_2X (MTK_PIN_NO(20) | 3) + +#define MT6320_GPIO21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define MT6320_GPIO21__FUNC_COL5 (MTK_PIN_NO(21) | 1) +#define MT6320_GPIO21__FUNC_EINT15 (MTK_PIN_NO(21) | 2) +#define MT6320_GPIO21__FUNC_SCL2_2X (MTK_PIN_NO(21) | 3) + +#define MT6320_GPIO22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define MT6320_GPIO22__FUNC_COL6 (MTK_PIN_NO(22) | 1) +#define MT6320_GPIO22__FUNC_EINT16 (MTK_PIN_NO(22) | 2) +#define MT6320_GPIO22__FUNC_SDA2_2X (MTK_PIN_NO(22) | 3) +#define MT6320_GPIO22__FUNC_GPIO32K_0 (MTK_PIN_NO(22) | 4) +#define MT6320_GPIO22__FUNC_GPIO26M_0 (MTK_PIN_NO(22) | 5) + +#define MT6320_GPIO23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define MT6320_GPIO23__FUNC_COL7 (MTK_PIN_NO(23) | 1) +#define MT6320_GPIO23__FUNC_EINT17 (MTK_PIN_NO(23) | 2) +#define MT6320_GPIO23__FUNC_PWM2_3X (MTK_PIN_NO(23) | 3) +#define MT6320_GPIO23__FUNC_GPIO32K_1 (MTK_PIN_NO(23) | 4) +#define MT6320_GPIO23__FUNC_GPIO26M_1 (MTK_PIN_NO(23) | 5) + +#define MT6320_GPIO24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define MT6320_GPIO24__FUNC_ROW0 (MTK_PIN_NO(24) | 1) +#define MT6320_GPIO24__FUNC_EINT18 (MTK_PIN_NO(24) | 2) +#define MT6320_GPIO24__FUNC_SCL0_3X (MTK_PIN_NO(24) | 3) + +#define MT6320_GPIO25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define MT6320_GPIO25__FUNC_ROW1 (MTK_PIN_NO(25) | 1) +#define MT6320_GPIO25__FUNC_EINT19 (MTK_PIN_NO(25) | 2) +#define MT6320_GPIO25__FUNC_SDA0_3X (MTK_PIN_NO(25) | 3) + +#define MT6320_GPIO26__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define MT6320_GPIO26__FUNC_ROW2 (MTK_PIN_NO(26) | 1) +#define MT6320_GPIO26__FUNC_EINT20 (MTK_PIN_NO(26) | 2) +#define MT6320_GPIO26__FUNC_SCL1_3X (MTK_PIN_NO(26) | 3) + +#define MT6320_GPIO27__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define MT6320_GPIO27__FUNC_ROW3 (MTK_PIN_NO(27) | 1) +#define MT6320_GPIO27__FUNC_EINT21 (MTK_PIN_NO(27) | 2) +#define MT6320_GPIO27__FUNC_SDA1_3X (MTK_PIN_NO(27) | 3) + +#define MT6320_GPIO28__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define MT6320_GPIO28__FUNC_ROW4 (MTK_PIN_NO(28) | 1) +#define MT6320_GPIO28__FUNC_EINT22 (MTK_PIN_NO(28) | 2) +#define MT6320_GPIO28__FUNC_SCL2_3X (MTK_PIN_NO(28) | 3) + +#define MT6320_GPIO29__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define MT6320_GPIO29__FUNC_ROW5 (MTK_PIN_NO(29) | 1) +#define MT6320_GPIO29__FUNC_EINT23 (MTK_PIN_NO(29) | 2) +#define MT6320_GPIO29__FUNC_SDA2_3X (MTK_PIN_NO(29) | 3) + +#define MT6320_GPIO30__FUNC_GPIO30 (MTK_PIN_NO(30) | 0) +#define MT6320_GPIO30__FUNC_ROW6 (MTK_PIN_NO(30) | 1) +#define MT6320_GPIO30__FUNC_EINT24 (MTK_PIN_NO(30) | 2) +#define MT6320_GPIO30__FUNC_PWM3_3X (MTK_PIN_NO(30) | 3) +#define MT6320_GPIO30__FUNC_GPIO32K_2 (MTK_PIN_NO(30) | 4) +#define MT6320_GPIO30__FUNC_GPIO26M_2 (MTK_PIN_NO(30) | 5) + +#define MT6320_GPIO31__FUNC_GPIO31 (MTK_PIN_NO(31) | 0) +#define MT6320_GPIO31__FUNC_ROW7 (MTK_PIN_NO(31) | 1) +#define MT6320_GPIO31__FUNC_EINT3 (MTK_PIN_NO(31) | 2) +#define MT6320_GPIO31__FUNC_GPIO32K_3 (MTK_PIN_NO(31) | 4) +#define MT6320_GPIO31__FUNC_GPIO26M_3 (MTK_PIN_NO(31) | 5) + +#define MT6320_GPIO32__FUNC_GPIO32 (MTK_PIN_NO(32) | 0) +#define MT6320_GPIO32__FUNC_PWM1 (MTK_PIN_NO(32) | 1) +#define MT6320_GPIO32__FUNC_EINT4 (MTK_PIN_NO(32) | 2) +#define MT6320_GPIO32__FUNC_GPIO32K_4 (MTK_PIN_NO(32) | 4) +#define MT6320_GPIO32__FUNC_GPIO26M_4 (MTK_PIN_NO(32) | 5) + +#define MT6320_GPIO33__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define MT6320_GPIO33__FUNC_PWM2 (MTK_PIN_NO(33) | 1) +#define MT6320_GPIO33__FUNC_EINT5 (MTK_PIN_NO(33) | 2) +#define MT6320_GPIO33__FUNC_GPIO32K_5 (MTK_PIN_NO(33) | 4) +#define MT6320_GPIO33__FUNC_GPIO26M_5 (MTK_PIN_NO(33) | 5) + +#define MT6320_GPIO34__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define MT6320_GPIO34__FUNC_PWM3 (MTK_PIN_NO(34) | 1) +#define MT6320_GPIO34__FUNC_EINT6 (MTK_PIN_NO(34) | 2) +#define MT6320_GPIO34__FUNC_COL0 (MTK_PIN_NO(34) | 3) +#define MT6320_GPIO34__FUNC_GPIO32K_6 (MTK_PIN_NO(34) | 4) +#define MT6320_GPIO34__FUNC_GPIO26M_6 (MTK_PIN_NO(34) | 5) + +#define MT6320_GPIO35__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define MT6320_GPIO35__FUNC_SCL0 (MTK_PIN_NO(35) | 1) +#define MT6320_GPIO35__FUNC_EINT7 (MTK_PIN_NO(35) | 2) +#define MT6320_GPIO35__FUNC_PWM1_2X (MTK_PIN_NO(35) | 3) + +#define MT6320_GPIO36__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define MT6320_GPIO36__FUNC_SDA0 (MTK_PIN_NO(36) | 1) +#define MT6320_GPIO36__FUNC_EINT8 (MTK_PIN_NO(36) | 2) + +#define MT6320_GPIO37__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define MT6320_GPIO37__FUNC_SCL1 (MTK_PIN_NO(37) | 1) +#define MT6320_GPIO37__FUNC_EINT9 (MTK_PIN_NO(37) | 2) +#define MT6320_GPIO37__FUNC_PWM2_2X (MTK_PIN_NO(37) | 3) + +#define MT6320_GPIO38__FUNC_GPIO38 (MTK_PIN_NO(38) | 0) +#define MT6320_GPIO38__FUNC_SDA1 (MTK_PIN_NO(38) | 1) +#define MT6320_GPIO38__FUNC_EINT0 (MTK_PIN_NO(38) | 2) + +#define MT6320_GPIO39__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define MT6320_GPIO39__FUNC_SCL2 (MTK_PIN_NO(39) | 1) +#define MT6320_GPIO39__FUNC_EINT1 (MTK_PIN_NO(39) | 2) +#define MT6320_GPIO39__FUNC_PWM3_2X (MTK_PIN_NO(39) | 3) + +#define MT6320_GPIO40__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define MT6320_GPIO40__FUNC_SDA2 (MTK_PIN_NO(40) | 1) +#define MT6320_GPIO40__FUNC_EINT2 (MTK_PIN_NO(40) | 2) + +#define MT6320_GPIO41__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define MT6320_GPIO41__FUNC_SIM1_AP_SCLK (MTK_PIN_NO(41) | 1) + +#define MT6320_GPIO42__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define MT6320_GPIO42__FUNC_SIM1_AP_SRST (MTK_PIN_NO(42) | 1) + +#define MT6320_GPIO43__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define MT6320_GPIO43__FUNC_SIM2_AP_SCLK (MTK_PIN_NO(43) | 1) + +#define MT6320_GPIO44__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define MT6320_GPIO44__FUNC_SIM2_AP_SRST (MTK_PIN_NO(44) | 1) + +#define MT6320_GPIO45__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define MT6320_GPIO45__FUNC_SIMLS1_SCLK (MTK_PIN_NO(45) | 1) + +#define MT6320_GPIO46__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define MT6320_GPIO46__FUNC_SIMLS1_SRST (MTK_PIN_NO(46) | 1) + +#define MT6320_GPIO47__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define MT6320_GPIO47__FUNC_SIMLS2_SCLK (MTK_PIN_NO(47) | 1) +#define MT6320_GPIO47__FUNC_EINT10 (MTK_PIN_NO(47) | 5) + +#define MT6320_GPIO48__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define MT6320_GPIO48__FUNC_SIMLS2_SRST (MTK_PIN_NO(48) | 1) + +#endif /* __DTS_MT6320_PINFUNC_H */ diff --git a/include/dt-bindings/pinctrl/mt6589-pinfunc.h b/include/dt-bindings/pinctrl/mt6589-pinfunc.h new file mode 100644 index 00000000000000..0e91a361c2c99e --- /dev/null +++ b/include/dt-bindings/pinctrl/mt6589-pinfunc.h @@ -0,0 +1,1644 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Akari Tsuyukusa + */ + +#ifndef __MT6589_PINFUNC_H +#define __MT6589_PINFUNC_H + +#include + +#define MT6589_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define MT6589_GPIO0__FUNC_MSDC0_DAT7 (MTK_PIN_NO(0) | 1) +#define MT6589_GPIO0__FUNC_EINT49 (MTK_PIN_NO(0) | 2) +#define MT6589_GPIO0__FUNC_I2SOUT_DAT (MTK_PIN_NO(0) | 3) +#define MT6589_GPIO0__FUNC_DAC_DAT_OUT (MTK_PIN_NO(0) | 4) +#define MT6589_GPIO0__FUNC_PCM1_DO (MTK_PIN_NO(0) | 5) +#define MT6589_GPIO0__FUNC_SPI1_MO (MTK_PIN_NO(0) | 6) +#define MT6589_GPIO0__FUNC_NALE (MTK_PIN_NO(0) | 7) + +#define MT6589_GPIO1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define MT6589_GPIO1__FUNC_MSDC0_DAT6 (MTK_PIN_NO(1) | 1) +#define MT6589_GPIO1__FUNC_EINT48 (MTK_PIN_NO(1) | 2) +#define MT6589_GPIO1__FUNC_I2SIN_WS (MTK_PIN_NO(1) | 3) +#define MT6589_GPIO1__FUNC_DAC_WS (MTK_PIN_NO(1) | 4) +#define MT6589_GPIO1__FUNC_PCM1_WS (MTK_PIN_NO(1) | 5) +#define MT6589_GPIO1__FUNC_SPI1_CSN (MTK_PIN_NO(1) | 6) +#define MT6589_GPIO1__FUNC_NCLE (MTK_PIN_NO(1) | 7) + +#define MT6589_GPIO2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define MT6589_GPIO2__FUNC_MSDC0_DAT5 (MTK_PIN_NO(2) | 1) +#define MT6589_GPIO2__FUNC_EINT47 (MTK_PIN_NO(2) | 2) +#define MT6589_GPIO2__FUNC_I2SIN_CK (MTK_PIN_NO(2) | 3) +#define MT6589_GPIO2__FUNC_DAC_CK (MTK_PIN_NO(2) | 4) +#define MT6589_GPIO2__FUNC_PCM1_CK (MTK_PIN_NO(2) | 5) +#define MT6589_GPIO2__FUNC_SPI1_CLK (MTK_PIN_NO(2) | 6) +#define MT6589_GPIO2__FUNC_NLD4 (MTK_PIN_NO(2) | 7) + +#define MT6589_GPIO3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define MT6589_GPIO3__FUNC_MSDC0_DAT4 (MTK_PIN_NO(3) | 1) +#define MT6589_GPIO3__FUNC_EINT46 (MTK_PIN_NO(3) | 2) +#define MT6589_GPIO3__FUNC_LSCE1B_2X (MTK_PIN_NO(3) | 6) +#define MT6589_GPIO3__FUNC_NLD5 (MTK_PIN_NO(3) | 7) + +#define MT6589_GPIO4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define MT6589_GPIO4__FUNC_MSDC0_RSTB (MTK_PIN_NO(4) | 1) +#define MT6589_GPIO4__FUNC_EINT50 (MTK_PIN_NO(4) | 2) +#define MT6589_GPIO4__FUNC_I2SIN_DAT (MTK_PIN_NO(4) | 3) +#define MT6589_GPIO4__FUNC_PCM1_DI (MTK_PIN_NO(4) | 5) +#define MT6589_GPIO4__FUNC_SPI1_MI (MTK_PIN_NO(4) | 6) +#define MT6589_GPIO4__FUNC_NLD10 (MTK_PIN_NO(4) | 7) + +#define MT6589_GPIO5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define MT6589_GPIO5__FUNC_MSDC0_CMD (MTK_PIN_NO(5) | 1) +#define MT6589_GPIO5__FUNC_EINT41 (MTK_PIN_NO(5) | 2) +#define MT6589_GPIO5__FUNC_LRSTB_2X (MTK_PIN_NO(5) | 6) +#define MT6589_GPIO5__FUNC_NRNB (MTK_PIN_NO(5) | 7) + +#define MT6589_GPIO6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define MT6589_GPIO6__FUNC_MSDC0_CLK (MTK_PIN_NO(6) | 1) +#define MT6589_GPIO6__FUNC_EINT40 (MTK_PIN_NO(6) | 2) +#define MT6589_GPIO6__FUNC_LPTE (MTK_PIN_NO(6) | 6) +#define MT6589_GPIO6__FUNC_NREB (MTK_PIN_NO(6) | 7) + +#define MT6589_GPIO7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define MT6589_GPIO7__FUNC_MSDC0_DAT3 (MTK_PIN_NO(7) | 1) +#define MT6589_GPIO7__FUNC_EINT45 (MTK_PIN_NO(7) | 2) +#define MT6589_GPIO7__FUNC_LSCE0B_2X (MTK_PIN_NO(7) | 6) +#define MT6589_GPIO7__FUNC_NLD7 (MTK_PIN_NO(7) | 7) + +#define MT6589_GPIO8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define MT6589_GPIO8__FUNC_MSDC0_DAT2 (MTK_PIN_NO(8) | 1) +#define MT6589_GPIO8__FUNC_EINT44 (MTK_PIN_NO(8) | 2) +#define MT6589_GPIO8__FUNC_LSA0_2X (MTK_PIN_NO(8) | 6) +#define MT6589_GPIO8__FUNC_NLD14 (MTK_PIN_NO(8) | 7) + +#define MT6589_GPIO9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define MT6589_GPIO9__FUNC_MSDC0_DAT1 (MTK_PIN_NO(9) | 1) +#define MT6589_GPIO9__FUNC_EINT43 (MTK_PIN_NO(9) | 2) +#define MT6589_GPIO9__FUNC_LSCK_2X (MTK_PIN_NO(9) | 6) +#define MT6589_GPIO9__FUNC_NLD11 (MTK_PIN_NO(9) | 7) + +#define MT6589_GPIO10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define MT6589_GPIO10__FUNC_MSDC0_DAT0 (MTK_PIN_NO(10) | 1) +#define MT6589_GPIO10__FUNC_EINT42 (MTK_PIN_NO(10) | 2) +#define MT6589_GPIO10__FUNC_LSDA_2X (MTK_PIN_NO(10) | 6) + +#define MT6589_GPIO11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define MT6589_GPIO11__FUNC_NCEB0 (MTK_PIN_NO(11) | 1) +#define MT6589_GPIO11__FUNC_EINT139 (MTK_PIN_NO(11) | 2) +#define MT6589_GPIO11__FUNC_TESTA_OUT4 (MTK_PIN_NO(11) | 7) + +#define MT6589_GPIO12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define MT6589_GPIO12__FUNC_NCEB1 (MTK_PIN_NO(12) | 1) +#define MT6589_GPIO12__FUNC_EINT140 (MTK_PIN_NO(12) | 2) +#define MT6589_GPIO12__FUNC_MD1_GPS_SYNC (MTK_PIN_NO(12) | 4) +#define MT6589_GPIO12__FUNC_MD2_GPS_SYNC (MTK_PIN_NO(12) | 5) +#define MT6589_GPIO12__FUNC_USB_DRVVBUS (MTK_PIN_NO(12) | 6) +#define MT6589_GPIO12__FUNC_TESTA_OUT5 (MTK_PIN_NO(12) | 7) + +#define MT6589_GPIO13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define MT6589_GPIO13__FUNC_NRNB (MTK_PIN_NO(13) | 1) +#define MT6589_GPIO13__FUNC_EINT141 (MTK_PIN_NO(13) | 2) +#define MT6589_GPIO13__FUNC_MD_ABB_AFUNC_D_0 (MTK_PIN_NO(13) | 6) +#define MT6589_GPIO13__FUNC_TESTA_OUT6 (MTK_PIN_NO(13) | 7) + +#define MT6589_GPIO14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define MT6589_GPIO14__FUNC_NCLE (MTK_PIN_NO(14) | 1) +#define MT6589_GPIO14__FUNC_EINT142 (MTK_PIN_NO(14) | 2) +#define MT6589_GPIO14__FUNC_DPI1_CK_1X (MTK_PIN_NO(14) | 3) +#define MT6589_GPIO14__FUNC_CM2PDN_1X (MTK_PIN_NO(14) | 4) +#define MT6589_GPIO14__FUNC_NALE (MTK_PIN_NO(14) | 6) +#define MT6589_GPIO14__FUNC_TESTA_OUT7 (MTK_PIN_NO(14) | 7) + +#define MT6589_GPIO15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define MT6589_GPIO15__FUNC_NALE (MTK_PIN_NO(15) | 1) +#define MT6589_GPIO15__FUNC_EINT143 (MTK_PIN_NO(15) | 2) +#define MT6589_GPIO15__FUNC_DPI1_DE_1X (MTK_PIN_NO(15) | 3) +#define MT6589_GPIO15__FUNC_CM2MCLK_1X (MTK_PIN_NO(15) | 4) +#define MT6589_GPIO15__FUNC_IRDA_RXD (MTK_PIN_NO(15) | 5) +#define MT6589_GPIO15__FUNC_NCLE (MTK_PIN_NO(15) | 6) +#define MT6589_GPIO15__FUNC_TESTA_OUT8 (MTK_PIN_NO(15) | 7) + +#define MT6589_GPIO16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0) +#define MT6589_GPIO16__FUNC_NREB (MTK_PIN_NO(16) | 1) +#define MT6589_GPIO16__FUNC_EINT144 (MTK_PIN_NO(16) | 2) +#define MT6589_GPIO16__FUNC_DPI1_HSYNC_1X (MTK_PIN_NO(16) | 3) +#define MT6589_GPIO16__FUNC_CM2RST_1X (MTK_PIN_NO(16) | 4) +#define MT6589_GPIO16__FUNC_IRDA_TXD (MTK_PIN_NO(16) | 5) +#define MT6589_GPIO16__FUNC_MD_ABB_AFUNC_D_1 (MTK_PIN_NO(16) | 6) +#define MT6589_GPIO16__FUNC_TESTA_OUT9 (MTK_PIN_NO(16) | 7) + +#define MT6589_GPIO17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0) +#define MT6589_GPIO17__FUNC_NWEB (MTK_PIN_NO(17) | 1) +#define MT6589_GPIO17__FUNC_EINT145 (MTK_PIN_NO(17) | 2) +#define MT6589_GPIO17__FUNC_DPI1_VSYNC_1X (MTK_PIN_NO(17) | 3) +#define MT6589_GPIO17__FUNC_CM2PCLK_1X (MTK_PIN_NO(17) | 4) +#define MT6589_GPIO17__FUNC_IRDA_PDN (MTK_PIN_NO(17) | 5) +#define MT6589_GPIO17__FUNC_MD_ABB_AFUNC_D_2 (MTK_PIN_NO(17) | 6) +#define MT6589_GPIO17__FUNC_TESTA_OUT10 (MTK_PIN_NO(17) | 7) + +#define MT6589_GPIO18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define MT6589_GPIO18__FUNC_NLD0 (MTK_PIN_NO(18) | 1) +#define MT6589_GPIO18__FUNC_EINT146 (MTK_PIN_NO(18) | 2) +#define MT6589_GPIO18__FUNC_DPI1_D_1X_0 (MTK_PIN_NO(18) | 3) +#define MT6589_GPIO18__FUNC_CM2DAT_1X_0 (MTK_PIN_NO(18) | 4) +#define MT6589_GPIO18__FUNC_I2SIN_CK (MTK_PIN_NO(18) | 5) +#define MT6589_GPIO18__FUNC_DAC_CK (MTK_PIN_NO(18) | 6) +#define MT6589_GPIO18__FUNC_TESTA_OUT11 (MTK_PIN_NO(18) | 7) + +#define MT6589_GPIO19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define MT6589_GPIO19__FUNC_NLD1 (MTK_PIN_NO(19) | 1) +#define MT6589_GPIO19__FUNC_EINT147 (MTK_PIN_NO(19) | 2) +#define MT6589_GPIO19__FUNC_DPI1_D_1X_1 (MTK_PIN_NO(19) | 3) +#define MT6589_GPIO19__FUNC_CM2DAT_1X_1 (MTK_PIN_NO(19) | 4) +#define MT6589_GPIO19__FUNC_I2SIN_WS (MTK_PIN_NO(19) | 5) +#define MT6589_GPIO19__FUNC_DAC_WS (MTK_PIN_NO(19) | 6) +#define MT6589_GPIO19__FUNC_TESTA_OUT12 (MTK_PIN_NO(19) | 7) + +#define MT6589_GPIO20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define MT6589_GPIO20__FUNC_NLD2 (MTK_PIN_NO(20) | 1) +#define MT6589_GPIO20__FUNC_EINT148 (MTK_PIN_NO(20) | 2) +#define MT6589_GPIO20__FUNC_DPI1_D_1X_2 (MTK_PIN_NO(20) | 3) +#define MT6589_GPIO20__FUNC_CM2DAT_1X_2 (MTK_PIN_NO(20) | 4) +#define MT6589_GPIO20__FUNC_I2SOUT_DAT (MTK_PIN_NO(20) | 5) +#define MT6589_GPIO20__FUNC_DAC_DAT_OUT (MTK_PIN_NO(20) | 6) +#define MT6589_GPIO20__FUNC_TESTA_OUT13 (MTK_PIN_NO(20) | 7) + +#define MT6589_GPIO21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define MT6589_GPIO21__FUNC_NLD3 (MTK_PIN_NO(21) | 1) +#define MT6589_GPIO21__FUNC_EINT149 (MTK_PIN_NO(21) | 2) +#define MT6589_GPIO21__FUNC_DPI1_D_1X_3 (MTK_PIN_NO(21) | 3) +#define MT6589_GPIO21__FUNC_CM2DAT_1X_3 (MTK_PIN_NO(21) | 4) +#define MT6589_GPIO21__FUNC_MD_ABB_AFUNC_D_3 (MTK_PIN_NO(21) | 6) +#define MT6589_GPIO21__FUNC_TESTA_OUT14 (MTK_PIN_NO(21) | 7) + +#define MT6589_GPIO22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define MT6589_GPIO22__FUNC_NLD4 (MTK_PIN_NO(22) | 1) +#define MT6589_GPIO22__FUNC_EINT150 (MTK_PIN_NO(22) | 2) +#define MT6589_GPIO22__FUNC_DPI1_D_1X_4 (MTK_PIN_NO(22) | 3) +#define MT6589_GPIO22__FUNC_CM2DAT_1X_4 (MTK_PIN_NO(22) | 4) +#define MT6589_GPIO22__FUNC_MD1_DAI_RX_GPIO (MTK_PIN_NO(22) | 5) +#define MT6589_GPIO22__FUNC_MD2_DAI_RX_GPIO (MTK_PIN_NO(22) | 6) +#define MT6589_GPIO22__FUNC_TESTA_OUT15 (MTK_PIN_NO(22) | 7) + +#define MT6589_GPIO23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define MT6589_GPIO23__FUNC_NLD5 (MTK_PIN_NO(23) | 1) +#define MT6589_GPIO23__FUNC_EINT151 (MTK_PIN_NO(23) | 2) +#define MT6589_GPIO23__FUNC_DPI1_D_1X_5 (MTK_PIN_NO(23) | 3) +#define MT6589_GPIO23__FUNC_CM2DAT_1X_5 (MTK_PIN_NO(23) | 4) +#define MT6589_GPIO23__FUNC_MD_ABB_AFUNC_D_4 (MTK_PIN_NO(23) | 6) +#define MT6589_GPIO23__FUNC_TESTA_OUT16 (MTK_PIN_NO(23) | 7) + +#define MT6589_GPIO24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define MT6589_GPIO24__FUNC_NLD6 (MTK_PIN_NO(24) | 1) +#define MT6589_GPIO24__FUNC_EINT152 (MTK_PIN_NO(24) | 2) +#define MT6589_GPIO24__FUNC_DPI1_D_1X_6 (MTK_PIN_NO(24) | 3) +#define MT6589_GPIO24__FUNC_CM2DAT_1X_6 (MTK_PIN_NO(24) | 4) +#define MT6589_GPIO24__FUNC_MD_ABB_AFUNC_D_5 (MTK_PIN_NO(24) | 6) +#define MT6589_GPIO24__FUNC_TESTA_OUT17 (MTK_PIN_NO(24) | 7) + +#define MT6589_GPIO25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define MT6589_GPIO25__FUNC_NLD7 (MTK_PIN_NO(25) | 1) +#define MT6589_GPIO25__FUNC_EINT153 (MTK_PIN_NO(25) | 2) +#define MT6589_GPIO25__FUNC_DPI1_D_1X_7 (MTK_PIN_NO(25) | 3) +#define MT6589_GPIO25__FUNC_CM2DAT_1X_7 (MTK_PIN_NO(25) | 4) +#define MT6589_GPIO25__FUNC_MD_ABB_AFUNC_D_6 (MTK_PIN_NO(25) | 6) +#define MT6589_GPIO25__FUNC_TESTA_OUT18 (MTK_PIN_NO(25) | 7) + +#define MT6589_GPIO26__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define MT6589_GPIO26__FUNC_NLD8 (MTK_PIN_NO(26) | 1) +#define MT6589_GPIO26__FUNC_EINT154 (MTK_PIN_NO(26) | 2) +#define MT6589_GPIO26__FUNC_DPI1_D_1X_8 (MTK_PIN_NO(26) | 3) +#define MT6589_GPIO26__FUNC_CM2DAT_1X_8 (MTK_PIN_NO(26) | 4) +#define MT6589_GPIO26__FUNC_MD_ABB_AFUNC_D_7 (MTK_PIN_NO(26) | 6) +#define MT6589_GPIO26__FUNC_TESTA_OUT19 (MTK_PIN_NO(26) | 7) + +#define MT6589_GPIO27__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define MT6589_GPIO27__FUNC_NLD9 (MTK_PIN_NO(27) | 1) +#define MT6589_GPIO27__FUNC_EINT155 (MTK_PIN_NO(27) | 2) +#define MT6589_GPIO27__FUNC_DPI1_D_1X_9 (MTK_PIN_NO(27) | 3) +#define MT6589_GPIO27__FUNC_CM2DAT_1X_9 (MTK_PIN_NO(27) | 4) +#define MT6589_GPIO27__FUNC_PWM1 (MTK_PIN_NO(27) | 5) +#define MT6589_GPIO27__FUNC_MD_ABB_AFUNC_D_8 (MTK_PIN_NO(27) | 6) +#define MT6589_GPIO27__FUNC_TESTA_OUT20 (MTK_PIN_NO(27) | 7) + +#define MT6589_GPIO28__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define MT6589_GPIO28__FUNC_NLD10 (MTK_PIN_NO(28) | 1) +#define MT6589_GPIO28__FUNC_EINT156 (MTK_PIN_NO(28) | 2) +#define MT6589_GPIO28__FUNC_DPI1_D_1X_10 (MTK_PIN_NO(28) | 3) +#define MT6589_GPIO28__FUNC_CM2VSYNC_1X (MTK_PIN_NO(28) | 4) +#define MT6589_GPIO28__FUNC_PWM2 (MTK_PIN_NO(28) | 5) +#define MT6589_GPIO28__FUNC_MD_ABB_AFUNC_D_9 (MTK_PIN_NO(28) | 6) +#define MT6589_GPIO28__FUNC_TESTA_OUT21 (MTK_PIN_NO(28) | 7) + +#define MT6589_GPIO29__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define MT6589_GPIO29__FUNC_NLD11 (MTK_PIN_NO(29) | 1) +#define MT6589_GPIO29__FUNC_EINT157 (MTK_PIN_NO(29) | 2) +#define MT6589_GPIO29__FUNC_DPI1_D_1X_11 (MTK_PIN_NO(29) | 3) +#define MT6589_GPIO29__FUNC_CM2HSYNC_1X (MTK_PIN_NO(29) | 4) +#define MT6589_GPIO29__FUNC_PWM3 (MTK_PIN_NO(29) | 5) +#define MT6589_GPIO29__FUNC_MD_ABB_AFUNC_D_10 (MTK_PIN_NO(29) | 6) +#define MT6589_GPIO29__FUNC_TESTA_OUT22 (MTK_PIN_NO(29) | 7) + +#define MT6589_GPIO30__FUNC_GPIO30 (MTK_PIN_NO(30) | 0) +#define MT6589_GPIO30__FUNC_NLD12 (MTK_PIN_NO(30) | 1) +#define MT6589_GPIO30__FUNC_EINT158 (MTK_PIN_NO(30) | 2) +#define MT6589_GPIO30__FUNC_I2SIN_CK (MTK_PIN_NO(30) | 3) +#define MT6589_GPIO30__FUNC_DAC_CK (MTK_PIN_NO(30) | 4) +#define MT6589_GPIO30__FUNC_PCM1_CK (MTK_PIN_NO(30) | 5) +#define MT6589_GPIO30__FUNC_MD_ABB_AFUNC_D_11 (MTK_PIN_NO(30) | 6) +#define MT6589_GPIO30__FUNC_TESTA_OUT23 (MTK_PIN_NO(30) | 7) + +#define MT6589_GPIO31__FUNC_GPIO31 (MTK_PIN_NO(31) | 0) +#define MT6589_GPIO31__FUNC_NLD13 (MTK_PIN_NO(31) | 1) +#define MT6589_GPIO31__FUNC_EINT159 (MTK_PIN_NO(31) | 2) +#define MT6589_GPIO31__FUNC_I2SIN_WS (MTK_PIN_NO(31) | 3) +#define MT6589_GPIO31__FUNC_DAC_WS (MTK_PIN_NO(31) | 4) +#define MT6589_GPIO31__FUNC_PCM1_WS (MTK_PIN_NO(31) | 5) +#define MT6589_GPIO31__FUNC_MD_ABB_AFUNC_D_12 (MTK_PIN_NO(31) | 6) +#define MT6589_GPIO31__FUNC_TESTA_OUT24 (MTK_PIN_NO(31) | 7) + +#define MT6589_GPIO32__FUNC_GPIO32 (MTK_PIN_NO(32) | 0) +#define MT6589_GPIO32__FUNC_NLD14 (MTK_PIN_NO(32) | 1) +#define MT6589_GPIO32__FUNC_EINT160 (MTK_PIN_NO(32) | 2) +#define MT6589_GPIO32__FUNC_I2SOUT_DAT (MTK_PIN_NO(32) | 3) +#define MT6589_GPIO32__FUNC_DAC_DAT_OUT (MTK_PIN_NO(32) | 4) +#define MT6589_GPIO32__FUNC_PCM1_DO (MTK_PIN_NO(32) | 5) +#define MT6589_GPIO32__FUNC_MD_ABB_AFUNC_D_13 (MTK_PIN_NO(32) | 6) +#define MT6589_GPIO32__FUNC_TESTA_OUT25 (MTK_PIN_NO(32) | 7) + +#define MT6589_GPIO33__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define MT6589_GPIO33__FUNC_NLD15 (MTK_PIN_NO(33) | 1) +#define MT6589_GPIO33__FUNC_EINT161 (MTK_PIN_NO(33) | 2) +#define MT6589_GPIO33__FUNC_DISP_PWM (MTK_PIN_NO(33) | 3) +#define MT6589_GPIO33__FUNC_PWM4 (MTK_PIN_NO(33) | 4) +#define MT6589_GPIO33__FUNC_PCM1_DI (MTK_PIN_NO(33) | 5) +#define MT6589_GPIO33__FUNC_MD_ABB_AFUNC_D_14 (MTK_PIN_NO(33) | 6) +#define MT6589_GPIO33__FUNC_TESTA_OUT26 (MTK_PIN_NO(33) | 7) + +#define MT6589_GPIO34__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define MT6589_GPIO34__FUNC_EINT0 (MTK_PIN_NO(34) | 1) +#define MT6589_GPIO34__FUNC_PWM1 (MTK_PIN_NO(34) | 2) +#define MT6589_GPIO34__FUNC_CLKM0 (MTK_PIN_NO(34) | 3) +#define MT6589_GPIO34__FUNC_MD2_UTXD (MTK_PIN_NO(34) | 5) +#define MT6589_GPIO34__FUNC_MD1_EINT1 (MTK_PIN_NO(34) | 6) +#define MT6589_GPIO34__FUNC_USB_SCL (MTK_PIN_NO(34) | 7) + +#define MT6589_GPIO35__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define MT6589_GPIO35__FUNC_EINT1 (MTK_PIN_NO(35) | 1) +#define MT6589_GPIO35__FUNC_PWM2 (MTK_PIN_NO(35) | 2) +#define MT6589_GPIO35__FUNC_CLKM1 (MTK_PIN_NO(35) | 3) +#define MT6589_GPIO35__FUNC_MD2_URXD (MTK_PIN_NO(35) | 5) +#define MT6589_GPIO35__FUNC_MD1_EINT2 (MTK_PIN_NO(35) | 6) +#define MT6589_GPIO35__FUNC_USB_SDA (MTK_PIN_NO(35) | 7) + +#define MT6589_GPIO36__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define MT6589_GPIO36__FUNC_EINT2 (MTK_PIN_NO(36) | 1) +#define MT6589_GPIO36__FUNC_PWM3 (MTK_PIN_NO(36) | 2) +#define MT6589_GPIO36__FUNC_CLKM2 (MTK_PIN_NO(36) | 3) +#define MT6589_GPIO36__FUNC_SRCLKENAI2 (MTK_PIN_NO(36) | 4) +#define MT6589_GPIO36__FUNC_MD1_EINT3 (MTK_PIN_NO(36) | 6) + +#define MT6589_GPIO37__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define MT6589_GPIO37__FUNC_EINT3 (MTK_PIN_NO(37) | 1) +#define MT6589_GPIO37__FUNC_MD1_EINT5 (MTK_PIN_NO(37) | 6) +#define MT6589_GPIO37__FUNC_EXT_26M_CK (MTK_PIN_NO(37) | 7) + +#define MT6589_GPIO38__FUNC_GPIO38 (MTK_PIN_NO(38) | 0) +#define MT6589_GPIO38__FUNC_EINT4 (MTK_PIN_NO(38) | 1) +#define MT6589_GPIO38__FUNC_PWM4 (MTK_PIN_NO(38) | 2) +#define MT6589_GPIO38__FUNC_MD1_GPS_SYNC (MTK_PIN_NO(38) | 3) +#define MT6589_GPIO38__FUNC_MD2_GPS_SYNC (MTK_PIN_NO(38) | 4) +#define MT6589_GPIO38__FUNC_USB_DRVVBUS (MTK_PIN_NO(38) | 5) +#define MT6589_GPIO38__FUNC_MD1_EINT4 (MTK_PIN_NO(38) | 6) + +#define MT6589_GPIO39__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define MT6589_GPIO39__FUNC_PWRAP_SPIDI (MTK_PIN_NO(39) | 1) +#define MT6589_GPIO39__FUNC_EINT29 (MTK_PIN_NO(39) | 2) + +#define MT6589_GPIO40__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define MT6589_GPIO40__FUNC_PWRAP_SPIDO (MTK_PIN_NO(40) | 1) +#define MT6589_GPIO40__FUNC_EINT28 (MTK_PIN_NO(40) | 2) + +#define MT6589_GPIO41__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define MT6589_GPIO41__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(41) | 1) +#define MT6589_GPIO41__FUNC_EINT27 (MTK_PIN_NO(41) | 2) + +#define MT6589_GPIO42__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define MT6589_GPIO42__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(42) | 1) +#define MT6589_GPIO42__FUNC_EINT26 (MTK_PIN_NO(42) | 2) + +#define MT6589_GPIO43__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define MT6589_GPIO43__FUNC_PWRAP_EVENT_IN (MTK_PIN_NO(43) | 1) +#define MT6589_GPIO43__FUNC_EINT25 (MTK_PIN_NO(43) | 2) + +#define MT6589_GPIO44__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define MT6589_GPIO44__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(44) | 1) +#define MT6589_GPIO44__FUNC_EINT30 (MTK_PIN_NO(44) | 2) +#define MT6589_GPIO44__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(44) | 3) +#define MT6589_GPIO44__FUNC_MD2_SIM1_SCLK (MTK_PIN_NO(44) | 4) +#define MT6589_GPIO44__FUNC_MD2_SIM2_SCLK (MTK_PIN_NO(44) | 5) +#define MT6589_GPIO44__FUNC_MD_ABB_AFUNC_D_15 (MTK_PIN_NO(44) | 6) + +#define MT6589_GPIO45__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define MT6589_GPIO45__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(45) | 1) +#define MT6589_GPIO45__FUNC_EINT31 (MTK_PIN_NO(45) | 2) +#define MT6589_GPIO45__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(45) | 3) +#define MT6589_GPIO45__FUNC_MD2_SIM1_SRST (MTK_PIN_NO(45) | 4) +#define MT6589_GPIO45__FUNC_MD2_SIM2_SRST (MTK_PIN_NO(45) | 5) +#define MT6589_GPIO45__FUNC_MD_ABB_AFUNC_D_16 (MTK_PIN_NO(45) | 6) + +#define MT6589_GPIO46__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define MT6589_GPIO46__FUNC_MD1_SIM1_SDAT (MTK_PIN_NO(46) | 1) +#define MT6589_GPIO46__FUNC_EINT32 (MTK_PIN_NO(46) | 2) +#define MT6589_GPIO46__FUNC_MD1_SIM2_SDAT (MTK_PIN_NO(46) | 3) +#define MT6589_GPIO46__FUNC_MD2_SIM1_SDAT (MTK_PIN_NO(46) | 4) +#define MT6589_GPIO46__FUNC_MD2_SIM2_SDAT (MTK_PIN_NO(46) | 5) +#define MT6589_GPIO46__FUNC_MD_ABB_AFUNC_D_17 (MTK_PIN_NO(46) | 6) + +#define MT6589_GPIO47__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define MT6589_GPIO47__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(47) | 1) +#define MT6589_GPIO47__FUNC_EINT33 (MTK_PIN_NO(47) | 2) +#define MT6589_GPIO47__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(47) | 3) +#define MT6589_GPIO47__FUNC_MD2_SIM2_SCLK (MTK_PIN_NO(47) | 4) +#define MT6589_GPIO47__FUNC_MD2_SIM1_SCLK (MTK_PIN_NO(47) | 5) +#define MT6589_GPIO47__FUNC_MD_ABB_AFUNC_D_18 (MTK_PIN_NO(47) | 6) + +#define MT6589_GPIO48__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define MT6589_GPIO48__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(48) | 1) +#define MT6589_GPIO48__FUNC_EINT34 (MTK_PIN_NO(48) | 2) +#define MT6589_GPIO48__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(48) | 3) +#define MT6589_GPIO48__FUNC_MD2_SIM2_SRST (MTK_PIN_NO(48) | 4) +#define MT6589_GPIO48__FUNC_MD2_SIM1_SRST (MTK_PIN_NO(48) | 5) +#define MT6589_GPIO48__FUNC_MD_ABB_AFUNC_D_19 (MTK_PIN_NO(48) | 6) + +#define MT6589_GPIO49__FUNC_GPIO49 (MTK_PIN_NO(49) | 0) +#define MT6589_GPIO49__FUNC_MD1_SIM2_SDAT (MTK_PIN_NO(49) | 1) +#define MT6589_GPIO49__FUNC_EINT35 (MTK_PIN_NO(49) | 2) +#define MT6589_GPIO49__FUNC_MD1_SIM1_SDAT (MTK_PIN_NO(49) | 3) +#define MT6589_GPIO49__FUNC_MD2_SIM2_SDAT (MTK_PIN_NO(49) | 4) +#define MT6589_GPIO49__FUNC_MD2_SIM1_SDAT (MTK_PIN_NO(49) | 5) +#define MT6589_GPIO49__FUNC_MD_ABB_AFUNC_D_20 (MTK_PIN_NO(49) | 6) + +#define MT6589_GPIO50__FUNC_GPIO50 (MTK_PIN_NO(50) | 0) +#define MT6589_GPIO50__FUNC_ADC_CK (MTK_PIN_NO(50) | 1) +#define MT6589_GPIO50__FUNC_EINT19 (MTK_PIN_NO(50) | 2) + +#define MT6589_GPIO51__FUNC_GPIO51 (MTK_PIN_NO(51) | 0) +#define MT6589_GPIO51__FUNC_ADC_WS (MTK_PIN_NO(51) | 1) +#define MT6589_GPIO51__FUNC_EINT21 (MTK_PIN_NO(51) | 2) + +#define MT6589_GPIO52__FUNC_GPIO52 (MTK_PIN_NO(52) | 0) +#define MT6589_GPIO52__FUNC_ADC_DAT_IN (MTK_PIN_NO(52) | 1) +#define MT6589_GPIO52__FUNC_EINT20 (MTK_PIN_NO(52) | 2) + +#define MT6589_GPIO53__FUNC_GPIO53 (MTK_PIN_NO(53) | 0) +#define MT6589_GPIO53__FUNC_DAC_CK (MTK_PIN_NO(53) | 1) +#define MT6589_GPIO53__FUNC_EINT22 (MTK_PIN_NO(53) | 2) + +#define MT6589_GPIO54__FUNC_GPIO54 (MTK_PIN_NO(54) | 0) +#define MT6589_GPIO54__FUNC_DAC_WS (MTK_PIN_NO(54) | 1) +#define MT6589_GPIO54__FUNC_EINT24 (MTK_PIN_NO(54) | 2) + +#define MT6589_GPIO55__FUNC_GPIO55 (MTK_PIN_NO(55) | 0) +#define MT6589_GPIO55__FUNC_DAC_DAT_OUT (MTK_PIN_NO(55) | 1) +#define MT6589_GPIO55__FUNC_EINT23 (MTK_PIN_NO(55) | 2) + +#define MT6589_GPIO56__FUNC_GPIO56 (MTK_PIN_NO(56) | 0) +#define MT6589_GPIO56__FUNC_RTC32K_CK (MTK_PIN_NO(56) | 1) + +#define MT6589_GPIO57__FUNC_GPIO57 (MTK_PIN_NO(57) | 0) +#define MT6589_GPIO57__FUNC_IDDIG (MTK_PIN_NO(57) | 1) +#define MT6589_GPIO57__FUNC_EINT34 (MTK_PIN_NO(57) | 2) + +#define MT6589_GPIO58__FUNC_GPIO58 (MTK_PIN_NO(58) | 0) +#define MT6589_GPIO58__FUNC_WATCHDOG (MTK_PIN_NO(58) | 1) +#define MT6589_GPIO58__FUNC_EINT36 (MTK_PIN_NO(58) | 2) + +#define MT6589_GPIO59__FUNC_GPIO59 (MTK_PIN_NO(59) | 0) +#define MT6589_GPIO59__FUNC_SRCLKENA (MTK_PIN_NO(59) | 1) +#define MT6589_GPIO59__FUNC_EINT38 (MTK_PIN_NO(59) | 2) + +#define MT6589_GPIO60__FUNC_GPIO60 (MTK_PIN_NO(60) | 0) +#define MT6589_GPIO60__FUNC_SRCVOLTEN (MTK_PIN_NO(60) | 1) +#define MT6589_GPIO60__FUNC_EINT37 (MTK_PIN_NO(60) | 2) + +#define MT6589_GPIO61__FUNC_GPIO61 (MTK_PIN_NO(61) | 0) +#define MT6589_GPIO61__FUNC_JTCK (MTK_PIN_NO(61) | 1) +#define MT6589_GPIO61__FUNC_EINT188 (MTK_PIN_NO(61) | 2) +#define MT6589_GPIO61__FUNC_DSP1_ICK (MTK_PIN_NO(61) | 3) +#define MT6589_GPIO61__FUNC_MD2_TCK_PAD (MTK_PIN_NO(61) | 7) + +#define MT6589_GPIO62__FUNC_GPIO62 (MTK_PIN_NO(62) | 0) +#define MT6589_GPIO62__FUNC_JTDO (MTK_PIN_NO(62) | 1) +#define MT6589_GPIO62__FUNC_EINT190 (MTK_PIN_NO(62) | 2) +#define MT6589_GPIO62__FUNC_DSP2_IMS (MTK_PIN_NO(62) | 3) +#define MT6589_GPIO62__FUNC_MD2_TDO_PAD (MTK_PIN_NO(62) | 7) + +#define MT6589_GPIO63__FUNC_GPIO63 (MTK_PIN_NO(63) | 0) +#define MT6589_GPIO63__FUNC_JTRST_B (MTK_PIN_NO(63) | 1) +#define MT6589_GPIO63__FUNC_EINT0 (MTK_PIN_NO(63) | 2) +#define MT6589_GPIO63__FUNC_DSP2_ICK (MTK_PIN_NO(63) | 3) +#define MT6589_GPIO63__FUNC_MD2_NTRST_PAD (MTK_PIN_NO(63) | 7) + +#define MT6589_GPIO64__FUNC_GPIO64 (MTK_PIN_NO(64) | 0) +#define MT6589_GPIO64__FUNC_JTDI (MTK_PIN_NO(64) | 1) +#define MT6589_GPIO64__FUNC_EINT189 (MTK_PIN_NO(64) | 2) +#define MT6589_GPIO64__FUNC_DSP1_IMS (MTK_PIN_NO(64) | 3) +#define MT6589_GPIO64__FUNC_MD2_TDI_PAD (MTK_PIN_NO(64) | 7) + +#define MT6589_GPIO65__FUNC_GPIO65 (MTK_PIN_NO(65) | 0) +#define MT6589_GPIO65__FUNC_JRTCK (MTK_PIN_NO(65) | 1) +#define MT6589_GPIO65__FUNC_EINT187 (MTK_PIN_NO(65) | 2) +#define MT6589_GPIO65__FUNC_DSP1_ID (MTK_PIN_NO(65) | 3) +#define MT6589_GPIO65__FUNC_MD2_RTCK_PAD (MTK_PIN_NO(65) | 7) + +#define MT6589_GPIO66__FUNC_GPIO66 (MTK_PIN_NO(66) | 0) +#define MT6589_GPIO66__FUNC_JTMS (MTK_PIN_NO(66) | 1) +#define MT6589_GPIO66__FUNC_EINT191 (MTK_PIN_NO(66) | 2) +#define MT6589_GPIO66__FUNC_DSP2_ID (MTK_PIN_NO(66) | 3) +#define MT6589_GPIO66__FUNC_MD2_TMS_PAD (MTK_PIN_NO(66) | 7) + +#define MT6589_GPIO67__FUNC_GPIO67 (MTK_PIN_NO(67) | 0) +#define MT6589_GPIO67__FUNC_SDA3 (MTK_PIN_NO(67) | 1) +#define MT6589_GPIO67__FUNC_EINT97 (MTK_PIN_NO(67) | 2) +#define MT6589_GPIO67__FUNC_A_FUNC_DIN_13 (MTK_PIN_NO(67) | 7) + +#define MT6589_GPIO68__FUNC_GPIO68 (MTK_PIN_NO(68) | 0) +#define MT6589_GPIO68__FUNC_SCL3 (MTK_PIN_NO(68) | 1) +#define MT6589_GPIO68__FUNC_EINT96 (MTK_PIN_NO(68) | 2) +#define MT6589_GPIO68__FUNC_CLKM6 (MTK_PIN_NO(68) | 3) +#define MT6589_GPIO68__FUNC_PWM6 (MTK_PIN_NO(68) | 4) +#define MT6589_GPIO68__FUNC_A_FUNC_DIN_14 (MTK_PIN_NO(68) | 7) + +#define MT6589_GPIO69__FUNC_GPIO69 (MTK_PIN_NO(69) | 0) +#define MT6589_GPIO69__FUNC_URXD2 (MTK_PIN_NO(69) | 1) +#define MT6589_GPIO69__FUNC_EINT83 (MTK_PIN_NO(69) | 2) +#define MT6589_GPIO69__FUNC_BSI2_CLK (MTK_PIN_NO(69) | 3) +#define MT6589_GPIO69__FUNC_MD1_URXD (MTK_PIN_NO(69) | 4) +#define MT6589_GPIO69__FUNC_CLKM3 (MTK_PIN_NO(69) | 5) +#define MT6589_GPIO69__FUNC_UTXD2 (MTK_PIN_NO(69) | 6) +#define MT6589_GPIO69__FUNC_MD1_EINT4 (MTK_PIN_NO(69) | 7) + +#define MT6589_GPIO70__FUNC_GPIO70 (MTK_PIN_NO(70) | 0) +#define MT6589_GPIO70__FUNC_UTXD2 (MTK_PIN_NO(70) | 1) +#define MT6589_GPIO70__FUNC_EINT82 (MTK_PIN_NO(70) | 2) +#define MT6589_GPIO70__FUNC_BSI2_CS (MTK_PIN_NO(70) | 3) +#define MT6589_GPIO70__FUNC_MD1_UTXD (MTK_PIN_NO(70) | 4) +#define MT6589_GPIO70__FUNC_CLKM2 (MTK_PIN_NO(70) | 5) +#define MT6589_GPIO70__FUNC_URXD2 (MTK_PIN_NO(70) | 6) +#define MT6589_GPIO70__FUNC_MD1_EINT3 (MTK_PIN_NO(70) | 7) + +#define MT6589_GPIO71__FUNC_GPIO71 (MTK_PIN_NO(71) | 0) +#define MT6589_GPIO71__FUNC_UCTS2 (MTK_PIN_NO(71) | 1) +#define MT6589_GPIO71__FUNC_EINT84 (MTK_PIN_NO(71) | 2) +#define MT6589_GPIO71__FUNC_BSI2_DATA0 (MTK_PIN_NO(71) | 3) +#define MT6589_GPIO71__FUNC_MD2_UTXD (MTK_PIN_NO(71) | 4) +#define MT6589_GPIO71__FUNC_PWM1 (MTK_PIN_NO(71) | 5) +#define MT6589_GPIO71__FUNC_URTS2 (MTK_PIN_NO(71) | 6) +#define MT6589_GPIO71__FUNC_MD2_EINT1 (MTK_PIN_NO(71) | 7) + +#define MT6589_GPIO72__FUNC_GPIO72 (MTK_PIN_NO(72) | 0) +#define MT6589_GPIO72__FUNC_URTS2 (MTK_PIN_NO(72) | 1) +#define MT6589_GPIO72__FUNC_EINT85 (MTK_PIN_NO(72) | 2) +#define MT6589_GPIO72__FUNC_BSI2_DATA1 (MTK_PIN_NO(72) | 3) +#define MT6589_GPIO72__FUNC_MD2_URXD (MTK_PIN_NO(72) | 4) +#define MT6589_GPIO72__FUNC_PWM2 (MTK_PIN_NO(72) | 5) +#define MT6589_GPIO72__FUNC_UCTS2 (MTK_PIN_NO(72) | 6) +#define MT6589_GPIO72__FUNC_MD2_EINT2 (MTK_PIN_NO(72) | 7) + +#define MT6589_GPIO73__FUNC_GPIO73 (MTK_PIN_NO(73) | 0) +#define MT6589_GPIO73__FUNC_PWM1 (MTK_PIN_NO(73) | 1) +#define MT6589_GPIO73__FUNC_EINT73 (MTK_PIN_NO(73) | 2) +#define MT6589_GPIO73__FUNC_MD1_GPS_SYNC (MTK_PIN_NO(73) | 3) +#define MT6589_GPIO73__FUNC_MD2_GPS_SYNC (MTK_PIN_NO(73) | 4) +#define MT6589_GPIO73__FUNC_USB_DRVVBUS (MTK_PIN_NO(73) | 5) +#define MT6589_GPIO73__FUNC_DISP_PWM (MTK_PIN_NO(73) | 6) +#define MT6589_GPIO73__FUNC_MD2_TCK_PAD (MTK_PIN_NO(73) | 7) + +#define MT6589_GPIO74__FUNC_GPIO74 (MTK_PIN_NO(74) | 0) +#define MT6589_GPIO74__FUNC_PWM2 (MTK_PIN_NO(74) | 1) +#define MT6589_GPIO74__FUNC_EINT74 (MTK_PIN_NO(74) | 2) +#define MT6589_GPIO74__FUNC_BPI2_BUS11 (MTK_PIN_NO(74) | 3) +#define MT6589_GPIO74__FUNC_PWM5 (MTK_PIN_NO(74) | 4) +#define MT6589_GPIO74__FUNC_URXD2 (MTK_PIN_NO(74) | 5) +#define MT6589_GPIO74__FUNC_DISP_PWM (MTK_PIN_NO(74) | 6) +#define MT6589_GPIO74__FUNC_MD2_RTCK_PAD (MTK_PIN_NO(74) | 7) + +#define MT6589_GPIO75__FUNC_GPIO75 (MTK_PIN_NO(75) | 0) +#define MT6589_GPIO75__FUNC_PWM3 (MTK_PIN_NO(75) | 1) +#define MT6589_GPIO75__FUNC_EINT75 (MTK_PIN_NO(75) | 2) +#define MT6589_GPIO75__FUNC_BPI2_BUS12 (MTK_PIN_NO(75) | 3) +#define MT6589_GPIO75__FUNC_PWM6 (MTK_PIN_NO(75) | 4) +#define MT6589_GPIO75__FUNC_UTXD2 (MTK_PIN_NO(75) | 5) +#define MT6589_GPIO75__FUNC_DISP_PWM (MTK_PIN_NO(75) | 6) +#define MT6589_GPIO75__FUNC_MD2_NTRST_PAD (MTK_PIN_NO(75) | 7) + +#define MT6589_GPIO76__FUNC_GPIO76 (MTK_PIN_NO(76) | 0) +#define MT6589_GPIO76__FUNC_PWM4 (MTK_PIN_NO(76) | 1) +#define MT6589_GPIO76__FUNC_EINT76 (MTK_PIN_NO(76) | 2) +#define MT6589_GPIO76__FUNC_BPI2_BUS13 (MTK_PIN_NO(76) | 3) +#define MT6589_GPIO76__FUNC_PWM7 (MTK_PIN_NO(76) | 4) +#define MT6589_GPIO76__FUNC_DISP_PWM (MTK_PIN_NO(76) | 6) +#define MT6589_GPIO76__FUNC_MD2_TMS_PAD (MTK_PIN_NO(76) | 7) + +#define MT6589_GPIO77__FUNC_GPIO77 (MTK_PIN_NO(77) | 0) +#define MT6589_GPIO77__FUNC_URXD1 (MTK_PIN_NO(77) | 1) +#define MT6589_GPIO77__FUNC_EINT79 (MTK_PIN_NO(77) | 2) +#define MT6589_GPIO77__FUNC_URXD4 (MTK_PIN_NO(77) | 3) +#define MT6589_GPIO77__FUNC_MD1_URXD (MTK_PIN_NO(77) | 4) +#define MT6589_GPIO77__FUNC_MD2_URXD (MTK_PIN_NO(77) | 5) +#define MT6589_GPIO77__FUNC_UTXD1 (MTK_PIN_NO(77) | 6) +#define MT6589_GPIO77__FUNC_MD2_TDO_PAD (MTK_PIN_NO(77) | 7) + +#define MT6589_GPIO78__FUNC_GPIO78 (MTK_PIN_NO(78) | 0) +#define MT6589_GPIO78__FUNC_UTXD1 (MTK_PIN_NO(78) | 1) +#define MT6589_GPIO78__FUNC_EINT78 (MTK_PIN_NO(78) | 2) +#define MT6589_GPIO78__FUNC_UTXD4 (MTK_PIN_NO(78) | 3) +#define MT6589_GPIO78__FUNC_MD1_UTXD (MTK_PIN_NO(78) | 4) +#define MT6589_GPIO78__FUNC_MD2_UTXD (MTK_PIN_NO(78) | 5) +#define MT6589_GPIO78__FUNC_URXD1 (MTK_PIN_NO(78) | 6) +#define MT6589_GPIO78__FUNC_MD2_TDI_PAD (MTK_PIN_NO(78) | 7) + +#define MT6589_GPIO79__FUNC_GPIO79 (MTK_PIN_NO(79) | 0) +#define MT6589_GPIO79__FUNC_UCTS1 (MTK_PIN_NO(79) | 1) +#define MT6589_GPIO79__FUNC_EINT80 (MTK_PIN_NO(79) | 2) +#define MT6589_GPIO79__FUNC_DUAL_BPI1_BUS14 (MTK_PIN_NO(79) | 3) +#define MT6589_GPIO79__FUNC_MD1_UTXD (MTK_PIN_NO(79) | 4) +#define MT6589_GPIO79__FUNC_CLKM0 (MTK_PIN_NO(79) | 5) +#define MT6589_GPIO79__FUNC_URTS1 (MTK_PIN_NO(79) | 6) +#define MT6589_GPIO79__FUNC_MD1_EINT1 (MTK_PIN_NO(79) | 7) + +#define MT6589_GPIO80__FUNC_GPIO80 (MTK_PIN_NO(80) | 0) +#define MT6589_GPIO80__FUNC_URTS1 (MTK_PIN_NO(80) | 1) +#define MT6589_GPIO80__FUNC_EINT81 (MTK_PIN_NO(80) | 2) +#define MT6589_GPIO80__FUNC_DUAL_BPI1_BUS15 (MTK_PIN_NO(80) | 3) +#define MT6589_GPIO80__FUNC_MD1_URXD (MTK_PIN_NO(80) | 4) +#define MT6589_GPIO80__FUNC_CLKM1 (MTK_PIN_NO(80) | 5) +#define MT6589_GPIO80__FUNC_UCTS1 (MTK_PIN_NO(80) | 6) +#define MT6589_GPIO80__FUNC_MD1_EINT2 (MTK_PIN_NO(80) | 7) + +#define MT6589_GPIO81__FUNC_GPIO81 (MTK_PIN_NO(81) | 0) +#define MT6589_GPIO81__FUNC_URXD4 (MTK_PIN_NO(81) | 1) +#define MT6589_GPIO81__FUNC_EINT89 (MTK_PIN_NO(81) | 2) +#define MT6589_GPIO81__FUNC_URXD1 (MTK_PIN_NO(81) | 3) +#define MT6589_GPIO81__FUNC_MD1_URXD (MTK_PIN_NO(81) | 4) +#define MT6589_GPIO81__FUNC_MD2_URXD (MTK_PIN_NO(81) | 5) +#define MT6589_GPIO81__FUNC_UTXD4 (MTK_PIN_NO(81) | 6) +#define MT6589_GPIO81__FUNC_MD2_EINT5 (MTK_PIN_NO(81) | 7) + +#define MT6589_GPIO82__FUNC_GPIO82 (MTK_PIN_NO(82) | 0) +#define MT6589_GPIO82__FUNC_UTXD4 (MTK_PIN_NO(82) | 1) +#define MT6589_GPIO82__FUNC_EINT88 (MTK_PIN_NO(82) | 2) +#define MT6589_GPIO82__FUNC_UTXD1 (MTK_PIN_NO(82) | 3) +#define MT6589_GPIO82__FUNC_MD1_UTXD (MTK_PIN_NO(82) | 4) +#define MT6589_GPIO82__FUNC_MD2_UTXD (MTK_PIN_NO(82) | 5) +#define MT6589_GPIO82__FUNC_URXD4 (MTK_PIN_NO(82) | 6) +#define MT6589_GPIO82__FUNC_MD1_EINT5 (MTK_PIN_NO(82) | 7) + +#define MT6589_GPIO83__FUNC_GPIO83 (MTK_PIN_NO(83) | 0) +#define MT6589_GPIO83__FUNC_DUAL_BPI1_BUS0 (MTK_PIN_NO(83) | 1) +#define MT6589_GPIO83__FUNC_EINT1 (MTK_PIN_NO(83) | 2) +#define MT6589_GPIO83__FUNC_BPI2_BUS0 (MTK_PIN_NO(83) | 3) +#define MT6589_GPIO83__FUNC_USB_TEST_IO_0 (MTK_PIN_NO(83) | 5) +#define MT6589_GPIO83__FUNC_A_FUNC_DIN_31 (MTK_PIN_NO(83) | 7) + +#define MT6589_GPIO84__FUNC_GPIO84 (MTK_PIN_NO(84) | 0) +#define MT6589_GPIO84__FUNC_DUAL_BPI1_BUS1 (MTK_PIN_NO(84) | 1) +#define MT6589_GPIO84__FUNC_EINT2 (MTK_PIN_NO(84) | 2) +#define MT6589_GPIO84__FUNC_BPI2_BUS1 (MTK_PIN_NO(84) | 3) +#define MT6589_GPIO84__FUNC_USB_TEST_IO_1 (MTK_PIN_NO(84) | 5) +#define MT6589_GPIO84__FUNC_A_FUNC_DIN_30 (MTK_PIN_NO(84) | 7) + +#define MT6589_GPIO85__FUNC_GPIO85 (MTK_PIN_NO(85) | 0) +#define MT6589_GPIO85__FUNC_DUAL_BPI1_BUS2 (MTK_PIN_NO(85) | 1) +#define MT6589_GPIO85__FUNC_EINT3 (MTK_PIN_NO(85) | 2) +#define MT6589_GPIO85__FUNC_BPI2_BUS2 (MTK_PIN_NO(85) | 3) +#define MT6589_GPIO85__FUNC_USB_TEST_IO_2 (MTK_PIN_NO(85) | 5) +#define MT6589_GPIO85__FUNC_A_FUNC_DIN_29 (MTK_PIN_NO(85) | 7) + +#define MT6589_GPIO86__FUNC_GPIO86 (MTK_PIN_NO(86) | 0) +#define MT6589_GPIO86__FUNC_DUAL_BPI1_BUS3 (MTK_PIN_NO(86) | 1) +#define MT6589_GPIO86__FUNC_EINT4 (MTK_PIN_NO(86) | 2) +#define MT6589_GPIO86__FUNC_BPI2_BUS3 (MTK_PIN_NO(86) | 3) +#define MT6589_GPIO86__FUNC_USB_TEST_IO_3 (MTK_PIN_NO(86) | 5) +#define MT6589_GPIO86__FUNC_A_FUNC_DIN_28 (MTK_PIN_NO(86) | 7) + +#define MT6589_GPIO87__FUNC_GPIO87 (MTK_PIN_NO(87) | 0) +#define MT6589_GPIO87__FUNC_DUAL_BPI1_BUS4 (MTK_PIN_NO(87) | 1) +#define MT6589_GPIO87__FUNC_EINT5 (MTK_PIN_NO(87) | 2) +#define MT6589_GPIO87__FUNC_BPI2_BUS4 (MTK_PIN_NO(87) | 3) +#define MT6589_GPIO87__FUNC_USB_TEST_IO_4 (MTK_PIN_NO(87) | 5) +#define MT6589_GPIO87__FUNC_A_FUNC_DIN_27 (MTK_PIN_NO(87) | 7) + +#define MT6589_GPIO88__FUNC_GPIO88 (MTK_PIN_NO(88) | 0) +#define MT6589_GPIO88__FUNC_DUAL_BPI1_BUS5 (MTK_PIN_NO(88) | 1) +#define MT6589_GPIO88__FUNC_EINT6 (MTK_PIN_NO(88) | 2) +#define MT6589_GPIO88__FUNC_BPI2_BUS5 (MTK_PIN_NO(88) | 3) +#define MT6589_GPIO88__FUNC_USB_TEST_IO_5 (MTK_PIN_NO(88) | 5) +#define MT6589_GPIO88__FUNC_A_FUNC_DIN_26 (MTK_PIN_NO(88) | 7) + +#define MT6589_GPIO89__FUNC_GPIO89 (MTK_PIN_NO(89) | 0) +#define MT6589_GPIO89__FUNC_DUAL_BPI1_BUS6 (MTK_PIN_NO(89) | 1) +#define MT6589_GPIO89__FUNC_EINT7 (MTK_PIN_NO(89) | 2) +#define MT6589_GPIO89__FUNC_BPI2_BUS6 (MTK_PIN_NO(89) | 3) +#define MT6589_GPIO89__FUNC_USB_TEST_IO_6 (MTK_PIN_NO(89) | 5) +#define MT6589_GPIO89__FUNC_A_FUNC_DIN_25 (MTK_PIN_NO(89) | 7) + +#define MT6589_GPIO90__FUNC_GPIO90 (MTK_PIN_NO(90) | 0) +#define MT6589_GPIO90__FUNC_DUAL_BPI1_BUS7 (MTK_PIN_NO(90) | 1) +#define MT6589_GPIO90__FUNC_EINT8 (MTK_PIN_NO(90) | 2) +#define MT6589_GPIO90__FUNC_MD1_GPS_SYNC (MTK_PIN_NO(90) | 3) +#define MT6589_GPIO90__FUNC_MD2_GPS_SYNC (MTK_PIN_NO(90) | 4) +#define MT6589_GPIO90__FUNC_USB_TEST_IO_7 (MTK_PIN_NO(90) | 5) +#define MT6589_GPIO90__FUNC_USB_DRVVBUS (MTK_PIN_NO(90) | 6) +#define MT6589_GPIO90__FUNC_A_FUNC_DIN_24 (MTK_PIN_NO(90) | 7) + +#define MT6589_GPIO91__FUNC_GPIO91 (MTK_PIN_NO(91) | 0) +#define MT6589_GPIO91__FUNC_DUAL_BPI1_BUS8 (MTK_PIN_NO(91) | 1) +#define MT6589_GPIO91__FUNC_EINT9 (MTK_PIN_NO(91) | 2) +#define MT6589_GPIO91__FUNC_DUAL_BPI1_BUS14 (MTK_PIN_NO(91) | 3) +#define MT6589_GPIO91__FUNC_USB_TEST_IO_8 (MTK_PIN_NO(91) | 5) +#define MT6589_GPIO91__FUNC_A_FUNC_DIN_23 (MTK_PIN_NO(91) | 7) + +#define MT6589_GPIO92__FUNC_GPIO92 (MTK_PIN_NO(92) | 0) +#define MT6589_GPIO92__FUNC_DUAL_BPI1_BUS9 (MTK_PIN_NO(92) | 1) +#define MT6589_GPIO92__FUNC_EINT10 (MTK_PIN_NO(92) | 2) +#define MT6589_GPIO92__FUNC_DUAL_BPI1_BUS15 (MTK_PIN_NO(92) | 3) +#define MT6589_GPIO92__FUNC_USB_TEST_IO_9 (MTK_PIN_NO(92) | 5) +#define MT6589_GPIO92__FUNC_A_FUNC_DIN_22 (MTK_PIN_NO(92) | 7) + +#define MT6589_GPIO93__FUNC_GPIO93 (MTK_PIN_NO(93) | 0) +#define MT6589_GPIO93__FUNC_DUAL_BPI1_BUS10 (MTK_PIN_NO(93) | 1) +#define MT6589_GPIO93__FUNC_EINT11 (MTK_PIN_NO(93) | 2) +#define MT6589_GPIO93__FUNC_USB_TEST_IO_10 (MTK_PIN_NO(93) | 5) +#define MT6589_GPIO93__FUNC_A_FUNC_DIN_21 (MTK_PIN_NO(93) | 7) + +#define MT6589_GPIO94__FUNC_GPIO94 (MTK_PIN_NO(94) | 0) +#define MT6589_GPIO94__FUNC_DUAL_BPI1_BUS11 (MTK_PIN_NO(94) | 1) +#define MT6589_GPIO94__FUNC_EINT12 (MTK_PIN_NO(94) | 2) +#define MT6589_GPIO94__FUNC_BPI2_BUS11 (MTK_PIN_NO(94) | 3) +#define MT6589_GPIO94__FUNC_USB_TEST_IO_11 (MTK_PIN_NO(94) | 5) +#define MT6589_GPIO94__FUNC_A_FUNC_DOUT_7 (MTK_PIN_NO(94) | 7) + +#define MT6589_GPIO95__FUNC_GPIO95 (MTK_PIN_NO(95) | 0) +#define MT6589_GPIO95__FUNC_DUAL_BPI1_BUS12 (MTK_PIN_NO(95) | 1) +#define MT6589_GPIO95__FUNC_EINT13 (MTK_PIN_NO(95) | 2) +#define MT6589_GPIO95__FUNC_BPI2_BUS12 (MTK_PIN_NO(95) | 3) +#define MT6589_GPIO95__FUNC_USB_TEST_IO_12 (MTK_PIN_NO(95) | 5) +#define MT6589_GPIO95__FUNC_A_FUNC_DOUT_6 (MTK_PIN_NO(95) | 7) + +#define MT6589_GPIO96__FUNC_GPIO96 (MTK_PIN_NO(96) | 0) +#define MT6589_GPIO96__FUNC_DUAL_BPI1_BUS13 (MTK_PIN_NO(96) | 1) +#define MT6589_GPIO96__FUNC_EINT14 (MTK_PIN_NO(96) | 2) +#define MT6589_GPIO96__FUNC_BPI2_BUS13 (MTK_PIN_NO(96) | 3) +#define MT6589_GPIO96__FUNC_USB_TEST_IO_13 (MTK_PIN_NO(96) | 5) +#define MT6589_GPIO96__FUNC_A_FUNC_DOUT_5 (MTK_PIN_NO(96) | 7) + +#define MT6589_GPIO97__FUNC_GPIO97 (MTK_PIN_NO(97) | 0) +#define MT6589_GPIO97__FUNC_DUAL_BPI1_BUS14 (MTK_PIN_NO(97) | 1) +#define MT6589_GPIO97__FUNC_EINT15 (MTK_PIN_NO(97) | 2) +#define MT6589_GPIO97__FUNC_BPI2_BUS16 (MTK_PIN_NO(97) | 3) +#define MT6589_GPIO97__FUNC_USB_TEST_IO_14 (MTK_PIN_NO(97) | 5) +#define MT6589_GPIO97__FUNC_A_FUNC_DOUT_4 (MTK_PIN_NO(97) | 7) + +#define MT6589_GPIO98__FUNC_GPIO98 (MTK_PIN_NO(98) | 0) +#define MT6589_GPIO98__FUNC_DUAL_BPI1_BUS17 (MTK_PIN_NO(98) | 1) +#define MT6589_GPIO98__FUNC_EINT16 (MTK_PIN_NO(98) | 2) +#define MT6589_GPIO98__FUNC_BPI2_BUS17 (MTK_PIN_NO(98) | 3) +#define MT6589_GPIO98__FUNC_USB_TEST_IO_15 (MTK_PIN_NO(98) | 5) +#define MT6589_GPIO98__FUNC_A_FUNC_DOUT_3 (MTK_PIN_NO(98) | 7) + +#define MT6589_GPIO99__FUNC_GPIO99 (MTK_PIN_NO(99) | 0) +#define MT6589_GPIO99__FUNC_DUAL_BPI1_BUS15 (MTK_PIN_NO(99) | 1) +#define MT6589_GPIO99__FUNC_EINT17 (MTK_PIN_NO(99) | 2) +#define MT6589_GPIO99__FUNC_BPI2_BUS18 (MTK_PIN_NO(99) | 3) +#define MT6589_GPIO99__FUNC_USB_TEST_IO_16 (MTK_PIN_NO(99) | 5) +#define MT6589_GPIO99__FUNC_A_FUNC_DOUT_2 (MTK_PIN_NO(99) | 7) + +#define MT6589_GPIO100__FUNC_GPIO100 (MTK_PIN_NO(100) | 0) +#define MT6589_GPIO100__FUNC_VM1 (MTK_PIN_NO(100) | 1) +#define MT6589_GPIO100__FUNC_EINT19 (MTK_PIN_NO(100) | 2) +#define MT6589_GPIO100__FUNC_USB_TEST_IO_17 (MTK_PIN_NO(100) | 5) +#define MT6589_GPIO100__FUNC_A_FUNC_DOUT_0 (MTK_PIN_NO(100) | 7) + +#define MT6589_GPIO101__FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define MT6589_GPIO101__FUNC_VM0 (MTK_PIN_NO(101) | 1) +#define MT6589_GPIO101__FUNC_EINT18 (MTK_PIN_NO(101) | 2) +#define MT6589_GPIO101__FUNC_USB_TEST_IO_18 (MTK_PIN_NO(101) | 5) +#define MT6589_GPIO101__FUNC_A_FUNC_DOUT_1 (MTK_PIN_NO(101) | 7) + +#define MT6589_GPIO102__FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define MT6589_GPIO102__FUNC_BSI1B_CS0 (MTK_PIN_NO(102) | 1) +#define MT6589_GPIO102__FUNC_EINT26 (MTK_PIN_NO(102) | 2) +#define MT6589_GPIO102__FUNC_USB_TEST_IO_19 (MTK_PIN_NO(102) | 5) +#define MT6589_GPIO102__FUNC_MD_ABB_AFUNC_D_21 (MTK_PIN_NO(102) | 6) + +#define MT6589_GPIO103__FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define MT6589_GPIO103__FUNC_BSI1B_DATA0 (MTK_PIN_NO(103) | 1) +#define MT6589_GPIO103__FUNC_EINT27 (MTK_PIN_NO(103) | 2) +#define MT6589_GPIO103__FUNC_USB_TEST_IO_20 (MTK_PIN_NO(103) | 5) +#define MT6589_GPIO103__FUNC_MD_ABB_AFUNC_D_22 (MTK_PIN_NO(103) | 6) + +#define MT6589_GPIO104__FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define MT6589_GPIO104__FUNC_BSI1B_CLK (MTK_PIN_NO(104) | 1) +#define MT6589_GPIO104__FUNC_EINT25 (MTK_PIN_NO(104) | 2) +#define MT6589_GPIO104__FUNC_USB_TEST_IO_21 (MTK_PIN_NO(104) | 5) +#define MT6589_GPIO104__FUNC_MD_ABB_AFUNC_D_23 (MTK_PIN_NO(104) | 6) + +#define MT6589_GPIO105__FUNC_GPIO105 (MTK_PIN_NO(105) | 0) +#define MT6589_GPIO105__FUNC_TXBPI1 (MTK_PIN_NO(105) | 1) +#define MT6589_GPIO105__FUNC_EINT30 (MTK_PIN_NO(105) | 2) + +#define MT6589_GPIO106__FUNC_GPIO106 (MTK_PIN_NO(106) | 0) +#define MT6589_GPIO106__FUNC_EXT_CLK_EN (MTK_PIN_NO(106) | 1) + +#define MT6589_GPIO107__FUNC_GPIO107 (MTK_PIN_NO(107) | 0) +#define MT6589_GPIO107__FUNC_SRCLKENA2 (MTK_PIN_NO(107) | 1) +#define MT6589_GPIO107__FUNC_EINT39 (MTK_PIN_NO(107) | 2) + +#define MT6589_GPIO108__FUNC_GPIO108 (MTK_PIN_NO(108) | 0) +#define MT6589_GPIO108__FUNC_BSI1A_CS0 (MTK_PIN_NO(108) | 1) +#define MT6589_GPIO108__FUNC_EINT21 (MTK_PIN_NO(108) | 2) +#define MT6589_GPIO108__FUNC_BSI2_CS (MTK_PIN_NO(108) | 3) +#define MT6589_GPIO108__FUNC_USB_TEST_IO_22 (MTK_PIN_NO(108) | 5) +#define MT6589_GPIO108__FUNC_MD_ABB_AFUNC_D_24 (MTK_PIN_NO(108) | 6) + +#define MT6589_GPIO109__FUNC_GPIO109 (MTK_PIN_NO(109) | 0) +#define MT6589_GPIO109__FUNC_BSI1A_DATA2 (MTK_PIN_NO(109) | 1) +#define MT6589_GPIO109__FUNC_EINT24 (MTK_PIN_NO(109) | 2) +#define MT6589_GPIO109__FUNC_USB_TEST_IO_23 (MTK_PIN_NO(109) | 5) +#define MT6589_GPIO109__FUNC_MD_ABB_AFUNC_D_25 (MTK_PIN_NO(109) | 6) + +#define MT6589_GPIO110__FUNC_GPIO110 (MTK_PIN_NO(110) | 0) +#define MT6589_GPIO110__FUNC_BSI1A_DATA1 (MTK_PIN_NO(110) | 1) +#define MT6589_GPIO110__FUNC_EINT23 (MTK_PIN_NO(110) | 2) +#define MT6589_GPIO110__FUNC_BSI2_DATA1 (MTK_PIN_NO(110) | 3) +#define MT6589_GPIO110__FUNC_USB_TEST_IO_24 (MTK_PIN_NO(110) | 5) +#define MT6589_GPIO110__FUNC_MD_ABB_AFUNC_D_26 (MTK_PIN_NO(110) | 6) + +#define MT6589_GPIO111__FUNC_GPIO111 (MTK_PIN_NO(111) | 0) +#define MT6589_GPIO111__FUNC_BSI1A_DATA0 (MTK_PIN_NO(111) | 1) +#define MT6589_GPIO111__FUNC_EINT22 (MTK_PIN_NO(111) | 2) +#define MT6589_GPIO111__FUNC_BSI2_DATA0 (MTK_PIN_NO(111) | 3) +#define MT6589_GPIO111__FUNC_USB_TEST_IO_25 (MTK_PIN_NO(111) | 5) +#define MT6589_GPIO111__FUNC_MD_ABB_AFUNC_D_27 (MTK_PIN_NO(111) | 6) + +#define MT6589_GPIO112__FUNC_GPIO112 (MTK_PIN_NO(112) | 0) +#define MT6589_GPIO112__FUNC_BSI1A_CLK (MTK_PIN_NO(112) | 1) +#define MT6589_GPIO112__FUNC_EINT20 (MTK_PIN_NO(112) | 2) +#define MT6589_GPIO112__FUNC_BSI2_CLK (MTK_PIN_NO(112) | 3) +#define MT6589_GPIO112__FUNC_USB_TEST_IO_26 (MTK_PIN_NO(112) | 5) +#define MT6589_GPIO112__FUNC_MD_ABB_AFUNC_D_28 (MTK_PIN_NO(112) | 6) + +#define MT6589_GPIO113__FUNC_GPIO113 (MTK_PIN_NO(113) | 0) +#define MT6589_GPIO113__FUNC_BSI1C_DATA (MTK_PIN_NO(113) | 1) +#define MT6589_GPIO113__FUNC_EINT29 (MTK_PIN_NO(113) | 2) +#define MT6589_GPIO113__FUNC_MD1_GPS_SYNC (MTK_PIN_NO(113) | 3) +#define MT6589_GPIO113__FUNC_MD2_GPS_SYNC (MTK_PIN_NO(113) | 4) +#define MT6589_GPIO113__FUNC_USB_TEST_IO_27 (MTK_PIN_NO(113) | 5) +#define MT6589_GPIO113__FUNC_MD_ABB_AFUNC_D_29 (MTK_PIN_NO(113) | 6) +#define MT6589_GPIO113__FUNC_USB_DRVVBUS (MTK_PIN_NO(113) | 7) + +#define MT6589_GPIO114__FUNC_GPIO114 (MTK_PIN_NO(114) | 0) +#define MT6589_GPIO114__FUNC_BSI1C_CLK (MTK_PIN_NO(114) | 1) +#define MT6589_GPIO114__FUNC_EINT28 (MTK_PIN_NO(114) | 2) +#define MT6589_GPIO114__FUNC_USB_TEST_IO_28 (MTK_PIN_NO(114) | 5) +#define MT6589_GPIO114__FUNC_MD_ABB_AFUNC_D_30 (MTK_PIN_NO(114) | 6) + +#define MT6589_GPIO115__FUNC_GPIO115 (MTK_PIN_NO(115) | 0) +#define MT6589_GPIO115__FUNC_EINT10 (MTK_PIN_NO(115) | 1) +#define MT6589_GPIO115__FUNC_MD_ABB_AFUNC_D_31 (MTK_PIN_NO(115) | 6) + +#define MT6589_GPIO116__FUNC_GPIO116 (MTK_PIN_NO(116) | 0) +#define MT6589_GPIO116__FUNC_EINT11 (MTK_PIN_NO(116) | 1) +#define MT6589_GPIO116__FUNC_MD_ABB_AFUNC_D_32 (MTK_PIN_NO(116) | 6) + +#define MT6589_GPIO117__FUNC_GPIO117 (MTK_PIN_NO(117) | 0) +#define MT6589_GPIO117__FUNC_EINT16 (MTK_PIN_NO(117) | 1) +#define MT6589_GPIO117__FUNC_MD_ABB_AFUNC_D_33 (MTK_PIN_NO(117) | 6) + +#define MT6589_GPIO118__FUNC_GPIO118 (MTK_PIN_NO(118) | 0) +#define MT6589_GPIO118__FUNC_SDA0 (MTK_PIN_NO(118) | 1) +#define MT6589_GPIO118__FUNC_EINT91 (MTK_PIN_NO(118) | 2) +#define MT6589_GPIO118__FUNC_CLKM1 (MTK_PIN_NO(118) | 3) +#define MT6589_GPIO118__FUNC_PWM1 (MTK_PIN_NO(118) | 4) +#define MT6589_GPIO118__FUNC_A_FUNC_DIN_19 (MTK_PIN_NO(118) | 7) + +#define MT6589_GPIO119__FUNC_GPIO119 (MTK_PIN_NO(119) | 0) +#define MT6589_GPIO119__FUNC_SCL0 (MTK_PIN_NO(119) | 1) +#define MT6589_GPIO119__FUNC_EINT90 (MTK_PIN_NO(119) | 2) +#define MT6589_GPIO119__FUNC_CLKM0 (MTK_PIN_NO(119) | 3) +#define MT6589_GPIO119__FUNC_DISP_PWM (MTK_PIN_NO(119) | 4) +#define MT6589_GPIO119__FUNC_A_FUNC_DIN_20 (MTK_PIN_NO(119) | 7) + +#define MT6589_GPIO120__FUNC_GPIO120 (MTK_PIN_NO(120) | 0) +#define MT6589_GPIO120__FUNC_I2SIN_CK (MTK_PIN_NO(120) | 1) +#define MT6589_GPIO120__FUNC_EINT10 (MTK_PIN_NO(120) | 2) +#define MT6589_GPIO120__FUNC_DAC_CK (MTK_PIN_NO(120) | 3) +#define MT6589_GPIO120__FUNC_PCM1_CK (MTK_PIN_NO(120) | 4) +#define MT6589_GPIO120__FUNC_DSP1_ICK (MTK_PIN_NO(120) | 5) +#define MT6589_GPIO120__FUNC_MD_ABB_AFUNC_D_34 (MTK_PIN_NO(120) | 6) + +#define MT6589_GPIO121__FUNC_GPIO121 (MTK_PIN_NO(121) | 0) +#define MT6589_GPIO121__FUNC_I2SIN_WS (MTK_PIN_NO(121) | 1) +#define MT6589_GPIO121__FUNC_EINT13 (MTK_PIN_NO(121) | 2) +#define MT6589_GPIO121__FUNC_DAC_WS (MTK_PIN_NO(121) | 3) +#define MT6589_GPIO121__FUNC_PCM1_WS (MTK_PIN_NO(121) | 4) +#define MT6589_GPIO121__FUNC_DSP1_ID (MTK_PIN_NO(121) | 5) +#define MT6589_GPIO121__FUNC_MD_ABB_AFUNC_D_35 (MTK_PIN_NO(121) | 6) + +#define MT6589_GPIO122__FUNC_GPIO122 (MTK_PIN_NO(122) | 0) +#define MT6589_GPIO122__FUNC_I2SIN_DAT (MTK_PIN_NO(122) | 1) +#define MT6589_GPIO122__FUNC_EINT11 (MTK_PIN_NO(122) | 2) +#define MT6589_GPIO122__FUNC_PCM1_DI (MTK_PIN_NO(122) | 4) +#define MT6589_GPIO122__FUNC_DSP1_IMS (MTK_PIN_NO(122) | 5) +#define MT6589_GPIO122__FUNC_MD_ABB_AFUNC_D_36 (MTK_PIN_NO(122) | 6) + +#define MT6589_GPIO123__FUNC_GPIO123 (MTK_PIN_NO(123) | 0) +#define MT6589_GPIO123__FUNC_I2SOUT_DAT (MTK_PIN_NO(123) | 1) +#define MT6589_GPIO123__FUNC_EINT12 (MTK_PIN_NO(123) | 2) +#define MT6589_GPIO123__FUNC_DAC_DAT_OUT (MTK_PIN_NO(123) | 3) +#define MT6589_GPIO123__FUNC_PCM1_DO (MTK_PIN_NO(123) | 4) +#define MT6589_GPIO123__FUNC_MD2_EINT5 (MTK_PIN_NO(123) | 5) +#define MT6589_GPIO123__FUNC_MD_ABB_AFUNC_D_37 (MTK_PIN_NO(123) | 6) + +#define MT6589_GPIO124__FUNC_GPIO124 (MTK_PIN_NO(124) | 0) +#define MT6589_GPIO124__FUNC_EINT5 (MTK_PIN_NO(124) | 1) +#define MT6589_GPIO124__FUNC_PWM5 (MTK_PIN_NO(124) | 2) +#define MT6589_GPIO124__FUNC_CLKM3 (MTK_PIN_NO(124) | 3) +#define MT6589_GPIO124__FUNC_MD1_UTXD (MTK_PIN_NO(124) | 4) +#define MT6589_GPIO124__FUNC_MD2_EINT1 (MTK_PIN_NO(124) | 5) +#define MT6589_GPIO124__FUNC_MD_ABB_AFUNC_D_38 (MTK_PIN_NO(124) | 6) + +#define MT6589_GPIO125__FUNC_GPIO125 (MTK_PIN_NO(125) | 0) +#define MT6589_GPIO125__FUNC_EINT6 (MTK_PIN_NO(125) | 1) +#define MT6589_GPIO125__FUNC_PWM6 (MTK_PIN_NO(125) | 2) +#define MT6589_GPIO125__FUNC_CLKM4 (MTK_PIN_NO(125) | 3) +#define MT6589_GPIO125__FUNC_MD1_URXD (MTK_PIN_NO(125) | 4) +#define MT6589_GPIO125__FUNC_MD2_EINT2 (MTK_PIN_NO(125) | 5) +#define MT6589_GPIO125__FUNC_MD_ABB_AFUNC_D_39 (MTK_PIN_NO(125) | 6) + +#define MT6589_GPIO126__FUNC_GPIO126 (MTK_PIN_NO(126) | 0) +#define MT6589_GPIO126__FUNC_EINT7 (MTK_PIN_NO(126) | 1) +#define MT6589_GPIO126__FUNC_PWM7 (MTK_PIN_NO(126) | 2) +#define MT6589_GPIO126__FUNC_CLKM5 (MTK_PIN_NO(126) | 3) +#define MT6589_GPIO126__FUNC_SRCLKENAI2 (MTK_PIN_NO(126) | 4) +#define MT6589_GPIO126__FUNC_MD2_EINT3 (MTK_PIN_NO(126) | 5) +#define MT6589_GPIO126__FUNC_MD_ABB_AFUNC_D_40 (MTK_PIN_NO(126) | 6) + +#define MT6589_GPIO127__FUNC_GPIO127 (MTK_PIN_NO(127) | 0) +#define MT6589_GPIO127__FUNC_EINT8 (MTK_PIN_NO(127) | 1) +#define MT6589_GPIO127__FUNC_DISP_PWM (MTK_PIN_NO(127) | 2) +#define MT6589_GPIO127__FUNC_CLKM6 (MTK_PIN_NO(127) | 3) +#define MT6589_GPIO127__FUNC_MD2_EINT4 (MTK_PIN_NO(127) | 5) +#define MT6589_GPIO127__FUNC_MD_ABB_AFUNC_D_41 (MTK_PIN_NO(127) | 6) +#define MT6589_GPIO127__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(127) | 7) + +#define MT6589_GPIO128__FUNC_GPIO128 (MTK_PIN_NO(128) | 0) +#define MT6589_GPIO128__FUNC_EINT9 (MTK_PIN_NO(128) | 1) +#define MT6589_GPIO128__FUNC_MD1_GPS_SYNC (MTK_PIN_NO(128) | 3) +#define MT6589_GPIO128__FUNC_MD2_GPS_SYNC (MTK_PIN_NO(128) | 4) +#define MT6589_GPIO128__FUNC_USB_DRVVBUS (MTK_PIN_NO(128) | 5) +#define MT6589_GPIO128__FUNC_MD_ABB_AFUNC_D_42 (MTK_PIN_NO(128) | 6) + +#define MT6589_GPIO129__FUNC_GPIO129 (MTK_PIN_NO(129) | 0) +#define MT6589_GPIO129__FUNC_DISP_PWM (MTK_PIN_NO(129) | 1) +#define MT6589_GPIO129__FUNC_EINT77 (MTK_PIN_NO(129) | 2) +#define MT6589_GPIO129__FUNC_LSDI (MTK_PIN_NO(129) | 3) +#define MT6589_GPIO129__FUNC_PWM1 (MTK_PIN_NO(129) | 4) +#define MT6589_GPIO129__FUNC_PWM2 (MTK_PIN_NO(129) | 5) +#define MT6589_GPIO129__FUNC_MD_ABB_AFUNC_D_43 (MTK_PIN_NO(129) | 6) +#define MT6589_GPIO129__FUNC_PWM3 (MTK_PIN_NO(129) | 7) + +#define MT6589_GPIO130__FUNC_GPIO130 (MTK_PIN_NO(130) | 0) +#define MT6589_GPIO130__FUNC_MSDC4_DAT0 (MTK_PIN_NO(130) | 1) +#define MT6589_GPIO130__FUNC_EINT133 (MTK_PIN_NO(130) | 2) +#define MT6589_GPIO130__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(130) | 4) +#define MT6589_GPIO130__FUNC_USB_DRVVBUS (MTK_PIN_NO(130) | 5) +#define MT6589_GPIO130__FUNC_MD_ABB_AFUNC_D_46 (MTK_PIN_NO(130) | 6) +#define MT6589_GPIO130__FUNC_LPTE (MTK_PIN_NO(130) | 7) + +#define MT6589_GPIO131__FUNC_GPIO131 (MTK_PIN_NO(131) | 0) +#define MT6589_GPIO131__FUNC_MSDC4_DAT1 (MTK_PIN_NO(131) | 1) +#define MT6589_GPIO131__FUNC_EINT134 (MTK_PIN_NO(131) | 2) +#define MT6589_GPIO131__FUNC_MD_ABB_AFUNC_D_47 (MTK_PIN_NO(131) | 6) +#define MT6589_GPIO131__FUNC_LRSTB_1X (MTK_PIN_NO(131) | 7) + +#define MT6589_GPIO132__FUNC_GPIO132 (MTK_PIN_NO(132) | 0) +#define MT6589_GPIO132__FUNC_LPCE1B (MTK_PIN_NO(132) | 1) +#define MT6589_GPIO132__FUNC_EINT127 (MTK_PIN_NO(132) | 2) +#define MT6589_GPIO132__FUNC_DPI1_HSYNC_2X (MTK_PIN_NO(132) | 3) +#define MT6589_GPIO132__FUNC_PWM2 (MTK_PIN_NO(132) | 5) +#define MT6589_GPIO132__FUNC_MD_ABB_AFUNC_D_44 (MTK_PIN_NO(132) | 6) + +#define MT6589_GPIO133__FUNC_GPIO133 (MTK_PIN_NO(133) | 0) +#define MT6589_GPIO133__FUNC_LPCE0B (MTK_PIN_NO(133) | 1) +#define MT6589_GPIO133__FUNC_EINT126 (MTK_PIN_NO(133) | 2) +#define MT6589_GPIO133__FUNC_DPI1_VSYNC_2X (MTK_PIN_NO(133) | 3) +#define MT6589_GPIO133__FUNC_PWM1 (MTK_PIN_NO(133) | 5) +#define MT6589_GPIO133__FUNC_MD_ABB_AFUNC_D_45 (MTK_PIN_NO(133) | 6) + +#define MT6589_GPIO134__FUNC_GPIO134 (MTK_PIN_NO(134) | 0) +#define MT6589_GPIO134__FUNC_MSDC4_DAT5 (MTK_PIN_NO(134) | 1) +#define MT6589_GPIO134__FUNC_EINT136 (MTK_PIN_NO(134) | 2) +#define MT6589_GPIO134__FUNC_I2SIN_WS (MTK_PIN_NO(134) | 3) +#define MT6589_GPIO134__FUNC_DAC_WS (MTK_PIN_NO(134) | 4) +#define MT6589_GPIO134__FUNC_PCM1_WS (MTK_PIN_NO(134) | 5) +#define MT6589_GPIO134__FUNC_MD_ABB_AFUNC_D_48 (MTK_PIN_NO(134) | 6) +#define MT6589_GPIO134__FUNC_SPI1_CSN (MTK_PIN_NO(134) | 7) + +#define MT6589_GPIO135__FUNC_GPIO135 (MTK_PIN_NO(135) | 0) +#define MT6589_GPIO135__FUNC_MSDC4_DAT6 (MTK_PIN_NO(135) | 1) +#define MT6589_GPIO135__FUNC_EINT137 (MTK_PIN_NO(135) | 2) +#define MT6589_GPIO135__FUNC_I2SOUT_DAT (MTK_PIN_NO(135) | 3) +#define MT6589_GPIO135__FUNC_DAC_DAT_OUT (MTK_PIN_NO(135) | 4) +#define MT6589_GPIO135__FUNC_PCM1_DO (MTK_PIN_NO(135) | 5) +#define MT6589_GPIO135__FUNC_MD_ABB_AFUNC_D_49 (MTK_PIN_NO(135) | 6) +#define MT6589_GPIO135__FUNC_SPI1_MO (MTK_PIN_NO(135) | 7) + +#define MT6589_GPIO136__FUNC_GPIO136 (MTK_PIN_NO(136) | 0) +#define MT6589_GPIO136__FUNC_MSDC4_DAT7 (MTK_PIN_NO(136) | 1) +#define MT6589_GPIO136__FUNC_EINT138 (MTK_PIN_NO(136) | 2) +#define MT6589_GPIO136__FUNC_I2SIN_DAT (MTK_PIN_NO(136) | 3) +#define MT6589_GPIO136__FUNC_PCM1_DI (MTK_PIN_NO(136) | 5) +#define MT6589_GPIO136__FUNC_MD_ABB_AFUNC_D_50 (MTK_PIN_NO(136) | 6) +#define MT6589_GPIO136__FUNC_SPI1_MI (MTK_PIN_NO(136) | 7) + +#define MT6589_GPIO137__FUNC_GPIO137 (MTK_PIN_NO(137) | 0) +#define MT6589_GPIO137__FUNC_MSDC4_DAT4 (MTK_PIN_NO(137) | 1) +#define MT6589_GPIO137__FUNC_EINT135 (MTK_PIN_NO(137) | 2) +#define MT6589_GPIO137__FUNC_I2SIN_CK (MTK_PIN_NO(137) | 3) +#define MT6589_GPIO137__FUNC_DAC_CK (MTK_PIN_NO(137) | 4) +#define MT6589_GPIO137__FUNC_PCM1_CK (MTK_PIN_NO(137) | 5) +#define MT6589_GPIO137__FUNC_MD_ABB_AFUNC_D_51 (MTK_PIN_NO(137) | 6) +#define MT6589_GPIO137__FUNC_SPI1_CLK (MTK_PIN_NO(137) | 7) + +#define MT6589_GPIO138__FUNC_GPIO138 (MTK_PIN_NO(138) | 0) +#define MT6589_GPIO138__FUNC_MSDC4_DAT2 (MTK_PIN_NO(138) | 1) +#define MT6589_GPIO138__FUNC_EINT131 (MTK_PIN_NO(138) | 2) +#define MT6589_GPIO138__FUNC_I2SIN_WS (MTK_PIN_NO(138) | 3) +#define MT6589_GPIO138__FUNC_CM2PDN_2X (MTK_PIN_NO(138) | 4) +#define MT6589_GPIO138__FUNC_DAC_WS (MTK_PIN_NO(138) | 5) +#define MT6589_GPIO138__FUNC_PCM1_WS (MTK_PIN_NO(138) | 6) +#define MT6589_GPIO138__FUNC_LSCE0B_1X (MTK_PIN_NO(138) | 7) + +#define MT6589_GPIO139__FUNC_GPIO139 (MTK_PIN_NO(139) | 0) +#define MT6589_GPIO139__FUNC_MSDC4_CLK (MTK_PIN_NO(139) | 1) +#define MT6589_GPIO139__FUNC_EINT129 (MTK_PIN_NO(139) | 2) +#define MT6589_GPIO139__FUNC_DPI1_CK_2X (MTK_PIN_NO(139) | 3) +#define MT6589_GPIO139__FUNC_CM2PCLK_2X (MTK_PIN_NO(139) | 4) +#define MT6589_GPIO139__FUNC_PWM4 (MTK_PIN_NO(139) | 5) +#define MT6589_GPIO139__FUNC_PCM1_DI (MTK_PIN_NO(139) | 6) +#define MT6589_GPIO139__FUNC_LSCK_1X (MTK_PIN_NO(139) | 7) + +#define MT6589_GPIO140__FUNC_GPIO140 (MTK_PIN_NO(140) | 0) +#define MT6589_GPIO140__FUNC_MSDC4_DAT3 (MTK_PIN_NO(140) | 1) +#define MT6589_GPIO140__FUNC_EINT132 (MTK_PIN_NO(140) | 2) +#define MT6589_GPIO140__FUNC_I2SOUT_DAT (MTK_PIN_NO(140) | 3) +#define MT6589_GPIO140__FUNC_CM2RST_2X (MTK_PIN_NO(140) | 4) +#define MT6589_GPIO140__FUNC_DAC_DAT_OUT (MTK_PIN_NO(140) | 5) +#define MT6589_GPIO140__FUNC_PCM1_DO (MTK_PIN_NO(140) | 6) +#define MT6589_GPIO140__FUNC_LSCE1B_1X (MTK_PIN_NO(140) | 7) + +#define MT6589_GPIO141__FUNC_GPIO141 (MTK_PIN_NO(141) | 0) +#define MT6589_GPIO141__FUNC_MSDC4_CMD (MTK_PIN_NO(141) | 1) +#define MT6589_GPIO141__FUNC_EINT128 (MTK_PIN_NO(141) | 2) +#define MT6589_GPIO141__FUNC_DPI1_DE_2X (MTK_PIN_NO(141) | 3) +#define MT6589_GPIO141__FUNC_MD1_GPS_SYNC (MTK_PIN_NO(141) | 4) +#define MT6589_GPIO141__FUNC_PWM3 (MTK_PIN_NO(141) | 5) +#define MT6589_GPIO141__FUNC_MD2_GPS_SYNC (MTK_PIN_NO(141) | 6) +#define MT6589_GPIO141__FUNC_LSDA_1X (MTK_PIN_NO(141) | 7) + +#define MT6589_GPIO142__FUNC_GPIO142 (MTK_PIN_NO(142) | 0) +#define MT6589_GPIO142__FUNC_MSDC4_RSTB (MTK_PIN_NO(142) | 1) +#define MT6589_GPIO142__FUNC_EINT130 (MTK_PIN_NO(142) | 2) +#define MT6589_GPIO142__FUNC_I2SIN_CK (MTK_PIN_NO(142) | 3) +#define MT6589_GPIO142__FUNC_CM2MCLK_2X (MTK_PIN_NO(142) | 4) +#define MT6589_GPIO142__FUNC_DAC_CK (MTK_PIN_NO(142) | 5) +#define MT6589_GPIO142__FUNC_PCM1_CK (MTK_PIN_NO(142) | 6) +#define MT6589_GPIO142__FUNC_LSA0_1X (MTK_PIN_NO(142) | 7) + +#define MT6589_GPIO143__FUNC_GPIO143 (MTK_PIN_NO(143) | 0) +#define MT6589_GPIO143__FUNC_DPI0_VSYNC (MTK_PIN_NO(143) | 1) +#define MT6589_GPIO143__FUNC_EINT98 (MTK_PIN_NO(143) | 2) +#define MT6589_GPIO143__FUNC_I2SIN_CK (MTK_PIN_NO(143) | 3) +#define MT6589_GPIO143__FUNC_DAC_CK (MTK_PIN_NO(143) | 4) +#define MT6589_GPIO143__FUNC_PCM1_CK (MTK_PIN_NO(143) | 5) +#define MT6589_GPIO143__FUNC_MD_ABB_AFUNC_D_52 (MTK_PIN_NO(143) | 6) +#define MT6589_GPIO143__FUNC_TESTB_OUT8 (MTK_PIN_NO(143) | 7) + +#define MT6589_GPIO144__FUNC_GPIO144 (MTK_PIN_NO(144) | 0) +#define MT6589_GPIO144__FUNC_DPI0_HSYNC (MTK_PIN_NO(144) | 1) +#define MT6589_GPIO144__FUNC_EINT99 (MTK_PIN_NO(144) | 2) +#define MT6589_GPIO144__FUNC_I2SIN_WS (MTK_PIN_NO(144) | 3) +#define MT6589_GPIO144__FUNC_DAC_WS (MTK_PIN_NO(144) | 4) +#define MT6589_GPIO144__FUNC_PCM1_WS (MTK_PIN_NO(144) | 5) +#define MT6589_GPIO144__FUNC_IRDA_RXD (MTK_PIN_NO(144) | 6) +#define MT6589_GPIO144__FUNC_TESTB_OUT9 (MTK_PIN_NO(144) | 7) + +#define MT6589_GPIO145__FUNC_GPIO145 (MTK_PIN_NO(145) | 0) +#define MT6589_GPIO145__FUNC_DPI0_DE (MTK_PIN_NO(145) | 1) +#define MT6589_GPIO145__FUNC_EINT100 (MTK_PIN_NO(145) | 2) +#define MT6589_GPIO145__FUNC_I2SOUT_DAT (MTK_PIN_NO(145) | 3) +#define MT6589_GPIO145__FUNC_DAC_DAT_OUT (MTK_PIN_NO(145) | 4) +#define MT6589_GPIO145__FUNC_PCM1_DO (MTK_PIN_NO(145) | 5) +#define MT6589_GPIO145__FUNC_IRDA_TXD (MTK_PIN_NO(145) | 6) +#define MT6589_GPIO145__FUNC_TESTB_OUT10 (MTK_PIN_NO(145) | 7) + +#define MT6589_GPIO146__FUNC_GPIO146 (MTK_PIN_NO(146) | 0) +#define MT6589_GPIO146__FUNC_DPI0_CK (MTK_PIN_NO(146) | 1) +#define MT6589_GPIO146__FUNC_EINT101 (MTK_PIN_NO(146) | 2) +#define MT6589_GPIO146__FUNC_I2SIN_DAT (MTK_PIN_NO(146) | 3) +#define MT6589_GPIO146__FUNC_PCM1_DI (MTK_PIN_NO(146) | 5) +#define MT6589_GPIO146__FUNC_IRDA_PDN (MTK_PIN_NO(146) | 6) +#define MT6589_GPIO146__FUNC_TESTB_OUT11 (MTK_PIN_NO(146) | 7) + +#define MT6589_GPIO147__FUNC_GPIO147 (MTK_PIN_NO(147) | 0) +#define MT6589_GPIO147__FUNC_DPI0_B0 (MTK_PIN_NO(147) | 1) +#define MT6589_GPIO147__FUNC_EINT102 (MTK_PIN_NO(147) | 2) +#define MT6589_GPIO147__FUNC_SCL0 (MTK_PIN_NO(147) | 4) +#define MT6589_GPIO147__FUNC_DISP_PWM (MTK_PIN_NO(147) | 5) +#define MT6589_GPIO147__FUNC_MD_ABB_AFUNC_D_57 (MTK_PIN_NO(147) | 6) +#define MT6589_GPIO147__FUNC_TESTB_OUT12 (MTK_PIN_NO(147) | 7) + +#define MT6589_GPIO148__FUNC_GPIO148 (MTK_PIN_NO(148) | 0) +#define MT6589_GPIO148__FUNC_DPI0_B1 (MTK_PIN_NO(148) | 1) +#define MT6589_GPIO148__FUNC_EINT103 (MTK_PIN_NO(148) | 2) +#define MT6589_GPIO148__FUNC_CLKM0 (MTK_PIN_NO(148) | 3) +#define MT6589_GPIO148__FUNC_SDA0 (MTK_PIN_NO(148) | 4) +#define MT6589_GPIO148__FUNC_PWM1 (MTK_PIN_NO(148) | 5) +#define MT6589_GPIO148__FUNC_MD_ABB_AFUNC_D_58 (MTK_PIN_NO(148) | 6) +#define MT6589_GPIO148__FUNC_TESTB_OUT13 (MTK_PIN_NO(148) | 7) + +#define MT6589_GPIO149__FUNC_GPIO149 (MTK_PIN_NO(149) | 0) +#define MT6589_GPIO149__FUNC_DPI0_B2 (MTK_PIN_NO(149) | 1) +#define MT6589_GPIO149__FUNC_EINT104 (MTK_PIN_NO(149) | 2) +#define MT6589_GPIO149__FUNC_CLKM1 (MTK_PIN_NO(149) | 3) +#define MT6589_GPIO149__FUNC_SCL1 (MTK_PIN_NO(149) | 4) +#define MT6589_GPIO149__FUNC_PWM2 (MTK_PIN_NO(149) | 5) +#define MT6589_GPIO149__FUNC_MD_ABB_AFUNC_D_59 (MTK_PIN_NO(149) | 6) +#define MT6589_GPIO149__FUNC_TESTB_OUT14 (MTK_PIN_NO(149) | 7) + +#define MT6589_GPIO150__FUNC_GPIO150 (MTK_PIN_NO(150) | 0) +#define MT6589_GPIO150__FUNC_DPI0_B3 (MTK_PIN_NO(150) | 1) +#define MT6589_GPIO150__FUNC_EINT105 (MTK_PIN_NO(150) | 2) +#define MT6589_GPIO150__FUNC_CLKM2 (MTK_PIN_NO(150) | 3) +#define MT6589_GPIO150__FUNC_SDA1 (MTK_PIN_NO(150) | 4) +#define MT6589_GPIO150__FUNC_PWM3 (MTK_PIN_NO(150) | 5) +#define MT6589_GPIO150__FUNC_MD_ABB_AFUNC_D_60 (MTK_PIN_NO(150) | 6) +#define MT6589_GPIO150__FUNC_TESTB_OUT15 (MTK_PIN_NO(150) | 7) + +#define MT6589_GPIO151__FUNC_GPIO151 (MTK_PIN_NO(151) | 0) +#define MT6589_GPIO151__FUNC_DPI0_B4 (MTK_PIN_NO(151) | 1) +#define MT6589_GPIO151__FUNC_EINT106 (MTK_PIN_NO(151) | 2) +#define MT6589_GPIO151__FUNC_CLKM3 (MTK_PIN_NO(151) | 3) +#define MT6589_GPIO151__FUNC_SCL2 (MTK_PIN_NO(151) | 4) +#define MT6589_GPIO151__FUNC_PWM4 (MTK_PIN_NO(151) | 5) +#define MT6589_GPIO151__FUNC_MD_ABB_AFUNC_D_61 (MTK_PIN_NO(151) | 6) +#define MT6589_GPIO151__FUNC_TESTB_OUT16 (MTK_PIN_NO(151) | 7) + +#define MT6589_GPIO152__FUNC_GPIO152 (MTK_PIN_NO(152) | 0) +#define MT6589_GPIO152__FUNC_DPI0_B5 (MTK_PIN_NO(152) | 1) +#define MT6589_GPIO152__FUNC_EINT107 (MTK_PIN_NO(152) | 2) +#define MT6589_GPIO152__FUNC_CLKM4 (MTK_PIN_NO(152) | 3) +#define MT6589_GPIO152__FUNC_SDA2 (MTK_PIN_NO(152) | 4) +#define MT6589_GPIO152__FUNC_PWM5 (MTK_PIN_NO(152) | 5) +#define MT6589_GPIO152__FUNC_MD_ABB_AFUNC_D_62 (MTK_PIN_NO(152) | 6) +#define MT6589_GPIO152__FUNC_TESTB_OUT17 (MTK_PIN_NO(152) | 7) + +#define MT6589_GPIO153__FUNC_GPIO153 (MTK_PIN_NO(153) | 0) +#define MT6589_GPIO153__FUNC_DPI0_B6 (MTK_PIN_NO(153) | 1) +#define MT6589_GPIO153__FUNC_EINT108 (MTK_PIN_NO(153) | 2) +#define MT6589_GPIO153__FUNC_CLKM5 (MTK_PIN_NO(153) | 3) +#define MT6589_GPIO153__FUNC_SCL3 (MTK_PIN_NO(153) | 4) +#define MT6589_GPIO153__FUNC_PWM6 (MTK_PIN_NO(153) | 5) +#define MT6589_GPIO153__FUNC_MD_ABB_AFUNC_D_63 (MTK_PIN_NO(153) | 6) +#define MT6589_GPIO153__FUNC_TESTB_OUT18 (MTK_PIN_NO(153) | 7) + +#define MT6589_GPIO154__FUNC_GPIO154 (MTK_PIN_NO(154) | 0) +#define MT6589_GPIO154__FUNC_DPI0_B7 (MTK_PIN_NO(154) | 1) +#define MT6589_GPIO154__FUNC_EINT109 (MTK_PIN_NO(154) | 2) +#define MT6589_GPIO154__FUNC_CLKM6 (MTK_PIN_NO(154) | 3) +#define MT6589_GPIO154__FUNC_SDA3 (MTK_PIN_NO(154) | 4) +#define MT6589_GPIO154__FUNC_PWM7 (MTK_PIN_NO(154) | 5) +#define MT6589_GPIO154__FUNC_MD1_PLL_A_FUNC_DOUT_0 (MTK_PIN_NO(154) | 6) +#define MT6589_GPIO154__FUNC_TESTB_OUT19 (MTK_PIN_NO(154) | 7) + +#define MT6589_GPIO155__FUNC_GPIO155 (MTK_PIN_NO(155) | 0) +#define MT6589_GPIO155__FUNC_DPI0_G0 (MTK_PIN_NO(155) | 1) +#define MT6589_GPIO155__FUNC_EINT110 (MTK_PIN_NO(155) | 2) +#define MT6589_GPIO155__FUNC_DSP1_ID (MTK_PIN_NO(155) | 5) +#define MT6589_GPIO155__FUNC_MD1_PLL_A_FUNC_DOUT_1 (MTK_PIN_NO(155) | 6) +#define MT6589_GPIO155__FUNC_TESTB_OUT20 (MTK_PIN_NO(155) | 7) + +#define MT6589_GPIO156__FUNC_GPIO156 (MTK_PIN_NO(156) | 0) +#define MT6589_GPIO156__FUNC_DPI0_G1 (MTK_PIN_NO(156) | 1) +#define MT6589_GPIO156__FUNC_EINT111 (MTK_PIN_NO(156) | 2) +#define MT6589_GPIO156__FUNC_DSP1_ICK (MTK_PIN_NO(156) | 5) +#define MT6589_GPIO156__FUNC_MD_ABB_AFUNC_D_56 (MTK_PIN_NO(156) | 6) +#define MT6589_GPIO156__FUNC_TESTB_OUT21 (MTK_PIN_NO(156) | 7) + +#define MT6589_GPIO157__FUNC_GPIO157 (MTK_PIN_NO(157) | 0) +#define MT6589_GPIO157__FUNC_DPI0_G2 (MTK_PIN_NO(157) | 1) +#define MT6589_GPIO157__FUNC_EINT112 (MTK_PIN_NO(157) | 2) +#define MT6589_GPIO157__FUNC_DSP1_IMS (MTK_PIN_NO(157) | 5) +#define MT6589_GPIO157__FUNC_MD1_PLL_A_FUNC_DOUT_2 (MTK_PIN_NO(157) | 6) +#define MT6589_GPIO157__FUNC_TESTB_OUT22 (MTK_PIN_NO(157) | 7) + +#define MT6589_GPIO158__FUNC_GPIO158 (MTK_PIN_NO(158) | 0) +#define MT6589_GPIO158__FUNC_DPI0_G3 (MTK_PIN_NO(158) | 1) +#define MT6589_GPIO158__FUNC_EINT113 (MTK_PIN_NO(158) | 2) +#define MT6589_GPIO158__FUNC_DSP2_IMS (MTK_PIN_NO(158) | 5) +#define MT6589_GPIO158__FUNC_MD1_PLL_A_FUNC_DOUT_3 (MTK_PIN_NO(158) | 6) +#define MT6589_GPIO158__FUNC_TESTB_OUT23 (MTK_PIN_NO(158) | 7) + +#define MT6589_GPIO159__FUNC_GPIO159 (MTK_PIN_NO(159) | 0) +#define MT6589_GPIO159__FUNC_DPI0_G4 (MTK_PIN_NO(159) | 1) +#define MT6589_GPIO159__FUNC_EINT114 (MTK_PIN_NO(159) | 2) +#define MT6589_GPIO159__FUNC_DPI1_D_2X_0 (MTK_PIN_NO(159) | 3) +#define MT6589_GPIO159__FUNC_CM2DAT_2X_0 (MTK_PIN_NO(159) | 4) +#define MT6589_GPIO159__FUNC_DSP2_ID (MTK_PIN_NO(159) | 5) +#define MT6589_GPIO159__FUNC_MD_ABB_AFUNC_D_53 (MTK_PIN_NO(159) | 6) +#define MT6589_GPIO159__FUNC_TESTB_OUT24 (MTK_PIN_NO(159) | 7) + +#define MT6589_GPIO160__FUNC_GPIO160 (MTK_PIN_NO(160) | 0) +#define MT6589_GPIO160__FUNC_DPI0_G5 (MTK_PIN_NO(160) | 1) +#define MT6589_GPIO160__FUNC_EINT115 (MTK_PIN_NO(160) | 2) +#define MT6589_GPIO160__FUNC_DPI1_D_2X_1 (MTK_PIN_NO(160) | 3) +#define MT6589_GPIO160__FUNC_CM2DAT_2X_1 (MTK_PIN_NO(160) | 4) +#define MT6589_GPIO160__FUNC_DSP2_ICK (MTK_PIN_NO(160) | 5) +#define MT6589_GPIO160__FUNC_MD_ABB_AFUNC_D_54 (MTK_PIN_NO(160) | 6) +#define MT6589_GPIO160__FUNC_TESTB_OUT25 (MTK_PIN_NO(160) | 7) + +#define MT6589_GPIO161__FUNC_GPIO161 (MTK_PIN_NO(161) | 0) +#define MT6589_GPIO161__FUNC_DPI0_G6 (MTK_PIN_NO(161) | 1) +#define MT6589_GPIO161__FUNC_EINT116 (MTK_PIN_NO(161) | 2) +#define MT6589_GPIO161__FUNC_DPI1_D_2X_2 (MTK_PIN_NO(161) | 3) +#define MT6589_GPIO161__FUNC_CM2DAT_2X_2 (MTK_PIN_NO(161) | 4) +#define MT6589_GPIO161__FUNC_MD2_RTCK_PAD (MTK_PIN_NO(161) | 5) +#define MT6589_GPIO161__FUNC_MD1_PLL_A_FUNC_DOUT_4 (MTK_PIN_NO(161) | 6) +#define MT6589_GPIO161__FUNC_TESTB_OUT26 (MTK_PIN_NO(161) | 7) + +#define MT6589_GPIO162__FUNC_GPIO162 (MTK_PIN_NO(162) | 0) +#define MT6589_GPIO162__FUNC_DPI0_G7 (MTK_PIN_NO(162) | 1) +#define MT6589_GPIO162__FUNC_EINT117 (MTK_PIN_NO(162) | 2) +#define MT6589_GPIO162__FUNC_DPI1_D_2X_3 (MTK_PIN_NO(162) | 3) +#define MT6589_GPIO162__FUNC_CM2DAT_2X_3 (MTK_PIN_NO(162) | 4) +#define MT6589_GPIO162__FUNC_MD2_TCK_PAD (MTK_PIN_NO(162) | 5) +#define MT6589_GPIO162__FUNC_MD1_PLL_A_FUNC_DOUT_5 (MTK_PIN_NO(162) | 6) +#define MT6589_GPIO162__FUNC_TESTB_OUT27 (MTK_PIN_NO(162) | 7) + +#define MT6589_GPIO163__FUNC_GPIO163 (MTK_PIN_NO(163) | 0) +#define MT6589_GPIO163__FUNC_DPI0_R0 (MTK_PIN_NO(163) | 1) +#define MT6589_GPIO163__FUNC_EINT118 (MTK_PIN_NO(163) | 2) +#define MT6589_GPIO163__FUNC_DPI1_D_2X_4 (MTK_PIN_NO(163) | 3) +#define MT6589_GPIO163__FUNC_CM2DAT_2X_4 (MTK_PIN_NO(163) | 4) +#define MT6589_GPIO163__FUNC_MD2_TDI_PAD (MTK_PIN_NO(163) | 5) +#define MT6589_GPIO163__FUNC_MD1_PLL_A_FUNC_DOUT_6 (MTK_PIN_NO(163) | 6) +#define MT6589_GPIO163__FUNC_TESTB_OUT28 (MTK_PIN_NO(163) | 7) + +#define MT6589_GPIO164__FUNC_GPIO164 (MTK_PIN_NO(164) | 0) +#define MT6589_GPIO164__FUNC_DPI0_R1 (MTK_PIN_NO(164) | 1) +#define MT6589_GPIO164__FUNC_EINT119 (MTK_PIN_NO(164) | 2) +#define MT6589_GPIO164__FUNC_DPI1_D_2X_5 (MTK_PIN_NO(164) | 3) +#define MT6589_GPIO164__FUNC_CM2DAT_2X_5 (MTK_PIN_NO(164) | 4) +#define MT6589_GPIO164__FUNC_MD2_TDO_PAD (MTK_PIN_NO(164) | 5) +#define MT6589_GPIO164__FUNC_MD1_PLL_A_FUNC_DOUT_7 (MTK_PIN_NO(164) | 6) +#define MT6589_GPIO164__FUNC_TESTB_OUT29 (MTK_PIN_NO(164) | 7) + +#define MT6589_GPIO165__FUNC_GPIO165 (MTK_PIN_NO(165) | 0) +#define MT6589_GPIO165__FUNC_DPI0_R2 (MTK_PIN_NO(165) | 1) +#define MT6589_GPIO165__FUNC_EINT120 (MTK_PIN_NO(165) | 2) +#define MT6589_GPIO165__FUNC_DPI1_D_2X_6 (MTK_PIN_NO(165) | 3) +#define MT6589_GPIO165__FUNC_CM2DAT_2X_6 (MTK_PIN_NO(165) | 4) +#define MT6589_GPIO165__FUNC_MD2_TMS_PAD (MTK_PIN_NO(165) | 5) +#define MT6589_GPIO165__FUNC_TESTB_OUT30 (MTK_PIN_NO(165) | 7) + +#define MT6589_GPIO166__FUNC_GPIO166 (MTK_PIN_NO(166) | 0) +#define MT6589_GPIO166__FUNC_DPI0_R3 (MTK_PIN_NO(166) | 1) +#define MT6589_GPIO166__FUNC_EINT121 (MTK_PIN_NO(166) | 2) +#define MT6589_GPIO166__FUNC_DPI1_D_2X_7 (MTK_PIN_NO(166) | 3) +#define MT6589_GPIO166__FUNC_CM2DAT_2X_7 (MTK_PIN_NO(166) | 4) +#define MT6589_GPIO166__FUNC_MD2_NTRST_PAD (MTK_PIN_NO(166) | 5) +#define MT6589_GPIO166__FUNC_MD_ABB_AFUNC_D_55 (MTK_PIN_NO(166) | 6) +#define MT6589_GPIO166__FUNC_TESTB_OUT31 (MTK_PIN_NO(166) | 7) + +#define MT6589_GPIO167__FUNC_GPIO167 (MTK_PIN_NO(167) | 0) +#define MT6589_GPIO167__FUNC_DPI0_R4 (MTK_PIN_NO(167) | 1) +#define MT6589_GPIO167__FUNC_EINT122 (MTK_PIN_NO(167) | 2) +#define MT6589_GPIO167__FUNC_DPI1_D_2X_8 (MTK_PIN_NO(167) | 3) +#define MT6589_GPIO167__FUNC_CM2DAT_2X_8 (MTK_PIN_NO(167) | 4) +#define MT6589_GPIO167__FUNC_TESTA_OUT0 (MTK_PIN_NO(167) | 7) + +#define MT6589_GPIO168__FUNC_GPIO168 (MTK_PIN_NO(168) | 0) +#define MT6589_GPIO168__FUNC_DPI0_R5 (MTK_PIN_NO(168) | 1) +#define MT6589_GPIO168__FUNC_EINT123 (MTK_PIN_NO(168) | 2) +#define MT6589_GPIO168__FUNC_DPI1_D_2X_9 (MTK_PIN_NO(168) | 3) +#define MT6589_GPIO168__FUNC_CM2DAT_2X_9 (MTK_PIN_NO(168) | 4) +#define MT6589_GPIO168__FUNC_MD1_DAI_RX_GPIO (MTK_PIN_NO(168) | 5) +#define MT6589_GPIO168__FUNC_MD2_DAI_RX_GPIO (MTK_PIN_NO(168) | 6) +#define MT6589_GPIO168__FUNC_TESTA_OUT1 (MTK_PIN_NO(168) | 7) + +#define MT6589_GPIO169__FUNC_GPIO169 (MTK_PIN_NO(169) | 0) +#define MT6589_GPIO169__FUNC_DPI0_R6 (MTK_PIN_NO(169) | 1) +#define MT6589_GPIO169__FUNC_EINT124 (MTK_PIN_NO(169) | 2) +#define MT6589_GPIO169__FUNC_DPI1_D_2X_10 (MTK_PIN_NO(169) | 3) +#define MT6589_GPIO169__FUNC_CM2VSYNC_2X (MTK_PIN_NO(169) | 4) +#define MT6589_GPIO169__FUNC_TESTA_OUT2 (MTK_PIN_NO(169) | 7) + +#define MT6589_GPIO170__FUNC_GPIO170 (MTK_PIN_NO(170) | 0) +#define MT6589_GPIO170__FUNC_DPI0_R7 (MTK_PIN_NO(170) | 1) +#define MT6589_GPIO170__FUNC_EINT125 (MTK_PIN_NO(170) | 2) +#define MT6589_GPIO170__FUNC_DPI1_D_2X_11 (MTK_PIN_NO(170) | 3) +#define MT6589_GPIO170__FUNC_CM2HSYNC_2X (MTK_PIN_NO(170) | 4) +#define MT6589_GPIO170__FUNC_TESTA_OUT3 (MTK_PIN_NO(170) | 7) + +#define MT6589_GPIO171__FUNC_GPIO171 (MTK_PIN_NO(171) | 0) +#define MT6589_GPIO171__FUNC_MSDC1_INSI (MTK_PIN_NO(171) | 1) +#define MT6589_GPIO171__FUNC_EINT57 (MTK_PIN_NO(171) | 2) +#define MT6589_GPIO171__FUNC_SCL5 (MTK_PIN_NO(171) | 3) +#define MT6589_GPIO171__FUNC_PWM6 (MTK_PIN_NO(171) | 4) +#define MT6589_GPIO171__FUNC_CLKM5 (MTK_PIN_NO(171) | 5) +#define MT6589_GPIO171__FUNC_MD2_PLL_A_FUNC_DOUT_0 (MTK_PIN_NO(171) | 6) +#define MT6589_GPIO171__FUNC_TESTB_OUT6 (MTK_PIN_NO(171) | 7) + +#define MT6589_GPIO172__FUNC_GPIO172 (MTK_PIN_NO(172) | 0) +#define MT6589_GPIO172__FUNC_MSDC2_INSI (MTK_PIN_NO(172) | 1) +#define MT6589_GPIO172__FUNC_EINT65 (MTK_PIN_NO(172) | 2) +#define MT6589_GPIO172__FUNC_BPI2_BUS6 (MTK_PIN_NO(172) | 3) +#define MT6589_GPIO172__FUNC_A_FUNC_DIN_6 (MTK_PIN_NO(172) | 7) + +#define MT6589_GPIO173__FUNC_GPIO173 (MTK_PIN_NO(173) | 0) +#define MT6589_GPIO173__FUNC_MSDC2_SDWPI (MTK_PIN_NO(173) | 1) +#define MT6589_GPIO173__FUNC_EINT66 (MTK_PIN_NO(173) | 2) +#define MT6589_GPIO173__FUNC_BPI2_BUS17 (MTK_PIN_NO(173) | 3) +#define MT6589_GPIO173__FUNC_DUAL_BPI1_BUS14 (MTK_PIN_NO(173) | 4) +#define MT6589_GPIO173__FUNC_DUAL_BPI1_BUS15 (MTK_PIN_NO(173) | 5) +#define MT6589_GPIO173__FUNC_A_FUNC_DIN_5 (MTK_PIN_NO(173) | 7) + +#define MT6589_GPIO174__FUNC_GPIO174 (MTK_PIN_NO(174) | 0) +#define MT6589_GPIO174__FUNC_MSDC2_DAT2 (MTK_PIN_NO(174) | 1) +#define MT6589_GPIO174__FUNC_EINT63 (MTK_PIN_NO(174) | 2) +#define MT6589_GPIO174__FUNC_BPI2_BUS4 (MTK_PIN_NO(174) | 3) +#define MT6589_GPIO174__FUNC_DSP2_IMS (MTK_PIN_NO(174) | 4) +#define MT6589_GPIO174__FUNC_A_FUNC_DIN_8 (MTK_PIN_NO(174) | 7) + +#define MT6589_GPIO175__FUNC_GPIO175 (MTK_PIN_NO(175) | 0) +#define MT6589_GPIO175__FUNC_MSDC2_DAT3 (MTK_PIN_NO(175) | 1) +#define MT6589_GPIO175__FUNC_EINT64 (MTK_PIN_NO(175) | 2) +#define MT6589_GPIO175__FUNC_BPI2_BUS5 (MTK_PIN_NO(175) | 3) +#define MT6589_GPIO175__FUNC_DSP2_ID (MTK_PIN_NO(175) | 4) +#define MT6589_GPIO175__FUNC_A_FUNC_DIN_7 (MTK_PIN_NO(175) | 7) + +#define MT6589_GPIO176__FUNC_GPIO176 (MTK_PIN_NO(176) | 0) +#define MT6589_GPIO176__FUNC_MSDC2_CMD (MTK_PIN_NO(176) | 1) +#define MT6589_GPIO176__FUNC_EINT60 (MTK_PIN_NO(176) | 2) +#define MT6589_GPIO176__FUNC_BPI2_BUS1 (MTK_PIN_NO(176) | 3) +#define MT6589_GPIO176__FUNC_DSP1_IMS (MTK_PIN_NO(176) | 4) +#define MT6589_GPIO176__FUNC_PCM1_WS (MTK_PIN_NO(176) | 5) +#define MT6589_GPIO176__FUNC_A_FUNC_DIN_11 (MTK_PIN_NO(176) | 7) + +#define MT6589_GPIO177__FUNC_GPIO177 (MTK_PIN_NO(177) | 0) +#define MT6589_GPIO177__FUNC_MSDC2_CLK (MTK_PIN_NO(177) | 1) +#define MT6589_GPIO177__FUNC_EINT59 (MTK_PIN_NO(177) | 2) +#define MT6589_GPIO177__FUNC_BPI2_BUS0 (MTK_PIN_NO(177) | 3) +#define MT6589_GPIO177__FUNC_DSP1_ICK (MTK_PIN_NO(177) | 4) +#define MT6589_GPIO177__FUNC_PCM1_CK (MTK_PIN_NO(177) | 5) +#define MT6589_GPIO177__FUNC_A_FUNC_DIN_12 (MTK_PIN_NO(177) | 7) + +#define MT6589_GPIO178__FUNC_GPIO178 (MTK_PIN_NO(178) | 0) +#define MT6589_GPIO178__FUNC_MSDC2_DAT1 (MTK_PIN_NO(178) | 1) +#define MT6589_GPIO178__FUNC_EINT62 (MTK_PIN_NO(178) | 2) +#define MT6589_GPIO178__FUNC_BPI2_BUS3 (MTK_PIN_NO(178) | 3) +#define MT6589_GPIO178__FUNC_DSP2_ICK (MTK_PIN_NO(178) | 4) +#define MT6589_GPIO178__FUNC_PCM1_DO (MTK_PIN_NO(178) | 5) +#define MT6589_GPIO178__FUNC_A_FUNC_DIN_9 (MTK_PIN_NO(178) | 7) + +#define MT6589_GPIO179__FUNC_GPIO179 (MTK_PIN_NO(179) | 0) +#define MT6589_GPIO179__FUNC_MSDC2_DAT0 (MTK_PIN_NO(179) | 1) +#define MT6589_GPIO179__FUNC_EINT61 (MTK_PIN_NO(179) | 2) +#define MT6589_GPIO179__FUNC_BPI2_BUS2 (MTK_PIN_NO(179) | 3) +#define MT6589_GPIO179__FUNC_DSP1_ID (MTK_PIN_NO(179) | 4) +#define MT6589_GPIO179__FUNC_PCM1_DI (MTK_PIN_NO(179) | 5) +#define MT6589_GPIO179__FUNC_A_FUNC_DIN_10 (MTK_PIN_NO(179) | 7) + +#define MT6589_GPIO180__FUNC_GPIO180 (MTK_PIN_NO(180) | 0) +#define MT6589_GPIO180__FUNC_MSDC1_DAT0 (MTK_PIN_NO(180) | 1) +#define MT6589_GPIO180__FUNC_EINT53 (MTK_PIN_NO(180) | 2) +#define MT6589_GPIO180__FUNC_SCL1 (MTK_PIN_NO(180) | 3) +#define MT6589_GPIO180__FUNC_PWM2 (MTK_PIN_NO(180) | 4) +#define MT6589_GPIO180__FUNC_CLKM1 (MTK_PIN_NO(180) | 5) +#define MT6589_GPIO180__FUNC_MD2_PLL_A_FUNC_DOUT_1 (MTK_PIN_NO(180) | 6) +#define MT6589_GPIO180__FUNC_TESTB_OUT2 (MTK_PIN_NO(180) | 7) + +#define MT6589_GPIO181__FUNC_GPIO181 (MTK_PIN_NO(181) | 0) +#define MT6589_GPIO181__FUNC_MSDC1_DAT1 (MTK_PIN_NO(181) | 1) +#define MT6589_GPIO181__FUNC_EINT54 (MTK_PIN_NO(181) | 2) +#define MT6589_GPIO181__FUNC_SDA1 (MTK_PIN_NO(181) | 3) +#define MT6589_GPIO181__FUNC_PWM3 (MTK_PIN_NO(181) | 4) +#define MT6589_GPIO181__FUNC_CLKM2 (MTK_PIN_NO(181) | 5) +#define MT6589_GPIO181__FUNC_MD2_PLL_A_FUNC_DOUT_2 (MTK_PIN_NO(181) | 6) +#define MT6589_GPIO181__FUNC_TESTB_OUT3 (MTK_PIN_NO(181) | 7) + +#define MT6589_GPIO182__FUNC_GPIO182 (MTK_PIN_NO(182) | 0) +#define MT6589_GPIO182__FUNC_MSDC1_SDWPI (MTK_PIN_NO(182) | 1) +#define MT6589_GPIO182__FUNC_EINT58 (MTK_PIN_NO(182) | 2) +#define MT6589_GPIO182__FUNC_SDA5 (MTK_PIN_NO(182) | 3) +#define MT6589_GPIO182__FUNC_PWM7 (MTK_PIN_NO(182) | 4) +#define MT6589_GPIO182__FUNC_CLKM6 (MTK_PIN_NO(182) | 5) +#define MT6589_GPIO182__FUNC_MD2_PLL_A_FUNC_DOUT_3 (MTK_PIN_NO(182) | 6) +#define MT6589_GPIO182__FUNC_TESTB_OUT7 (MTK_PIN_NO(182) | 7) + +#define MT6589_GPIO183__FUNC_GPIO183 (MTK_PIN_NO(183) | 0) +#define MT6589_GPIO183__FUNC_MSDC1_CMD (MTK_PIN_NO(183) | 1) +#define MT6589_GPIO183__FUNC_EINT52 (MTK_PIN_NO(183) | 2) +#define MT6589_GPIO183__FUNC_SDA0 (MTK_PIN_NO(183) | 3) +#define MT6589_GPIO183__FUNC_PWM1 (MTK_PIN_NO(183) | 4) +#define MT6589_GPIO183__FUNC_CLKM0 (MTK_PIN_NO(183) | 5) +#define MT6589_GPIO183__FUNC_MD2_PLL_A_FUNC_DOUT_4 (MTK_PIN_NO(183) | 6) +#define MT6589_GPIO183__FUNC_TESTB_OUT1 (MTK_PIN_NO(183) | 7) + +#define MT6589_GPIO184__FUNC_GPIO184 (MTK_PIN_NO(184) | 0) +#define MT6589_GPIO184__FUNC_MSDC1_CLK (MTK_PIN_NO(184) | 1) +#define MT6589_GPIO184__FUNC_EINT51 (MTK_PIN_NO(184) | 2) +#define MT6589_GPIO184__FUNC_SCL0 (MTK_PIN_NO(184) | 3) +#define MT6589_GPIO184__FUNC_DISP_PWM (MTK_PIN_NO(184) | 4) +#define MT6589_GPIO184__FUNC_MD2_PLL_A_FUNC_DOUT_5 (MTK_PIN_NO(184) | 6) +#define MT6589_GPIO184__FUNC_TESTB_OUT0 (MTK_PIN_NO(184) | 7) + +#define MT6589_GPIO185__FUNC_GPIO185 (MTK_PIN_NO(185) | 0) +#define MT6589_GPIO185__FUNC_MSDC1_DAT2 (MTK_PIN_NO(185) | 1) +#define MT6589_GPIO185__FUNC_EINT55 (MTK_PIN_NO(185) | 2) +#define MT6589_GPIO185__FUNC_SCL4 (MTK_PIN_NO(185) | 3) +#define MT6589_GPIO185__FUNC_PWM4 (MTK_PIN_NO(185) | 4) +#define MT6589_GPIO185__FUNC_CLKM3 (MTK_PIN_NO(185) | 5) +#define MT6589_GPIO185__FUNC_MD2_PLL_A_FUNC_DOUT_6 (MTK_PIN_NO(185) | 6) +#define MT6589_GPIO185__FUNC_TESTB_OUT4 (MTK_PIN_NO(185) | 7) + +#define MT6589_GPIO186__FUNC_GPIO186 (MTK_PIN_NO(186) | 0) +#define MT6589_GPIO186__FUNC_MSDC1_DAT3 (MTK_PIN_NO(186) | 1) +#define MT6589_GPIO186__FUNC_EINT56 (MTK_PIN_NO(186) | 2) +#define MT6589_GPIO186__FUNC_SDA4 (MTK_PIN_NO(186) | 3) +#define MT6589_GPIO186__FUNC_PWM5 (MTK_PIN_NO(186) | 4) +#define MT6589_GPIO186__FUNC_CLKM4 (MTK_PIN_NO(186) | 5) +#define MT6589_GPIO186__FUNC_MD2_PLL_A_FUNC_DOUT_7 (MTK_PIN_NO(186) | 6) +#define MT6589_GPIO186__FUNC_TESTB_OUT5 (MTK_PIN_NO(186) | 7) + +#define MT6589_GPIO187__FUNC_GPIO187 (MTK_PIN_NO(187) | 0) +#define MT6589_GPIO187__FUNC_EINT36 (MTK_PIN_NO(187) | 2) + +#define MT6589_GPIO188__FUNC_GPIO188 (MTK_PIN_NO(188) | 0) +#define MT6589_GPIO188__FUNC_EINT35 (MTK_PIN_NO(188) | 2) + +#define MT6589_GPIO189__FUNC_GPIO189 (MTK_PIN_NO(189) | 0) +#define MT6589_GPIO189__FUNC_EINT169 (MTK_PIN_NO(189) | 2) + +#define MT6589_GPIO190__FUNC_GPIO190 (MTK_PIN_NO(190) | 0) +#define MT6589_GPIO190__FUNC_EINT168 (MTK_PIN_NO(190) | 2) + +#define MT6589_GPIO191__FUNC_GPIO191 (MTK_PIN_NO(191) | 0) +#define MT6589_GPIO191__FUNC_EINT163 (MTK_PIN_NO(191) | 2) + +#define MT6589_GPIO192__FUNC_GPIO192 (MTK_PIN_NO(192) | 0) +#define MT6589_GPIO192__FUNC_EINT162 (MTK_PIN_NO(192) | 2) + +#define MT6589_GPIO193__FUNC_GPIO193 (MTK_PIN_NO(193) | 0) +#define MT6589_GPIO193__FUNC_EINT167 (MTK_PIN_NO(193) | 2) + +#define MT6589_GPIO194__FUNC_GPIO194 (MTK_PIN_NO(194) | 0) +#define MT6589_GPIO194__FUNC_EINT166 (MTK_PIN_NO(194) | 2) + +#define MT6589_GPIO195__FUNC_GPIO195 (MTK_PIN_NO(195) | 0) +#define MT6589_GPIO195__FUNC_EINT165 (MTK_PIN_NO(195) | 2) + +#define MT6589_GPIO196__FUNC_GPIO196 (MTK_PIN_NO(196) | 0) +#define MT6589_GPIO196__FUNC_EINT164 (MTK_PIN_NO(196) | 2) + +#define MT6589_GPIO197__FUNC_GPIO197 (MTK_PIN_NO(197) | 0) +#define MT6589_GPIO197__FUNC_CMDAT6 (MTK_PIN_NO(197) | 1) +#define MT6589_GPIO197__FUNC_EINT175 (MTK_PIN_NO(197) | 2) + +#define MT6589_GPIO198__FUNC_GPIO198 (MTK_PIN_NO(198) | 0) +#define MT6589_GPIO198__FUNC_CMDAT7 (MTK_PIN_NO(198) | 1) +#define MT6589_GPIO198__FUNC_EINT174 (MTK_PIN_NO(198) | 2) + +#define MT6589_GPIO199__FUNC_GPIO199 (MTK_PIN_NO(199) | 0) +#define MT6589_GPIO199__FUNC_CMDAT8 (MTK_PIN_NO(199) | 1) +#define MT6589_GPIO199__FUNC_EINT171 (MTK_PIN_NO(199) | 2) + +#define MT6589_GPIO200__FUNC_GPIO200 (MTK_PIN_NO(200) | 0) +#define MT6589_GPIO200__FUNC_CMDAT9 (MTK_PIN_NO(200) | 1) +#define MT6589_GPIO200__FUNC_EINT170 (MTK_PIN_NO(200) | 2) + +#define MT6589_GPIO201__FUNC_GPIO201 (MTK_PIN_NO(201) | 0) +#define MT6589_GPIO201__FUNC_CMHSYNC (MTK_PIN_NO(201) | 1) +#define MT6589_GPIO201__FUNC_EINT173 (MTK_PIN_NO(201) | 2) + +#define MT6589_GPIO202__FUNC_GPIO202 (MTK_PIN_NO(202) | 0) +#define MT6589_GPIO202__FUNC_CMVSYNC (MTK_PIN_NO(202) | 1) +#define MT6589_GPIO202__FUNC_EINT172 (MTK_PIN_NO(202) | 2) + +#define MT6589_GPIO203__FUNC_GPIO203 (MTK_PIN_NO(203) | 0) +#define MT6589_GPIO203__FUNC_CMDAT2 (MTK_PIN_NO(203) | 1) +#define MT6589_GPIO203__FUNC_EINT181 (MTK_PIN_NO(203) | 2) +#define MT6589_GPIO203__FUNC_CMCSD2 (MTK_PIN_NO(203) | 3) + +#define MT6589_GPIO204__FUNC_GPIO204 (MTK_PIN_NO(204) | 0) +#define MT6589_GPIO204__FUNC_CMDAT3 (MTK_PIN_NO(204) | 1) +#define MT6589_GPIO204__FUNC_EINT180 (MTK_PIN_NO(204) | 2) +#define MT6589_GPIO204__FUNC_CMCSD3 (MTK_PIN_NO(204) | 3) + +#define MT6589_GPIO205__FUNC_GPIO205 (MTK_PIN_NO(205) | 0) +#define MT6589_GPIO205__FUNC_CMDAT4 (MTK_PIN_NO(205) | 1) +#define MT6589_GPIO205__FUNC_EINT177 (MTK_PIN_NO(205) | 2) + +#define MT6589_GPIO206__FUNC_GPIO206 (MTK_PIN_NO(206) | 0) +#define MT6589_GPIO206__FUNC_CMDAT5 (MTK_PIN_NO(206) | 1) +#define MT6589_GPIO206__FUNC_EINT176 (MTK_PIN_NO(206) | 2) + +#define MT6589_GPIO207__FUNC_GPIO207 (MTK_PIN_NO(207) | 0) +#define MT6589_GPIO207__FUNC_CMDAT0 (MTK_PIN_NO(207) | 1) +#define MT6589_GPIO207__FUNC_EINT179 (MTK_PIN_NO(207) | 2) +#define MT6589_GPIO207__FUNC_CMCSD0 (MTK_PIN_NO(207) | 3) + +#define MT6589_GPIO208__FUNC_GPIO208 (MTK_PIN_NO(208) | 0) +#define MT6589_GPIO208__FUNC_CMDAT1 (MTK_PIN_NO(208) | 1) +#define MT6589_GPIO208__FUNC_EINT178 (MTK_PIN_NO(208) | 2) +#define MT6589_GPIO208__FUNC_CMCSD1 (MTK_PIN_NO(208) | 3) + +#define MT6589_GPIO209__FUNC_GPIO209 (MTK_PIN_NO(209) | 0) +#define MT6589_GPIO209__FUNC_CMPCLK (MTK_PIN_NO(209) | 1) +#define MT6589_GPIO209__FUNC_EINT182 (MTK_PIN_NO(209) | 2) +#define MT6589_GPIO209__FUNC_CMCSK (MTK_PIN_NO(209) | 3) +#define MT6589_GPIO209__FUNC_CM2MCLK_4X (MTK_PIN_NO(209) | 4) +#define MT6589_GPIO209__FUNC_TS_AUXADC_SEL_3 (MTK_PIN_NO(209) | 5) +#define MT6589_GPIO209__FUNC_TESTA_OUT27 (MTK_PIN_NO(209) | 7) + +#define MT6589_GPIO210__FUNC_GPIO210 (MTK_PIN_NO(210) | 0) +#define MT6589_GPIO210__FUNC_CMMCLK (MTK_PIN_NO(210) | 1) +#define MT6589_GPIO210__FUNC_EINT183 (MTK_PIN_NO(210) | 2) +#define MT6589_GPIO210__FUNC_TS_AUXADC_SEL_2 (MTK_PIN_NO(210) | 5) +#define MT6589_GPIO210__FUNC_TESTA_OUT28 (MTK_PIN_NO(210) | 7) + +#define MT6589_GPIO211__FUNC_GPIO211 (MTK_PIN_NO(211) | 0) +#define MT6589_GPIO211__FUNC_CMRST (MTK_PIN_NO(211) | 1) +#define MT6589_GPIO211__FUNC_EINT185 (MTK_PIN_NO(211) | 2) +#define MT6589_GPIO211__FUNC_TS_AUXADC_SEL_1 (MTK_PIN_NO(211) | 5) +#define MT6589_GPIO211__FUNC_TESTA_OUT30 (MTK_PIN_NO(211) | 7) + +#define MT6589_GPIO212__FUNC_GPIO212 (MTK_PIN_NO(212) | 0) +#define MT6589_GPIO212__FUNC_CMPDN (MTK_PIN_NO(212) | 1) +#define MT6589_GPIO212__FUNC_EINT184 (MTK_PIN_NO(212) | 2) +#define MT6589_GPIO212__FUNC_TS_AUXADC_SEL_0 (MTK_PIN_NO(212) | 5) +#define MT6589_GPIO212__FUNC_TESTA_OUT29 (MTK_PIN_NO(212) | 7) + +#define MT6589_GPIO213__FUNC_GPIO213 (MTK_PIN_NO(213) | 0) +#define MT6589_GPIO213__FUNC_CMFLASH (MTK_PIN_NO(213) | 1) +#define MT6589_GPIO213__FUNC_EINT186 (MTK_PIN_NO(213) | 2) +#define MT6589_GPIO213__FUNC_CM2MCLK_3X (MTK_PIN_NO(213) | 3) +#define MT6589_GPIO213__FUNC_TESTA_OUT31 (MTK_PIN_NO(213) | 7) + +#define MT6589_GPIO214__FUNC_GPIO214 (MTK_PIN_NO(214) | 0) +#define MT6589_GPIO214__FUNC_SDA1 (MTK_PIN_NO(214) | 1) +#define MT6589_GPIO214__FUNC_EINT93 (MTK_PIN_NO(214) | 2) +#define MT6589_GPIO214__FUNC_CLKM3 (MTK_PIN_NO(214) | 3) +#define MT6589_GPIO214__FUNC_PWM3 (MTK_PIN_NO(214) | 4) +#define MT6589_GPIO214__FUNC_TS_AUX_SCLK_PWDB (MTK_PIN_NO(214) | 5) +#define MT6589_GPIO214__FUNC_A_FUNC_DIN_17 (MTK_PIN_NO(214) | 7) + +#define MT6589_GPIO215__FUNC_GPIO215 (MTK_PIN_NO(215) | 0) +#define MT6589_GPIO215__FUNC_SCL1 (MTK_PIN_NO(215) | 1) +#define MT6589_GPIO215__FUNC_EINT92 (MTK_PIN_NO(215) | 2) +#define MT6589_GPIO215__FUNC_CLKM2 (MTK_PIN_NO(215) | 3) +#define MT6589_GPIO215__FUNC_PWM2 (MTK_PIN_NO(215) | 4) +#define MT6589_GPIO215__FUNC_TS_AUX_DIN (MTK_PIN_NO(215) | 5) +#define MT6589_GPIO215__FUNC_A_FUNC_DIN_18 (MTK_PIN_NO(215) | 7) + +#define MT6589_GPIO216__FUNC_GPIO216 (MTK_PIN_NO(216) | 0) +#define MT6589_GPIO216__FUNC_SDA2 (MTK_PIN_NO(216) | 1) +#define MT6589_GPIO216__FUNC_EINT95 (MTK_PIN_NO(216) | 2) +#define MT6589_GPIO216__FUNC_CLKM5 (MTK_PIN_NO(216) | 3) +#define MT6589_GPIO216__FUNC_PWM5 (MTK_PIN_NO(216) | 4) +#define MT6589_GPIO216__FUNC_TS_AUX_PWDB (MTK_PIN_NO(216) | 5) +#define MT6589_GPIO216__FUNC_A_FUNC_DIN_15 (MTK_PIN_NO(216) | 7) + +#define MT6589_GPIO217__FUNC_GPIO217 (MTK_PIN_NO(217) | 0) +#define MT6589_GPIO217__FUNC_SCL2 (MTK_PIN_NO(217) | 1) +#define MT6589_GPIO217__FUNC_EINT94 (MTK_PIN_NO(217) | 2) +#define MT6589_GPIO217__FUNC_CLKM4 (MTK_PIN_NO(217) | 3) +#define MT6589_GPIO217__FUNC_PWM4 (MTK_PIN_NO(217) | 4) +#define MT6589_GPIO217__FUNC_TS_AUXADC_TEST_CK (MTK_PIN_NO(217) | 5) +#define MT6589_GPIO217__FUNC_A_FUNC_DIN_16 (MTK_PIN_NO(217) | 7) + +#define MT6589_GPIO218__FUNC_GPIO218 (MTK_PIN_NO(218) | 0) +#define MT6589_GPIO218__FUNC_SRCLKENAI (MTK_PIN_NO(218) | 1) + +#define MT6589_GPIO219__FUNC_GPIO219 (MTK_PIN_NO(219) | 0) +#define MT6589_GPIO219__FUNC_URXD3 (MTK_PIN_NO(219) | 1) +#define MT6589_GPIO219__FUNC_EINT87 (MTK_PIN_NO(219) | 2) +#define MT6589_GPIO219__FUNC_UTXD3 (MTK_PIN_NO(219) | 3) +#define MT6589_GPIO219__FUNC_MD2_URXD (MTK_PIN_NO(219) | 4) +#define MT6589_GPIO219__FUNC_TS_AUX_ST (MTK_PIN_NO(219) | 5) +#define MT6589_GPIO219__FUNC_PWM4 (MTK_PIN_NO(219) | 6) +#define MT6589_GPIO219__FUNC_MD2_EINT4 (MTK_PIN_NO(219) | 7) + +#define MT6589_GPIO220__FUNC_GPIO220 (MTK_PIN_NO(220) | 0) +#define MT6589_GPIO220__FUNC_UTXD3 (MTK_PIN_NO(220) | 1) +#define MT6589_GPIO220__FUNC_EINT86 (MTK_PIN_NO(220) | 2) +#define MT6589_GPIO220__FUNC_URXD3 (MTK_PIN_NO(220) | 3) +#define MT6589_GPIO220__FUNC_MD2_UTXD (MTK_PIN_NO(220) | 4) +#define MT6589_GPIO220__FUNC_TS_AUX_CS_B (MTK_PIN_NO(220) | 5) +#define MT6589_GPIO220__FUNC_PWM3 (MTK_PIN_NO(220) | 6) +#define MT6589_GPIO220__FUNC_MD2_EINT3 (MTK_PIN_NO(220) | 7) + +#define MT6589_GPIO221__FUNC_GPIO221 (MTK_PIN_NO(221) | 0) +#define MT6589_GPIO221__FUNC_MRG_I2S_PCM_CLK (MTK_PIN_NO(221) | 1) +#define MT6589_GPIO221__FUNC_EINT14 (MTK_PIN_NO(221) | 2) +#define MT6589_GPIO221__FUNC_I2SIN_CK (MTK_PIN_NO(221) | 3) +#define MT6589_GPIO221__FUNC_PCM0_CK (MTK_PIN_NO(221) | 4) +#define MT6589_GPIO221__FUNC_DSP2_ICK (MTK_PIN_NO(221) | 5) +#define MT6589_GPIO221__FUNC_IMG_TEST_CK (MTK_PIN_NO(221) | 6) +#define MT6589_GPIO221__FUNC_USB_SCL (MTK_PIN_NO(221) | 7) + +#define MT6589_GPIO222__FUNC_GPIO222 (MTK_PIN_NO(222) | 0) +#define MT6589_GPIO222__FUNC_MRG_I2S_PCM_SYNC (MTK_PIN_NO(222) | 1) +#define MT6589_GPIO222__FUNC_EINT16 (MTK_PIN_NO(222) | 2) +#define MT6589_GPIO222__FUNC_I2SIN_WS (MTK_PIN_NO(222) | 3) +#define MT6589_GPIO222__FUNC_PCM0_WS (MTK_PIN_NO(222) | 4) +#define MT6589_GPIO222__FUNC_DISP_TEST_CK (MTK_PIN_NO(222) | 6) + +#define MT6589_GPIO223__FUNC_GPIO223 (MTK_PIN_NO(223) | 0) +#define MT6589_GPIO223__FUNC_MRG_I2S_PCM_RX (MTK_PIN_NO(223) | 1) +#define MT6589_GPIO223__FUNC_EINT15 (MTK_PIN_NO(223) | 2) +#define MT6589_GPIO223__FUNC_I2SIN_DAT (MTK_PIN_NO(223) | 3) +#define MT6589_GPIO223__FUNC_PCM0_DI (MTK_PIN_NO(223) | 4) +#define MT6589_GPIO223__FUNC_DSP2_ID (MTK_PIN_NO(223) | 5) +#define MT6589_GPIO223__FUNC_MFG_TEST_CK (MTK_PIN_NO(223) | 6) +#define MT6589_GPIO223__FUNC_USB_SDA (MTK_PIN_NO(223) | 7) + +#define MT6589_GPIO224__FUNC_GPIO224 (MTK_PIN_NO(224) | 0) +#define MT6589_GPIO224__FUNC_MRG_I2S_PCM_TX (MTK_PIN_NO(224) | 1) +#define MT6589_GPIO224__FUNC_EINT17 (MTK_PIN_NO(224) | 2) +#define MT6589_GPIO224__FUNC_I2SOUT_DAT (MTK_PIN_NO(224) | 3) +#define MT6589_GPIO224__FUNC_PCM0_DO (MTK_PIN_NO(224) | 4) +#define MT6589_GPIO224__FUNC_VDEC_TEST_CK (MTK_PIN_NO(224) | 6) + +#define MT6589_GPIO225__FUNC_GPIO225 (MTK_PIN_NO(225) | 0) +#define MT6589_GPIO225__FUNC_MD1_DAI_RX_GPIO (MTK_PIN_NO(225) | 1) +#define MT6589_GPIO225__FUNC_EINT18 (MTK_PIN_NO(225) | 2) +#define MT6589_GPIO225__FUNC_BT_SYNC (MTK_PIN_NO(225) | 3) +#define MT6589_GPIO225__FUNC_MD2_DAI_RX_GPIO (MTK_PIN_NO(225) | 4) +#define MT6589_GPIO225__FUNC_DSP2_IMS (MTK_PIN_NO(225) | 5) +#define MT6589_GPIO225__FUNC_VENC_TEST_CK (MTK_PIN_NO(225) | 6) + +#define MT6589_GPIO226__FUNC_GPIO226 (MTK_PIN_NO(226) | 0) +#define MT6589_GPIO226__FUNC_MSDC3_DAT2 (MTK_PIN_NO(226) | 1) +#define MT6589_GPIO226__FUNC_EINT71 (MTK_PIN_NO(226) | 2) +#define MT6589_GPIO226__FUNC_SCL6 (MTK_PIN_NO(226) | 3) +#define MT6589_GPIO226__FUNC_PWM5 (MTK_PIN_NO(226) | 4) +#define MT6589_GPIO226__FUNC_CLKM4 (MTK_PIN_NO(226) | 5) +#define MT6589_GPIO226__FUNC_A_FUNC_DIN_0 (MTK_PIN_NO(226) | 7) + +#define MT6589_GPIO227__FUNC_GPIO227 (MTK_PIN_NO(227) | 0) +#define MT6589_GPIO227__FUNC_MSDC3_DAT3 (MTK_PIN_NO(227) | 1) +#define MT6589_GPIO227__FUNC_EINT72 (MTK_PIN_NO(227) | 2) +#define MT6589_GPIO227__FUNC_SDA6 (MTK_PIN_NO(227) | 3) +#define MT6589_GPIO227__FUNC_PWM6 (MTK_PIN_NO(227) | 4) +#define MT6589_GPIO227__FUNC_CLKM5 (MTK_PIN_NO(227) | 5) +#define MT6589_GPIO227__FUNC_A_FUNC_CK (MTK_PIN_NO(227) | 7) + +#define MT6589_GPIO228__FUNC_GPIO228 (MTK_PIN_NO(228) | 0) +#define MT6589_GPIO228__FUNC_MSDC3_CMD (MTK_PIN_NO(228) | 1) +#define MT6589_GPIO228__FUNC_EINT68 (MTK_PIN_NO(228) | 2) +#define MT6589_GPIO228__FUNC_SDA2 (MTK_PIN_NO(228) | 3) +#define MT6589_GPIO228__FUNC_PWM2 (MTK_PIN_NO(228) | 4) +#define MT6589_GPIO228__FUNC_CLKM1 (MTK_PIN_NO(228) | 5) +#define MT6589_GPIO228__FUNC_A_FUNC_DIN_3 (MTK_PIN_NO(228) | 7) + +#define MT6589_GPIO229__FUNC_GPIO229 (MTK_PIN_NO(229) | 0) +#define MT6589_GPIO229__FUNC_MSDC3_CLK (MTK_PIN_NO(229) | 1) +#define MT6589_GPIO229__FUNC_EINT67 (MTK_PIN_NO(229) | 2) +#define MT6589_GPIO229__FUNC_SCL2 (MTK_PIN_NO(229) | 3) +#define MT6589_GPIO229__FUNC_PWM1 (MTK_PIN_NO(229) | 4) +#define MT6589_GPIO229__FUNC_CLKM0 (MTK_PIN_NO(229) | 5) +#define MT6589_GPIO229__FUNC_A_FUNC_DIN_4 (MTK_PIN_NO(229) | 7) + +#define MT6589_GPIO230__FUNC_GPIO230 (MTK_PIN_NO(230) | 0) +#define MT6589_GPIO230__FUNC_MSDC3_DAT1 (MTK_PIN_NO(230) | 1) +#define MT6589_GPIO230__FUNC_EINT70 (MTK_PIN_NO(230) | 2) +#define MT6589_GPIO230__FUNC_SDA3 (MTK_PIN_NO(230) | 3) +#define MT6589_GPIO230__FUNC_PWM4 (MTK_PIN_NO(230) | 4) +#define MT6589_GPIO230__FUNC_CLKM3 (MTK_PIN_NO(230) | 5) +#define MT6589_GPIO230__FUNC_A_FUNC_DIN_1 (MTK_PIN_NO(230) | 7) + +#define MT6589_GPIO231__FUNC_GPIO231 (MTK_PIN_NO(231) | 0) +#define MT6589_GPIO231__FUNC_MSDC3_DAT0 (MTK_PIN_NO(231) | 1) +#define MT6589_GPIO231__FUNC_EINT69 (MTK_PIN_NO(231) | 2) +#define MT6589_GPIO231__FUNC_SCL3 (MTK_PIN_NO(231) | 3) +#define MT6589_GPIO231__FUNC_PWM3 (MTK_PIN_NO(231) | 4) +#define MT6589_GPIO231__FUNC_CLKM2 (MTK_PIN_NO(231) | 5) +#define MT6589_GPIO231__FUNC_A_FUNC_DIN_2 (MTK_PIN_NO(231) | 7) + +#endif /* __MT6589_PINFUNC_H */ diff --git a/include/dt-bindings/power/mt6589-power.h b/include/dt-bindings/power/mt6589-power.h new file mode 100644 index 00000000000000..14d2c941015543 --- /dev/null +++ b/include/dt-bindings/power/mt6589-power.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + +#ifndef _DT_BINDINGS_POWER_MT6589_POWER_H +#define _DT_BINDINGS_POWER_MT6589_POWER_H + +#define MT6589_POWER_DOMAIN_MD1 0 +#define MT6589_POWER_DOMAIN_MD2 1 +#define MT6589_POWER_DOMAIN_DPY 2 +#define MT6589_POWER_DOMAIN_DIS 3 +#define MT6589_POWER_DOMAIN_MFG 4 +#define MT6589_POWER_DOMAIN_ISP 5 +#define MT6589_POWER_DOMAIN_IFR 6 +#define MT6589_POWER_DOMAIN_VEN 7 +#define MT6589_POWER_DOMAIN_VDE 8 + +#endif /* _DT_BINDINGS_POWER_MT6589_POWER_H */ diff --git a/include/dt-bindings/reset/mt6589-resets.h b/include/dt-bindings/reset/mt6589-resets.h new file mode 100644 index 00000000000000..3292b774b08490 --- /dev/null +++ b/include/dt-bindings/reset/mt6589-resets.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT6589 +#define _DT_BINDINGS_RESET_CONTROLLER_MT6589 + +/* PERI */ +#define MT6589_PERI_UART0_SW_RST 0 +#define MT6589_PERI_UART1_SW_RST 1 +#define MT6589_PERI_UART2_SW_RST 2 +#define MT6589_PERI_UART3_SW_RST 3 +#define MT6589_PERI_IRDA_SW_RST 4 +#define MT6589_PERI_PTP_RST 5 +#define MT6589_PERI_AP_HIF_SW_RST 6 +#define MT6589_PERI_MD_HIF_SW_RST 8 +#define MT6589_PERI_NLI_SW_RST 9 +#define MT6589_PERI_AUXADC_SW_RST 10 +#define MT6589_PERI_DMA_SW_RS_RST 11 +#define MT6589_PERI_NFI_SW_RST_RST 14 +#define MT6589_PERI_PWM_SW_RST 15 +#define MT6589_PERI_THERM_SW_RST 16 +#define MT6589_PERI_MSDC0_SW_RST 17 +#define MT6589_PERI_MSDC1_SW_RST 18 +#define MT6589_PERI_MSDC2_SW_RST 19 +#define MT6589_PERI_MSDC3_SW_RST 20 +#define MT6589_PERI_I2C0_SW_RST 22 +#define MT6589_PERI_I2C1_SW_RST 23 +#define MT6589_PERI_I2C2_SW_RST 24 +#define MT6589_PERI_I2C3_SW_RST 25 +#define MT6589_PERI_I2C4_SW_RST 26 +#define MT6589_PERI_I2C5_SW_RST 27 +#define MT6589_PERI_I2C6_SW_RST 28 +#define MT6589_PERI_USB_SW_RST 29 +#define MT6589_PERI_SPI0_SW_RST 33 +#define MT6589_PERI_PWRAP_BRIDGE_SW_RST 34 + +/* INFRA */ +#define MT6589_INFRA_EMI_REG_RST 0 +#define MT6589_INFRA_DRAMC0_AO_RST 1 +#define MT6589_INFRA_CCIF0_RST 2 +#define MT6589_INFRA_AP_CIRP_EINT_RST 3 +#define MT6589_INFRA_APXGPT_RST 4 +#define MT6589_INFRA_SCPSYS_RST 5 +#define MT6589_INFRA_CCIF1_RST 6 +#define MT6589_INFRA_PMIC_WRAP_RST 7 +#define MT6589_INFRA_KP_RST 8 +#define MT6589_INFRA_EMI_RST 32 +#define MT6589_INFRA_DRAMC0_RST 34 +#define MT6589_INFRA_SMI_RST 35 +#define MT6589_INFRA_M4U_RST 36 + +/* TOPRGU */ +#define MT6589_TOPRGU_INFRA_RST 0 +#define MT6589_TOPRGU_DISP_RST 1 +#define MT6589_TOPRGU_MFG_RST 2 +#define MT6589_TOPRGU_VENC_RST 3 +#define MT6589_TOPRGU_VDEC_RST 4 +#define MT6589_TOPRGU_IMG_RST 5 +#define MT6589_TOPRGU_DDRPHY_RST 6 +#define MT6589_TOPRGU_MD_RST 7 +#define MT6589_TOPRGU_INFRA_AO_RST 8 +#define MT6589_TOPRGU_MD_LITE_RST 9 +#define MT6589_TOPRGU_APMIXED_RST 10 +#define MT6589_TOPRGU_PWRAP_SPICTL_RST 11 + +#define MT6589_TOPRGU_RST_NUM 12 + +/* MFG */ +#define MT6589_MFG_G3D_RESET 0 +#define MT6589_MFG_AXI_RESET 1 + +/* DISP */ +#define MT6589_DISP_SMI_LARB2_RST 0 +#define MT6589_DISP_ROT_RST 1 +#define MT6589_DISP_SCL_RST 2 +#define MT6589_DISP_OVL_RST 3 +#define MT6589_DISP_COLOR_RST 4 +#define MT6589_DISP_TDSHP_RST 5 +#define MT6589_DISP_BLS_RST 6 +#define MT6589_DISP_WDMA0_RST 7 +#define MT6589_DISP_WDMA1_RST 8 +#define MT6589_DISP_RDMA0_RST 9 +#define MT6589_DISP_RDMA1_RST 10 +#define MT6589_DISP_GAMMA_RST 11 +#define MT6589_DISP_CMDQ_DISPCK_RST 12 +#define MT6589_DISP_CMDQ_SMICK_RST 13 +#define MT6589_DISP_G2D_RST 14 +#define MT6589_DISP_DBI_DISPCK_RST 15 +#define MT6589_DISP_DBI_SMICK_RST 16 +#define MT6589_DISP_DBI_INTERFACECK_RST 17 +#define MT6589_DISP_DSI_RST 18 +#define MT6589_DISP_DPI0_RST 19 +#define MT6589_DISP_DPI1_RST 20 + +#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT6589 */ diff --git a/include/linux/mfd/mt6320/core.h b/include/linux/mfd/mt6320/core.h new file mode 100644 index 00000000000000..320414a7758653 --- /dev/null +++ b/include/linux/mfd/mt6320/core.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2026 Akari Tsuyukusa + */ + +#ifndef __MFD_MT6320_CORE_H__ +#define __MFD_MT6320_CORE_H__ + +enum mt6320_irq_numbers { + MT6320_IRQ_SPKL_AB = 0, + MT6320_IRQ_SPKR_AB, + MT6320_IRQ_SPKL, + MT6320_IRQ_SPKR, + MT6320_IRQ_BAT_L, + MT6320_IRQ_BAT_H, + MT6320_IRQ_FG_BAT_L, + MT6320_IRQ_FG_BAT_H, + MT6320_IRQ_WATCHDOG, + MT6320_IRQ_PWRKEY, + MT6320_IRQ_THR_L, + MT6320_IRQ_THR_H, + MT6320_IRQ_VBATON_UNDET, + MT6320_IRQ_BVALID_DET, + MT6320_IRQ_CHRDET, + MT6320_IRQ_OV, + MT6320_IRQ_LDO = 16, + MT6320_IRQ_HOMEKEY, + MT6320_IRQ_ACCDET, + MT6320_IRQ_AUDIO, + MT6320_IRQ_RTC, + MT6320_IRQ_VPROC = 24, + MT6320_IRQ_VSRAM, + MT6320_IRQ_VCORE, + MT6320_IRQ_VM, + MT6320_IRQ_VIO18, + MT6320_IRQ_VPA, + MT6320_IRQ_VRF18, + MT6320_IRQ_VRF18_2, + MT6320_IRQ_NR, +}; + +#endif /* __MFD_MT6320_CORE_H__ */ diff --git a/include/linux/mfd/mt6320/registers.h b/include/linux/mfd/mt6320/registers.h new file mode 100644 index 00000000000000..fd93fd0ccef46c --- /dev/null +++ b/include/linux/mfd/mt6320/registers.h @@ -0,0 +1,513 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014 MediaTek Inc. + * Copyright (C) 2014 BQ + * Copyright (C) 2026 Akari Tsuyukusa + * + * MT6320 Register Map based on bq Aquaris 5 kernel + */ + +#ifndef __MFD_MT6320_REGISTERS_H__ +#define __MFD_MT6320_REGISTERS_H__ + +/* PMIC Registers */ +#define MT6320_CHR_CON0 0x0000 +#define MT6320_CHR_CON1 0x0002 +#define MT6320_CHR_CON2 0x0004 +#define MT6320_CHR_CON3 0x0006 +#define MT6320_CHR_CON4 0x0008 +#define MT6320_CHR_CON5 0x000a +#define MT6320_CHR_CON6 0x000c +#define MT6320_CHR_CON7 0x000e +#define MT6320_CHR_CON8 0x0010 +#define MT6320_CHR_CON9 0x0012 +#define MT6320_CHR_CON10 0x0014 +#define MT6320_CHR_CON11 0x0016 +#define MT6320_CHR_CON12 0x0018 +#define MT6320_CHR_CON13 0x001a +#define MT6320_CHR_CON14 0x001c +#define MT6320_CHR_CON15 0x001e +#define MT6320_CHR_CON16 0x0020 +#define MT6320_CHR_CON17 0x0022 +#define MT6320_CHR_CON18 0x0024 +#define MT6320_CHR_CON19 0x0026 +#define MT6320_CHR_CON20 0x0028 +#define MT6320_CHR_CON21 0x002a +#define MT6320_CHR_CON22 0x002c +#define MT6320_CHR_CON23 0x002e +#define MT6320_CHR_CON24 0x0030 +#define MT6320_CHR_CON25 0x0032 +#define MT6320_CHR_CON26 0x0034 +#define MT6320_CHR_CON27 0x0036 +#define MT6320_CHR_CON28 0x0038 +#define MT6320_CHR_CON29 0x003a +#define MT6320_CID 0x0100 +#define MT6320_TOP_CKPDN 0x0102 +#define MT6320_TOP_CKPDN_SET 0x0104 +#define MT6320_TOP_CKPDN_CLR 0x0106 +#define MT6320_TOP_CKPDN2 0x0108 +#define MT6320_TOP_CKPDN2_SET 0x010a +#define MT6320_TOP_CKPDN2_CLR 0x010c +#define MT6320_TOP_GPIO_CKPDN 0x010e +#define MT6320_TOP_RST_CON 0x0114 +#define MT6320_TOP_RST_ACCDET_SET 0x0116 +#define MT6320_TOP_RST_ACCDET_CLR 0x0118 +#define MT6320_WRP_CKPDN 0x011a +#define MT6320_WRP_RST_CON 0x0120 +#define MT6320_TOP_RST_MISC 0x0126 +#define MT6320_TOP_CKCON1 0x0128 +#define MT6320_TOP_CKCON2 0x012a +#define MT6320_TOP_CKTST1 0x012c +#define MT6320_TOP_CKTST2 0x012e +#define MT6320_OC_DEG_EN 0x0130 +#define MT6320_OC_CTL0 0x0132 +#define MT6320_OC_CTL1 0x0134 +#define MT6320_OC_CTL2 0x0136 +#define MT6320_INT_RSV 0x0138 +#define MT6320_TEST_CON0 0x013a +#define MT6320_TEST_CON1 0x013c +#define MT6320_STATUS0 0x013e +#define MT6320_STATUS1 0x0140 +#define MT6320_PGSTATUS 0x0142 +#define MT6320_CHRSTATUS 0x0144 +#define MT6320_OCSTATUS0 0x0146 +#define MT6320_OCSTATUS1 0x0148 +#define MT6320_OCSTATUS2 0x014a +#define MT6320_SIMLS_CON 0x014c +#define MT6320_TEST_OUT_L 0x014e +#define MT6320_TEST_OUT_H 0x0150 +#define MT6320_TDSEL_CON 0x0152 +#define MT6320_RDSEL_CON 0x0154 +#define MT6320_GPIO_SMT_CON0 0x0156 +#define MT6320_GPIO_SMT_CON1 0x0158 +#define MT6320_GPIO_SMT_CON2 0x015a +#define MT6320_GPIO_SMT_CON3 0x015c +#define MT6320_DRV_CON0 0x015e +#define MT6320_DRV_CON1 0x0160 +#define MT6320_DRV_CON2 0x0162 +#define MT6320_DRV_CON3 0x0164 +#define MT6320_DRV_CON4 0x0166 +#define MT6320_DRV_CON5 0x0168 +#define MT6320_DRV_CON6 0x016a +#define MT6320_DRV_CON7 0x016c +#define MT6320_DRV_CON8 0x016e +#define MT6320_DRV_CON9 0x0170 +#define MT6320_DRV_CON10 0x0172 +#define MT6320_DRV_CON11 0x0174 +#define MT6320_DRV_CON12 0x0176 +#define MT6320_INT_CON0 0x0178 +#define MT6320_INT_CON1 0x017e +#define MT6320_INT_CON1_SET 0x0180 +#define MT6320_INT_CON1_CLR 0x0182 +#define MT6320_INT_STATUS0 0x0184 +#define MT6320_INT_STATUS1 0x0186 +#define MT6320_FQMTR_CON0 0x0188 +#define MT6320_FQMTR_CON1 0x018a +#define MT6320_FQMTR_CON2 0x018c +#define MT6320_EFUSE_CON0 0x018e +#define MT6320_EFUSE_CON1 0x0190 +#define MT6320_EFUSE_CON2 0x0192 +#define MT6320_EFUSE_CON3 0x0194 +#define MT6320_EFUSE_CON4 0x0196 +#define MT6320_EFUSE_CON5 0x0198 +#define MT6320_EFUSE_CON6 0x019a +#define MT6320_EFUSE_VAL_0_15 0x019c +#define MT6320_EFUSE_VAL_16_31 0x019e +#define MT6320_EFUSE_VAL_32_47 0x01a0 +#define MT6320_EFUSE_VAL_48_63 0x01a2 +#define MT6320_EFUSE_VAL_64_79 0x01a4 +#define MT6320_EFUSE_VAL_80_95 0x01a6 +#define MT6320_EFUSE_VAL_96_111 0x01a8 +#define MT6320_EFUSE_VAL_112_127 0x01aa +#define MT6320_EFUSE_VAL_128_143 0x01ac +#define MT6320_EFUSE_VAL_144_159 0x01ae +#define MT6320_EFUSE_VAL_160_175 0x01b0 +#define MT6320_EFUSE_VAL_176_191 0x01b2 +#define MT6320_EFUSE_DOUT_0_15 0x01b4 +#define MT6320_EFUSE_DOUT_16_31 0x01b6 +#define MT6320_EFUSE_DOUT_32_47 0x01b8 +#define MT6320_EFUSE_DOUT_48_63 0x01ba +#define MT6320_EFUSE_DOUT_64_79 0x01bc +#define MT6320_EFUSE_DOUT_80_95 0x01be +#define MT6320_EFUSE_DOUT_96_111 0x01c0 +#define MT6320_EFUSE_DOUT_112_127 0x01c2 +#define MT6320_EFUSE_DOUT_128_143 0x01c4 +#define MT6320_EFUSE_DOUT_144_159 0x01c6 +#define MT6320_EFUSE_DOUT_160_175 0x01c8 +#define MT6320_EFUSE_DOUT_176_191 0x01ca +#define MT6320_SPI_CON 0x01cc +#define MT6320_BUCK_CON0 0x0200 +#define MT6320_BUCK_CON1 0x0202 +#define MT6320_BUCK_CON2 0x0204 +#define MT6320_VPROC_CON0 0x0206 +#define MT6320_VPROC_CON1 0x0208 +#define MT6320_VPROC_CON2 0x020a +#define MT6320_VPROC_CON3 0x020c +#define MT6320_VPROC_CON4 0x020e +#define MT6320_VPROC_CON5 0x0210 +#define MT6320_VPROC_CON6 0x0212 +#define MT6320_VPROC_CON7 0x0214 +#define MT6320_VPROC_CON8 0x0216 +#define MT6320_VPROC_CON9 0x0218 +#define MT6320_VPROC_CON10 0x021a +#define MT6320_VPROC_CON11 0x021c +#define MT6320_VPROC_CON12 0x021e +#define MT6320_VPROC_CON13 0x0220 +#define MT6320_VPROC_CON14 0x0222 +#define MT6320_VPROC_CON15 0x0224 +#define MT6320_VPROC_CON16 0x0226 +#define MT6320_VPROC_CON17 0x0228 +#define MT6320_VPROC_CON18 0x022a +#define MT6320_VSRAM_CON0 0x022c +#define MT6320_VSRAM_CON1 0x022e +#define MT6320_VSRAM_CON2 0x0230 +#define MT6320_VSRAM_CON3 0x0232 +#define MT6320_VSRAM_CON4 0x0234 +#define MT6320_VSRAM_CON5 0x0236 +#define MT6320_VSRAM_CON6 0x0238 +#define MT6320_VSRAM_CON7 0x023a +#define MT6320_VSRAM_CON8 0x023c +#define MT6320_VSRAM_CON9 0x023e +#define MT6320_VSRAM_CON10 0x0240 +#define MT6320_VSRAM_CON11 0x0242 +#define MT6320_VSRAM_CON12 0x0244 +#define MT6320_VSRAM_CON13 0x0246 +#define MT6320_VSRAM_CON14 0x0248 +#define MT6320_VSRAM_CON15 0x024a +#define MT6320_VSRAM_CON16 0x024c +#define MT6320_VSRAM_CON17 0x024e +#define MT6320_VSRAM_CON18 0x0250 +#define MT6320_VSRAM_CON19 0x0252 +#define MT6320_VSRAM_CON20 0x0254 +#define MT6320_VSRAM_CON21 0x0256 +#define MT6320_VCORE_CON0 0x0258 +#define MT6320_VCORE_CON1 0x025a +#define MT6320_VCORE_CON2 0x025c +#define MT6320_VCORE_CON3 0x025e +#define MT6320_VCORE_CON4 0x0260 +#define MT6320_VCORE_CON5 0x0262 +#define MT6320_VCORE_CON6 0x0264 +#define MT6320_VCORE_CON7 0x0266 +#define MT6320_VCORE_CON8 0x0268 +#define MT6320_VCORE_CON9 0x026a +#define MT6320_VCORE_CON10 0x026c +#define MT6320_VCORE_CON11 0x026e +#define MT6320_VCORE_CON12 0x0270 +#define MT6320_VCORE_CON13 0x0272 +#define MT6320_VCORE_CON14 0x0274 +#define MT6320_VCORE_CON15 0x0276 +#define MT6320_VCORE_CON16 0x0278 +#define MT6320_VCORE_CON17 0x027a +#define MT6320_VCORE_CON18 0x027c +#define MT6320_VM_CON0 0x027e +#define MT6320_VM_CON1 0x0280 +#define MT6320_VM_CON2 0x0282 +#define MT6320_VM_CON3 0x0284 +#define MT6320_VM_CON4 0x0286 +#define MT6320_VM_CON5 0x0288 +#define MT6320_VM_CON6 0x028a +#define MT6320_VM_CON7 0x028c +#define MT6320_VM_CON8 0x028e +#define MT6320_VM_CON9 0x0290 +#define MT6320_VM_CON10 0x0292 +#define MT6320_VM_CON11 0x0294 +#define MT6320_VM_CON12 0x0296 +#define MT6320_VM_CON13 0x0298 +#define MT6320_VM_CON14 0x029a +#define MT6320_VM_CON15 0x029c +#define MT6320_VM_CON16 0x029e +#define MT6320_VM_CON17 0x02a0 +#define MT6320_VM_CON18 0x02a2 +#define MT6320_VIO18_CON0 0x0300 +#define MT6320_VIO18_CON1 0x0302 +#define MT6320_VIO18_CON2 0x0304 +#define MT6320_VIO18_CON3 0x0306 +#define MT6320_VIO18_CON4 0x0308 +#define MT6320_VIO18_CON5 0x030a +#define MT6320_VIO18_CON6 0x030c +#define MT6320_VIO18_CON7 0x030e +#define MT6320_VIO18_CON8 0x0310 +#define MT6320_VIO18_CON9 0x0312 +#define MT6320_VIO18_CON10 0x0314 +#define MT6320_VIO18_CON11 0x0316 +#define MT6320_VIO18_CON12 0x0318 +#define MT6320_VIO18_CON13 0x031a +#define MT6320_VIO18_CON14 0x031c +#define MT6320_VIO18_CON15 0x031e +#define MT6320_VIO18_CON16 0x0320 +#define MT6320_VIO18_CON17 0x0322 +#define MT6320_VIO18_CON18 0x0324 +#define MT6320_VPA_CON0 0x0326 +#define MT6320_VPA_CON1 0x0328 +#define MT6320_VPA_CON2 0x032a +#define MT6320_VPA_CON3 0x032c +#define MT6320_VPA_CON4 0x032e +#define MT6320_VPA_CON5 0x0330 +#define MT6320_VPA_CON6 0x0332 +#define MT6320_VPA_CON7 0x0334 +#define MT6320_VPA_CON8 0x0336 +#define MT6320_VPA_CON9 0x0338 +#define MT6320_VPA_CON10 0x033a +#define MT6320_VPA_CON11 0x033c +#define MT6320_VPA_CON12 0x033e +#define MT6320_VPA_CON13 0x0340 +#define MT6320_VPA_CON14 0x0342 +#define MT6320_VPA_CON15 0x0344 +#define MT6320_VPA_CON16 0x0346 +#define MT6320_VPA_CON17 0x0348 +#define MT6320_VPA_CON18 0x034a +#define MT6320_VPA_CON19 0x034c +#define MT6320_VPA_CON20 0x034e +#define MT6320_VRF18_CON0 0x0350 +#define MT6320_VRF18_CON1 0x0352 +#define MT6320_VRF18_CON2 0x0354 +#define MT6320_VRF18_CON3 0x0356 +#define MT6320_VRF18_CON4 0x0358 +#define MT6320_VRF18_CON5 0x035a +#define MT6320_VRF18_CON6 0x035c +#define MT6320_VRF18_CON7 0x035e +#define MT6320_VRF18_CON8 0x0360 +#define MT6320_VRF18_CON9 0x0362 +#define MT6320_VRF18_CON10 0x0364 +#define MT6320_VRF18_CON11 0x0366 +#define MT6320_VRF18_CON12 0x0368 +#define MT6320_VRF18_CON13 0x036a +#define MT6320_VRF18_CON14 0x036c +#define MT6320_VRF18_CON15 0x036e +#define MT6320_VRF18_CON16 0x0370 +#define MT6320_VRF18_CON17 0x0372 +#define MT6320_VRF18_CON18 0x0374 +#define MT6320_VRF18_CON19 0x0376 +#define MT6320_VRF18_CON20 0x0378 +#define MT6320_VRF18_2_CON0 0x037a +#define MT6320_VRF18_2_CON1 0x037c +#define MT6320_VRF18_2_CON2 0x037e +#define MT6320_VRF18_2_CON3 0x0380 +#define MT6320_VRF18_2_CON4 0x0382 +#define MT6320_VRF18_2_CON5 0x0384 +#define MT6320_VRF18_2_CON6 0x0386 +#define MT6320_VRF18_2_CON7 0x0388 +#define MT6320_VRF18_2_CON8 0x038a +#define MT6320_VRF18_2_CON9 0x038c +#define MT6320_VRF18_2_CON10 0x038e +#define MT6320_VRF18_2_CON11 0x0390 +#define MT6320_VRF18_2_CON12 0x0392 +#define MT6320_VRF18_2_CON13 0x0394 +#define MT6320_VRF18_2_CON14 0x0396 +#define MT6320_VRF18_2_CON15 0x0398 +#define MT6320_VRF18_2_CON16 0x039a +#define MT6320_VRF18_2_CON17 0x039c +#define MT6320_VRF18_2_CON18 0x039e +#define MT6320_BUCK_K_CON0 0x03a0 +#define MT6320_BUCK_K_CON1 0x03a2 +#define MT6320_ANALDO_CON0 0x0400 +#define MT6320_ANALDO_CON1 0x0402 +#define MT6320_ANALDO_CON2 0x0404 +#define MT6320_ANALDO_CON3 0x0406 +#define MT6320_ANALDO_CON4 0x0408 +#define MT6320_ANALDO_CON5 0x040a +#define MT6320_ANALDO_CON6 0x040c +#define MT6320_ANALDO_CON7 0x040e +#define MT6320_ANALDO_CON8 0x0410 +#define MT6320_ANALDO_CON9 0x0412 +#define MT6320_ANALDO_CON10 0x0414 +#define MT6320_ANALDO_CON11 0x0416 +#define MT6320_ANALDO_CON12 0x0418 +#define MT6320_ANALDO_CON13 0x041a +#define MT6320_ANALDO_CON14 0x041c +#define MT6320_ANALDO_CON15 0x041e +#define MT6320_DIGLDO_CON0 0x0420 +#define MT6320_DIGLDO_CON2 0x0422 +#define MT6320_DIGLDO_CON3 0x0424 +#define MT6320_DIGLDO_CON5 0x0426 +#define MT6320_DIGLDO_CON6 0x0428 +#define MT6320_DIGLDO_CON7 0x042a +#define MT6320_DIGLDO_CON8 0x042c +#define MT6320_DIGLDO_CON9 0x042e +#define MT6320_DIGLDO_CON10 0x0430 +#define MT6320_DIGLDO_CON11 0x0432 +#define MT6320_DIGLDO_CON12 0x0434 +#define MT6320_DIGLDO_CON13 0x0436 +#define MT6320_DIGLDO_CON14 0x0438 +#define MT6320_DIGLDO_CON15 0x043a +#define MT6320_DIGLDO_CON16 0x043c +#define MT6320_DIGLDO_CON17 0x043e +#define MT6320_DIGLDO_CON18 0x0440 +#define MT6320_DIGLDO_CON19 0x0442 +#define MT6320_DIGLDO_CON20 0x0444 +#define MT6320_DIGLDO_CON21 0x0446 +#define MT6320_DIGLDO_CON23 0x0448 +#define MT6320_DIGLDO_CON24 0x044a +#define MT6320_DIGLDO_CON26 0x044c +#define MT6320_DIGLDO_CON27 0x044e +#define MT6320_DIGLDO_CON28 0x0450 +#define MT6320_DIGLDO_CON29 0x0452 +#define MT6320_DIGLDO_CON30 0x0454 +#define MT6320_DIGLDO_CON31 0x0456 +#define MT6320_DIGLDO_CON32 0x0458 +#define MT6320_DIGLDO_CON33 0x045a +#define MT6320_DIGLDO_CON34 0x045c +#define MT6320_DIGLDO_CON35 0x045e +#define MT6320_DIGLDO_CON36 0x0460 +#define MT6320_DIGLDO_CON37 0x0462 +#define MT6320_DIGLDO_CON38 0x0464 +#define MT6320_DIGLDO_CON39 0x0466 +#define MT6320_DIGLDO_CON40 0x0468 +#define MT6320_DIGLDO_CON41 0x046a +#define MT6320_DIGLDO_CON42 0x046c +#define MT6320_DIGLDO_CON43 0x046e +#define MT6320_DIGLDO_CON44 0x0470 +#define MT6320_STRUP_CON0 0x0500 +#define MT6320_STRUP_CON2 0x0502 +#define MT6320_STRUP_CON3 0x0504 +#define MT6320_STRUP_CON4 0x0506 +#define MT6320_STRUP_CON5 0x0508 +#define MT6320_STRUP_CON6 0x050a +#define MT6320_STRUP_CON7 0x050c +#define MT6320_STRUP_CON8 0x050e +#define MT6320_STRUP_CON9 0x0510 +#define MT6320_AUXADC_ADC0 0x0512 +#define MT6320_AUXADC_ADC1 0x0514 +#define MT6320_AUXADC_ADC2 0x0516 +#define MT6320_AUXADC_ADC3 0x0518 +#define MT6320_AUXADC_ADC4 0x051a +#define MT6320_AUXADC_ADC5 0x051c +#define MT6320_AUXADC_ADC6 0x051e +#define MT6320_AUXADC_ADC7 0x0520 +#define MT6320_AUXADC_ADC8 0x0522 +#define MT6320_AUXADC_ADC9 0x0524 +#define MT6320_AUXADC_ADC10 0x0526 +#define MT6320_AUXADC_ADC11 0x0528 +#define MT6320_AUXADC_ADC12 0x052a +#define MT6320_AUXADC_ADC13 0x052c +#define MT6320_AUXADC_ADC14 0x052e +#define MT6320_AUXADC_ADC15 0x0530 +#define MT6320_AUXADC_ADC16 0x0532 +#define MT6320_AUXADC_ADC17 0x0534 +#define MT6320_AUXADC_ADC18 0x0536 +#define MT6320_AUXADC_ADC19 0x0538 +#define MT6320_AUXADC_ADC20 0x053a +#define MT6320_AUXADC_ADC21 0x053c +#define MT6320_AUXADC_ADC22 0x053e +#define MT6320_AUXADC_CON0 0x0540 +#define MT6320_AUXADC_CON1 0x0542 +#define MT6320_AUXADC_CON2 0x0544 +#define MT6320_AUXADC_CON3 0x0546 +#define MT6320_AUXADC_CON4 0x0548 +#define MT6320_AUXADC_CON5 0x054a +#define MT6320_AUXADC_CON6 0x054c +#define MT6320_AUXADC_CON7 0x054e +#define MT6320_AUXADC_CON8 0x0550 +#define MT6320_AUXADC_CON9 0x0552 +#define MT6320_AUXADC_CON10 0x0554 +#define MT6320_AUXADC_CON11 0x0556 +#define MT6320_AUXADC_CON12 0x0558 +#define MT6320_AUXADC_CON13 0x055a +#define MT6320_AUXADC_CON14 0x055c +#define MT6320_FLASH_CON0 0x055e +#define MT6320_FLASH_CON1 0x0560 +#define MT6320_FLASH_CON2 0x0562 +#define MT6320_KPLED_CON0 0x0564 +#define MT6320_KPLED_CON1 0x0566 +#define MT6320_KPLED_CON2 0x0568 +#define MT6320_ISINKS_CON0 0x056a +#define MT6320_ISINKS_CON1 0x056c +#define MT6320_ISINKS_CON2 0x056e +#define MT6320_ISINKS_CON3 0x0570 +#define MT6320_ISINKS_CON4 0x0572 +#define MT6320_ISINKS_CON5 0x0574 +#define MT6320_ISINKS_CON6 0x0576 +#define MT6320_ISINKS_CON7 0x0578 +#define MT6320_ISINKS_CON8 0x057a +#define MT6320_ISINKS_CON9 0x057c +#define MT6320_ISINKS_CON10 0x057e +#define MT6320_ISINKS_CON11 0x0580 +#define MT6320_ACCDET_CON0 0x0582 +#define MT6320_ACCDET_CON1 0x0584 +#define MT6320_ACCDET_CON2 0x0586 +#define MT6320_ACCDET_CON3 0x0588 +#define MT6320_ACCDET_CON4 0x058a +#define MT6320_ACCDET_CON5 0x058c +#define MT6320_ACCDET_CON6 0x058e +#define MT6320_ACCDET_CON7 0x0590 +#define MT6320_ACCDET_CON8 0x0592 +#define MT6320_ACCDET_CON9 0x0594 +#define MT6320_ACCDET_CON10 0x0596 +#define MT6320_ACCDET_CON11 0x0598 +#define MT6320_ACCDET_CON12 0x059a +#define MT6320_ACCDET_CON13 0x059c +#define MT6320_ACCDET_CON14 0x059e +#define MT6320_ACCDET_CON15 0x05a0 +#define MT6320_ACCDET_CON16 0x05a2 +#define MT6320_SPK_CON0 0x0600 +#define MT6320_SPK_CON1 0x0602 +#define MT6320_SPK_CON2 0x0604 +#define MT6320_SPK_CON3 0x0606 +#define MT6320_SPK_CON4 0x0608 +#define MT6320_SPK_CON5 0x060a +#define MT6320_SPK_CON6 0x060c +#define MT6320_SPK_CON7 0x060e +#define MT6320_SPK_CON8 0x0610 +#define MT6320_SPK_CON9 0x0612 +#define MT6320_SPK_CON10 0x0614 +#define MT6320_SPK_CON11 0x0616 +#define MT6320_FGADC_CON0 0x0618 +#define MT6320_FGADC_CON1 0x061a +#define MT6320_FGADC_CON2 0x061c +#define MT6320_FGADC_CON3 0x061e +#define MT6320_FGADC_CON4 0x0620 +#define MT6320_FGADC_CON5 0x0622 +#define MT6320_FGADC_CON6 0x0624 +#define MT6320_FGADC_CON7 0x0626 +#define MT6320_FGADC_CON8 0x0628 +#define MT6320_FGADC_CON9 0x062a +#define MT6320_FGADC_CON10 0x062c +#define MT6320_FGADC_CON11 0x062e +#define MT6320_FGADC_CON12 0x0630 +#define MT6320_FGADC_CON13 0x0632 +#define MT6320_FGADC_CON14 0x0634 +#define MT6320_FGADC_CON15 0x0636 +#define MT6320_FGADC_CON16 0x0638 +#define MT6320_FGADC_CON17 0x063a +#define MT6320_FGADC_CON18 0x063c +#define MT6320_FGADC_CON19 0x063e +#define MT6320_RTC_MIX_CON0 0x0640 +#define MT6320_RTC_MIX_CON1 0x0642 +#define MT6320_AUDDAC_CON0 0x0700 +#define MT6320_AUDBUF_CFG0 0x0702 +#define MT6320_AUDBUF_CFG1 0x0704 +#define MT6320_AUDBUF_CFG2 0x0706 +#define MT6320_AUDBUF_CFG3 0x0708 +#define MT6320_AUDBUF_CFG4 0x070a +#define MT6320_IBIASDIST_CFG0 0x070c +#define MT6320_AUDACCDEPOP_CFG0 0x070e +#define MT6320_AUD_IV_CFG0 0x0710 +#define MT6320_AUDCLKGEN_CFG0 0x0712 +#define MT6320_AUDLDO_CFG0 0x0714 +#define MT6320_AUDLDO_CFG1 0x0716 +#define MT6320_AUDNVREGGLB_CFG0 0x0718 +#define MT6320_AUD_NCP0 0x071a +#define MT6320_AUDPREAMP_CON0 0x071c +#define MT6320_AUDADC_CON0 0x071e +#define MT6320_AUDADC_CON1 0x0720 +#define MT6320_AUDADC_CON2 0x0722 +#define MT6320_AUDADC_CON3 0x0724 +#define MT6320_AUDADC_CON4 0x0726 +#define MT6320_AUDADC_CON5 0x0728 +#define MT6320_AUDADC_CON6 0x072a +#define MT6320_AUDDIGMI_CON0 0x072c +#define MT6320_AUDLSBUF_CON0 0x072e +#define MT6320_AUDLSBUF_CON1 0x0730 +#define MT6320_AUDENCSPARE_CON0 0x0732 +#define MT6320_AUDENCCLKSQ_CON0 0x0734 +#define MT6320_AUDPREAMPGAIN_CON0 0x0736 +#define MT6320_ZCD_CON0 0x0738 +#define MT6320_ZCD_CON1 0x073a +#define MT6320_ZCD_CON2 0x073c +#define MT6320_ZCD_CON3 0x073e +#define MT6320_ZCD_CON4 0x0740 +#define MT6320_ZCD_CON5 0x0742 +#define MT6320_NCP_CLKDIV_CON0 0x0744 +#define MT6320_NCP_CLKDIV_CON1 0x0746 + +#endif /* __MFD_MT6320_REGISTERS_H__ */ diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h index 340fc72e22aa64..dadffd3669591d 100644 --- a/include/linux/mfd/mt6397/core.h +++ b/include/linux/mfd/mt6397/core.h @@ -11,6 +11,7 @@ #include enum chip_id { + MT6320_CHIP_ID = 0x20, MT6323_CHIP_ID = 0x23, MT6328_CHIP_ID = 0x28, MT6331_CHIP_ID = 0x31, diff --git a/include/linux/regulator/mt6320-regulator.h b/include/linux/regulator/mt6320-regulator.h new file mode 100644 index 00000000000000..52214dc080545c --- /dev/null +++ b/include/linux/regulator/mt6320-regulator.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2026 Akari Tsuyukusa + * + * based on MT6589 v3.4.67 downstream kernel + * Copyright (c) 2014 BQ + * Copyright (c) 2014 MediaTek Inc. + */ + +#ifndef __LINUX_REGULATOR_MT6320_H +#define __LINUX_REGULATOR_MT6320_H + +enum { + /* Buck */ + MT6320_ID_VPROC, + MT6320_ID_VSRAM, + MT6320_ID_VCORE, + MT6320_ID_VM, + MT6320_ID_VIO18, + MT6320_ID_VPA, + MT6320_ID_VRF18, + MT6320_ID_VRF18_2, + + /* Digital LDO */ + MT6320_ID_VIO28, + MT6320_ID_VUSB, + MT6320_ID_VMC1, + MT6320_ID_VMCH1, + MT6320_ID_VEMC_3V3, + MT6320_ID_VEMC_1V8, + MT6320_ID_VGP1, + MT6320_ID_VGP2, + MT6320_ID_VGP3, + MT6320_ID_VGP4, + MT6320_ID_VGP5, + MT6320_ID_VGP6, + MT6320_ID_VSIM1, + MT6320_ID_VSIM2, + MT6320_ID_VIBR, + MT6320_ID_VRTC, + MT6320_ID_VAST, + + /* Analog LDO */ + MT6320_ID_VRF28, + MT6320_ID_VRF28_2, + MT6320_ID_VTCXO, + MT6320_ID_VTCXO_2, + MT6320_ID_VA, + MT6320_ID_VA28, + MT6320_ID_VCAMA, + + MT6320_ID_RG_MAX, +}; + +#define MT6320_MAX_REGULATOR MT6320_ID_RG_MAX + +#endif /* __LINUX_REGULATOR_MT6320_H */ diff --git a/include/linux/rmi.h b/include/linux/rmi.h index ab7eea01ab4274..c7d46edad16285 100644 --- a/include/linux/rmi.h +++ b/include/linux/rmi.h @@ -208,6 +208,9 @@ struct rmi_device_platform_data_spi { * @reset_delay_ms - after issuing a reset command to the touch sensor, the * driver waits a few milliseconds to give the firmware a chance to * re-initialize. You can override the default wait period here. + * @initial_reset_control - optional F01 Control 0 value written before the + * reset command. + * @initial_reset_delay_ms - delay after the initial reset command. * @irq: irq associated with the attn gpio line, or negative */ struct rmi_device_platform_data { @@ -220,6 +223,8 @@ struct rmi_device_platform_data { struct rmi_2d_sensor_platform_data sensor_pdata; struct rmi_f01_power_management power_management; struct rmi_gpio_data gpio_data; + u32 initial_reset_control; + u32 initial_reset_delay_ms; }; /** diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h index 4885b065b849fb..2345c8c1f5af05 100644 --- a/include/linux/soc/mediatek/mtk-mmsys.h +++ b/include/linux/soc/mediatek/mtk-mmsys.h @@ -21,6 +21,7 @@ enum mtk_dpi_out_format_con { }; enum mtk_ddp_comp_id { + DDP_COMPONENT_2DSHARP, DDP_COMPONENT_AAL0, DDP_COMPONENT_AAL1, DDP_COMPONENT_BLS, @@ -78,9 +79,13 @@ enum mtk_ddp_comp_id { DDP_COMPONENT_RDMA1, DDP_COMPONENT_RDMA2, DDP_COMPONENT_RDMA4, + DDP_COMPONENT_ROT, + DDP_COMPONENT_SCL, + DDP_COMPONENT_TDSHP, DDP_COMPONENT_UFOE, DDP_COMPONENT_WDMA0, DDP_COMPONENT_WDMA1, + DDP_COMPONENT_DBI0, DDP_COMPONENT_ID_MAX, }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 269c31ce081431..e1321616cfd06a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -164,6 +164,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MAX9877 imply SND_SOC_MC13783 imply SND_SOC_ML26124 + imply SND_SOC_MT6323 imply SND_SOC_MT6351 imply SND_SOC_MT6357 imply SND_SOC_MT6358 @@ -2767,6 +2768,27 @@ config SND_SOC_ML26124 tristate depends on I2C +config SND_SOC_MT6320 + tristate "MediaTek MT6320 Codec" + depends on MFD_MT6397 + select SND_SOC_MEDIATEK + help + Enable support for the MT6320 PMIC analog codec, which sits + behind the MT6397 MFD parent rather than on its own I2C + address. The codec provides the headphone, speaker and + microphone analog paths and the AFE-side serial link; the + external headset detection cell is a separate option, + SND_SOC_MT6320_ACCDET. + +config SND_SOC_MT6320_ACCDET + tristate "MediaTek MT6320 ACCDET" + depends on MFD_MT6397 + depends on IIO + depends on SND_SOC + help + Enable headset/accessory detection for the MediaTek MT6320 + PMIC on MT6589 platforms. + config SND_SOC_MT6351 tristate "MediaTek MT6351 Codec" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 172861d17cfd06..3b8c7b1b9554bc 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -187,6 +187,7 @@ snd-soc-mc13783-y := mc13783.o snd-soc-ml26124-y := ml26124.o snd-soc-msm8916-analog-y := msm8916-wcd-analog.o snd-soc-msm8916-digital-y := msm8916-wcd-digital.o +snd-soc-mt6323-y := mt6323.o mt6323-accdet.o snd-soc-mt6351-y := mt6351.o snd-soc-mt6357-y := mt6357.o snd-soc-mt6358-y := mt6358.o @@ -621,6 +622,9 @@ obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o obj-$(CONFIG_SND_SOC_MT6357) += snd-soc-mt6357.o +obj-$(CONFIG_SND_SOC_MT6323) += snd-soc-mt6323.o +obj-$(CONFIG_SND_SOC_MT6320) += mt6320.o +obj-$(CONFIG_SND_SOC_MT6320_ACCDET) += mt6320-accdet.o obj-$(CONFIG_SND_SOC_MT6358) += snd-soc-mt6358.o obj-$(CONFIG_SND_SOC_MT6359) += snd-soc-mt6359.o obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o diff --git a/sound/soc/codecs/mt6320-accdet.c b/sound/soc/codecs/mt6320-accdet.c new file mode 100644 index 00000000000000..f7fc6fca162ad4 --- /dev/null +++ b/sound/soc/codecs/mt6320-accdet.c @@ -0,0 +1,1015 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek MT6320 headset accessory detection. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MT6320_INT_CON_ACCDET_SET MT6320_INT_CON1_SET +#define MT6320_INT_CON_ACCDET_CLR MT6320_INT_CON1_CLR + +#define MT6320_ACCDET_CTRL MT6320_ACCDET_CON1 +#define MT6320_ACCDET_STATE_SWCTRL MT6320_ACCDET_CON2 +#define MT6320_ACCDET_PWM_WIDTH MT6320_ACCDET_CON3 +#define MT6320_ACCDET_PWM_THRESH MT6320_ACCDET_CON4 +#define MT6320_ACCDET_EN_DELAY_NUM MT6320_ACCDET_CON5 +#define MT6320_ACCDET_DEBOUNCE0 MT6320_ACCDET_CON6 +#define MT6320_ACCDET_DEBOUNCE1 MT6320_ACCDET_CON7 +#define MT6320_ACCDET_DEBOUNCE3 MT6320_ACCDET_CON9 +#define MT6320_ACCDET_IRQ_STS MT6320_ACCDET_CON11 +#define MT6320_ACCDET_STATE_RG MT6320_ACCDET_CON13 + + +#define MT6320_ACCDET_KEY_SAMPLE_MS 60 +/* + * Settle time before the first cable-class read after a plug-in. The stock + * driver never reads ACCDET_STATE_RG until its debounce window has elapsed + * (it is interrupt driven, and the interrupt is the debounced transition), + * so sampling earlier would race the PWM. 200 ms covers DEBOUNCE1 = 0x800 + * plus EN_DELAY (rise/fall 0x01f0 cycles) with margin. + */ +#define MT6320_ACCDET_SETTLE_MS 200 + +#define MT6320_ACCDET_CTRL_EN BIT(0) +#define MT6320_ACCDET_SWCTRL_EN 0x07 +#define MT6320_ACCDET_IRQ_CLR_BIT BIT(8) +#define MT6320_ACCDET_IRQ_STATUS_BIT BIT(0) +#define MT6320_ACCDET_IRQ_SET_BIT BIT(2) +#define MT6320_ACCDET_RESET_BIT BIT(4) + +#define MT6320_ACCDET_PWM_WIDTH_VALUE 0x0900 +#define MT6320_ACCDET_PWM_THRESH_VALUE 0x0200 +#define MT6320_ACCDET_EN_DELAY_VALUE ((1U << 15) | 0x01f0) +#define MT6320_ACCDET_DEBOUNCE0_VALUE 0x0800 +#define MT6320_ACCDET_DEBOUNCE1_VALUE 0x0800 +#define MT6320_ACCDET_DEBOUNCE3_VALUE 0x0020 +/* + * Hook switch debounce while a headset is present. The stock driver + * shortens it so a remote button press is noticed quickly during a + * call, then restores it once the hook switch settles. + */ +#define MT6320_ACCDET_DEBOUNCE0_BTN 0x0400 +/* + * Mic bias / AUXADC switch. This board uses ACCDET_28V_MODE, where the + * downstream driver drives AUDENCSPARE_CON0 rather than the ACCDET_RSV + * (ACCDET_CON0) 1.9 V encoding. + * + * This is the switch the *analog* mic-bias supply hangs off, not a gate on + * jack presence, and the vendor drives it from the analog path rather than + * from headset detection: accdet_auxadc_switch() sets it while it reads the + * key ADC (accdet.c:159-181), and accdet_eint_work_callback() clears it when + * it tears the detector down on plug-out (accdet.c:410-417, the + * ACCDET_28V_MODE branch writing 0x0732 = 0x00). Nothing in the vendor + * detection path waits on it, so a failure to write it must not abort + * plug-in handling either. + */ +#define MT6320_AUDENCSPARE_CON0 0x0732 +#define MT6320_ACCDET_MICBIAS_ENABLE 0x01 +#define MT6320_ACCDET_MICBIAS_DISABLE 0x00 + +struct mt6320_accdet { + struct device *dev; + struct regmap *regmap; + struct clk *clk_accdet; + struct gpio_desc *detect; + struct iio_channel *key; + struct snd_soc_jack *jack; + struct mutex lock; + struct delayed_work key_work; + struct delayed_work eint_work; + struct delayed_work class_work; + int accdet_irq; + int eint_irq; + int last_state; + bool plugged; +}; + +static int mt6320_accdet_clear_irq(struct mt6320_accdet *priv) +{ + unsigned int val; + int ret; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_IRQ_STS, + MT6320_ACCDET_IRQ_CLR_BIT); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(priv->regmap, + MT6320_ACCDET_IRQ_STS, val, + !(val & MT6320_ACCDET_IRQ_STATUS_BIT), + 500, 15000); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, MT6320_ACCDET_IRQ_STS, &val); + if (ret) + return ret; + + return regmap_write(priv->regmap, MT6320_ACCDET_IRQ_STS, + val & ~MT6320_ACCDET_IRQ_CLR_BIT); +} + +static void mt6320_accdet_report(struct mt6320_accdet *priv, + unsigned int report) +{ + static const unsigned int mask = + SND_JACK_HEADPHONE | + SND_JACK_HEADSET | + SND_JACK_BTN_0 | + SND_JACK_BTN_1 | + SND_JACK_BTN_2; + + /* + * A missing jack here used to be entirely silent, and that is a + * bad failure mode for exactly the bug this driver keeps having: + * mt6320_accdet_set_jack() stores whatever it is given, and the + * machine driver treats a negative return as fatal-but-ignorable, so + * if binding ever missed, every report below would be dropped and + * nothing in dmesg would say so - the jack simply never changes + * state and the speaker/headphone handover never happens. + * + * Warn once per report so dmesg answers "is the report path even + * connected?" without needing debugfs on the device. + */ + if (!priv->jack) { + dev_warn_ratelimited(priv->dev, + "jack report 0x%x dropped: no snd_soc_jack bound\n", + report); + return; + } + + snd_soc_jack_report(priv->jack, report, mask); +} + +static int mt6320_accdet_key(struct mt6320_accdet *priv) +{ + int uv, mv; + int ret; + + if (!priv->key) + return -1; + + ret = iio_read_channel_processed(priv->key, &uv); + if (ret) + return -1; + + /* + * The AUXADC driver advertises its 1.2 V full-scale 10-bit range + * through IIO_CHAN_INFO_SCALE, so take the converted value from the + * IIO core rather than repeating the constants here and risking the + * two drifting apart. The processed value is in microvolts, and + * the Blade BSP thresholds below are in millivolts. + */ + mv = uv / 1000; + + /* + * Blade BSP thresholds: + * 0..89mV middle + * 90..239mV up + * 240..499mV down + */ + if (mv < 90) + return SND_JACK_BTN_0; + if (mv < 240) + return SND_JACK_BTN_1; + if (mv < 500) + return SND_JACK_BTN_2; + + return -1; +} + +static void mt6320_accdet_key_work(struct work_struct *work) +{ + struct mt6320_accdet *priv = + container_of(to_delayed_work(work), + struct mt6320_accdet, key_work); + unsigned int val; + int state; + int button; + + mutex_lock(&priv->lock); + + if (!priv->plugged || !priv->jack || priv->last_state != 0) + goto out; + + if (regmap_read(priv->regmap, MT6320_ACCDET_STATE_RG, &val)) + goto out; + + state = FIELD_GET(GENMASK(7, 6), val); + if (state != 0) { + if (priv->last_state == 0) { + if (state == 1) + mt6320_accdet_report(priv, + SND_JACK_HEADSET); + else if (state == 3) + mt6320_accdet_report(priv, 0); + } + priv->last_state = state; + goto out; + } + + button = mt6320_accdet_key(priv); + if (button >= 0) + mt6320_accdet_report(priv, SND_JACK_HEADSET | button); + else + mt6320_accdet_report(priv, SND_JACK_HEADSET); + + schedule_delayed_work(&priv->key_work, + msecs_to_jiffies(MT6320_ACCDET_KEY_SAMPLE_MS)); + +out: + mutex_unlock(&priv->lock); +} + +static void mt6320_accdet_handle_state(struct mt6320_accdet *priv) +{ + unsigned int val; + int state; + int ret; + bool start_key_work = false; + + ret = regmap_read(priv->regmap, MT6320_ACCDET_STATE_RG, &val); + if (ret) + return; + + state = FIELD_GET(GENMASK(7, 6), val); + + switch (state) { + case 0: + if (priv->last_state == 1) { + int button = mt6320_accdet_key(priv); + + if (button >= 0) + mt6320_accdet_report(priv, + SND_JACK_HEADSET | button); + else + mt6320_accdet_report(priv, SND_JACK_HEADSET); + start_key_work = true; + } else if (priv->last_state != 0) { + mt6320_accdet_report(priv, SND_JACK_HEADPHONE); + } + break; + case 1: + /* + * Entering MIC_BIAS: shorten the hook switch debounce so a + * remote button press is picked up quickly, and re-assert + * the mic bias duty cycle. The stock driver restores the + * regular debounce on the next transition out of MIC_BIAS. + */ + if (priv->last_state != 1) { + ret = regmap_write(priv->regmap, + MT6320_ACCDET_DEBOUNCE0, + MT6320_ACCDET_DEBOUNCE0_BTN); + if (ret) + return; + ret = regmap_write(priv->regmap, + MT6320_ACCDET_PWM_WIDTH, + MT6320_ACCDET_PWM_WIDTH_VALUE); + if (ret) + return; + /* + * The threshold keeps its own value. Downstream + * writes the width into this register too, but only + * under ACCDET_PIN_RECOGNIZATION, which this board + * does not enable. + */ + ret = regmap_write(priv->regmap, + MT6320_ACCDET_PWM_THRESH, + MT6320_ACCDET_PWM_THRESH_VALUE); + if (ret) + return; + } + + mt6320_accdet_report(priv, SND_JACK_HEADSET); + break; + case 2: + /* Leaving MIC_BIAS: restore the regular debounce window. */ + ret = regmap_write(priv->regmap, MT6320_ACCDET_DEBOUNCE0, + MT6320_ACCDET_DEBOUNCE0_VALUE); + if (ret) + return; + break; + case 3: + /* + * Class 3 means the detector sees no cable, which on a + * headphone-only plug is also what ACCDET_STATE_RG reads + * while the PWM is still settling. Presence comes from the + * detect GPIO, so never let this clear a jack that the GPIO + * says is seated: report it as headphones, which is the + * conservative class for an unclassified seated jack. The + * plug-out path reports the removal. + */ + mt6320_accdet_report(priv, SND_JACK_HEADPHONE); + break; + default: + break; + } + + priv->last_state = state; + + if (start_key_work) + schedule_delayed_work(&priv->key_work, + msecs_to_jiffies( + MT6320_ACCDET_KEY_SAMPLE_MS)); +} + +/* + * Resolve the cable class right after a plug-in, without waiting for the + * ACCDET interrupt. + * + * The vendor leaves this to the interrupt, but only because its own EINT + * work has just armed the detector. Reading ACCDET_STATE_RG immediately + * would sample mid-transition: the PWM needs its debounce window + * (ACCDET_DEBOUNCE1 = 0x800 on this board) to settle before AB is valid. + * So wait that window out in work context, then run the normal state + * handler, which does the full headphone-vs-headset distinction and starts + * the key scanner. + * + * This cannot be the key worker: that one deliberately returns early + * unless the class is already resolved and the jack is seated. + */ +static void mt6320_accdet_class_work(struct work_struct *work) +{ + struct mt6320_accdet *priv = + container_of(to_delayed_work(work), struct mt6320_accdet, + class_work); + + mutex_lock(&priv->lock); + if (priv->plugged) + mt6320_accdet_handle_state(priv); + mutex_unlock(&priv->lock); +} + +static void mt6320_accdet_read_class(struct mt6320_accdet *priv) +{ + schedule_delayed_work(&priv->class_work, + msecs_to_jiffies(MT6320_ACCDET_SETTLE_MS)); +} + +static int mt6320_accdet_enable(struct mt6320_accdet *priv) +{ + int ret, cleanup_ret; + + ret = clk_prepare_enable(priv->clk_accdet); + if (ret) + return ret; + + ret = regmap_set_bits(priv->regmap, MT6320_ACCDET_STATE_SWCTRL, + MT6320_ACCDET_SWCTRL_EN); + if (ret) + goto err_clk; + + ret = regmap_set_bits(priv->regmap, MT6320_ACCDET_CTRL, + MT6320_ACCDET_CTRL_EN); + if (ret) + goto err_swctrl; + + ret = regmap_write(priv->regmap, MT6320_INT_CON_ACCDET_SET, + MT6320_ACCDET_IRQ_SET_BIT); + if (ret) + goto err_ctrl; + + return 0; + +err_ctrl: + cleanup_ret = regmap_clear_bits(priv->regmap, MT6320_ACCDET_CTRL, + MT6320_ACCDET_CTRL_EN); + if (cleanup_ret) + dev_err_ratelimited(priv->dev, + "failed to roll back ACCDET control: %d\n", + cleanup_ret); +err_swctrl: + cleanup_ret = regmap_clear_bits(priv->regmap, + MT6320_ACCDET_STATE_SWCTRL, + MT6320_ACCDET_SWCTRL_EN); + if (cleanup_ret) + dev_err_ratelimited(priv->dev, + "failed to roll back ACCDET switch control: %d\n", + cleanup_ret); +err_clk: + clk_disable_unprepare(priv->clk_accdet); + return ret; +} + +static int mt6320_accdet_disable_hw(struct mt6320_accdet *priv) +{ + int ret, first_err = 0; + + ret = regmap_write(priv->regmap, MT6320_INT_CON_ACCDET_CLR, + MT6320_ACCDET_IRQ_SET_BIT); + if (ret && !first_err) + first_err = ret; + + ret = mt6320_accdet_clear_irq(priv); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(priv->regmap, MT6320_ACCDET_CTRL, + MT6320_ACCDET_CTRL_EN); + if (ret && !first_err) + first_err = ret; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_STATE_SWCTRL, 0); + if (ret && !first_err) + first_err = ret; + + return first_err; +} + +static int mt6320_accdet_disable(struct mt6320_accdet *priv) +{ + int ret; + + ret = mt6320_accdet_disable_hw(priv); + clk_disable_unprepare(priv->clk_accdet); + return ret; +} + +static int mt6320_accdet_hw_init(struct mt6320_accdet *priv) +{ + int ret; + + ret = clk_prepare_enable(priv->clk_accdet); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_TOP_RST_ACCDET_SET, + MT6320_ACCDET_RESET_BIT); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_TOP_RST_ACCDET_CLR, + MT6320_ACCDET_RESET_BIT); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_PWM_WIDTH, + MT6320_ACCDET_PWM_WIDTH_VALUE); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_PWM_THRESH, + MT6320_ACCDET_PWM_THRESH_VALUE); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_STATE_SWCTRL, + MT6320_ACCDET_SWCTRL_EN); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_EN_DELAY_NUM, + MT6320_ACCDET_EN_DELAY_VALUE); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_DEBOUNCE0, + MT6320_ACCDET_DEBOUNCE0_VALUE); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_DEBOUNCE1, + MT6320_ACCDET_DEBOUNCE1_VALUE); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_ACCDET_DEBOUNCE3, + MT6320_ACCDET_DEBOUNCE3_VALUE); + if (ret) + goto err_clk; + + ret = regmap_write(priv->regmap, MT6320_INT_CON_ACCDET_CLR, + MT6320_ACCDET_IRQ_SET_BIT); + if (ret) + goto err_clk; + + ret = mt6320_accdet_clear_irq(priv); + clk_disable_unprepare(priv->clk_accdet); + + return ret; + +err_clk: + clk_disable_unprepare(priv->clk_accdet); + return ret; +} + +/* + * The PMIC's ACCDET interrupt only ever reports that the *debounced* cable + * class moved, which the vendor only ever arms while a jack is already + * seated: enable_accdet() runs from the EINT plug-in work + * (accdet.c:344-360) and disable_accdet() from the plug-out work + * (accdet.c:288-303). Our detect GPIO handler below is the authority on + * presence, so this handler reports a class change and nothing else. It + * must not be used to decide plugged/unplugged: with the jack out the + * detector is torn down and this line never fires at all. + */ +static irqreturn_t mt6320_accdet_irq(int irq, void *data) +{ + struct mt6320_accdet *priv = data; + unsigned int val; + + mutex_lock(&priv->lock); + + if (!regmap_read(priv->regmap, MT6320_ACCDET_IRQ_STS, &val) && + (val & MT6320_ACCDET_IRQ_STATUS_BIT) && priv->plugged) + mt6320_accdet_handle_state(priv); + + mt6320_accdet_clear_irq(priv); + mutex_unlock(&priv->lock); + + return IRQ_HANDLED; +} + +static irqreturn_t mt6320_accdet_eint(int irq, void *data); + +static void mt6320_accdet_eint_work(struct work_struct *work) +{ + struct mt6320_accdet *priv = + container_of(to_delayed_work(work), struct mt6320_accdet, + eint_work); + int inserted; + int ret; + + inserted = gpiod_get_value_cansleep(priv->detect); + if (inserted < 0) + goto retry; + + mutex_lock(&priv->lock); + if (!!inserted != priv->plugged) { + /* Recover a transition missed while switching the IRQ edge. */ + mutex_unlock(&priv->lock); + mt6320_accdet_eint(priv->eint_irq, priv); + return; + } + + ret = irq_set_irq_type(priv->eint_irq, + priv->plugged ? IRQ_TYPE_LEVEL_HIGH : + IRQ_TYPE_LEVEL_LOW); + mutex_unlock(&priv->lock); + if (!ret) + return; + +retry: + schedule_delayed_work(&priv->eint_work, msecs_to_jiffies(100)); +} + +static irqreturn_t mt6320_accdet_eint(int irq, void *data) +{ + struct mt6320_accdet *priv = data; + int inserted; + int ret; + + inserted = gpiod_get_value_cansleep(priv->detect); + if (inserted < 0) { + dev_err_ratelimited(priv->dev, + "failed to read detect GPIO: %d\n", + inserted); + return IRQ_HANDLED; + } + + /* + * Log every detected transition. + * + * The EINT is the only source of jack presence, and its plumbing + * (pin table, EIC domain enable, mask/unmask, debounce, level + * polarity) all reads correctly in this tree, so the question "did the + * interrupt arrive, and what level did the pad actually show?" cannot + * be answered by reading the code - it needs a hardware observation. + * This line is that observation: it fires only on a real transition, + * so its absence over a plug/unplug cycle means the EINT never + * reached us, and its presence together with an implausible level + * means the pad or its polarity is wrong rather than the report path. + */ + dev_info(priv->dev, "detect: gpio level %d -> %s\n", inserted, + inserted ? "plugged" : "unplugged"); + + /* + * Stop the key scanner before taking the lock on plug-out: the + * worker needs the lock itself, so cancelling it underneath would + * deadlock. It would otherwise re-arm itself, read the ACCDET + * state again and could report a second removal, and it reads the + * AUXADC, which no longer makes sense once the jack is empty. + */ + if (!inserted) { + cancel_delayed_work_sync(&priv->class_work); + cancel_delayed_work_sync(&priv->key_work); + } + + mutex_lock(&priv->lock); + + if (!!inserted == priv->plugged) + goto out; + + if (!!inserted) { + /* + * The mic-bias switch is not a prerequisite for detection: the + * vendor turns it on to read the key ADC and off again when it + * tears the detector down, but its own plug-in path never waits + * on it. Treat a failure here as non-fatal, otherwise a single + * unwritable analog register disables headset detection + * entirely and the speaker route is never handed over. + */ + ret = regmap_write(priv->regmap, MT6320_AUDENCSPARE_CON0, + MT6320_ACCDET_MICBIAS_ENABLE); + if (ret) + dev_err_ratelimited(priv->dev, + "failed to enable mic bias switch: %d\n", + ret); + + ret = mt6320_accdet_enable(priv); + if (ret) { + dev_err_ratelimited(priv->dev, + "failed to enable ACCDET: %d\n", + ret); + if (regmap_write(priv->regmap, MT6320_AUDENCSPARE_CON0, + MT6320_ACCDET_MICBIAS_DISABLE)) + dev_err_ratelimited(priv->dev, + "failed to roll back mic bias switch\n"); + goto out; + } + + /* + * detect-gpios is GPIO_ACTIVE_LOW, so the line is asserted + * (logical 1 / physical low) while the jack is in. Wait for + * it to leave that state, i.e. level-high in logical terms. + */ + ret = irq_set_irq_type(priv->eint_irq, + IRQ_TYPE_LEVEL_HIGH); + if (ret) { + dev_err_ratelimited(priv->dev, + "failed to configure plug-in IRQ: %d\n", + ret); + priv->plugged = false; + if (mt6320_accdet_disable(priv)) + dev_err_ratelimited(priv->dev, + "failed to roll back ACCDET after IRQ setup failure\n"); + if (regmap_write(priv->regmap, MT6320_AUDENCSPARE_CON0, + MT6320_ACCDET_MICBIAS_DISABLE)) + dev_err_ratelimited(priv->dev, + "failed to roll back mic bias switch\n"); + schedule_delayed_work(&priv->eint_work, + msecs_to_jiffies(100)); + goto out; + } + + priv->plugged = true; + + /* + * Report the jack. The detect GPIO is the authority on + * presence - the vendor only ever arms the PMIC ACCDET unit + * from this same plug-in work (accdet.c accdet_eint_work_callback + * -> accdet_init()/enable_accdet()) and tears it down on + * plug-out, so the ACCDET interrupt cannot be relied on to + * announce the jack in the first place. + * + * This is the whole of problem 1: the plug-in path used to set + * priv->plugged and return without ever reporting, and the only + * other caller of mt6320_accdet_report() is the ACCDET + * interrupt, which does not fire while the detector is off. + * The jack therefore never left its empty state, the Speaker + * pin was never disabled, and plugging headphones changed + * nothing. + * + * Report the conservative class first (headphone only) so the + * speaker is handed over even if the detector does not settle, + * then let the poll below refine it to a headset with mic. + * mt6320_accdet_handle_state() runs the same distinction once + * ACCDET reports. + */ + priv->last_state = 3; + mt6320_accdet_report(priv, SND_JACK_HEADPHONE); + + /* + * Give the detector time to resolve the cable class before + * reading it. The stock driver arms the same PWM + * (ACCDET_PWM_WIDTH 0x900, DEBOUNCE1 0x800) and only reads + * ACCDET_STATE_RG from its interrupt, i.e. after the debounce + * window has elapsed; we read it directly, so wait at least + * that long rather than sampling mid-transition. + */ + mt6320_accdet_read_class(priv); + } else { + /* + * Drop the mic-bias switch, as the vendor does at the end of + * its plug-out work: accdet_eint_work_callback() writes + * 0x0732 = 0x00 in the ACCDET_28V_MODE branch + * (mediatek/platform/mt6589/kernel/drivers/accdet/accdet.c, + * "ACCDET diable switch in 2.8v mode"). The 0x1090 word in + * the same place belongs to the 1.9 V ACCDET_RSV encoding, + * which this board does not use. + * + * This is the analog mic-bias supply switch, not a presence + * gate: the AUXADC driver asserts it for each voltage read, so + * it has to be dropped again on the way out or it keeps + * driving bias into an unpopulated connector. + */ + ret = regmap_write(priv->regmap, MT6320_AUDENCSPARE_CON0, + MT6320_ACCDET_MICBIAS_DISABLE); + if (ret) + dev_err_ratelimited(priv->dev, + "failed to disable mic bias: %d\n", + ret); + + ret = mt6320_accdet_disable(priv); + if (ret) + dev_err_ratelimited(priv->dev, + "failed to disable ACCDET: %d\n", + ret); + + priv->plugged = false; + priv->last_state = 3; + mt6320_accdet_report(priv, 0); + + /* Jack is out; wait for insertion, i.e. the active level. */ + ret = irq_set_irq_type(priv->eint_irq, + IRQ_TYPE_LEVEL_LOW); + if (ret) { + dev_err_ratelimited(priv->dev, + "failed to configure next plug-in IRQ: %d\n", + ret); + schedule_delayed_work(&priv->eint_work, + msecs_to_jiffies(100)); + } + } + +out: + mutex_unlock(&priv->lock); + return IRQ_HANDLED; +} + +static int mt6320_accdet_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) +{ + struct mt6320_accdet *priv = + snd_soc_component_get_drvdata(component); + + mutex_lock(&priv->lock); + priv->jack = jack; + if (!jack) { + mutex_unlock(&priv->lock); + return 0; + } + /* + * Always publish a full-mask report. The Speaker jack pin is + * inverted on SND_JACK_HEADPHONE; without an initial report DAPM + * never enables it and the built-in speaker stays silent even + * though the AFE period IRQ is running. + * + * When a jack is already seated at bind time the detector has not + * been armed (probe only runs the hardware init; the detector is + * enabled from the plug-in work), so ACCDET_STATE_RG carries + * whatever it held last rather than a live class. Report the + * conservative headphone-only class and let the settle worker + * refine it once the detector is running - reporting straight from + * handle_state() here would trust a stale register. + */ + if (priv->plugged) { + mt6320_accdet_report(priv, SND_JACK_HEADPHONE); + mt6320_accdet_read_class(priv); + } else { + mt6320_accdet_report(priv, 0); + } + mutex_unlock(&priv->lock); + + return 0; +} + +static const struct snd_soc_component_driver mt6320_accdet_component = { + .name = "mt6320-accdet", + .set_jack = mt6320_accdet_set_jack, +}; + +static int mt6320_accdet_probe(struct platform_device *pdev) +{ + struct mt6320_accdet *priv; + struct mt6397_chip *pmic; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + pmic = dev_get_drvdata(pdev->dev.parent); + if (!pmic || !pmic->regmap) + return dev_err_probe(&pdev->dev, -ENODEV, + "missing PMIC regmap\n"); + priv->regmap = pmic->regmap; + + priv->clk_accdet = devm_clk_get(&pdev->dev, "accdet"); + if (IS_ERR(priv->clk_accdet)) + return dev_err_probe(&pdev->dev, + PTR_ERR(priv->clk_accdet), + "failed to get ACCDET clock\n"); + + mutex_init(&priv->lock); + INIT_DELAYED_WORK(&priv->key_work, mt6320_accdet_key_work); + INIT_DELAYED_WORK(&priv->eint_work, mt6320_accdet_eint_work); + INIT_DELAYED_WORK(&priv->class_work, mt6320_accdet_class_work); + platform_set_drvdata(pdev, priv); + + priv->detect = devm_gpiod_get(&pdev->dev, "detect", GPIOD_IN); + if (IS_ERR(priv->detect)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->detect), + "failed to get detect GPIO\n"); + + priv->key = devm_iio_channel_get(&pdev->dev, "key"); + if (IS_ERR(priv->key)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->key), + "failed to get key ADC\n"); + + ret = mt6320_accdet_hw_init(priv); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to initialize ACCDET\n"); + + priv->accdet_irq = + platform_get_irq_byname(pdev, "accdet_irq"); + if (priv->accdet_irq < 0) + return priv->accdet_irq; + + ret = devm_request_threaded_irq(&pdev->dev, priv->accdet_irq, + NULL, mt6320_accdet_irq, + IRQF_ONESHOT, + "mt6320-accdet", priv); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to request ACCDET IRQ\n"); + + priv->eint_irq = gpiod_to_irq(priv->detect); + if (priv->eint_irq < 0) + return dev_err_probe(&pdev->dev, priv->eint_irq, + "failed to map detect GPIO to IRQ\n"); + + ret = gpiod_get_value_cansleep(priv->detect); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "failed to read detect GPIO\n"); + priv->plugged = !!ret; + priv->last_state = 3; + + /* + * Record the level seen at probe. The jack is usually empty here, so + * this should read 0 (including on the very first boot, where nothing + * has touched the pad yet), and it is the baseline the per-transition + * log below is compared against. + */ + dev_info(&pdev->dev, "detect: gpio level at probe %d (%s)\n", + ret, ret ? "plugged" : "unplugged"); + + /* + * Arm for the level that reports the *next* transition. + * + * The detect line is level-triggered on the vendor board, not edge. + * mediatek/custom/blade10/kernel/dct/dct/cust_eint.h declares + * CUST_EINT_ACCDET_SENSITIVE = CUST_EINT_LEVEL_SENSITIVE with + * CUST_EINT_ACCDET_TYPE = CUST_EINTF_TRIGGER_LOW and + * CUST_EINT_ACCDET_DEBOUNCE_CN = 256, and the vendor handler + * accdet_eint_func() (kernel_blade10_row_wifi.elf @ c054c75c) drives + * mt_eint_set_polarity(10, ...) on every interrupt to flip which level + * is active. mt_eint_set_polarity() writes EINT_POL_SET/CLR and then + * acks - the polarity register is the level control, so the vendor is + * genuinely running the line level-triggered and re-arming it by + * inverting the sense. + * + * detect-gpios is GPIO_ACTIVE_LOW, so the line is asserted (logical 1) + * while the jack is in. A line sitting at its active level would + * storm an edge-irrelevant handler, but this one is IRQF_ONESHOT and + * changes the polarity before returning, exactly as the vendor does, + * so the level deasserts and the next interrupt is the opposite + * transition. + */ + ret = irq_set_irq_type(priv->eint_irq, + priv->plugged ? + IRQ_TYPE_LEVEL_HIGH : IRQ_TYPE_LEVEL_LOW); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to configure detect IRQ\n"); + + ret = devm_request_threaded_irq(&pdev->dev, priv->eint_irq, + NULL, mt6320_accdet_eint, + IRQF_ONESHOT, + "mt6320-accdet-eint", priv); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to request detect IRQ\n"); + + /* + * Program the EINT debounce only now that the line is ours. + * + * gpiod_set_debounce() ends in mtk_eint_set_debounce(), which masks + * and then *unmasks* the EINT line it touches. Unmasking before + * request_irq() has run is not a harmless early enable: the EINT's + * polarity register still holds its reset value (mtk_eint_set_type() + * is what programs it, and that runs just above), the pin is still a + * GPIO (mtk_eint_irq_request_resources() is what calls + * set_gpio_as_eint(), and that only runs from the request) and no + * handler is registered. An edge arriving in that window latches the + * EINT status bit that mtk_eint_irq_handler() has to see and ack on + * behalf of a *child* handler; with no child registered, nothing acks + * it, the status register stays non-zero, and the chained handler + * spins on it forever. That is the observed symptom of the jack + * interrupt never arriving at all, and it is permanent for the boot. + * + * -EINVAL is tolerated: mtk_eint_can_en_debounce() accepts a debounce + * value only for a pin some other consumer marked debounce-capable, + * and nothing in this SoC's pin table does. The debounce is an + * optimisation for a mechanical jack switch, not a requirement. + */ + ret = gpiod_set_debounce(priv->detect, 256000); + if (ret && ret != -ENOTSUPP && ret != -EINVAL) + return dev_err_probe(&pdev->dev, ret, + "failed to set detect debounce\n"); + + if (priv->plugged) { + ret = regmap_write(priv->regmap, MT6320_AUDENCSPARE_CON0, + MT6320_ACCDET_MICBIAS_ENABLE); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to enable mic bias switch\n"); + + ret = mt6320_accdet_enable(priv); + if (ret) { + if (regmap_write(priv->regmap, MT6320_AUDENCSPARE_CON0, + MT6320_ACCDET_MICBIAS_DISABLE)) + dev_err(&pdev->dev, "failed to roll back mic bias switch\n"); + return dev_err_probe(&pdev->dev, ret, + "failed to enable ACCDET\n"); + } + } else { + ret = clk_prepare_enable(priv->clk_accdet); + if (!ret) { + ret = mt6320_accdet_disable_hw(priv); + clk_disable_unprepare(priv->clk_accdet); + } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to disable idle ACCDET\n"); + } + + return devm_snd_soc_register_component(&pdev->dev, + &mt6320_accdet_component, + NULL, 0); +} + +static void mt6320_accdet_remove(struct platform_device *pdev) +{ + struct mt6320_accdet *priv = platform_get_drvdata(pdev); + int ret = 0; + int bias_ret; + + cancel_delayed_work_sync(&priv->key_work); + cancel_delayed_work_sync(&priv->eint_work); + + mutex_lock(&priv->lock); + if (priv->plugged) + ret = mt6320_accdet_disable(priv); + priv->plugged = false; + priv->last_state = 3; + mt6320_accdet_report(priv, 0); + + /* The switch is ACCDET-owned and must be off even on driver removal. */ + bias_ret = regmap_write(priv->regmap, MT6320_AUDENCSPARE_CON0, + MT6320_ACCDET_MICBIAS_DISABLE); + if (!ret) + ret = bias_ret; + mutex_unlock(&priv->lock); + + if (ret) + dev_err(&pdev->dev, + "failed to clean up ACCDET during remove: %d\n", ret); +} + +static const struct of_device_id mt6320_accdet_of_match[] = { + { .compatible = "mediatek,mt6320-accdet" }, + { } +}; +MODULE_DEVICE_TABLE(of, mt6320_accdet_of_match); + +static struct platform_driver mt6320_accdet_driver = { + .probe = mt6320_accdet_probe, + .remove = mt6320_accdet_remove, + .driver = { + .name = "mt6320-accdet", + .of_match_table = mt6320_accdet_of_match, + }, +}; +module_platform_driver(mt6320_accdet_driver); + +MODULE_DESCRIPTION("MediaTek MT6320 headset accessory detection"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/mt6320.c b/sound/soc/codecs/mt6320.c new file mode 100644 index 00000000000000..ea8e2e853cc09f --- /dev/null +++ b/sound/soc/codecs/mt6320.c @@ -0,0 +1,1876 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek MT6320 PMIC analog audio codec. + * + * Analog audio back-end (DAC, headphone driver) of the MT6320 PMIC, + * reached over the parent mt6397 MFD pwrap regmap. The SoC-side AFE + * (mt6589 AFE driver) and the sound card are separate drivers. + * + * Register map follows the MT6589 BSP AudDrv_ANA: the analog blocks sit + * at 0x0700.. (AUDBUF/ZCD) and the ABB AFE bridge at 0x4000.., which + * differs from the MT6323 layout. Audio clocks come from CCF through + * the mt6320-clk provider instead of direct TOP_CKPDN poking. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Downlink and uplink rate sets, deliberately different. + * + * The downlink SRC covers the full nine-rate ladder 8/11.025/12/16/22.05/24/32/ + * 44.1/48 kHz. Note that SNDRV_PCM_RATE_8000_48000 does *not* contain 12000 or + * 24000: ALSA gives those two their own bits, added long after the range macro + * was defined (SNDRV_PCM_RATE_12000 = 1U<<17, SNDRV_PCM_RATE_24000 = 1U<<18, + * include/sound/pcm.h:127-128), so they have to be ORed in explicitly or a + * supported rate silently becomes unavailable to userspace. + * + * The uplink SRC is narrower - only 8/16/32/48 kHz are encodable - so the + * capture DAI must not advertise the others. See mt6320_ul_src_rate_code(). + * + * Deliberately absent: 88200, 96000 and 192000. The MT6589 data sheet's "6 kHz + * to 96 kHz" audio claim is not backed by anything in the hardware description + * available for this part, and every rate ladder reachable from this SoC tops + * out at 48000: + * + * - AFE memif / IRQ counters, u4SamplingRateConvert[9] + * (mediatek/platform/mt6589/kernel/drivers/ldvt/audio/AudioAfe.c:66) + * = {0,1,2,4,5,6,8,9,10} + * - the AFE kernel driver's own SampleRateTransform() + * (kernel/sound/soc/__mediatek/mt_soc_afe_control.c:374-400) has no case + * for anything above 48 kHz and falls through to `return ..._44K` + * - the codec downlink SRC, GetDLFrequency() + * (AudioPlatformDevice.cpp:91-127), codes 0..8 + * - the codec uplink SRC, GetULFrequency() + * (AudioPlatformDevice.cpp:130-152), codes 0x0/0x5/0xa/0xf + * + * The enum in the shared audio V2 header + * (mediatek/platform/common/hardware/audio/V2/include/AudioStreamAttribute.h:50-61) + * does define AFE_88K/96K/174K/192K, and the AFE kernel driver's + * Soc_Aud_I2S_SAMPLERATE repeats them (mt_soc_digital_type.h:256-259), but no + * code ever emits those values: SampleRateTransform() has no case for them, so + * 88.2/96/192 kHz would reach the hardware as 44.1 kHz. The DL_SRC2_CON0_H rate + * field is four bits wide (GENMASK(15,12) below) and the documented ladder 0..8 + * already fills it, so there is no code to extend it with either. Advertising + * these rates would mean playing 44.1 kHz while reporting 96 kHz, so they are + * rejected here rather than accepted and silently mistrusted. + */ +#define MT6320_CODEC_DL_RATES (SNDRV_PCM_RATE_8000_48000 | \ + SNDRV_PCM_RATE_12000 | \ + SNDRV_PCM_RATE_24000) + +/* Only the four rates the uplink SRC can encode. */ +#define MT6320_CODEC_UL_RATES (SNDRV_PCM_RATE_8000 | \ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_48000) + +/* + * Only S16_LE. The AFE memif's fetch widths are 16-bit and 32-bit-with-24-bit- + * data (SetMemIfFetchFormatPerSample, mt_soc_afe_control.c:1351-1390, writing + * AFE_MEMIF_PBUF_SIZE) - there is no 8-bit fetch format in that hardware, so + * U8 cannot be offered even though the downstream PCM advertises it + * (USE_FORMATS, mt_soc_pcm_afe.c:164). + */ +#define MT6320_CODEC_FORMATS SNDRV_PCM_FMTBIT_S16_LE + +/* + * Audio registers in the PMIC 16-bit space: ABB_AFE<->PMIC bridge @ 0x4000, + * AUDTOP analog DAC/headphone block @ 0x0700. + */ +#define MT6320_ABB_AFE_BASE 0x4000 +#define MT6320_ABB_AFE_CON(n) (MT6320_ABB_AFE_BASE + (n) * 2) + +/* + * Register names for the 0x4xxx window, all derived from + * MT6320_ABB_AFE_CON() so the 0x4000 base is written down exactly once. + * + * The vendor names are AudioAnalogReg.h (AFE_PMICDIG_AUDIO_BASE == 0x4000). + * Deriving them here rather than spelling out 0x4000/0x4002/... is the whole + * point: the 0x04xx block is a *different* window, holding the PMIC + * regulator/power registers (ANALDO_CON*, DIGLDO_CON*, VPROC_CON*, ...), and + * the two differ only in the high byte. A raw 0x4xxx literal is therefore + * the single easiest way to reintroduce this bug, so every AFE address in + * this file goes through the helper. + */ +#define MT6320_AFE_UL_DL_CON0 (MT6320_ABB_AFE_CON(0x00)) +#define MT6320_AFE_DL_SRC2_CON0_L (MT6320_ABB_AFE_CON(0x02)) +#define MT6320_AFE_DL_SRC2_CON1_H (MT6320_ABB_AFE_CON(0x03)) +#define MT6320_AFE_DL_SDM_CON1 (MT6320_ABB_AFE_CON(0x06)) +#define MT6320_AFE_UL_SRC_CON0_H (MT6320_ABB_AFE_CON(0x07)) +#define MT6320_AFE_UL_SRC_CON0_L (MT6320_ABB_AFE_CON(0x08)) +#define MT6320_AFE_UL_SRC_CON1_H (MT6320_ABB_AFE_CON(0x09)) +#define MT6320_AFE_I2S_FIFO_UL_CFG0 (MT6320_ABB_AFE_CON(0x10)) +#define MT6320_AFE_I2S_FIFO_DL_CFG0 (MT6320_ABB_AFE_CON(0x11)) +#define MT6320_AFE_ANA_AFE_TOP_CON0 (MT6320_ABB_AFE_CON(0x12)) +#define MT6320_AFE_ANA_AUDIO_TOP_CON0 (MT6320_ABB_AFE_CON(0x13)) +#define MT6320_AFE_AFUNC_AUD_CON0 (MT6320_ABB_AFE_CON(0x1a)) +#define MT6320_AFE_AFUNC_AUD_CON2 (MT6320_ABB_AFE_CON(0x1c)) +#define MT6320_ABB_AFE_DL_SRC2_CON0_H (MT6320_ABB_AFE_CON(0x01)) +/* + * The sample rate lives in bits [15:12], not a low nibble. The stock + * driver sets this register as 0x0300 | GetDLFrequency(rate), where + * GetDLFrequency() returns the code shifted left by twelve: 48 kHz gives + * 8 << 12, so the register becomes 0x8300. + */ +#define MT6320_ABB_AFE_DL_SRC2_CON0_H_RATE GENMASK(15, 12) +#define MT6320_ABB_AFE_DL_SRC2_CON0_H_BASE 0x0300 + +/* + * Capture (uplink) rate lives in UL_SRC_CON0_H at [4:1], which is a + * different position and a different encoding from the downlink one above: + * the vendor's GetULFrequency() returns the *unshifted* code and the + * sequence itself does the "<< 1", so 8 kHz (code 0x0) reaches the register + * as 0x00 and 48 kHz (code 0xf) as 0x1e. The field therefore needs bit 4 + * as well, not just [3:1]. Note also that GetULFrequency() only decodes + * 8/16/32/48 kHz and warns on anything else, so a rate it does not know + * silently programs 0 - which is why mt6320_ul_src_rate_code() rejects + * unsupported rates instead of reproducing that behaviour. + */ +#define MT6320_ABB_AFE_UL_SRC_CON0_H_RATE GENMASK(4, 1) + +/* + * AUDCLKGEN_CFG0 bit 1 gates the ADC clock. The vendor reaches this + * register as 0x0712 with mask 0x0002, so it only ever touches that one bit + * even though the register is shared with the SRC gate in bit 0. + */ +#define MT6320_ADCCLK_ENABLE BIT(1) + +/* B8000 vendor AnalogSetMux() encodings for the internal dual microphones. */ +#define MT6320_AUDPREAMP_L_INPUT_SEL GENMASK(4, 2) +#define MT6320_AUDPREAMP_R_INPUT_SEL GENMASK(7, 5) +#define MT6320_AUDPREAMP_L_MIC1 (1U << 2) +#define MT6320_AUDPREAMP_R_MIC3 (3U << 5) +#define MT6320_AUDPREAMP_POWER GENMASK(1, 0) + +/* + * AUD_NCP0 (0x071A) carries the audio LDO enables in bits [14:13]: + * DA_HCLDO_EN_VA33 and DA_LCLDO_EN_VA33 (upmu_hw.h:4328-4331). These are + * the supplies the DAC cores and the headphone amplifiers run from, and the + * vendor writes 0xe000 with mask 0xe000 at the top of every AnalogOpen case + * (AudioMachineDevice.cpp:711/:632/:223) and clears bits [14:13] on + * AnalogClose (:1184). Bit 15 is NCP_REMOTE_SENSE_VA18 and bit 11 is + * DA_VBATPREREG_EN_VBAT - neither is part of the playback enable, so name + * just the two bits that are. + */ +#define MT6320_AUD_NCP0_LDO_ENABLE (GENMASK(14, 13)) + +/* + * AFUNC_AUD_CON2 is the analog mute (bit 7), kept by name because the + * pre/post-PMU handlers below use it for both directions. + */ +#define MT6320_AFUNC_AUD_CON2 MT6320_AFE_AFUNC_AUD_CON2 + +/* ACCDET state is also used to select the wired-headset capture input. */ +#define MT6320_ACCDET_STATE_RG MT6320_ACCDET_CON13 +#define MT6320_ACCDET_STATE_MASK GENMASK(7, 6) +#define MT6320_ACCDET_STATE_HEADSET_MIC 1 +/* AUXADC and AUDENCSPARE_CON0 are owned by the ACCDET/AUXADC drivers. */ + +/* + * Headphone amplifier trim lives in the efuse data-out words. The + * kernel's MT6320 register header still labels these + * EFUSE_DOUT_112_127 / EFUSE_DOUT_128_143; name them for what they are + * used for here. Bit 12 of the first word is the "trim valid" flag. + */ +#define MT6320_EFUSE_DOUT_112_127 0x01c2 +#define MT6320_EFUSE_DOUT_128_143 0x01c4 +#define MT6320_PMIC_TRIM_REG1_DEFAULT 0x0220 +#define MT6320_PMIC_TRIM_REG2_DEFAULT 0x0006 +/* + * PMIC chip ID read from MT6320_CID, not a register address: + * PMIC6320_E1_CID_CODE / PMIC6320_E2_CID_CODE. The E2 revision selects the + * auto-trim path and the E2 regulator idle values. + */ +#define MT6320_E1_CID 0x1020 +#define MT6320_E2_CID 0x2020 +/* + * External speaker amplifier timing, from the vendor kernel's SN2145B + * support (mediatek/custom/common/kernel/sound/amp_sn2145b/ + * yusu_android_speaker.c): Sound_Speaker_Turnon() waits out the remainder of + * an 80 ms shutdown window before raising GPIO73, then warms up for 40 ms + * before audio is allowed through. + */ +#define MT6320_AMP_SHUTDOWN_MS 80 +#define MT6320_AMP_WARMUP_MS 40 +#define MT6320_EFUSE_DOUT_176_191 0x01ca +#define MT6320_SPK_TRIM_DEFAULT 0x0010 +/* + * SPK_CON1 carries the measured class-D offset on E2 silicon. E1 reads + * it from the trim efuse instead (see mt6320_apply_spk_trim()). + */ +#define MT6320_SPK_OFFSET_L_MODE BIT(14) +#define MT6320_SPK_OFFSET_L_SW GENMASK(12, 8) +/* SPK_CON11 is a one-hot software override selector, not a plain ramp. */ +#define MT6320_SPK_OUTSTG_EN_L_SW BIT(11) +#define MT6320_SPK_EN_L_SW BIT(9) +#define MT6320_SPK_OUTSTG_EN_R_SW BIT(10) +#define MT6320_SPK_EN_R_SW BIT(8) +#define ZCD_GAIN_0DB 8 +#define ZCD_GAIN_CTL_MAX 0x0c /* +8dB .. -4dB */ +#define ZCD_GAIN_REG(g) (((g) << 8) | (g)) +/* + * ZCD_CON2 bits [3:0] and [11:8]: the headphone left/right volume indexes, + * i.e. exactly the two fields SOC_DOUBLE_TLV below drives (shift 0 and 8). + * Named here so the power-down path can park the gain without also trampling + * the rest of the register the way a full 0x0c0c write does. + */ +#define MT6320_ZCD_CON2_VOL_MASK (GENMASK(11, 8) | GENMASK(3, 0)) + +struct mt6320_codec_priv { + struct device *dev; + struct regmap *regmap; /* borrowed from the parent MFD */ + struct clk *clk_aud26m; /* codec master clock via CCF */ + /* + * Sample rate code for the current stream, saved by hw_params() and + * read by the DAC and ADC power-up handlers. Those run from the + * DAPM stream events, which ASoC issues after hw_params() for the + * same substream, so the value is already valid by then. The vendor + * instead keeps the rate in mBlockSampleRate[] and consults it from + * AnalogOpen(); this is the equivalent for a codec that does not + * implement hw_params() before its widgets power up. + */ + unsigned int rate_code; + /* + * Same, for the capture (uplink) SRC, whose rate encoding is a + * different one from the downlink - see mt6320_ul_src_rate_code(). + */ + unsigned int ul_rate_code; + bool analog_output_active; + bool capture_active; + /* + * Speaker amplifier enable, when the board has one. The Blade drives + * an external amp from GPIO73 and GPIO142; the PMIC's own Class-D + * output is not connected to the speaker. Both pins are optional so + * boards with the PMIC speaker path keep working. + */ + struct gpio_desc *amp_en_gpio; + /* When the amplifier was last switched off, for the re-enable guard. */ + unsigned long amp_off_jiffies; + bool amp_on; +}; + +/* + * Downlink SRC rate code, i.e. the vendor's GetDLFrequency() before the <<12. + * + * This is a dense 0..8 ladder, distinct from the AFE's sparse one (see + * mt6589_afe_rate_code_sparse()); the two must not be unified. Verified + * case by case against GetDLFrequency(), AudioPlatformDevice.cpp:91-127. + */ +static int mt6320_dl_src_rate_code(unsigned int rate) +{ + switch (rate) { + case 8000: + return 0; + case 11025: + return 1; + case 12000: + return 2; + case 16000: + return 3; + case 22050: + return 4; + case 24000: + return 5; + case 32000: + return 6; + case 44100: + return 7; + case 48000: + return 8; + default: + /* + * The field is four bits wide (GENMASK(15,12) above) and the + * ladder above fills every documented code, so there is nothing + * to map a higher rate onto. 88200/96000/192000 in particular + * are rejected rather than approximated: encoding them as 9/10 + * would be invention, and letting them fall through would + * record at 48 kHz while reporting otherwise. + */ + return -EINVAL; + } +} + +/* + * Uplink rate code for the capture SRC, i.e. the vendor's GetULFrequency(). + * + * This is deliberately *not* mt6320_dl_src_rate_code(): the uplink uses a + * different encoding (see MT6320_ABB_AFE_UL_SRC_CON0_H_RATE) and the vendor + * only decodes 8/16/32/48 kHz, warning - and programming 0 - for anything + * else. + * + * That four-rate limit is why the capture DAI advertises + * MT6320_CODEC_UL_RATES rather than the full downlink ladder: it is a hardware + * restriction, not a conservative choice. The field itself is four bits wide + * (GENMASK(4,1) above) and only these four of its sixteen codes are documented, + * so the remaining rates cannot be extended without guessing at the SRC's + * divider encoding. The error return is still kept so a rate reaching this + * function by some other route fails loudly instead of silently recording at + * the wrong rate - which is exactly what GetULFrequency() does. + * + * Consequence: capture is limited to 8/16/32/48 kHz even though playback + * reaches 12 and 24 kHz. A 12 kHz or 24 kHz capture stream is refused at + * hw_params rather than mis-recorded. + */ +static int mt6320_ul_src_rate_code(unsigned int rate) +{ + switch (rate) { + case 8000: + return 0x0; + case 16000: + return 0x5; + case 32000: + return 0xa; + case 48000: + return 0xf; + default: + /* Unencodable in this SRC; see above. */ + return -EINVAL; + } +} + +static int mt6320_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mt6320_codec_priv *priv = + snd_soc_component_get_drvdata(dai->component); + unsigned int rate = params_rate(params); + bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + int rate_code, ul_rate_code; + + /* + * Validate only the ladder this direction actually uses. The two are + * different sizes: the downlink SRC covers 8/11.025/12/16/22.05/24/32/ + * 44.1/48 kHz while the uplink SRC covers only 8/16/32/48 kHz, so + * resolving the uplink code during a playback hw_params rejected + * perfectly valid playback rates such as 44.1 kHz. + */ + if (playback) { + rate_code = mt6320_dl_src_rate_code(rate); + if (rate_code < 0) + return rate_code; + + priv->rate_code = rate_code; + } else { + ul_rate_code = mt6320_ul_src_rate_code(rate); + if (ul_rate_code < 0) + return ul_rate_code; + + priv->ul_rate_code = ul_rate_code; + } + + /* + * Write the whole register rather than updating only the rate field. + * regmap_update_bits() computes (orig & ~mask) | (val & mask), and the + * mask covers just the rate bits - so the SRC-enable/base field + * (0x0300) was ANDed away and never reached the register, leaving the + * PMIC downlink SRC disabled. A plain write is what the stock driver + * effectively does, and what the comment above this call describes. + * + * Only the downlink SRC is programmed from here, and only for a + * playback stream: it is the playback SRC2 rate register, so a capture + * hw_params writing it would reprogram the running playback stream's + * rate. The uplink SRC is written by mt6320_mic_event() during stream + * start, because the vendor sequences it there - it needs the mic path + * powered first, and writes the rate, clears it, then writes it back. + */ + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + return 0; + + return regmap_write(priv->regmap, MT6320_ABB_AFE_DL_SRC2_CON0_H, + MT6320_ABB_AFE_DL_SRC2_CON0_H_BASE | + (rate_code << 12)); +} + +static const struct snd_soc_dai_ops mt6320_dai_ops = { + .hw_params = mt6320_codec_hw_params, +}; + +static int mt6320_apply_hp_trim(struct mt6320_codec_priv *priv) +{ + u32 reg1, reg2, trim; + int ret; + + ret = regmap_read(priv->regmap, MT6320_EFUSE_DOUT_112_127, ®1); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, MT6320_EFUSE_DOUT_128_143, ®2); + if (ret) + return ret; + + if (!(reg1 & BIT(12))) { + reg1 = MT6320_PMIC_TRIM_REG1_DEFAULT & 0xfff0; + reg2 = MT6320_PMIC_TRIM_REG2_DEFAULT & 0x0fff; + } + + trim = BIT(8) | + FIELD_PREP(GENMASK(12, 11), + ((reg1 >> 15) & 0x1) | ((reg2 & 0x1) << 1)) | + FIELD_PREP(GENMASK(10, 9), (reg1 >> 13) & 0x3) | + FIELD_PREP(GENMASK(7, 4), (reg1 >> 8) & 0xf) | + FIELD_PREP(GENMASK(3, 0), (reg1 >> 4) & 0xf); + + return regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG3, + GENMASK(12, 0), trim); +} + +static int mt6320_analog_idle(struct mt6320_codec_priv *priv) +{ + unsigned int cid; + int ret; + + /* AUDCLKGEN_CFG0 bit 0 is the downlink SRC clock; no stream owns it now. */ + ret = regmap_clear_bits(priv->regmap, MT6320_AUDCLKGEN_CFG0, BIT(0)); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, MT6320_CID, &cid); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_NCP_CLKDIV_CON1, 0x0001); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AUD_NCP0, + cid >= MT6320_E2_CID ? 0x8000 : 0x9000); + if (ret) + return ret; + + if (cid >= MT6320_E2_CID) { + ret = regmap_write(priv->regmap, MT6320_AUDNVREGGLB_CFG0, 0x0006); + if (ret) + return ret; + return regmap_write(priv->regmap, MT6320_AUDLDO_CFG0, 0x0192); + } + + ret = regmap_write(priv->regmap, MT6320_AUDNVREGGLB_CFG0, 0x0004); + if (ret) + return ret; + return regmap_write(priv->regmap, MT6320_AUDLDO_CFG0, 0x0992); +} + + +static int mt6320_analog_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct mt6320_codec_priv *priv = + snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* + * Mute while reconfiguring, as the stock driver does, then + * clear it again at the end of this branch. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AFUNC_AUD_CON2, + BIT(7), BIT(7)); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AUDLDO_CFG0, 0x0d92); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDNVREGGLB_CFG0, 0x000c); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_NCP_CLKDIV_CON0, 0x102b); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_NCP_CLKDIV_CON1, 0x0000); + if (ret) + return ret; + /* + * AUD_NCP0 (0x071A) - the audio LDO enables. Bits [15:11] + * are NCP_REMOTE_SENSE_VA18 | DA_HCLDO_EN_VA33 | + * DA_LCLDO_EN_VA33 | DA_LCLDO_ENC_EN_VA28 | + * DA_VBATPREREG_EN_VBAT (upmu_hw.h:4326-4335), i.e. the + * high- and low-current audio LDO enable pair the DAC cores + * and the headphone amplifiers are supplied from. + * + * The vendor writes 0xe000 with mask 0xe000 at this exact + * point in the sequence, at the top of every AnalogOpen + * case (AudioMachineDevice.cpp:711 for the speaker, :632 for + * the headset, :223 for the earphone), and clears bits + * [14:13] again on AnalogClose (:1184). This path did not + * write the register at all on power-up, and the power-down + * below wrote it wholesale as 0x8000/0x9000 - a value whose + * bit 15 is set but whose DA_HCLDO/DA_LCLDO bits [14:13] are + * clear. So the first power-down cleared the audio LDO + * enables and no playback stream ever put them back: the + * bias ramp produced one pop as the rails collapsed and + * nothing was amplified afterwards, on the speaker and on + * the headphones alike. + * + * Set only the two enable bits and leave the rest of the + * register as it is, so this cannot disturb bit 15 or the + * VBAT pre-regulator bit that power_init() left behind. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AUD_NCP0, + MT6320_AUD_NCP0_LDO_ENABLE, + MT6320_AUD_NCP0_LDO_ENABLE); + if (ret) + return ret; + + usleep_range(900, 1100); + + /* + * The mute asserted at the top of this branch stays asserted. + * + * This used to unmute here, which is far too early: DAPM runs + * this supply at up_seq 3, three ordering groups before the + * DAC (8) and nine before the output drivers (12), so the + * analog output stage was released into an unpowered DAC and + * the resulting transient is the click heard when playback + * starts. The vendor brackets its whole AnalogOpen() with + * this mute - set on the first line, cleared on the last - so + * the unmute now happens at the end of the headphone power-up + * (mt6320_hp_event(), POST_PMU), once the buffers and their + * output muxes are programmed. + */ + return 0; + + case SND_SOC_DAPM_POST_PMD: + if (priv->analog_output_active || priv->capture_active) + return 0; + + ret = mt6320_analog_idle(priv); + if (ret) + return ret; + + /* + * Unmute. AFUNC_AUD_CON2 bit 7 is a mute, not an enable: the + * stock driver asserts it while it configures the path and + * clears it once the configuration is done + * (AudioMachineDevice, SetAnalogReg(AFUNC_AUD_CON2, mute << 7)). + * Leaving it set keeps the output muted for as long as the + * path is powered - that is, for as long as it is playing. + */ + return regmap_update_bits(priv->regmap, MT6320_AFUNC_AUD_CON2, + BIT(7), 0); + } + + return 0; +} + +/* + * Analog idle baseline, before any stream is running. + * + * The ABB digital path is deliberately NOT programmed here. Every 0x4xxx + * register this list used to open with is programmed per-stream in + * mt6320_dac_event() and mt6320_mic_event() instead, because that is where + * the vendor does it (AudioPlatformDevice::AnalogOpen, every DEVICE_OUT_* + * and DEVICE_IN_ADC* case) and several of them carry the sample rate. + * + * The block that was here was the MT6323 idle baseline, verbatim from the + * now-removed sound/soc/codecs/mt6323.c, MT6323 register numbering and all: + * + * { MT6320_ABB_AFE_CON(1), 0x0009 }, + * { MT6320_ABB_AFE_CON(3), 0x0221 }, + * { MT6320_ABB_AFE_CON(4), 0x0255 }, + * { MT6320_ABB_AFE_CON(5), 0x0028 }, + * { MT6320_ABB_AFE_CON(6), 0x0218 }, + * { MT6320_ABB_AFE_CON(7), 0x0204 }, + * { MT6320_ABB_AFE_CON(10), 0x0001 }, + * + * MT6320_ABB_AFE_CON() is the same arithmetic on both chips (0x4000 + n * 2), + * but the register *layout* behind that arithmetic is not the same, so the + * same n lands on a different register. Against the MT6320 map this driver + * follows (AudDrv_Ana.h) those seven entries are: + * + * CON(1) 0x4002 AFE_DL_SRC2_CON0_H the downlink sample-rate field + * CON(3) 0x4006 AFE_DL_SRC2_CON1_H + * CON(4) 0x4008 AFE_DL_SRC2_CON1_L + * CON(5) 0x400a AFE_DL_SDM_CON0 + * CON(6) 0x400c AFE_DL_SDM_CON1 + * CON(7) 0x400e AFE_UL_SRC_CON0_H the uplink sample-rate field + * CON(10) 0x4014 AFE_UL_SRC_CON1_L + * + * So probe was writing MT6323 SDM and UL-SRC trim values into MT6320's + * downlink-SRC and uplink-SRC *rate* registers, with the SRC enable/base + * bits left at their reset value. Both power-up handlers rewrite all of + * them before each stream, which is what made this survivable rather than + * fatal, but there is no reason to leave a wrong value behind at probe. + */ +static const struct reg_sequence mt6320_codec_init[] = { + /* Conservative default analog gain: headphone 0dB. */ + { MT6320_ZCD_CON2, ZCD_GAIN_REG(ZCD_GAIN_0DB) }, +}; + +/* Codec master clock gating handled by CCF (top-aud26m gate in mt6320-clk). */ +static int mt6320_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct mt6320_codec_priv *priv = + snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = regmap_write(priv->regmap, MT6320_TOP_CKPDN_CLR, 0x0003); + if (ret) + return ret; + + /* + * The digital path registers, following + * AudioPlatformDevice::AnalogOpen() for DEVICE_OUT_DAC + * (AudioPlatformDevice.cpp, the DEVICE_OUT_EARPIECE case). + * + * Every address here is derived from MT6320_ABB_AFE_CON(), so + * they all land in the 0x4000 AFE window. They used to be + * spelled with the MT6320_ANALDO_CON and MT6320_DIGLDO_CON + * macros, which are *not* the same registers: those live at + * 0x0400.., the PMIC regulator block, and only the low byte + * agreed, so 0x4034 became 0x0434, 0x4022 became 0x0422, and so + * on. Every microphone power-up was then overwriting + * power-management registers - VGP6, VSIM2, VMC1, VUSB - and + * disabling rails the rest of the system depends on. The values + * themselves were right; only the addresses were wrong. + * + * Note on 0x4000 (AFE_UL_DL_CON0, written 0x007f): this is an + * ABB/AFE register reached through the PMIC digital-audio + * bridge at base 0x4000 - not the regulator register that the + * MT6320_ANALDO_CON0 macro names at 0x0400. It is the register + * that enables the shared digital audio path for both + * directions, and the full 0x007f is what the vendor writes; + * a partial write of just BIT(0) does not get samples through. + */ + ret = regmap_write(priv->regmap, MT6320_AFE_AFUNC_AUD_CON0, 0xc3a1); + if (ret) + return ret; + + /* + * The three-step 0x0006 -> 0x0003 -> 0x000b digital enable + * sequence (AudioPlatformDevice::AnalogOpen, the + * DEVICE_OUT_EARPIECE case, which the DAC path follows). + * + * Bit 7 of this register is the analog mute, and those three + * literals all have it clear - they are the *digital* half of + * the vendor's bring-up, which runs before its analog half + * asserts the mute. Writing them verbatim here would clear + * the mute that mt6320_analog_event() just asserted, three + * DAPM ordering groups before the HP buffers are configured, + * which is the transient this file is fixing. Keep bit 7 set + * across the sequence so the mute is held until the output + * stage is settled; the vendor's own AnalogOpen() releases it + * on its last line, which is where mt6320_hp_event()'s + * POST_PMU release sits. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AFE_AFUNC_AUD_CON2, + GENMASK(3, 0), 0x0006); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_AFE_AFUNC_AUD_CON2, + GENMASK(3, 0), 0x0003); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_AFE_AFUNC_AUD_CON2, + GENMASK(3, 0), 0x000b); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AFE_DL_SDM_CON1, 0x001e); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_ABB_AFE_DL_SRC2_CON0_H, + MT6320_ABB_AFE_DL_SRC2_CON0_H_BASE | + (priv->rate_code << 12)); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AFE_UL_DL_CON0, 0x007f); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AFE_DL_SRC2_CON0_L, 0x1801); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AFE_DL_SRC2_CON1_H, 0x0000); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON1_H, 0x00e1); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AFE_ANA_AFE_TOP_CON0, 0x0000); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AFE_I2S_FIFO_DL_CFG0, 0x004f); + if (ret) + return ret; + + /* + * Power the DAC cores up: 0x0003 is RG_AUDDACLPWRUP_VAUDP12 + * (bit 0) | RG_AUDDACRPWRUP_VAUDP12 (bit 1). These two bits + * are the entire DAC power-up control - the vendor writes no + * other bit of this register on any path (power_init, all four + * AnalogOpen cases and all four AnalogClose cases use 0x0009, + * 0x000f or 0x0000). + * + * This used to write 0x7010 here and 0x6010 on POST_PMD. + * Both are the *MT6323* AUDTOP_CON0 values, carried over from + * the now-removed sound/soc/codecs/mt6323.c, and the MT6320 + * register map is not compatible with them: bits [15:13] are + * RG_AUDHPRSCDISABLE / RG_AUDHPLSCDISABLE / RG_AUDHSSCDISABLE + * and bits [10:9] are RG_HPOUTPUTRESET0 / RG_HPINPUTRESET0 + * (upmu_hw.h, VAUDP12 group). So 0x7010 powered the DAC on + * *and* held the headphone amplifiers in their disabled, input- + * and output-reset state: the path settled hard enough to make + * one pop as the bias ramped, and then nothing came out. + * 0x6010 differs from 0x7010 only in bit 12, so power-down + * cleared two of the three HS disable bits while leaving + * RG_AUDHSSCDISABLE (bit 13) asserted, which would have kept + * the headphone silent on every stream after the first even + * once power-up was right. (Bit 12 is not named in the + * VAUDP12 group in upmu_hw.h.) + * + * Written as an explicit full value, not a bit update: the + * surrounding sequence clears the HP power-up bits (bit 0) and + * sets the HP-only enable (bit 3) on the same register in + * mt6320_hp_event(), so leaving bits [15:9] untouched here is + * what let the disable bits survive. + * + * The AUDBUF_CFG4 = 0x0014 write that used to sit immediately + * before this one was also MT6323 carry-over (mt6323.c wrote + * AUDTOP_CON(5) = 0x0014). On MT6320 that register holds the ABI + * de-click reserved bits - RG_ABIDEC_RESERVED_VAUDP12 at [15:8] + * and RG_ABIDEC_RESERVED_VA28 at [7:0] (upmu_hw.h) - and + * upmu_set_rg_abidec_reserved_*(), the only vendor code that + * touches it, is never called from anywhere in the BSP. It is + * dropped rather than restored on POST_PMD for the same reason: + * there is no power-sequence state on this register to restore. + */ + ret = regmap_write(priv->regmap, MT6320_AUDDAC_CON0, 0x0003); + if (ret) + return ret; + + priv->analog_output_active = true; + + /* + * The analog mute stays asserted here. The DAC cores are the + * middle of the power-up, not the end of it: the HP buffers + * (out_drv, up_seq 12) and the output muxes still have to be + * programmed after this, and the vendor only releases the mute + * on the last line of its AnalogOpen(). Unmuting here - or + * earlier, from the "Analog" supply, which is where it used to + * happen - lets the transient out. mt6320_hp_event() clears it + * at POST_PMU instead. + */ + return 0; + + case SND_SOC_DAPM_POST_PMD: + /* + * The vendor's power-down for the DAC is a plain 0x0000 on + * AUDDAC_CON0 (AudioMachineDevice::AnalogClose, every case). + * Nothing else: no AUDBUF_CFG4 restore, because there is + * nothing on this register for a power sequence to restore. + */ + ret = regmap_write(priv->regmap, MT6320_AUDDAC_CON0, 0x0000); + if (!ret) + priv->analog_output_active = false; + return ret; + } + return 0; +} + +/* + * Headphone/line output power-up: AudioMachineDevice::AnalogOpen() for + * DEVICE_OUT_HEADSETR/L. + * + * This is also the sequence the Blade's speaker runs on. The board's audio + * configuration (blade10/hal/audioflinger/audio/audio_custom_exp.h) defines + * USING_EXTAMP_HP, and with that define the vendor's DEVICE_OUT_SPEAKER case + * does not touch the PMIC Class-D block at all - it just calls + * AnalogOpen(DEVICE_OUT_HEADSETR). The speaker is an SN2145B hung off the + * MT6320's *headphone/line* output buffers, enabled by GPIO73. + * + * The last two writes are the ones that matter for the speaker: they set + * MUX_AUDIO (4) in AUDBUF_CFG0's left [8:5] and right [12:9] output mux + * fields, which is what connects the DAC to those output buffers + * (AudioMachineDevice::AnalogSetMux, DEVICE_OUT_HEADSETL/R). Until both are + * set the DAC runs, the headphone amplifier is powered, and the buffers the + * SN2145B sits on carry nothing. + */ +static int mt6320_hp_power_up(struct mt6320_codec_priv *priv) +{ + int ret; + + ret = mt6320_apply_hp_trim(priv); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG0, 0x0008); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_ZCD_CON0, 0x0101); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG0, 0x0008); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_IBIASDIST_CFG0, 0x0552); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG1, 0x0900); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG2, 0x0082); + if (ret) + return ret; + + usleep_range(29000, 31000); + + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG0, 0x0009); + if (ret) + return ret; + + usleep_range(29000, 31000); + + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG1, 0x0940); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG0, 0x000f); + if (ret) + return ret; + + usleep_range(29000, 31000); + + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG1, 0x0100); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG2, 0x0082); + if (ret) + return ret; + /* + * Leave ZCD_CON2's volume fields alone. Bits [3:0] and + * [11:8] are the headphone left/right volume indexes - the + * stock driver writes them only from its volume setter + * (AudioMachineDevice, masks 0x0000000f and 0x00000f00) - so + * a full-word 0x0c0c here both forced index 12, the maximum + * of +8 dB, and discarded whatever the "Headphone Volume" + * control had set. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AUDCLKGEN_CFG0, + BIT(0), BIT(0)); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDDAC_CON0, 0x000f); + if (ret) + return ret; + + usleep_range(29000, 31000); + + /* + * The stock HP sequence leaves the common AUDBUF mux in state 6 + * before selecting the L/R DAC muxes. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG0, + GENMASK(2, 0), 0x0006); + if (ret) + return ret; + + /* + * HP L/R mux: MUX_AUDIO, i.e. the DAC. + * + * The fields are four bits wide, not three: the vendor's + * AnalogSetMux() writes DEVICE_OUT_HEADSETL with mask 0x000001e0 + * (bits [8:5]) and DEVICE_OUT_HEADSETR with mask 0x00001e00 + * (bits [12:9]), so bit 8 and bit 12 are part of each L/R mux + * select. These were GENMASK(7,5)/GENMASK(11,9) here, which left + * those two bits at whatever the common-mux write above (or the + * previous path) left in them. MUX_AUDIO is 4, so the *value* is + * unaffected - but a stale bit 8 or 12 makes the field read 4|8 = + * 12, MUX_IV_BUFFER, which for this board is a different source + * entirely. Use the vendor's masks so the field is written whole. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG0, + GENMASK(8, 5), 4 << 5); + if (ret) + return ret; + return regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG0, + GENMASK(12, 9), 4 << 9); +} + +static int mt6320_hp_power_down(struct mt6320_codec_priv *priv) +{ + int ret; + + /* + * The vendor does write ZCD_CON2 0x0c0c here (AnalogClose, + * DEVICE_OUT_HEADSET*), but that register is the headphone volume + * control's own register: bits [3:0] and [11:8] are the left and + * right volume indexes, which the "Headphone Volume" control and + * the mixer read and write. Forcing index 12 on every power-down + * throws the user's volume away, and it is exactly the bug this + * file already fixed once on the power-*up* side (commit + * "stop power-up from overwriting the headphone volume"). + * + * Park the volume at 0 dB instead - index 8, which is what the + * probe-time baseline in mt6320_codec_init[] uses and what + * GetAnalogGain() reports as volume 0 - and leave the control's + * own value otherwise alone. Powering the amplifier down is what + * silences it; the index is what it comes back at. + */ + ret = regmap_update_bits(priv->regmap, MT6320_ZCD_CON2, + MT6320_ZCD_CON2_VOL_MASK, + ZCD_GAIN_REG(ZCD_GAIN_0DB)); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG0, + GENMASK(12, 5), 0x0880); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG0, + GENMASK(2, 0), 0x0000); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_IBIASDIST_CFG0, 0x1552); + if (ret) + return ret; + return regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG1, BIT(8), 0); +} + +static int mt6320_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct mt6320_codec_priv *priv = + snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* + * The mute asserted at the top of mt6320_analog_event() is + * still held across this: the buffers below are programmed and + * only then released. + */ + ret = mt6320_hp_power_up(priv); + if (ret) + return ret; + return 0; + + case SND_SOC_DAPM_POST_PMU: + /* + * Release the analog mute last, once the HP buffers and their + * output muxes are programmed and settled. This is the + * vendor's ordering: AudioMachineDevice::AnalogOpen() asserts + * AFUNC_AUD_CON2 bit 7 on its first line and clears it on its + * last, after every buffer, mux and gain write in between. + * + * Unmuting before the buffers settle is what produced the + * click at the start of playback. This widget is up_seq 12 + * (out_drv), so POST_PMU here is the last write of the analog + * power-up on the headphone path; on ext-amp speaker playback + * the external amplifier is still gated off until the "Speaker" + * widget's POST_PMU (up_seq 13), so the mute is released into a + * settled, silent amplifier and then unmuted by the amp itself. + */ + return regmap_update_bits(priv->regmap, MT6320_AFUNC_AUD_CON2, + BIT(7), 0); + + case SND_SOC_DAPM_POST_PMD: + /* + * Re-assert the mute before the buffers come down, so the + * power-down transient stays inside the analog block. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AFUNC_AUD_CON2, + BIT(7), BIT(7)); + if (ret) + return ret; + return mt6320_hp_power_down(priv); + } + return 0; +} + +static int mt6320_apply_spk_trim(struct mt6320_codec_priv *priv) +{ + unsigned int cid, reg; + unsigned int polarity, trim; + int i, ret, cleanup_ret; + + ret = regmap_read(priv->regmap, MT6320_CID, &cid); + if (ret) + return ret; + + if (cid < MT6320_E2_CID) { + ret = regmap_read(priv->regmap, MT6320_EFUSE_DOUT_176_191, ®); + if (ret) + return ret; + + if (!(reg & BIT(13))) + reg = MT6320_SPK_TRIM_DEFAULT; + + polarity = FIELD_GET(BIT(12), reg); + trim = FIELD_GET(GENMASK(11, 7), reg); + } else { + ret = regmap_write(priv->regmap, MT6320_SPK_CON9, 0x2018); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_SPK_CON0, 0x0008); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, MT6320_SPK_CON0, + GENMASK(15, 12), 0x3000); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, MT6320_SPK_CON9, + GENMASK(11, 8), 0x0a00); + if (ret) + return ret; + ret = regmap_set_bits(priv->regmap, MT6320_SPK_CON0, BIT(0)); + if (ret) + return ret; + + for (i = 0; i < 10; i++) { + ret = regmap_read(priv->regmap, MT6320_SPK_CON1, ®); + if (ret) + goto trim_stop; + if (reg & BIT(15)) + break; + msleep(10); + } + + if (i == 10) { + ret = -ETIMEDOUT; + goto trim_stop; + } + + /* + * The trim engine has latched its result into SPK_CON1 by + * the time the status bit clears; read it back from there. + */ + ret = regmap_read(priv->regmap, MT6320_SPK_CON1, ®); + if (ret) + goto trim_stop; + + polarity = FIELD_GET(MT6320_SPK_OFFSET_L_MODE, reg); + trim = FIELD_GET(MT6320_SPK_OFFSET_L_SW, reg); + +trim_stop: + cleanup_ret = regmap_write(priv->regmap, MT6320_SPK_CON9, 0x0000); + if (!ret) + ret = cleanup_ret; + + cleanup_ret = regmap_clear_bits(priv->regmap, + MT6320_SPK_CON0, BIT(0)); + if (!ret) + ret = cleanup_ret; + + if (ret) + return ret; + } + + return regmap_update_bits(priv->regmap, MT6320_SPK_CON1, + 0x7f00, + BIT(14) | + FIELD_PREP(BIT(13), polarity) | + FIELD_PREP(GENMASK(12, 8), trim)); +} + +static int mt6320_speaker_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct mt6320_codec_priv *priv = + snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* + * A board with an external amplifier hung off the headphone + * output must not run the PMIC Class-D sequence at all: that + * path feeds SPK_CON* and the IV buffer, which on these boards + * has no load, and it leaves the headphone buffers - where the + * amplifier actually sits - unpowered. The vendor does the same + * switch with USING_EXTAMP_HP, where DEVICE_OUT_SPEAKER just + * forwards to AnalogOpen(DEVICE_OUT_HEADSETR). + */ + if (priv->amp_en_gpio) { + ret = mt6320_hp_power_up(priv); + if (ret) + return ret; + + /* + * Release the analog mute, as the headphone path + * does at its own POST_PMU. + * + * On an ext-amp board the "HP Driver" widget does not + * power during speaker playback: its only connected + * sink there is the headphones, so DAPM leaves it off + * and its POST_PMU - where the unmute lives - never + * runs. This branch is the analogue of that step. + * + * Ordering still holds: this is Speaker Driver's + * PRE_PMU (out_drv, up_seq 12) and the amplifier is + * not enabled until the "Speaker" widget's POST_PMU + * (up_seq 13), so the mute is released into a settled + * but silent amplifier and the amplifier is what + * unmutes. + */ + return regmap_update_bits(priv->regmap, + MT6320_AFUNC_AUD_CON2, + BIT(7), 0); + } + + /* + * TOP_CKPDN_CLR selects the audio clock for the speaker + * route: the stock driver writes 0x0607 here when opening + * DEVICE_OUT_SPEAKER, against 0x0003 for the DAC and + * headphone paths (AudioPlatformDevice::AnalogOpen). + */ + ret = regmap_write(priv->regmap, MT6320_TOP_CKPDN_CLR, 0x0607); + if (ret) + return ret; + + ret = mt6320_apply_spk_trim(priv); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_ZCD_CON0, 0x0301); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDACCDEPOP_CFG0, 0x0030); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG0, 0x0008); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_IBIASDIST_CFG0, 0x0552); + if (ret) + return ret; + /* + * As in the headphone path, do not write ZCD_CON2 wholesale: + * bits [3:0] and [11:8] are the headphone volume indexes and + * belong to the volume control. + */ + ret = regmap_write(priv->regmap, MT6320_ZCD_CON3, 0x000f); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG1, 0x0900); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG2, 0x0082); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG0, 0x0009); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG1, 0x0940); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG0, 0x0007); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG1, 0x0000); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDBUF_CFG2, 0x0022); + if (ret) + return ret; + /* + * The stock speaker sequence does not touch ZCD_CON2 at all; + * its volume indexes belong to the volume control. The + * preceding write used to set 0x0505 here, forcing index 5. + */ + ret = regmap_write(priv->regmap, MT6320_ZCD_CON4, 0x0505); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUD_IV_CFG0, 0x0011); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, MT6320_AUDCLKGEN_CFG0, + BIT(0), BIT(0)); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_AUDDAC_CON0, 0x0009); + if (ret) + return ret; + + usleep_range(900, 1100); + + /* Speaker mux: DAC through IV buffer. */ + ret = regmap_update_bits(priv->regmap, MT6320_AUD_IV_CFG0, + GENMASK(4, 2), 4 << 2); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, MT6320_AUDBUF_CFG0, + GENMASK(2, 0), 0); + if (ret) + return ret; + + usleep_range(900, 1100); + + ret = regmap_write(priv->regmap, MT6320_SPK_CON0, 0x3009); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_SPK_CON2, 0x0014); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_SPK_CON9, 0x0800); + if (ret) + return ret; + + /* + * Take both output stages and both driver enables under + * software control, as the stock driver does with 0x0f00. + * SPK_EN_MODE is deliberately not set: it makes the hardware + * follow the register mode instead of reading the EN_L/EN_R_SW + * bits, which would leave the enables above inert. + */ + ret = regmap_write(priv->regmap, MT6320_SPK_CON11, + MT6320_SPK_OUTSTG_EN_L_SW | + MT6320_SPK_OUTSTG_EN_R_SW | + MT6320_SPK_EN_L_SW | + MT6320_SPK_EN_R_SW); + if (ret) + return ret; + + /* + * Release the analog mute, as the headphone path does at + * its own POST_PMU. + * + * The "Speaker Driver" widget has no connected sink on an + * ext-amp board, so "HP Driver" stays off during speaker + * playback and the unmute that lives in its POST_PMU never + * runs; the Class-D branch below has the same problem, since + * that path does not power "HP Driver" either. This is the + * unmute for both. + * + * Ordering still holds: this is Speaker Driver's PRE_PMU + * (out_drv, up_seq 12). On ext-amp boards the amplifier is + * not enabled until the "Speaker" widget's POST_PMU + * (up_seq 13), so the mute is released into a settled but + * silent amplifier and the amplifier is what unmutes. The + * external amplifier itself is gated on that widget, not here + * - it used to be switched on here, which was wrong twice + * over: this is an out_drv handler, so it ran before the HP + * buffers it feeds had settled, and it could not gate the amp + * off on plug-in. See mt6320_spk_amp_event(). + */ + return regmap_update_bits(priv->regmap, + MT6320_AFUNC_AUD_CON2, BIT(7), 0); + + case SND_SOC_DAPM_POST_PMD: + /* + * On an ext-amp board the PMIC Class-D stage was never + * powered and the amplifier is gated on the "Speaker" + * widget, so there is nothing to unwind here. Reaching this + * point with an amp configured means the speaker sequence did + * not take the ext-amp branch above, which would be a bug; + * leave the Class-D registers alone rather than half-clearing + * state this board never set. + */ + if (priv->amp_en_gpio) + return 0; + + ret = regmap_write(priv->regmap, MT6320_SPK_CON11, 0x0000); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_SPK_CON9, 0x0000); + if (ret) + return ret; + ret = regmap_write(priv->regmap, MT6320_SPK_CON0, 0x0000); + if (ret) + return ret; + + return regmap_clear_bits(priv->regmap, MT6320_AUD_IV_CFG0, BIT(0)); + } + + return 0; +} + +/* + * External speaker amplifier gate (the "Speaker" widget). + * + * This is deliberately not folded into mt6320_speaker_event(). Two reasons: + * + * - Ordering. The "Speaker" widget is snd_soc_dapm_spk, which DAPM powers + * up at up_seq 13 and down at down_seq 4, i.e. *after* every out_drv + * (up 12) and *before* them on the way out (down 5). That is exactly the + * vendor's contract for the SN2145B: Sound_Speaker_Turnon() runs after + * the analog path is configured, and Sound_Speaker_Turnoff() runs before + * it collapses. Gating inside the out_drv handler instead would enable + * the amp while the HP buffers were still being programmed. + * + * - Exclusivity. "Speaker" sits behind the inverted Speaker jack pin, so + * DAPM powers this widget down - and therefore drives GPIO73 low - the + * moment headphones are reported, while the "HP Driver" the headphones + * actually use stays up through its own route. That is what makes the + * speaker yield to the headphones. The out_drv widget is shared by both + * paths and cannot express that. + * + * The vendor's Sound_Speaker_Turnon() (@ c0467388) refuses to re-enable an + * amplifier that was switched off less than 80 ms ago: it sleeps out the + * remainder of that window before raising the pin, so a rapid stop/start + * cannot click. The 40 ms warm-up afterwards is the figure the working + * B8000-H port uses (lenovo-b8000h-linux mt6589_audio.c). Reproduce both. + */ +static int mt6320_spk_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct mt6320_codec_priv *priv = + snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); + unsigned long elapsed; + + if (!priv->amp_en_gpio) + return 0; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (!priv->amp_on && priv->amp_off_jiffies) { + elapsed = jiffies - priv->amp_off_jiffies; + if (elapsed < msecs_to_jiffies(MT6320_AMP_SHUTDOWN_MS)) + msleep(jiffies_to_msecs( + msecs_to_jiffies(MT6320_AMP_SHUTDOWN_MS) - + elapsed)); + } + gpiod_set_value_cansleep(priv->amp_en_gpio, 1); + priv->amp_on = true; + dev_info(priv->dev, "speaker amplifier on (GPIO73 high)\n"); + msleep(MT6320_AMP_WARMUP_MS); + return 0; + + case SND_SOC_DAPM_PRE_PMD: + gpiod_set_value_cansleep(priv->amp_en_gpio, 0); + priv->amp_on = false; + priv->amp_off_jiffies = jiffies; + dev_info(priv->dev, "speaker amplifier off (GPIO73 low)\n"); + return 0; + } + + return 0; +} + +/* Analog mic input: AUXADC channel 0, buffer on, analog switch to 1.9 V. */ +static int mt6320_mic_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct mt6320_codec_priv *priv = + snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm)); + unsigned int accdet_state; + bool headset_mic; + int ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* + * Configure the B8000 internal dual-mic analog front-end using the + * vendor AnalogOpen(DEVICE_IN_ADC1/ADC2) sequence. The active Linux + * capture DAI is mono, so MIC1 is the left source; MIC3 is also + * selected on the right to preserve the vendor dual-mic setup. + */ + ret = regmap_write(priv->regmap, MT6320_AUDNVREGGLB_CFG0, 0x000c); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AUDLDO_CFG0, 0x0d92); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_AUD_NCP0, + 0x9000, 0x9000); + if (ret) + return ret; + + /* + * ACCDET_STATE_RG[7:6] is the vendor cable-class state: + * 0 = no-mic headset, 1 = headset with microphone, 3 = empty. + * A wired headset feeds MIC2 into both preamps; the internal dual-mic + * path remains MIC1/MIC3. + */ + ret = regmap_read(priv->regmap, MT6320_ACCDET_STATE_RG, + &accdet_state); + if (ret) + return ret; + + headset_mic = FIELD_GET(MT6320_ACCDET_STATE_MASK, accdet_state) == + MT6320_ACCDET_STATE_HEADSET_MIC; + + ret = regmap_update_bits(priv->regmap, MT6320_AUDPREAMP_CON0, + MT6320_AUDPREAMP_L_INPUT_SEL, + headset_mic ? (2U << 2) : MT6320_AUDPREAMP_L_MIC1); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_AUDPREAMP_CON0, + MT6320_AUDPREAMP_R_INPUT_SEL, + headset_mic ? (2U << 5) : MT6320_AUDPREAMP_R_MIC3); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_AUDPREAMP_CON0, + MT6320_AUDPREAMP_POWER, + MT6320_AUDPREAMP_POWER); + if (ret) + return ret; + + usleep_range(900, 1100); + + ret = regmap_write(priv->regmap, MT6320_AUDADC_CON0, 0x0093); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_NCP_CLKDIV_CON0, + 0x102b, 0x102b); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_NCP_CLKDIV_CON1, 0x0000); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_AUDDIGMI_CON0, + 0x0180, 0x0180); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MT6320_AUDPREAMPGAIN_CON0, + 0x0033, 0x0033); + if (ret) + return ret; + + /* + * 0x0712: AUDCLKGEN_CFG0, bit 1 - the ADC clock gate. The + * vendor writes this register with mask 0x0002, i.e. it only + * touches bit 1, so update just that bit rather than the whole + * word: bit 0 of the same register is the SRC gate that + * mt6320_hp_event() and mt6320_speaker_event() set, and a full + * write here would clear it out from under a concurrently + * active output path. + */ + ret = regmap_update_bits(priv->regmap, MT6320_AUDCLKGEN_CFG0, + MT6320_ADCCLK_ENABLE, 0); + if (ret) + return ret; + + /* 0x4010: AFE_UL_SRC_CON0_L - low half of the UL SRC. */ + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON0_L, + 0x0000); + if (ret) + return ret; + + /* 0x0712, bit 1 back on: enable the ADC clock. */ + ret = regmap_update_bits(priv->regmap, MT6320_AUDCLKGEN_CFG0, + MT6320_ADCCLK_ENABLE, + MT6320_ADCCLK_ENABLE); + if (ret) + return ret; + + /* 0x4026: ANA_AUDIO_TOP_CON0. */ + ret = regmap_write(priv->regmap, MT6320_AFE_ANA_AUDIO_TOP_CON0, + 0x0000); + if (ret) + return ret; + + /* 0x400e: AFE_UL_SRC_CON0_H - UL SRC high half, with rate. */ + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON0_H, + FIELD_PREP(MT6320_ABB_AFE_UL_SRC_CON0_H_RATE, + priv->ul_rate_code)); + if (ret) + return ret; + + /* 0x4000: AFE_UL_DL_CON0 - enable the shared digital path. */ + ret = regmap_write(priv->regmap, MT6320_AFE_UL_DL_CON0, 0x007f); + if (ret) + return ret; + + /* + * 0x4010: AFE_UL_SRC_CON0_L again. 0x0201 because this board + * is built with MTK_AUDIO_HD_REC_SUPPORT (it appears in + * eastaeon89_wet_td/ProjectConfig.mk), which is the branch the + * vendor takes here; the non-HD build would use 0x0601. + */ + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON0_L, + 0x0201); + if (ret) + return ret; + + /* 0x4020: AFE_I2S_FIFO_UL_CFG0 - UL FIFO enable. */ + ret = regmap_write(priv->regmap, MT6320_AFE_I2S_FIFO_UL_CFG0, + 0x004f); + if (ret) + return ret; + + usleep_range(600, 600); + + /* Clear the UL SRC rate, then let it settle. */ + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON0_H, + 0x0000); + if (ret) + return ret; + + usleep_range(600, 600); + + /* Reload the rate into the freshly cleared UL SRC. */ + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON0_H, + FIELD_PREP(MT6320_ABB_AFE_UL_SRC_CON0_H_RATE, + priv->ul_rate_code)); + if (ret) + return ret; + + usleep_range(600, 600); + + /* Drop the UL SRC, then bring it back up around the reload. */ + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON0_L, + 0x0000); + if (ret) + return ret; + + usleep_range(600, 600); + + ret = regmap_write(priv->regmap, MT6320_AFE_UL_SRC_CON0_L, + 0x0201); + if (ret) + return ret; + + priv->capture_active = true; + return 0; + case SND_SOC_DAPM_POST_PMD: + /* + * Mirror AnalogClose(DEVICE_IN_ADC1/ADC2). These are capture-only + * blocks, so they must be shut down even when the playback analog + * path remains active. Shared LDO/bias cleanup is deferred until no + * output path is using it. + */ + ret = regmap_clear_bits(priv->regmap, MT6320_AUDPREAMP_CON0, + MT6320_AUDPREAMP_POWER); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AUDADC_CON0, 0x00b4); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MT6320_AUDDIGMI_CON0, 0x0080); + if (ret) + return ret; + + { + unsigned int cid; + + ret = regmap_read(priv->regmap, MT6320_CID, &cid); + if (ret) + return ret; + + if (cid >= MT6320_E2_CID) { + ret = regmap_clear_bits(priv->regmap, MT6320_AUD_NCP0, + BIT(12)); + if (ret) + return ret; + } + } + + ret = regmap_clear_bits(priv->regmap, MT6320_AUDLSBUF_CON0, + BIT(0) | BIT(1)); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, MT6320_AUDCLKGEN_CFG0, + MT6320_ADCCLK_ENABLE); + if (ret) + return ret; + + priv->capture_active = false; + /* Shared analog idle is owned by the Analog supply's POST_PMD. */ + return 0; + } + + return 0; +} + +static const struct snd_soc_dapm_widget mt6320_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Analog", SND_SOC_NOPM, 0, 0, + mt6320_analog_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + /* + * NEWIF is the serial link to the SoC AFE. This generation of + * MT6320 has no PMIC-side NEWIF configuration registers, so there + * is nothing for the codec to program on that link: the AFE drives + * the I2S2 interface and the DAC is reached through AFE_CONN1/CON2. + * A "NEWIF" widget was here once, but as a supply with no sink path + * it never powered and only obscured that. + */ + SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, mt6320_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV_E("HP Driver", SND_SOC_NOPM, 0, 0, NULL, 0, + mt6320_hp_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV_E("Speaker Driver", SND_SOC_NOPM, 0, 0, NULL, 0, + mt6320_speaker_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + /* + * The analog mic front end, named after the "DAC" it mirrors on + * playback, and the widget that carries mt6320_mic_event (mic bias and + * AUXADC channel select). + * + * It must NOT be called "VUL Capture": that is the name ASoC gives the + * capture DAI widget, which it auto-creates from the DAI's stream_name + * below (snd_soc_dapm_new_dai_widgets()). This widget used to be + * called "AIF1 Capture" - the very same name as that auto-created DAI + * widget - so two widgets in this one component shared a name, and + * route lookup for the codec's own routes could not tell them apart. + * It needs a name of its own. + */ + SND_SOC_DAPM_ADC_E("ADC", NULL, SND_SOC_NOPM, 0, 0, + mt6320_mic_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_INPUT("Mic Bias"), + SND_SOC_DAPM_OUTPUT("Headphone"), + /* + * The external amplifier gate. SND_SOC_DAPM_SPK gives it + * POST_PMU/PRE_PMD, which is the ordering the amp needs; see + * mt6320_spk_amp_event(). Boards without amp-en-gpios leave the + * handler a no-op. + */ + SND_SOC_DAPM_SPK("Speaker", mt6320_spk_amp_event), +}; + +static const struct snd_soc_dapm_route mt6320_dapm_routes[] = { + /* + * "DL1 Playback" and "VUL Capture" are the AFE's DAI stream widgets. + * Each DAI gets an auto-created DAPM widget named after its + * stream_name (snd_soc_dapm_new_dai_widgets()), and + * dapm_connect_dai_pair() walks those widgets by pointer to join the + * codec DAI to the CPU DAI. The names matter for two other reasons, + * which is why they have to agree across components: + * + * - the routes below are looked up by name across every widget on the + * card (snd_soc_dapm_add_route()), so a route named for the wrong + * stream resolves to nothing, or worse to a same-named widget that + * is not on the path; and + * - snd_soc_dapm_link_dai_widgets() pairs widgets up by substring + * match on their stream names, so only equal names pair. + * + * Both AFE names are fixed by the hardware interface (AFE memory + * interfaces DL1 and VUL), so the codec matches them end to end rather + * than imposing "AIF1 ...", and the analog front ends hang off the + * matching widget just as "DAC" hangs off "DL1 Playback" above. + * + * A route is { sink, control, source }: the signal flows source -> + * sink, and the widget that consumes the audio is the sink. So the + * mic front end is the SOURCE feeding "Mic Bias", and the capture DAI + * widget is the SINK the front end feeds. Compare the playback pair + * just above, { "DAC", NULL, "DL1 Playback" }, where "DL1 Playback" is + * the sink. This matches upstream sound/soc/codecs/mt6357.c, which has + * the same { "ADC", NULL, ... } shape with the ADC as the sink of its + * supply route. + */ + { "DAC", NULL, "DL1 Playback" }, + { "HP Driver", NULL, "DAC" }, + { "HP Driver", NULL, "Analog" }, + { "Headphone", NULL, "HP Driver" }, + { "Speaker Driver", NULL, "DAC" }, + { "Speaker Driver", NULL, "Analog" }, + { "Speaker", NULL, "Speaker Driver" }, + { "ADC", NULL, "Mic Bias" }, + { "VUL Capture", NULL, "ADC" }, +}; + +/* Output volume: -4dB .. +8dB in 1dB steps. */ +static const DECLARE_TLV_DB_SCALE(mt6320_dl_tlv, -400, 100, 0); + +static const struct snd_kcontrol_new mt6320_snd_controls[] = { + SOC_DOUBLE_TLV("Headphone Volume", + MT6320_ZCD_CON2, 0, 8, ZCD_GAIN_CTL_MAX, 1, + mt6320_dl_tlv), +}; + +/* + * Boards whose speaker hangs off the headphone output (an external amplifier + * instead of the PMIC Class-D stage) need the HP driver powered for speaker + * playback too. Their "Speaker Driver" widget runs the headphone sequence - + * see mt6320_speaker_event() - but the HP driver is a separate DAPM widget, + * and the static route table cannot express "power this one only when the + * other one is in use". Adding the route here gives "Speaker Driver" a sink + * so DAPM keeps it (and therefore the headphone block it programs) powered + * while the speaker plays. + * + * This route is deliberately left as it is. Its obvious failure mode is + * that "Speaker Driver" now powers whenever the speaker does; the reason + * that used to make the speaker play *over* the headphones was not this + * route but that the speaker amplifier was never switched off, because the + * headset jack never reported a plug-in at all (see mt6320-accdet.c). The + * amplifier gate now lives on the "Speaker" widget + * (mt6320_spk_amp_event()), which the inverted Speaker jack pin disables as + * soon as headphones are reported, so the SN2145B goes quiet while the PMIC + * buffers keep running for the headphones. + */ +static const struct snd_soc_dapm_route mt6320_extamp_routes[] = { + { "HP Driver", NULL, "Speaker Driver" }, +};static int mt6320_component_probe(struct snd_soc_component *component) +{ + struct mt6320_codec_priv *priv = snd_soc_component_get_drvdata(component); + int ret; + + /* Route mixer controls to the PMIC regmap (see mt6323.c note). */ + snd_soc_component_init_regmap(component, priv->regmap); + + if (priv->amp_en_gpio) { + ret = snd_soc_dapm_add_routes(component->dapm, + mt6320_extamp_routes, + ARRAY_SIZE(mt6320_extamp_routes)); + if (ret) + return ret; + } + + return 0; +} + +static const struct snd_soc_component_driver mt6320_soc_component_driver = { + .probe = mt6320_component_probe, + .controls = mt6320_snd_controls, + .num_controls = ARRAY_SIZE(mt6320_snd_controls), + .dapm_widgets = mt6320_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt6320_dapm_widgets), + .dapm_routes = mt6320_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(mt6320_dapm_routes), + .endianness = 1, +}; + +static struct snd_soc_dai_driver mt6320_dai_driver[] = { + { + .name = "mt6320-snd-codec-aif1", + .ops = &mt6320_dai_ops, + .playback = { + /* + * Named for the AFE playback DAI's memory interface, + * which is also the machine dai_link's stream_name + * ("DL1 Playback" in both mt6589-afe-pcm.c and + * mt6589-mt6320.c). It has to be this exact string: + * it names the DAI widget the routes connect to, and + * only equal stream names pair up in + * snd_soc_dapm_link_dai_widgets(). + * + * This was "AIF1 Playback", which matched nothing: + * the route below connects "DL1 Playback" to the DAC, + * so the DAC had no path from the DAI and playback ran + * with the analog path powered but no data reaching it + * - one pop as the outputs settled, then silence. + */ + .stream_name = "DL1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MT6320_CODEC_DL_RATES, + .formats = MT6320_CODEC_FORMATS, + }, + .capture = { + /* + * Named for the AFE capture DAI's memory interface, + * which is also the machine dai_link's stream_name + * ("VUL Capture" in both mt6589-afe-pcm.c and + * mt6589-mt6320.c). It has to be this exact string: + * it names the DAI widget the routes connect to, and + * only equal stream names pair up in + * snd_soc_dapm_link_dai_widgets(). + */ + .stream_name = "VUL Capture", + .channels_min = 1, + .channels_max = 1, + /* + * Narrower than the playback mask above, and that is a + * hardware limit rather than a copy-and-paste: the uplink + * SRC only encodes these four rates. + */ + .rates = MT6320_CODEC_UL_RATES, + .formats = MT6320_CODEC_FORMATS, + }, + }, +}; + +static int mt6320_codec_probe(struct platform_device *pdev) +{ + struct mt6397_chip *pmic = dev_get_drvdata(pdev->dev.parent); + struct mt6320_codec_priv *priv; + int ret; + + if (!pmic || !pmic->regmap) + return dev_err_probe(&pdev->dev, -ENODEV, + "missing PMIC regmap\n"); + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + priv->regmap = pmic->regmap; + platform_set_drvdata(pdev, priv); + + /* + * Codec master clock through the CCF: the top-aud26m gate of + * mt6320-clk (TOP_CKPDN bit 0), fed by the aud26m fixed clock. + */ + priv->clk_aud26m = devm_clk_get_enabled(&pdev->dev, "top-aud26m"); + if (IS_ERR(priv->clk_aud26m)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk_aud26m), + "failed to get aud26m clock\n"); + + /* + * Optional external speaker amplifier enable. The Blade wires its + * SN2145B to GPIO73; boards that use the PMIC Class-D output leave + * the property out and this stays NULL. + */ + priv->amp_en_gpio = devm_gpiod_get_optional(&pdev->dev, "amp-en", + GPIOD_OUT_LOW); + if (IS_ERR(priv->amp_en_gpio)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->amp_en_gpio), + "failed to get amp-en GPIO\n"); + + /* Analog idle baseline; DAPM powers the path per stream. */ + ret = regmap_multi_reg_write(priv->regmap, mt6320_codec_init, + ARRAY_SIZE(mt6320_codec_init)); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to init analog codec\n"); + + ret = devm_snd_soc_register_component(&pdev->dev, + &mt6320_soc_component_driver, + mt6320_dai_driver, + ARRAY_SIZE(mt6320_dai_driver)); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to register component\n"); + + return 0; +} + +static const struct of_device_id mt6320_codec_of_match[] = { + { .compatible = "mediatek,mt6320-sound" }, + { } +}; +MODULE_DEVICE_TABLE(of, mt6320_codec_of_match); + +static struct platform_driver mt6320_codec_driver = { + .driver = { + .name = "mt6320-sound", + .of_match_table = mt6320_codec_of_match, + }, + .probe = mt6320_codec_probe, +}; +module_platform_driver(mt6320_codec_driver); + +MODULE_DESCRIPTION("MediaTek MT6320 PMIC audio codec"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 3a1e1fa3fe5cc7..e59ed6800ae79b 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -5,6 +5,29 @@ config SND_SOC_MEDIATEK tristate select REGMAP_MMIO +config SND_SOC_MT6589 + tristate "ASoC support for the MediaTek MT6589 chip" + depends on ARCH_MEDIATEK || COMPILE_TEST + select SND_SOC_MEDIATEK + # The DL1 ring has to live in the AFE on-chip SRAM. Without the + # generic allocator, SNDRV_DMA_TYPE_DEV_IRAM silently degrades to a + # plain device allocation and the ring ends up in DRAM. + depends on GENERIC_ALLOCATOR || COMPILE_TEST + help + This adds the ASoC platform (AFE) driver for the MediaTek MT6589 + SoC. Select a machine driver below to build a sound card. + Select Y if you have such a device. If unsure select "N". + +config SND_SOC_MT6589_MT6320 + tristate "ASoC machine driver for MT6589 with the MT6320 codec" + depends on SND_SOC_MT6589 + select SND_SOC_MT6320 + help + This adds the ASoC machine driver for a MediaTek MT6589 board with + the on-PMIC MT6320 analog audio codec: DL1 playback and optional + headphone-jack detection. + Select Y if you have such a device. If unsure select "N". + config SND_SOC_MT2701 tristate "ASoC support for Mediatek MT2701 chip" depends on ARCH_MEDIATEK diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile index 7cd67bce92e9a4..d1502c1ad044b2 100644 --- a/sound/soc/mediatek/Makefile +++ b/sound/soc/mediatek/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_SND_SOC_MEDIATEK) += common/ obj-$(CONFIG_SND_SOC_MT2701) += mt2701/ +obj-$(CONFIG_SND_SOC_MT6589) += mt6589/ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/ obj-$(CONFIG_SND_SOC_MT7986) += mt7986/ obj-$(CONFIG_SND_SOC_MT8173) += mt8173/ diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index a2a30a87a359f4..e3bf5ef07bceae 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -231,6 +231,10 @@ int mtk_soundcard_common_probe(struct platform_device *pdev) return ret; } + ret = snd_soc_of_parse_aux_devs(card, "aux-devs"); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to parse aux-devs\n"); + soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL); if (!soc_card_data) return -ENOMEM; @@ -249,14 +253,20 @@ int mtk_soundcard_common_probe(struct platform_device *pdev) accdet_pdev = of_find_device_by_node(accdet_node); if (accdet_pdev) { accdet_comp = snd_soc_lookup_component(&accdet_pdev->dev, NULL); - if (accdet_comp) + if (accdet_comp) { soc_card_data->accdet = accdet_comp; - else - dev_err(&pdev->dev, "No sound component found from mediatek,accdet property\n"); + } else { + put_device(&accdet_pdev->dev); + of_node_put(accdet_node); + return dev_err_probe(&pdev->dev, -EPROBE_DEFER, + "No sound component found from mediatek,accdet property\n"); + } put_device(&accdet_pdev->dev); } else { - dev_err(&pdev->dev, "No device found from mediatek,accdet property\n"); + of_node_put(accdet_node); + return dev_err_probe(&pdev->dev, -EPROBE_DEFER, + "No device found from mediatek,accdet property\n"); } of_node_put(accdet_node); diff --git a/sound/soc/mediatek/mt6589/Makefile b/sound/soc/mediatek/mt6589/Makefile new file mode 100644 index 00000000000000..6e643d20ba239e --- /dev/null +++ b/sound/soc/mediatek/mt6589/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_SND_SOC_MT6589) += mt6589-afe-pcm.o +obj-$(CONFIG_SND_SOC_MT6589_MT6320) += mt6589-mt6320.o diff --git a/sound/soc/mediatek/mt6589/mt6589-afe-pcm.c b/sound/soc/mediatek/mt6589/mt6589-afe-pcm.c new file mode 100644 index 00000000000000..891ef0f0b48a71 --- /dev/null +++ b/sound/soc/mediatek/mt6589/mt6589-afe-pcm.c @@ -0,0 +1,1271 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek MT6589 AFE platform driver. + * + * DL1 playback front-end feeding the ADDA downlink SRC and the AFE<->PMIC + * serial link to the mt6320 codec. The AFE registers are in the parent audsys + * syscon; a fast_io regmap keeps the trigger and the period IRQ atomic. + * + * based on mt6572-afe-pcm.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* AFE registers (classic mt65xx layout); stock magic values noted inline. */ +#define AUDIO_TOP_CON0 0x0000 +/* + * AUDIO_TOP_CON0 power bits: PDN_AFE at bit 2 and PDN_I2S at bit 6, both + * active-low ("0: Power on"). Bit 14 is APB3_SEL, the APB protocol select, + * and is left alone. These are the same bits the clock driver gates + * CLK_AUDIO_AFE and CLK_AUDIO_I2S on, so the AFE must not touch them + * directly - see mt6589_afe_pcm_dev_probe(). + */ +#define AUDIO_TOP_CON0_PDN_AFE BIT(2) +#define AUDIO_TOP_CON0_PDN_I2S BIT(6) +#define AFE_DAC_CON0 0x0010 +#define AFE_DAC_CON0_AFE_ON BIT(0) +#define AFE_DAC_CON0_DL1_ON BIT(1) +/* AFE_DAC_CON0 per-memif enables: DL1 bit1, DL2 bit2, VUL bit3, AWB bit4. + * The downstream driver uses 1 << (block + 1) with MEM_DL1 == 0. + */ +#define AFE_DAC_CON0_VUL_ON BIT(3) +#define AFE_DAC_CON1 0x0014 +#define AFE_DAC_CON1_DL1_RATE GENMASK(3, 0) +#define AFE_DAC_CON1_DL1_DATA BIT(21) +#define AFE_DAC_CON1_VUL_RATE GENMASK(19, 16) +/* + * AFE_DAC_CON1 is a bank of mode fields, one 4-bit slice per memory + * interface, followed by the per-interface data/mono bits: + * + * [3:0] DL1_MODE [7:4] DL2_MODE [11:8] I2S_MODE + * [15:12] AWB_MODE [19:16] VUL_MODE [20] DAI_MODE + * [21] DL1_DATA [22] DL2_DATA [23] I2S_DATA + * [24] AWB_DATA [25] AWB_R_MONO [27] VUL_DATA + * [28] VUL_R_MONO + * + * VUL_R_MONO is bit 28 - bit 27 is VUL_DATA, the VUL data width. Writing + * bit 27 here set the data width instead of the right-justification flag, + * which the stock driver never does for a 16-bit stream. + */ +#define AFE_DAC_CON1_VUL_DATA BIT(27) +#define AFE_DAC_CON1_VUL_R_MONO BIT(28) +#define AFE_VUL_BASE 0x0080 +#define AFE_VUL_CUR 0x008c +#define AFE_VUL_END 0x0088 /* ring end, inclusive */ + +/* + * There is no ADDA block on MT6589. AFE_ADDA_TOP_CON0 (+0x120) and + * AFE_ADDA_UL_SRC_CON0 (+0x114) are MT6797 registers: this part's AFE map + * has nothing between +0x00e0 (AFE_MEMIF_MON4) and +0x0170 (AFE_FOC_CON), + * in both the data sheet and the vendor header. Source selection is done + * with the interconnect CONN registers below. + */ + +#define AFE_DL1_BASE 0x0040 +#define AFE_DL1_CUR 0x0044 +#define AFE_DL1_END 0x0048 /* ring end, inclusive */ + +/* + * DL2, AWB, DAI, VUL - present in the hardware, deliberately not driven. + * + * Register map (AudDrv_Afe.h:449-463, the AFE's own map, not the codec's): + * + * DL1 BASE/CUR/END +0x40 / +0x44 / +0x48 driven by this driver + * DL2 BASE/CUR/END +0x50 / +0x54 / +0x58 not driven + * AWB BASE/END/CUR +0x70 / +0x78 / +0x7c not driven + * VUL BASE/END/CUR +0x80 / +0x88 / +0x8c driven by this driver + * DAI BASE/END/CUR +0x90 / +0x98 / +0x9c not driven + * + * Note DL2 is at +0x50..+0x58, NOT +0x80..; +0x80/+0x8c is VUL, which this + * driver already uses for capture. Anyone adding DL2 by copying the VUL + * offsets would silently overwrite the capture ring registers. + * + * DL2 is deliberately left unimplemented rather than wired up, because nothing + * in the vendor tree ever drives it as a stream: + * + * - it has no dai_link at all (no reference in mt_soc_dai_routing.c or + * mt_soc_pcm_routing.c), so there is no PCM to attach to it; + * - the only mention in the playback driver is + * mt_soc_pcm_afe.c:573, which sets DL2's *fetch format* while starting + * DL1 - it never enables DL2; + * - DL2 has no channel/mono configuration: SetChannels() + * (mt_soc_afe_control.c:468-487) handles AWB and VUL only and returns + * false from its default branch for MEM_DL1 and MEM_DL2 alike. + * + * Its enable bit does exist (AFE_DAC_CON0, DL2_ON = bit 2, + * mediatek/platform/mt6589/kernel/drivers/sound/AudDrv_Afe.h:574 - the same + * 1 << (block + 1) encoding SetMemoryPathEnable() shifts into place at + * mt_soc_afe_control.c:1104) and its rate lives in AFE_DAC_CON1[7:4], so a + * future second-output path is possible, but it would be untestable dead code + * today. + * + * AWB (asynchronous write buffer) and DAI are likewise not driven. + * + * AWB is not unused in the vendor tree: mt_soc_pcm_awb.c does enable and + * disable it (SetMemoryPathEnable(MEM_AWB) at lines 219 and 195). But that + * file registers its own snd_soc_platform rather than a dai_link, and no + * dai_link in mt_soc_machine.c names an AWB stream, so there is no PCM here + * to attach it to. The path it serves is the FM/modem interface + * (mt_soc_fm_i2s2.c), which has no mainline equivalent, and wiring it up + * would need a second AFE output, the 2nd I2S input and an MT6320 input, + * none of which this card's DT or DAI links describe. Left out on purpose. + * + * DAI has no driver-side use at all: nothing in the vendor _mediatek tree + * enables MEM_DAI, and it is only reachable over the DAI/BT pins + * (AFE_DAIBT_CON0, 0x001c) which this board does not wire up. + */ +#define AFE_IRQ_MCU_CON 0x03a0 +#define AFE_IRQ_MCU_CON_IRQ1_ON BIT(0) +#define AFE_IRQ_MCU_CON_IRQ2_ON BIT(1) +#define AFE_IRQ_MCU_CON_IRQ1_RATE GENMASK(7, 4) +#define AFE_IRQ_MCU_CON_IRQ2_RATE GENMASK(11, 8) +#define AFE_IRQ_MCU_STATUS 0x03a4 +#define AFE_IRQ_MCU_STATUS_IRQ1 BIT(0) +#define AFE_IRQ_MCU_STATUS_IRQ2 BIT(1) +#define AFE_IRQ_MCU_CLR 0x03a8 +/* + * AFE_IRQ_MCU_STATUS / CLR layout (data sheet p.2498-2501): + * + * bit 0 IRQ1_MCU DL1 / memif period (this driver) + * bit 1 IRQ2_MCU VUL period (this driver) + * bit 2 IRQ_MCU_DAI_SET DAI reset 1 -> 0 + * bit 3 IRQ_MCU_DAI_RST DAI reset 0 -> 1 + * bit 4 IRQ5_MCU HDMI 8ch I2S + * bit 5 IRQ6_MCU SPDIF + * bits 8-13 *_MCU_MISS per-IRQ missed-interrupt flags + * + * The GIC line (Afe_irq_mcu_b, SPI 104) is level-triggered. Any of the + * status bits above can hold it asserted until the matching CLR bit is + * written. OWNED is what this driver turns into snd_pcm_period_elapsed(); + * LINE is every bit that must be cleared to drop the wire. Treating the + * two as the same set (clear only IRQ1|IRQ2) leaves DAI/miss status latched + * and the hardirq handler re-enters forever - which is what froze boot + * once the AFE node was enabled. + * + * Bit 6 of CLR ("IRQ_MCU_CLR") is a handshake that only runs once every + * status is already zero; it cannot replace clearing bits 0-5 / 8-13. + */ +#define AFE_IRQ_MCU_STATUS_OWNED (AFE_IRQ_MCU_STATUS_IRQ1 | \ + AFE_IRQ_MCU_STATUS_IRQ2) +#define AFE_IRQ_MCU_STATUS_LINE (GENMASK(5, 0) | GENMASK(13, 8)) +#define AFE_IRQ_MCU_CLR_LINE AFE_IRQ_MCU_STATUS_LINE +/* + * AFE_IRQ_CLR bit 6: "clears the MCU IRQ for AFE while all IRQ statuses are + * 0". The vendor ISR writes this, and only this, when a line arrives whose + * status reads back with no bits in [3:0] set (AudDrv_Kernel.c:846-857). + */ +#define AFE_IRQ_MCU_CLR_HANDSHAKE BIT(6) +#define AFE_IRQ_MCU_CNT1 0x03ac /* IRQ1 MCU counter */ +#define AFE_IRQ_MCU_CNT2 0x03b0 /* IRQ2 MCU counter */ + +/* + * DL1 -> interconnect -> I2S2 DAC path. + * + * AFE_I2S_CON1 (0x0034) is the playback I2S block. The ADC input uses the + * third, input-only I2S block at AFE_I2S_CON2 (0x0038), matching the Lenovo + * BSP's SetI2SAdcIn()/SetI2SAdcEnable() implementation. + */ +#define AFE_I2S_CON1 0x0034 +#define AFE_I2S_CON1_BASE 0x00000008 /* I2S2_FMT: 0=EIAJ, 1=I2S; select I2S */ +#define AFE_I2S_CON1_RATE GENMASK(11, 8) +#define AFE_I2S_CON1_UPDATE_WORD GENMASK(28, 24) +#define AFE_I2S_CON1_ON BIT(0) +/* Same value the capture path forces on AFE_I2S_CON2 (LDVT / vendor). */ +#define AFE_I2S_CON1_UPDATE_WORD_8 (8) +#define AFE_I2S_CON2 0x0038 +#define AFE_I2S_CON2_BUFFER_UPDATE_WORD GENMASK(27, 24) +#define AFE_I2S_CON2_RATE GENMASK(11, 8) +#define AFE_I2S_CON2_INV_LRCK BIT(23) +#define AFE_I2S_CON2_FMT BIT(3) +#define AFE_I2S_CON2_WLEN BIT(1) +#define AFE_I2S_CON2_EN BIT(0) +#define AFE_CONN1 0x0024 +#define AFE_CONN1_DL1_O3 BIT(21) /* DL1 ch1 -> O3 */ +#define AFE_CONN2 0x0028 +#define AFE_CONN2_DL1_O4 BIT(6) /* DL1 ch2 -> O4 */ +/* + * I2S ADC -> VUL, the two connections the downstream capture driver makes: + * I03 -> O09 and I04 -> O10. Both are in AFE_CONN3, at bit 0 and bit 3 + * respectively. The downstream mConnection tables agree on the registers + * and bits; only their output *numbering* is offset by one against the + * data sheet, which names these bits I03_O09_S and I04_O10_S. + */ +#define AFE_CONN3 0x002c +#define AFE_CONN3_VUL_O9 BIT(0) /* I03 -> O09 */ +#define AFE_CONN3_VUL_O10 BIT(3) /* I04 -> O10 */ + +/* + * The downlink pre-distortion block is real on this part and lives at + * +0x260, so keep it - only the ADDA registers above it were wrong. + */ +#define AFE_ADDA_PREDIS_CON0 0x0260 +#define AFE_ADDA_PREDIS_CON1 0x0264 +/* + * The AFE's own 16 KiB SRAM. The DL1 and VUL memory interfaces fetch + * directly out of it with no DMA engine behind them: DL1_BASE/DL1_END are + * plain physical addresses the AFE dereferences itself. A buffer anywhere + * else is never fetched, and the failure is silent - the memif runs, but + * DL1_CUR never advances past the base while the period interrupt still + * fires off the counter, so ALSA sees a healthy stream carrying no audio. + * + * The base is 0x12008000. The data sheet, Table 3-9 "Multimedia system + * memory map" (p.48), splits 0x12000000..0x1200cfff into three banks whose + * sizes sum exactly to the 52 KiB span the table's thirteen 4 KiB rows + * cover: DISP SRAM (32 KiB) = 0x12000000..0x12007fff, AUDIO SRAM (16 KiB) = + * 0x12008000..0x1200bfff, ISP SRAM (4 KiB) = 0x1200c000..0x1200cfff. The + * bank names are set as two-line labels vertically centred over the group + * of rows each covers, so the boundary is the halfway point of the table, + * not the row a given label happens to sit beside. + * + * Two vendor headers agree on 0x12008000 and are what the shipping code + * runs. AudDrv_Afe.h:410,419 derives AFE_INTERNAL_SRAM_PHY_BASE as + * (AUDIO_HW_PHYSICAL_BASE - 0x70000 + 0x8000) with AUDIO_HW_PHYSICAL_BASE + * 0x12070000, i.e. 0x12008000, and AudDrv_Kernel.c:926,1457 ioremap()s + * that macro and hands it straight to the DL1 buffer allocation. The LDVT + * header AudioAfe.h:415,426 reaches the same address the other way round, + * AUDIO_HW_PHYSICAL_BASE + 0x4000 off a 0x12000000 base - an offset of + * exactly one 32 KiB DISP bank, which only makes sense if the audio bank + * starts where the DISP bank ends. + * + * The one dissenting source is the comment on AudDrv_Afe.h:418 itself + * ("0x12004000~0x12007FFF (16K)"), which contradicts the macro sitting + * directly beneath it - and 0x12004000 is a quarter-way address inside the + * DISP bank, not a bank start, which is what gives the comment away. + */ +#define AFE_SRAM_PHYS_BASE 0x12008000 +#define AFE_SRAM_PHYS_END 0x1200bfff /* inclusive */ +/* + * There is no NEWIF (AFE<->PMIC serial link) register on MT6589. The + * offsets this driver used to program - 0x0138 and 0x013c - are MT6797 + * ADDA registers: MT6589's AFE map goes from AFE_MEMIF_MON4 at +0x00e0 + * straight to AFE_FOC_CON at +0x0170 with nothing in between, in both the + * data sheet and the vendor header. The values written (0x03f87201 and a + * GENMASK(11,10) update) come from the same MT6797 code, so both were + * landing on unbacked addresses. + * + * The AFE<->PMIC link on this part is brought up by the MT6320 codec side + * plus the AFE clocks taken above; nothing needs programming here. + */ + +static const struct regmap_config mt6589_afe_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .max_register = 0x0ffc, +}; + +static int mt6589_afe_vul_prepare(struct snd_soc_component *comp, + struct snd_pcm_substream *substream); +static int mt6589_afe_vul_start(struct snd_soc_component *comp, + struct snd_pcm_substream *substream); +static int mt6589_afe_vul_stop_substream(struct snd_soc_component *comp, + struct snd_pcm_substream *substream); +static int mt6589_afe_sync_stop(struct snd_soc_component *comp, + struct snd_pcm_substream *substream); + +struct mt6589_afe { + struct device *dev; + struct regmap *regmap; + struct clk *clk; + struct clk *clk_i2s; + int irq; + struct snd_pcm_substream *dl1_substream; /* active DL1 stream */ + struct snd_pcm_substream *vul_substream; /* active VUL stream */ +}; + +/* + * Hz -> the AFE sample-rate code, as SampleRateTransform() produces it + * downstream (Soc_Aud_I2S_SAMPLERATE_*): 8k=0, 11.025k=1, 12k=2, 16k=3, + * 22.05k=4, 24k=5, 32k=6, 44.1k=7, 48k=8. + * + * Every rate field the driver programs - IRQ_MCU_CON[7:4] and [11:8], + * DAC_CON1[3:0] for DL1 and [19:16] for VUL, and I2S_CON1[11:8] - takes + * this same code, because SetMemIfSampleRate() and SetIRQMCUAttribute() + * both pass their argument through SampleRateTransform() before + * shifting it into place. There is no second, sparse table in that path. + * + * The data sheet's "6 kHz to 96 kHz" audio figure is not achievable on this + * part. SampleRateTransform() - the single function every AFE rate field goes + * through - has cases for exactly the nine rates below and falls through to + * `return Soc_Aud_I2S_SAMPLERATE_I2S_44K` for anything else + * (mt_soc_afe_control.c:374-400). The shared audio V2 header does define + * AFE_88K/96K/174K/192K and the AFE kernel driver's own enum repeats them + * (mediatek/platform/common/hardware/audio/V2/include/AudioStreamAttribute.h:50-61, + * mt_soc_digital_type.h:256-259), but nothing ever emits those values, so + * asking for 88.2 or 96 kHz would reach the hardware as 44.1 kHz. + * The 4-bit rate fields are likewise full at the highest documented code (10), + * leaving no spare code to extend into. Those rates are therefore rejected + * below with -EINVAL, and mt6589_afe_rate_code_sparse() returning an error is + * what keeps them out of the advertised mask. There is also no 6 kHz code + * anywhere in the ladder. + * + * 12000 and 24000 *are* encodable (codes 2 and 6) and are offered; see the + * rate masks below, which have to add them by hand because ALSA gives those + * two their own bits. + */ + +/* + * Hz -> the AFE's own rate code. + * + * This is a *sparse* table, distinct from the dense 0..8 one the PMIC + * codec uses for its DL SRC2 register (mt6320.c). The stock driver + * writes u4SamplingRateConvert[] = {0, 1, 2, 4, 5, 6, 8, 9, 10} + * (AudioAfe.c) into AFE_DAC_CON1's DL1 mode, AFE_I2S_CON1 and the IRQ + * counter select. The two agree only up to 12 kHz, so using the dense + * code here programs the wrong divider for nearly every rate. + * + * The table is verbatim u4SamplingRateConvert[] (AudioAfe.c:66) indexed by the + * dense rate enum, so the {0,1,2,4,5,6,8,9,10} code sequence must not be + * "tidied" into 0..8. Values below 8000 and above 48000 return -EINVAL on + * purpose - see the rate-transform note above this function. + */ +static int mt6589_afe_rate_code_sparse(unsigned int rate) +{ + switch (rate) { + case 8000: return 0; + case 11025: return 1; + case 12000: return 2; + case 16000: return 4; + case 22050: return 5; + case 24000: return 6; + case 32000: return 8; + case 44100: return 9; + case 48000: return 10; + default: return -EINVAL; + } +} + +/* + * Rates the AFE hardware can encode, as an ALSA rate mask. + * + * SNDRV_PCM_RATE_8000_48000 looks like it should cover everything the table + * above encodes, but it does not contain 12000 or 24000: ALSA assigns those two + * bits of their own, added long after the range macro was defined + * (SNDRV_PCM_RATE_12000 = 1U<<17, SNDRV_PCM_RATE_24000 = 1U<<18, + * include/sound/pcm.h:127-128). Without the explicit OR they are supported by + * the hardware and by the ladder above yet unavailable to userspace. + */ +#define MT6589_AFE_RATES (SNDRV_PCM_RATE_8000_48000 | \ + SNDRV_PCM_RATE_12000 | \ + SNDRV_PCM_RATE_24000) + +static struct snd_soc_dai_driver mt6589_afe_dais[] = { + { + .name = "mt6589-afe-dl1", + .playback = { + .stream_name = "DL1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MT6589_AFE_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + .name = "mt6589-afe-vul", + .capture = { + .stream_name = "VUL Capture", + .channels_min = 1, + .channels_max = 2, + /* + * The AFE's own VUL ladder does encode 12 kHz and + * 24 kHz, so this side advertises the full AFE set. + * + * A capture stream is nevertheless limited to + * 8/16/32/48 kHz end to end, because the codec's + * uplink SRC encodes only those four rates + * (MT6320_CODEC_UL_RATES, mt6320_ul_src_rate_code()). + * ALSA intersects the per-DAI rate masks of a link, so + * that narrower codec mask is what userspace + * negotiates against and the two extra rates never + * reach hw_params. They are deliberately not repeated + * here as a restriction: the AFE really can encode + * them, and it is the codec that cannot. + */ + .rates = MT6589_AFE_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +static const struct snd_pcm_hardware mt6589_afe_hardware = { + /* on-chip SRAM buffer, no mmap */ + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = MT6589_AFE_RATES, + .rate_min = 8000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .period_bytes_min = 1024, + .period_bytes_max = 8192, + .periods_min = 2, + .periods_max = 16, + /* + * The AFE SRAM is 16 KB and is shared by both directions. Handing + * the whole window to one stream leaves nothing for the other, so + * cap it at half. speaker-test asks for 8192 with a 4096 period, + * which still fits. + */ + .buffer_bytes_max = 8 * 1024, +}; + +/* + * DAPM graph helper for the DL1 and VUL memory-interface widgets. + * + * The memory-interface enable bits are owned by the PCM trigger path. That + * gives each stream one clear hardware owner and keeps the start sequence in + * the same place as CUR/CONN/I2S programming. AFE_ON remains derived from + * the active stream pointers by mt6589_afe_update_afe_on(). + */ +static int mt6589_afe_update_afe_on(struct mt6589_afe *afe) +{ + bool active = READ_ONCE(afe->dl1_substream) || + READ_ONCE(afe->vul_substream); + + return regmap_update_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_AFE_ON, + active ? AFE_DAC_CON0_AFE_ON : 0); +} + +static int mt6589_afe_memif_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + /* + * The DAPM widgets only model the memory-interface graph. The actual + * AFE_DAC_CON0 enable sequence belongs to the PCM trigger callbacks, + * where CUR/CONN/I2S configuration has already been completed. + */ + return 0; +} + +static int mt6589_afe_pcm_open(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + snd_soc_set_runtime_hwparams(substream, &mt6589_afe_hardware); + /* + * AFE_DL1_END[2:0] must be 7, so keep the period (and therefore the + * buffer) 8-byte aligned, and honour the AFE's 32-byte sample + * alignment requirement as well so the ring does not need masking. + */ + return snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); +} + +static int mt6589_afe_pcm_hw_params(struct snd_soc_component *comp, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int bytes = params_buffer_bytes(params); + dma_addr_t dma = runtime->dma_addr; + u64 base = lower_32_bits(dma); + int ret; + + /* + * The AFE has no DMA engine for these ring buffers - it dereferences + * DL1_BASE/DL1_END itself - so the buffer has to sit in the AFE SRAM. + * + * SNDRV_DMA_TYPE_DEV_IRAM cannot be trusted to have put it there: + * snd_dma_iram_alloc() falls back to plain dma_alloc_coherent() the + * moment the gen_pool lookup or the allocation fails (it does so + * silently, only retyping dmab->dev.type to SNDRV_DMA_TYPE_DEV), and + * it falls back whenever of_gen_pool_get() cannot resolve the "iram" + * phandle to a live pool - including when the sram@ node probed late + * or was never instantiated at all, since the phandle then has no + * platform_device and gen_pool_get() returns NULL. + * + * That fallback yields a perfectly ordinary SDRAM buffer that the AFE + * can never fetch, and the resulting failure is silent: the stream + * opens, periods elapse on schedule off the MCU counter, and the + * DAC is fed nothing. So refuse it loudly instead. + */ + if (dma < AFE_SRAM_PHYS_BASE || + dma > AFE_SRAM_PHYS_END || + dma + bytes - 1 > AFE_SRAM_PHYS_END) { + phys_addr_t sram_base = AFE_SRAM_PHYS_BASE; + phys_addr_t sram_end = AFE_SRAM_PHYS_END; + + return dev_err_probe(comp->dev, -EINVAL, + "PCM buffer at %pa (%u bytes) is outside the AFE SRAM window %pa..%pa; the AFE cannot fetch it\n", + &dma, bytes, &sram_base, &sram_end); + } + + /* Program this direction's memif DMA ring, in the AFE on-chip SRAM. */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = regmap_write(afe->regmap, AFE_DL1_BASE, base); + if (ret) + return ret; + + ret = regmap_write(afe->regmap, AFE_DL1_END, base + bytes - 1); + if (ret) + return ret; + + /* + * DL1_CUR is the memif's read pointer. The stock driver does + * not program it either, but it works around the consequence + * twice - in both its ISR and its pointer callback it reads + * DL1_CUR and, when it comes back 0, substitutes the buffer + * address. It really can read 0, so do the substitution here + * rather than in the callback: seed the register explicitly so + * the very first pointer read after start is already sane. + */ + return regmap_write(afe->regmap, AFE_DL1_CUR, base); + } + + ret = regmap_write(afe->regmap, AFE_VUL_BASE, base); + if (ret) + return ret; + + ret = regmap_write(afe->regmap, AFE_VUL_END, base + bytes - 1); + if (ret) + return ret; + + return 0; +} + +static int mt6589_afe_pcm_prepare(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + struct snd_pcm_runtime *runtime = substream->runtime; + int sparse_code = mt6589_afe_rate_code_sparse(runtime->rate); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + return mt6589_afe_vul_prepare(comp, substream); + int ret; + + if (sparse_code < 0) + return -EINVAL; + + /* + * Re-seed the memif read pointer on every start. hw_params() writes + * it once, but prepare() runs again before each restart, and a + * stopped stream leaves DL1_CUR wherever the memif left it. Starting + * a fresh stream from a stale cursor makes .pointer() report an + * arbitrary offset into the new buffer, so ALSA's first period is + * mis-counted. The AFE has no DMA engine to reset it for us. + */ + ret = regmap_write(afe->regmap, AFE_DL1_CUR, + lower_32_bits(runtime->dma_addr)); + if (ret) + return ret; + + /* IRQ1 rate + per-period frame count (enabled in the trigger) */ + ret = regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON, + AFE_IRQ_MCU_CON_IRQ1_RATE, + FIELD_PREP(AFE_IRQ_MCU_CON_IRQ1_RATE, + sparse_code)); + if (ret) + return ret; + + ret = regmap_write(afe->regmap, AFE_IRQ_MCU_CNT1, + runtime->period_size); + if (ret) + return ret; + + /* interconnect: DL1 ch1/ch2 -> O3/O4 */ + ret = regmap_set_bits(afe->regmap, AFE_CONN1, AFE_CONN1_DL1_O3); + if (ret) + return ret; + + ret = regmap_set_bits(afe->regmap, AFE_CONN2, AFE_CONN2_DL1_O4); + if (ret) + return ret; + + ret = regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0); + if (ret) + return ret; + + ret = regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0); + if (ret) + return ret; + + /* + * No sample-rate conversion block is programmed here. Normal DL1 + * playback does not go through the ASRC: the stock driver starts + * I2S_OUT_DAC by connecting I05 -> O03 and I06 -> O04 (the + * connections set above), enabling the memory interface, and turning + * on the I2S DAC. The rate itself goes to the DAC through + * DAC_CON1, which is programmed further down. + */ + /* + * AI2S_UPDATE_WORD lives in bits [28:24]. Leaving it at 0 is enough + * for the period IRQ counter to run, but the DAC then hands the + * PMIC an empty digital stream. The vendor LDVT helper and the + * capture-side CON2 path both use 8. + */ + ret = regmap_write(afe->regmap, AFE_I2S_CON1, + AFE_I2S_CON1_BASE | + FIELD_PREP(AFE_I2S_CON1_RATE, sparse_code) | + FIELD_PREP(AFE_I2S_CON1_UPDATE_WORD, + AFE_I2S_CON1_UPDATE_WORD_8)); + if (ret) + return ret; + + /* + * DAC_CON1 carries the DL1 memory-interface rate in bits [3:0]. + * SetMemIfSampleRate() writes it there for MEM_DL1, and passes it + * u4SamplingRateConvert[] - the same sparse table used above. + */ + ret = regmap_update_bits(afe->regmap, AFE_DAC_CON1, + AFE_DAC_CON1_DL1_RATE, + FIELD_PREP(AFE_DAC_CON1_DL1_RATE, + sparse_code)); + if (ret) + return ret; + + /* AFE_DAC_CON1 bit 21 selects mono (1) versus stereo (0) DL1 data. */ + return regmap_update_bits(afe->regmap, AFE_DAC_CON1, + AFE_DAC_CON1_DL1_DATA, + runtime->channels == 1 ? AFE_DAC_CON1_DL1_DATA : 0); +} + +static int mt6589_afe_stop(struct mt6589_afe *afe) +{ + int ret, first_err = 0; + + ret = regmap_clear_bits(afe->regmap, AFE_IRQ_MCU_CON, + AFE_IRQ_MCU_CON_IRQ1_ON); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_DL1_ON); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(afe->regmap, AFE_CONN1, + AFE_CONN1_DL1_O3); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(afe->regmap, AFE_CONN2, + AFE_CONN2_DL1_O4); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(afe->regmap, AFE_I2S_CON1, + AFE_I2S_CON1_ON); + if (ret && !first_err) + first_err = ret; + + /* + * Ack a period interrupt that arrived after IRQ1 was disabled above. + * Leaving it latched makes it fire again as soon as the next stream + * re-enables IRQ1, where the handler would report a period elapsed + * for a stream that has not started: the hw pointer jumps, and ALSA + * can see an xrun on the first buffer after a stop/start. + */ + ret = regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, + AFE_IRQ_MCU_STATUS_IRQ1); + if (ret && !first_err) + first_err = ret; + + WRITE_ONCE(afe->dl1_substream, NULL); + ret = mt6589_afe_update_afe_on(afe); + if (ret && !first_err) + first_err = ret; + return first_err; +} + +static int mt6589_afe_pcm_trigger(struct snd_soc_component *comp, + struct snd_pcm_substream *substream, int cmd) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + int ret; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + return mt6589_afe_vul_start(comp, substream); + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + return mt6589_afe_vul_stop_substream(comp, substream); + default: + return -EINVAL; + } + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + /* + * Publish the substream before enabling IRQ1 so the first + * period interrupt cannot race with this assignment. + */ + WRITE_ONCE(afe->dl1_substream, substream); + + /* Match the stock SetI2SDacEnable()/EnableAfe() ordering. */ + ret = regmap_set_bits(afe->regmap, AFE_I2S_CON1, + AFE_I2S_CON1_ON); + if (ret) + goto err_stop; + + /* + * Start the DL1 memory path before the period interrupt is + * enabled, as the stock mtk_pcm_dl1_start() does, so a + * period interrupt cannot arrive against a stopped DL1. + */ + ret = regmap_set_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_DL1_ON); + if (ret) + goto err_stop; + + ret = regmap_set_bits(afe->regmap, AFE_IRQ_MCU_CON, + AFE_IRQ_MCU_CON_IRQ1_ON); + if (ret) + goto err_stop; + + /* EnableAfe() is last in the stock start sequence. */ + ret = regmap_set_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_AFE_ON); + if (ret) + goto err_stop; + + return 0; + +err_stop: + mt6589_afe_stop(afe); + return ret; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + return mt6589_afe_stop(afe); + default: + return -EINVAL; + } +} + +static snd_pcm_uframes_t mt6589_afe_pcm_pointer(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + struct snd_pcm_runtime *runtime = substream->runtime; + u64 base = lower_32_bits(runtime->dma_addr); + unsigned int cur = 0; + + regmap_read(afe->regmap, + substream->stream == SNDRV_PCM_STREAM_CAPTURE ? + AFE_VUL_CUR : AFE_DL1_CUR, &cur); + + /* + * DL1_CUR legitimately reads back 0 until the memif has started + * fetching; the stock driver treats that one value specially and + * substitutes the buffer address rather than reporting a wrapped + * pointer. hw_params now seeds the register, but keep the same + * substitution here so a hardware reset under a running stream + * cannot turn into a wild pointer. + */ + if (!cur) + cur = base; + + if (cur < base || cur >= base + runtime->dma_bytes) + return 0; + return bytes_to_frames(runtime, cur - base); +} + +static int mt6589_afe_pcm_new(struct snd_soc_component *comp, + struct snd_soc_pcm_runtime *rtd) +{ + size_t size = mt6589_afe_hardware.buffer_bytes_max; + struct gen_pool *pool; + + /* + * The ring is not allocated yet - snd_pcm_lib_malloc_pages() runs + * from snd_pcm_hw_params(), not from here - but the AFE SRAM pool it + * will come from has to exist. snd_dma_iram_alloc() silently degrades + * to ordinary SDRAM when it does not, and the AFE cannot fetch SDRAM, + * so refuse to create the PCM at all rather than hand the user a + * stream that opens and then produces nothing. + */ + pool = of_gen_pool_get(comp->dev->of_node, "iram", 0); + if (!pool) + return dev_err_probe(comp->dev, -ENODEV, + "no gen_pool for the AFE SRAM (iram phandle)\n"); + + if (gen_pool_avail(pool) < size) + return dev_err_probe(comp->dev, -ENOMEM, + "AFE SRAM has %zu bytes free, need %zu\n", + gen_pool_avail(pool), size); + + return snd_pcm_set_managed_buffer_all(rtd->pcm, + SNDRV_DMA_TYPE_DEV_IRAM, + comp->dev, size, size); +} + +static int mt6589_afe_vul_stop(struct mt6589_afe *afe); +static int mt6589_afe_vul_stop_substream(struct snd_soc_component *comp, + struct snd_pcm_substream *substream); + +/* VUL capture: internal ADC -> I2S in -> VUL memif. */ +static int mt6589_afe_vul_prepare(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + struct snd_pcm_runtime *runtime = substream->runtime; + /* AFE rate fields use the sparse table, as SetMemIfSampleRate() does. */ + int rate_code = mt6589_afe_rate_code_sparse(runtime->rate); + int ret; + + /* + * Mirror the playback-side check in mt6589_afe_pcm_prepare(): that + * function returns to vul_prepare() before its own check, so without + * this a negative code reaches FIELD_PREP(). FIELD_PREP only masks + * the field, it does not reject the value, so -EINVAL would be + * truncated into the 4-bit VUL rate field and program a plausible + * looking but wrong divider. + */ + if (rate_code < 0) + return -EINVAL; + + /* Re-seed the capture cursor for the same reason as DL1_CUR above. */ + ret = regmap_write(afe->regmap, AFE_VUL_CUR, + lower_32_bits(runtime->dma_addr)); + if (ret) + return ret; + + ret = regmap_update_bits(afe->regmap, AFE_DAC_CON1, + AFE_DAC_CON1_VUL_RATE, + FIELD_PREP(AFE_DAC_CON1_VUL_RATE, rate_code)); + if (ret) + return ret; + + /* + * Configure the dedicated ADC I2S input block like the Lenovo BSP: + * buffer-update word 8, I2S framing, 16-bit samples, no LR swap/invert + * or loopback. Enable is asserted by the VUL trigger path. + */ + ret = regmap_write(afe->regmap, AFE_I2S_CON2, + FIELD_PREP(AFE_I2S_CON2_BUFFER_UPDATE_WORD, 8) | + FIELD_PREP(AFE_I2S_CON2_RATE, rate_code) | + AFE_I2S_CON2_FMT); + if (ret) + return ret; + + /* Match VUL_DATA/VUL_R_MONO to the ALSA channel count; mono uses L. */ + return regmap_update_bits(afe->regmap, AFE_DAC_CON1, + AFE_DAC_CON1_VUL_DATA | AFE_DAC_CON1_VUL_R_MONO, + runtime->channels == 1 ? AFE_DAC_CON1_VUL_DATA : 0); +} + +static int mt6589_afe_vul_start(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + struct snd_pcm_runtime *runtime = substream->runtime; + u32 base = lower_32_bits(runtime->dma_addr); + int rate_code = mt6589_afe_rate_code_sparse(runtime->rate); + int ret; + + /* Same guard as in vul_prepare(): this recomputes the code itself. */ + if (rate_code < 0) + return -EINVAL; + + WRITE_ONCE(afe->vul_substream, substream); + + ret = regmap_write(afe->regmap, AFE_VUL_CUR, base); + if (ret) + goto err; + + ret = regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON, + AFE_IRQ_MCU_CON_IRQ2_RATE, + FIELD_PREP(AFE_IRQ_MCU_CON_IRQ2_RATE, rate_code)); + if (ret) + goto err; + + /* IRQ2 counts into its own counter register, not IRQ1's. */ + ret = regmap_write(afe->regmap, AFE_IRQ_MCU_CNT2, + runtime->period_size); + if (ret) + goto err; + + /* Route the I2S ADC channels into the VUL memory interface. */ + ret = regmap_set_bits(afe->regmap, AFE_CONN3, AFE_CONN3_VUL_O9); + if (ret) + goto err; + + ret = regmap_set_bits(afe->regmap, AFE_CONN3, AFE_CONN3_VUL_O10); + if (ret) + goto err; + + ret = regmap_set_bits(afe->regmap, AFE_I2S_CON2, AFE_I2S_CON2_EN); + if (ret) + goto err; + + /* Start the memif before the interrupt, as the DL1 path does. */ + ret = regmap_update_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_VUL_ON, AFE_DAC_CON0_VUL_ON); + if (ret) + goto err; + + ret = regmap_set_bits(afe->regmap, AFE_IRQ_MCU_CON, + AFE_IRQ_MCU_CON_IRQ2_ON); + if (ret) + goto err; + + return regmap_set_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_AFE_ON); + +err: + mt6589_afe_vul_stop(afe); + return ret; +} + +static int mt6589_afe_vul_stop(struct mt6589_afe *afe) +{ + int ret, first_err = 0; + + ret = regmap_clear_bits(afe->regmap, AFE_IRQ_MCU_CON, + AFE_IRQ_MCU_CON_IRQ2_ON); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(afe->regmap, AFE_CONN3, AFE_CONN3_VUL_O9); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(afe->regmap, AFE_CONN3, AFE_CONN3_VUL_O10); + if (ret && !first_err) + first_err = ret; + + ret = regmap_clear_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_VUL_ON); + if (ret && !first_err) + first_err = ret; + + /* + * Disable the I2S input path again. AFE_I2S_CON is bidirectional, so + * leaving it enabled keeps the AFE's first I2S block driving pins it + * does not own after arecord exits, and the codec's AIF1 is the other + * end of that link. Clear I2S_EN explicitly rather than writing 0, so + * the rate and format fields keep whatever they held and the next + * open reprograms them (vul_prepare() does). + */ + ret = regmap_clear_bits(afe->regmap, AFE_I2S_CON2, AFE_I2S_CON2_EN); + if (ret && !first_err) + first_err = ret; + + /* + * Ack a period that landed after IRQ2 was disabled, so it does not + * fire again on the next start. + */ + ret = regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, + AFE_IRQ_MCU_STATUS_IRQ2); + if (ret && !first_err) + first_err = ret; + + WRITE_ONCE(afe->vul_substream, NULL); + ret = mt6589_afe_update_afe_on(afe); + if (ret && !first_err) + first_err = ret; + return first_err; +} + +static int mt6589_afe_vul_stop_substream(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + + return mt6589_afe_vul_stop(afe); +} + +/* + * DAPM graph. + * + * Without these the codec's routes have nothing to attach to: a route + * naming a widget that does not exist can never be walked, so the DAC is + * never powered up and mt6320_dac_event() never runs. That is what kept + * the whole analog side dead. + * + * The memory interfaces feeding the interconnect are "DL1" and "VUL", and + * the interconnect itself runs DL1 left/right into I05/I06 and out to + * O03/O04 - the path the stock driver builds with SetinputConnection(I05, + * O03) and SetinputConnection(I06, O04). + */ +static const struct snd_soc_dapm_widget mt6589_afe_widgets[] = { + /* + * DL1 and VUL are the memory interfaces. They carry an event + * handler that powers DAC_CON0 as DAPM walks the graph, mirroring + * what the stock driver does around SetMEMIFEnable(). + * + * The stream endpoints themselves ("DL1 Playback", "VUL Capture") + * need no widget of their own: a DAI gets an auto-created one named + * after its stream_name, and dapm_connect_dai_pair() joins the codec + * to the AFE through exactly those. + */ + SND_SOC_DAPM_OUT_DRV_E("DL1", SND_SOC_NOPM, 0, 0, NULL, 0, + mt6589_afe_memif_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_OUT_DRV_E("VUL", SND_SOC_NOPM, 0, 0, NULL, 0, + mt6589_afe_memif_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), + /* + * The Ixx/Oxx interconnect widgets the stock driver names in + * SetinputConnection() are deliberately absent here. They are not + * endpoints, and nothing on the codec side routes to them, so + * dapm_generic_check_power() would see no sink and they would never + * power - dead weight that misleads a reader into thinking the + * interconnect is modelled. The interconnect itself is hardware: + * AFE_CONN1 bit 21 (I05_O03_S) and AFE_CONN2 bit 6 (I06_O04_S) are + * programmed in prepare(). + * + * The graph therefore has just the two memory interfaces, with the + * codec's DAC hanging off the DAI widget DAPM creates for us: + * + * DL1 Playback -> DL1 -> (AFE_CONN1/CON2) -> I2S2 -> MT6320 DAC + */ +}; + +static const struct snd_soc_dapm_route mt6589_afe_routes[] = { + /* Playback: the DAI's own widget feeds the DL1 memory interface. */ + { "DL1", NULL, "DL1 Playback" }, + /* Capture: the I2S ADC feeds the VUL memory interface. */ + { "VUL", NULL, "VUL Capture" }, +}; + +static const struct snd_soc_component_driver mt6589_afe_component = { + .name = "mt6589-afe-pcm", + .dapm_widgets = mt6589_afe_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt6589_afe_widgets), + .dapm_routes = mt6589_afe_routes, + .num_dapm_routes = ARRAY_SIZE(mt6589_afe_routes), + .open = mt6589_afe_pcm_open, + .hw_params = mt6589_afe_pcm_hw_params, + .prepare = mt6589_afe_pcm_prepare, + .trigger = mt6589_afe_pcm_trigger, + .sync_stop = mt6589_afe_sync_stop, + .pointer = mt6589_afe_pcm_pointer, + .pcm_new = mt6589_afe_pcm_new, +}; + +/* + * IRQ1 marks a DL1 period, IRQ2 a VUL one; hardirq, fast_io regmap, + * atomic PCM. Active-low. + * + * The line is level triggered and the status bits are cleared nowhere else, + * so the handler has to ack before doing anything that can sleep: it writes + * the status it captured to AFE_IRQ_CLR first, and only then calls + * snd_pcm_period_elapsed(). Returning with the line still asserted would + * simply re-enter this handler forever. + * + * Not a shared handler - see the devm_request_irq() call in the probe. + */ +static irqreturn_t mt6589_afe_irq(int irq, void *dev_id) +{ + struct mt6589_afe *afe = dev_id; + struct snd_pcm_substream *dl1, *vul; + unsigned int status, to_clear, owned; + int ret; + + ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status); + if (ret) { + dev_err_ratelimited(afe->dev, + "failed to read AFE IRQ status: %d\n", + ret); + /* Best-effort drop of the level line so we do not spin. */ + regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, + AFE_IRQ_MCU_CLR_LINE); + return IRQ_HANDLED; + } + + /* + * Ack every bit that can hold the level line, then report periods + * only for the IRQs this driver enables. Capture the raw status + * first so period_elapsed still sees the edge we are clearing. + */ + to_clear = status & AFE_IRQ_MCU_STATUS_LINE; + if (!to_clear) + to_clear = AFE_IRQ_MCU_CLR_LINE; + + ret = regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, to_clear); + if (ret) + dev_err_ratelimited(afe->dev, + "failed to clear AFE IRQ status: %d\n", + ret); + + owned = status & AFE_IRQ_MCU_STATUS_OWNED; + if (!owned) { + /* + * The line asserted but no period bit is set. Both references + * treat this as "ack and stop", not as a period: downstream + * tests `status & 0xf` and, when zero, writes bit 6 of + * AFE_IRQ_CLR and returns (AudDrv_Kernel.c:839-858), and the + * working mt6572-afe-pcm.c does the same with + * AFE_IRQ_MCU_CLR_NOSTATUS (BIT(6)|BIT(1)|BIT(0)). + * + * Bit 6 is the "IRQ MCU clear while all IRQ statuses are 0" + * handshake (data sheet p.2500); a handler that only clears + * bits 0-5 / 8-13 leaves a line held in this state asserted + * and re-enters forever. + * + * Reporting a period here instead is wrong and was tried: it + * makes ALSA advance on an interrupt that carries no data. + */ + regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, + AFE_IRQ_MCU_CLR_HANDSHAKE); + return IRQ_HANDLED; + } + + dl1 = READ_ONCE(afe->dl1_substream); + vul = READ_ONCE(afe->vul_substream); + + /* Report the period for the direction whose counter fired. */ + if ((owned & AFE_IRQ_MCU_STATUS_IRQ1) && dl1) + snd_pcm_period_elapsed(dl1); + + if ((owned & AFE_IRQ_MCU_STATUS_IRQ2) && vul) + snd_pcm_period_elapsed(vul); + + return IRQ_HANDLED; +} + +static int mt6589_afe_sync_stop(struct snd_soc_component *comp, + struct snd_pcm_substream *substream) +{ + struct mt6589_afe *afe = snd_soc_component_get_drvdata(comp); + + synchronize_irq(afe->irq); + return 0; +} + +static int mt6589_afe_pcm_dev_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mt6589_afe *afe; + struct resource res; + void __iomem *base; + int ret, irq; + + afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL); + if (!afe) + return -ENOMEM; + afe->dev = dev; + platform_set_drvdata(pdev, afe); + + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) + return dev_err_probe(dev, ret, "failed to set DMA mask\n"); + + /* The AFE registers are in the parent audsys syscon window. */ + ret = of_address_to_resource(dev->parent->of_node, 0, &res); + if (ret) + return dev_err_probe(dev, ret, "no AFE reg in parent syscon\n"); + base = devm_ioremap(dev, res.start, resource_size(&res)); + if (!base) + return dev_err_probe(dev, -ENOMEM, "failed to map AFE registers\n"); + afe->regmap = devm_regmap_init_mmio(dev, base, &mt6589_afe_regmap_config); + if (IS_ERR(afe->regmap)) + return dev_err_probe(dev, PTR_ERR(afe->regmap), + "failed to init AFE regmap\n"); + + /* + * Release the AFE and I2S power-down bits before anything enables + * the clocks that live behind them, otherwise the register writes + * that follow land on a block that is still powered down. + * + * PDN_AFE resets to 0 (powered on) but PDN_I2S resets to 1 (powered + * down), so both are cleared explicitly. + */ + ret = regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, + AUDIO_TOP_CON0_PDN_AFE | + AUDIO_TOP_CON0_PDN_I2S, 0); + if (ret) + return dev_err_probe(dev, ret, + "failed to power on AFE\n"); + + afe->clk = devm_clk_get_enabled(dev, "afe"); + if (IS_ERR(afe->clk)) + return dev_err_probe(dev, PTR_ERR(afe->clk), + "failed to get/enable the audio clock\n"); + + afe->clk_i2s = devm_clk_get_enabled(dev, "i2s"); + if (IS_ERR(afe->clk_i2s)) + return dev_err_probe(dev, PTR_ERR(afe->clk_i2s), + "failed to get/enable the I2S clock\n"); + + /* mask all AFE IRQs + clear stale status before hooking the GIC */ + ret = regmap_write(afe->regmap, AFE_IRQ_MCU_CON, 0); + if (ret) + return dev_err_probe(dev, ret, + "failed to mask AFE IRQs\n"); + + /* Drop any sticky STATUS left by the bootloader before request_irq. */ + ret = regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, + AFE_IRQ_MCU_CLR_LINE); + if (ret) + return dev_err_probe(dev, ret, + "failed to clear AFE IRQ status\n"); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + afe->irq = irq; + /* + * Flags 0 is deliberate: it leaves the trigger type exactly as the + * device tree declared it (IRQ_TYPE_LEVEL_LOW for this node), and the + * level behaviour is required here - the AFE status bits stay set + * until mt6589_afe_irq() clears them, so an edge-triggered line would + * drop a period whose status it could not ack in time. + * + * Passing 0 does not silently downgrade the interrupt to an edge one: + * request_irq() only calls __irq_set_trigger() when IRQF_TRIGGER_MASK + * is actually set in the flags (kernel/irq/manage.c:1715-1721), so + * with 0 the trigger configured earlier from the DT by the GIC driver + * stands. + * + * No IRQF_SHARED: SPI 104 is the AFE's own interrupt line - the data + * sheet's interrupt table names it "Afe_irq_mcu_b" and gives no other + * source - so it is never requested twice and the handler does not + * need to be chained. + */ + ret = devm_request_irq(dev, irq, mt6589_afe_irq, 0, "mt6589-afe", afe); + if (ret) + return dev_err_probe(dev, ret, "failed to request AFE irq %d\n", irq); + + ret = devm_snd_soc_register_component(dev, &mt6589_afe_component, + mt6589_afe_dais, + ARRAY_SIZE(mt6589_afe_dais)); + if (ret) + return dev_err_probe(dev, ret, "failed to register AFE component\n"); + + return 0; +} + +static const struct of_device_id mt6589_afe_pcm_dt_match[] = { + { .compatible = "mediatek,mt6589-audio" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mt6589_afe_pcm_dt_match); + +static struct platform_driver mt6589_afe_pcm_driver = { + .driver = { + .name = "mt6589-afe-pcm", + .of_match_table = mt6589_afe_pcm_dt_match, + }, + .probe = mt6589_afe_pcm_dev_probe, +}; +module_platform_driver(mt6589_afe_pcm_driver); + +MODULE_DESCRIPTION("MediaTek mt6589 AFE platform driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/mediatek/mt6589/mt6589-mt6320.c b/sound/soc/mediatek/mt6589/mt6589-mt6320.c new file mode 100644 index 00000000000000..35d0ba964494fe --- /dev/null +++ b/sound/soc/mediatek/mt6589/mt6589-mt6320.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek MT6589 + MT6320 sound card. + * + * Machine driver binding the MT6589 AFE platform (DL1 playback) to the MT6320 PMIC analog codec, with headphone-jack detection that auto-routes between the + * speaker and the headphones, and an optional external speaker amplifier. + * Modelled on the mt8183-mt6358 PMIC-codec card. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +SND_SOC_DAILINK_DEFS(playback, + DAILINK_COMP_ARRAY(COMP_CPU("mt6589-afe-dl1")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6320-sound", "mt6320-snd-codec-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture, + DAILINK_COMP_ARRAY(COMP_CPU("mt6589-afe-vul")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6320-sound", "mt6320-snd-codec-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link mt6589_mt6320_dai_links[] = { + { + .name = "DL1", + .stream_name = "DL1 Playback", + SND_SOC_DAILINK_REG(playback), + }, + { + .name = "VUL Capture", + .stream_name = "VUL Capture", + SND_SOC_DAILINK_REG(capture), + }, +}; + +static struct snd_soc_jack mt6589_mt6320_hp_jack; + +static struct snd_soc_jack_pin mt6589_mt6320_jack_pins[] = { + { .pin = "Headphone", .mask = SND_JACK_HEADPHONE }, + { .pin = "Speaker", .mask = SND_JACK_HEADPHONE, .invert = 1 }, +}; + +static int mt6589_mt6320_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_component *accdet = NULL; + struct snd_soc_component *component; + int ret; + + ret = snd_soc_card_jack_new_pins(card, "Headphone Jack", + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2, + &mt6589_mt6320_hp_jack, + mt6589_mt6320_jack_pins, + ARRAY_SIZE(mt6589_mt6320_jack_pins)); + if (ret) + return ret; + + ret = snd_jack_set_key(mt6589_mt6320_hp_jack.jack, + SND_JACK_BTN_0, KEY_PLAYPAUSE); + if (ret) + return ret; + + ret = snd_jack_set_key(mt6589_mt6320_hp_jack.jack, + SND_JACK_BTN_1, KEY_PREVIOUSSONG); + if (ret) + return ret; + + ret = snd_jack_set_key(mt6589_mt6320_hp_jack.jack, + SND_JACK_BTN_2, KEY_NEXTSONG); + if (ret) + return ret; + + /* + * Find the headset detector among this card's aux components. + * + * This must not use snd_soc_lookup_component_by_name(). That helper + * takes client_mutex, and late_probe runs with client_mutex already + * held: snd_soc_register_card() acquires it, then reaches + * snd_soc_card_late_probe() through snd_soc_bind_card(), so a lookup + * from here re-acquires a non-recursive mutex the caller already + * holds and the card deadlocks part-way through probe. That is why + * enabling the AFE froze the boot: with the AFE node disabled the + * DAI lookup defers and late_probe is never reached. + * + * aux-devs are bound by soc_bind_aux_dev(), which runs in the same + * locked region but takes no lock of its own, so the component is + * already on card->aux_comp_list by the time we get here. + */ + for_each_card_auxs(card, component) { + if (component->driver && component->driver->name && + !strcmp(component->driver->name, "mt6320-accdet")) { + accdet = component; + break; + } + } + + if (!accdet) { + /* + * accdet is declared in this card's "aux-devs", so its + * absence means the aux component failed to bind - not that + * the board has no headset detection. Losing it silently is + * how the jack then never reports and the Speaker pin is + * never un-muted: DAPM keeps whatever state it had and the + * stream runs with no output. It cannot be fixed from here + * (late_probe runs after binding, too late to defer), so say + * so loudly instead of returning quietly. + */ + dev_err(card->dev, + "mt6320-accdet is in aux-devs but did not bind; headset detection and speaker un-mute will not work\n"); + return 0; + } + + /* + * Headphone detection is optional, so never let this fail the card. + * snd_soc_card_late_probe() runs through soc_card_ret(), and any + * negative return from here is fatal - the card is abandoned and + * never registered. -ENOTSUPP in particular comes back whenever the + * component has no set_jack callback. + */ + ret = snd_soc_component_set_jack(accdet, &mt6589_mt6320_hp_jack, NULL); + if (ret) + dev_info(card->dev, + "headset detection unavailable: %d\n", ret); + + /* + * ACCDET's set_jack reports the plug state; make sure the inverted + * Speaker pin is applied before userspace opens the PCM. + */ + snd_soc_dapm_sync(card->dapm); + + return 0; +} + +static struct snd_soc_card mt6589_mt6320_card = { + .name = "mt6589-mt6320", + .owner = THIS_MODULE, + .dai_link = mt6589_mt6320_dai_links, + .num_links = ARRAY_SIZE(mt6589_mt6320_dai_links), + .late_probe = mt6589_mt6320_late_probe, +}; + +static int mt6589_mt6320_dev_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &mt6589_mt6320_card; + struct device_node *platform_node; + struct snd_soc_dai_link *dai_link; + int i, ret; + + card->dev = &pdev->dev; + + platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); + if (!platform_node) + return dev_err_probe(&pdev->dev, -EINVAL, + "missing mediatek,platform\n"); + + /* + * Both links declare their CPU by name (COMP_CPU("mt6589-afe-dl1")), + * so leave the CPU component alone - adding of_node as well would make + * it invalid, since snd_soc_dlc_component_is_invalid() rejects a dlc + * that has both a name and a node. + * + * The platform component is declared COMP_EMPTY(), and that is fatal: + * the card fails to register with + * ASoC: Neither Component name/of_node are set for DL1 + * so fill it on every link. + * + * The codec is likewise found by the name the dai_link already + * declares, so no phandle is needed for it. + */ + for_each_card_prelinks(card, i, dai_link) { + dai_link->platforms->of_node = platform_node; + } + + if (of_property_present(pdev->dev.of_node, "audio-routing")) { + ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); + if (ret) + goto put_node; + } + + /* Optional external speaker amplifier(s) via "aux-devs". */ + ret = snd_soc_of_parse_aux_devs(card, "aux-devs"); + if (ret) + goto put_node; + + ret = devm_snd_soc_register_card(&pdev->dev, card); +put_node: + of_node_put(platform_node); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to set up sound card\n"); + + return 0; +} + +static const struct of_device_id mt6589_mt6320_dt_match[] = { + { .compatible = "mediatek,mt6589-mt6320-sound" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mt6589_mt6320_dt_match); + +static struct platform_driver mt6589_mt6320_driver = { + .driver = { + .name = "mt6589-mt6320", + .of_match_table = mt6589_mt6320_dt_match, + }, + .probe = mt6589_mt6320_dev_probe, +}; +module_platform_driver(mt6589_mt6320_driver); + +MODULE_DESCRIPTION("MediaTek MT6589 MT6320 sound card"); +MODULE_LICENSE("GPL");