diff options
| -rw-r--r-- | arch/arm/dts/Makefile | 5 | ||||
| -rw-r--r-- | arch/arm/dts/mt8189.dtsi | 325 | ||||
| -rw-r--r-- | arch/arm/dts/mt8371-genio-common-ufs.dtso | 18 | ||||
| -rw-r--r-- | arch/arm/dts/mt8371-genio-common.dtsi | 70 | ||||
| -rw-r--r-- | board/mediatek/MAINTAINERS | 8 | ||||
| -rw-r--r-- | configs/mt8189-ufs.config | 8 | ||||
| -rw-r--r-- | configs/mt8189.config | 8 | ||||
| -rw-r--r-- | configs/mt8195.config | 28 | ||||
| -rw-r--r-- | configs/mt8371_genio_520_evk_ufs_defconfig | 4 | ||||
| -rw-r--r-- | configs/mt8391_genio_720_evk_ufs_defconfig | 4 | ||||
| -rw-r--r-- | configs/mt8395_genio_1200_evk_defconfig | 26 | ||||
| -rw-r--r-- | configs/mt8395_genio_1200_evk_ufs_defconfig | 9 | ||||
| -rw-r--r-- | drivers/clk/mediatek/clk-mt8189.c | 44 | ||||
| -rw-r--r-- | drivers/clk/mediatek/clk-mtk.c | 24 | ||||
| -rw-r--r-- | drivers/phy/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/phy/Makefile | 1 | ||||
| -rw-r--r-- | drivers/phy/phy-mtk-ufs.c | 128 | ||||
| -rw-r--r-- | drivers/phy/phy-mtk-xsphy.c | 600 | ||||
| -rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mt7981.c | 16 | ||||
| -rw-r--r-- | drivers/ufs/ufs-mediatek.c | 42 | ||||
| -rw-r--r-- | drivers/ufs/ufs-mediatek.h | 2 |
21 files changed, 1247 insertions, 134 deletions
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 4085d4c2de1..bff341d6118 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1105,6 +1105,9 @@ dtb-$(CONFIG_SOC_K3_AM62D2) += k3-am62d2-r5-evm.dtb dtb-$(CONFIG_SOC_K3_AM62P5) += k3-am62p5-r5-sk.dtb \ k3-am62p5-verdin-r5.dtb +mt8371-genio-520-evk-ufs-dtbs := mt8371-genio-520-evk.dtb mt8371-genio-common-ufs.dtbo +mt8391-genio-720-evk-ufs-dtbs := mt8391-genio-720-evk.dtb mt8371-genio-common-ufs.dtbo + dtb-$(CONFIG_ARCH_MEDIATEK) += \ mt7622-rfb.dtb \ mt7623a-unielec-u7623-02-emmc.dtb \ @@ -1125,7 +1128,9 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ mt7988-sd-rfb.dtb \ mt8183-pumpkin.dtb \ mt8371-genio-520-evk.dtb \ + mt8371-genio-520-evk-ufs.dtb \ mt8391-genio-720-evk.dtb \ + mt8391-genio-720-evk-ufs.dtb \ mt8512-bm1-emmc.dtb \ mt8516-pumpkin.dtb \ mt8518-ap1-emmc.dtb diff --git a/arch/arm/dts/mt8189.dtsi b/arch/arm/dts/mt8189.dtsi index d246be63293..e550745ac5d 100644 --- a/arch/arm/dts/mt8189.dtsi +++ b/arch/arm/dts/mt8189.dtsi @@ -7,6 +7,8 @@ #include <dt-bindings/clock/mediatek,mt8189-clk.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/phy/phy.h> +#include <dt-bindings/reset/ti-syscon.h> / { compatible = "mediatek,mt8189"; @@ -179,6 +181,79 @@ status = "disabled"; }; + xhci0: usb@11200000 { + compatible = "mediatek,mt8189-xhci", "mediatek,mtk-xhci"; + reg = <0 0x11200000 0 0x1000>, + <0 0x11203e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts-extended = <&gic GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH 0>, + <&pio 207 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host","wakeup"; + phys = <&u2port0 PHY_TYPE_USB2>, + <&u3port0 PHY_TYPE_USB3>; + clocks = <&pericfg_ao_clk CLK_PERAO_SSUSB0_SYS>, + <&pericfg_ao_clk CLK_PERAO_SSUSB0_REF>, + <&pericfg_ao_clk CLK_PERAO_SSUSB0_H>, + <&pericfg_ao_clk CLK_PERAO_SSUSB0_F>, + <&pericfg_ao_clk CLK_PERAO_SSUSB0_XHCI>, + <&pericfg_ao_clk CLK_PERAO_SSUSB0_FRMCNT>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", + "dma_ck", "xhci_ck", "frmcnt_ck"; + #address-cells = <1>; + #size-cells = <0>; + wakeup-source; + mediatek,syscon-wakeup = <&pericfg_ao_clk 0x214 110>; + status = "disabled"; + }; + + xhci1: usb@11210000 { + compatible = "mediatek,mt8189-xhci", "mediatek,mtk-xhci"; + reg = <0 0x11210000 0 0x1000>, + <0 0x11213e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts-extended = <&gic GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH 0>, + <&pio 203 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host","wakeup"; + phys = <&u2port1 PHY_TYPE_USB2>; + clocks = <&pericfg_ao_clk CLK_PERAO_SSUSB1_SYS>, + <&pericfg_ao_clk CLK_PERAO_SSUSB1_REF>, + <&pericfg_ao_clk CLK_PERAO_SSUSB1_H>, + <&pericfg_ao_clk CLK_PERAO_SSUSB1_F>, + <&pericfg_ao_clk CLK_PERAO_SSUSB1_XHCI>, + <&pericfg_ao_clk CLK_PERAO_SSUSB1_FRMCNT>; + clock-names = "sys_ck", "ref_ck","mcu_ck", + "dma_ck", "xhci_ck", "frmcnt_ck"; + #address-cells = <1>; + #size-cells = <0>; + wakeup-source; + mediatek,syscon-wakeup = <&pericfg_ao_clk 0x21c 110>; + status = "disabled"; + }; + + xhci2: usb@11220000 { + compatible = "mediatek,mt8189-xhci", "mediatek,mtk-xhci"; + reg = <0 0x11220000 0 0x1000>, + <0 0x11223e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts-extended = <&gic GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH 0>, + <&pio 193 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host","wakeup"; + phys = <&u2port2 PHY_TYPE_USB2>; + clocks = <&pericfg_ao_clk CLK_PERAO_SSUSB2_SYS>, + <&pericfg_ao_clk CLK_PERAO_SSUSB2_REF>, + <&pericfg_ao_clk CLK_PERAO_SSUSB2_H>, + <&pericfg_ao_clk CLK_PERAO_SSUSB2_F>, + <&pericfg_ao_clk CLK_PERAO_SSUSB2_XHCI>, + <&pericfg_ao_clk CLK_PERAO_SSUSB2_FRMCNT>; + clock-names = "sys_ck", "ref_ck","mcu_ck", + "dma_ck", "xhci_ck", "frmcnt_ck"; + #address-cells = <1>; + #size-cells = <0>; + wakeup-source; + mediatek,syscon-wakeup = <&pericfg_ao_clk 0x27c 110>; + status = "disabled"; + }; + mmc0: mmc@11230000 { compatible = "mediatek,mt8189-mmc"; reg = <0 0x11230000 0 0x10000>, @@ -203,6 +278,55 @@ status = "disabled"; }; + xhci3: usb@11260000 { + compatible = "mediatek,mt8189-xhci", "mediatek,mtk-xhci"; + reg = <0 0x11260000 0 0x2e00>, + <0 0x11263e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts-extended = <&gic GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH 0>, + <&pio 188 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host","wakeup"; + phys = <&u2port3 PHY_TYPE_USB2>, + <&u3port3 PHY_TYPE_USB3>; + clocks = <&pericfg_ao_clk CLK_PERAO_SSUSB3_SYS>, + <&pericfg_ao_clk CLK_PERAO_SSUSB3_REF>, + <&pericfg_ao_clk CLK_PERAO_SSUSB3_H>, + <&pericfg_ao_clk CLK_PERAO_SSUSB3_F>, + <&pericfg_ao_clk CLK_PERAO_SSUSB3_XHCI>, + <&pericfg_ao_clk CLK_PERAO_SSUSB3_FRMCNT>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", + "dma_ck", "xhci_ck", "frmcnt_ck"; + #address-cells = <1>; + #size-cells = <0>; + wakeup-source; + mediatek,syscon-wakeup = <&pericfg_ao_clk 0x284 110>; + status = "disabled"; + }; + + xhci4: usb@11270000 { + compatible = "mediatek,mt8189-xhci", "mediatek,mtk-xhci"; + reg = <0 0x11270000 0 0x1000>, + <0 0x11273e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts-extended = <&gic GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH 0>, + <&pio 184 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host","wakeup"; + phys = <&u2port4 PHY_TYPE_USB2>; + clocks = <&pericfg_ao_clk CLK_PERAO_SSUSB4_SYS>, + <&pericfg_ao_clk CLK_PERAO_SSUSB4_REF>, + <&pericfg_ao_clk CLK_PERAO_SSUSB4_H>, + <&pericfg_ao_clk CLK_PERAO_SSUSB4_F>, + <&pericfg_ao_clk CLK_PERAO_SSUSB4_XHCI>, + <&pericfg_ao_clk CLK_PERAO_SSUSB4_FRMCNT>; + clock-names = "sys_ck", "ref_ck", "mcu_ck", + "dma_ck", "xhci_ck", "frmcnt_ck"; + #address-cells = <1>; + #size-cells = <0>; + wakeup-source; + mediatek,syscon-wakeup = <&pericfg_ao_clk 0x28c 110>; + status = "disabled"; + }; + clock-controller@1000c000 { compatible = "mediatek,mt8189-apmixedsys", "syscon"; reg = <0 0x1000c000 0 0x1000>; @@ -286,6 +410,207 @@ #interrupt-cells = <2>; }; + ufshci: ufshci@112b0000 { + compatible = "mediatek,mt8183-ufshci"; + reg = <0 0x112b0000 0 0x2300>; + interrupts = <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH 0>; + + clocks = <&topckgen_clk CLK_TOP_U_SEL>, + <&clk26m>, + <&topckgen_clk CLK_TOP_MSDCPLL_D2>, + <&topckgen_clk CLK_TOP_AES_UFSFDE_SEL>, + <&topckgen_clk CLK_TOP_U_MBIST_SEL>, + <&ufscfg_ao_reg_clk CLK_UFSCFG_AO_REG_UNIPRO_TX_SYM>, + <&ufscfg_ao_reg_clk CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM0>, + <&ufscfg_ao_reg_clk CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM1>, + <&ufscfg_ao_reg_clk CLK_UFSCFG_AO_REG_UNIPRO_SYS>, + <&ufscfg_ao_reg_clk CLK_UFSCFG_AO_REG_U_SAP_CFG>, + <&ufscfg_ao_reg_clk CLK_UFSCFG_AO_REG_U_PHY_TOP_AHB_S_BUS>, + <&ufscfg_pdn_reg_clk CLK_UFSCFG_REG_UFSHCI_UFS>, + <&ufscfg_pdn_reg_clk CLK_UFSCFG_REG_UFSHCI_AES>, + <&ufscfg_pdn_reg_clk CLK_UFSCFG_REG_UFSHCI_U_AHB>, + <&ufscfg_pdn_reg_clk CLK_UFSCFG_REG_UFSHCI_U_AXI>; + + clock-names = "ufs_sel", + "ufs_sel_min_src", + "ufs_sel_max_src", + "ufs_fde", + "ufs_mbist", + "unipro_tx_sym", + "unipro_rx_sym0", + "unipro_rx_sym1", + "unipro_sys", + "unipro_phy_sap", + "phy_top_ahb_s_bus", + "ufshci_ufs", + "ufshci_aes", + "ufshci_ufs_ahb", + "ufshci_aes_axi"; + + freq-table-hz = <26000000 208000000>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>, + <0 0>; + + vcc-supply = <&mt6359_vemc_1_ldo_reg>; + vccq-supply = <&mt6359_vio18_ldo_reg>; + vccq2-supply = <&mt6359_vufs_ldo_reg>; + + resets = <&ufscfgpdn_rst 0>, + <&ufscfgpdn_rst 1>, + <&ufscfgpdn_rst 2>; + + reset-names = "unipro_rst", + "crypto_rst", + "hci_rst"; + + mediatek,ufs-disable-mcq; + mediatek,ufs-rtff-mtcmos; + mediatek,ufs-broken-vcc; + + status = "disabled"; + }; + + u3phy3: t-phy@11b00000 { + compatible = "mediatek,mt8189-tphy", + "mediatek,generic-tphy-v2"; + reg = <0 0x11b00000 0 0x700>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + u2port3: usb-phy@11b00000 { + reg = <0 0x11b00000 0 0x700>; + clocks = <&topckgen_clk CLK_TOP_USB2_PHY_RF_P3_EN>; + clock-names = "ref"; + #phy-cells = <1>; + }; + + u3port3: usb-phy@11b00700 { + reg = <0 0x11b00700 0 0x700>; + clocks = <&topckgen_clk CLK_TOP_USB2_PHY_RF_P3_EN>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; + + u2phy4: xs-phy@11b10000 { + compatible = "mediatek,mt8189-xsphy", "mediatek,xsphy"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + u2port4: usb-phy@11b10000 { + reg = <0 0x11b10000 0 0x700>; + clocks = <&topckgen_clk CLK_TOP_USB2_PHY_RF_P4_EN>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; + + u3phy0: xs-phy@11e80000 { + compatible = "mediatek,mt8189-xsphy", "mediatek,xsphy"; + reg = <0 0x11e83000 0 0x200>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + u2port0: usb-phy@11e80000 { + reg = <0 0x11e80000 0 0x700>; + clocks = <&topckgen_clk CLK_TOP_USB2_PHY_RF_P0_EN>; + clock-names = "ref"; + #phy-cells = <1>; + }; + + u3port0: usb-phy@11e83000 { + reg = <0 0x11e83400 0 0x500>; + clocks = <&topckgen_clk CLK_TOP_USB2_PHY_RF_P0_EN>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; + + u2phy1: xs-phy@11e90000 { + compatible = "mediatek,mt8189-xsphy", "mediatek,xsphy"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + u2port1: usb-phy@11e90000 { + reg = <0 0x11e90000 0 0x700>; + clocks = <&topckgen_clk CLK_TOP_USB2_PHY_RF_P1_EN>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; + + u2phy2: xs-phy@11ef0000 { + compatible = "mediatek,mt8189-xsphy", "mediatek,xsphy"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + u2port2: usb-phy@11ef0000 { + reg = <0 0x11ef0000 0 0x700>; + clocks = <&topckgen_clk CLK_TOP_USB2_PHY_RF_P2_EN>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; + + ufscfg_ao_reg_clk: syscon@112b8000 { + compatible = "mediatek,mt8189-ufscfg-ao", "syscon", "simple-mfd"; + reg = <0 0x112b8000 0 0x1000>; + #clock-cells = <1>; + + ufscfgao_rst: reset-controller { + compatible = "ti,syscon-reset"; + #reset-cells = <1>; + + ti,reset-bits = < + /* ufs mphy reset */ + /* 8: mphy */ + 0x48 8 0x4c 8 0 0 + (ASSERT_SET | DEASSERT_SET | STATUS_NONE) + >; + }; + }; + + ufscfg_pdn_reg_clk: syscon@112bb000 { + compatible = "mediatek,mt8189-ufscfg-pdn", "syscon", "simple-mfd"; + reg = <0 0x112bb000 0 0x1000>; + #clock-cells = <1>; + + ufscfgpdn_rst: reset-controller { + compatible = "ti,syscon-reset"; + #reset-cells = <1>; + + ti,reset-bits = < + /* ufs ufschi/crypto/unipro reset */ + /* 0: unipro */ + 0x48 0 0x4c 0 0 0 + (ASSERT_SET | DEASSERT_SET | STATUS_NONE) + /* 1: ufs-crypto */ + 0x48 1 0x4c 1 0 0 + (ASSERT_SET | DEASSERT_SET | STATUS_NONE) + /* 2: ufshci */ + 0x48 2 0x4c 2 0 0 + (ASSERT_SET | DEASSERT_SET | STATUS_NONE) + >; + }; + }; + pwrap: pwrap@1cc04000 { compatible = "mediatek,mt8189-pwrap", "mediatek,mt8195-pwrap", "syscon"; reg = <0 0x1cc04000 0 0x1000>; diff --git a/arch/arm/dts/mt8371-genio-common-ufs.dtso b/arch/arm/dts/mt8371-genio-common-ufs.dtso new file mode 100644 index 00000000000..b75fdafcf9b --- /dev/null +++ b/arch/arm/dts/mt8371-genio-common-ufs.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2026 MediaTek Inc. + * + * Adjusts for when boot DIP switches/jumpers on EVK are set for UFS boot + * instead of eMMC. + */ + +/dts-v1/; +/plugin/; + +&ufshci { + status = "okay"; +}; + +&mmc0 { + status = "disabled"; +}; diff --git a/arch/arm/dts/mt8371-genio-common.dtsi b/arch/arm/dts/mt8371-genio-common.dtsi index 58322193aef..046e9d57752 100644 --- a/arch/arm/dts/mt8371-genio-common.dtsi +++ b/arch/arm/dts/mt8371-genio-common.dtsi @@ -19,6 +19,51 @@ stdout-path = "serial0:921600n8"; }; + usb_p0_vbus: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "p0_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pio 82 0>; + enable-active-high; + }; + + usb_p1_vbus: regulator@1 { + compatible = "regulator-fixed"; + regulator-name = "p1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pio 84 0>; + enable-active-high; + }; + + usb_p2_vbus: regulator@2 { + compatible = "regulator-fixed"; + regulator-name = "p2_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pio 85 0>; + enable-active-high; + }; + + usb_p3_vbus: regulator@3 { + compatible = "regulator-fixed"; + regulator-name = "p3_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pio 86 0>; + enable-active-high; + }; + + usb_p4_vbus: regulator@4 { + compatible = "regulator-fixed"; + regulator-name = "p4_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pio 87 0>; + enable-active-high; + }; + firmware { optee { compatible = "linaro,optee-tz"; @@ -241,3 +286,28 @@ &pmic { interrupts-extended = <&pio 194 IRQ_TYPE_LEVEL_HIGH>; }; + +&xhci0{ + vbus-supply = <&usb_p0_vbus>; + status = "okay"; +}; + +&xhci1{ + vbus-supply = <&usb_p1_vbus>; + status = "okay"; +}; + +&xhci2{ + vbus-supply = <&usb_p2_vbus>; + status = "okay"; +}; + +&xhci3{ + vbus-supply = <&usb_p3_vbus>; + status = "okay"; +}; + +&xhci4{ + vbus-supply = <&usb_p4_vbus>; + status = "okay"; +}; diff --git a/board/mediatek/MAINTAINERS b/board/mediatek/MAINTAINERS index c342ff24330..37ca35b4dd4 100644 --- a/board/mediatek/MAINTAINERS +++ b/board/mediatek/MAINTAINERS @@ -3,10 +3,14 @@ M: Macpaul Lin <[email protected]> S: Maintained F: arch/arm/dts/mt8371-genio-520-evk-u-boot.dtsi F: arch/arm/dts/mt8371-genio-common-u-boot.dtsi +F: arch/arm/dts/mt8371-genio-common-ufs.dtso F: arch/arm/dts/mt8391-genio-720-evk-u-boot.dtsi +F: configs/mt8189-ufs.config F: configs/mt8189.config F: configs/mt8371_genio_520_evk_defconfig +F: configs/mt8371_genio_520_evk_ufs_defconfig F: configs/mt8391_genio_720_evk_defconfig +F: configs/mt8391_genio_720_evk_ufs_defconfig MT8365 EVK M: Julien Masson <[email protected]> @@ -21,8 +25,10 @@ F: configs/mt8188.config F: configs/mt8370_genio_510_evk_defconfig F: configs/mt8390_genio_700_evk_defconfig -MT8395 +MT8195/MT8395 M: Macpaul Lin <[email protected]> M: Julien Stephan <[email protected]> S: Maintained +F: configs/mt8195.config F: configs/mt8395_genio_1200_evk_defconfig +F: configs/mt8395_genio_1200_evk_ufs_defconfig diff --git a/configs/mt8189-ufs.config b/configs/mt8189-ufs.config new file mode 100644 index 00000000000..8a7afb95b1b --- /dev/null +++ b/configs/mt8189-ufs.config @@ -0,0 +1,8 @@ +#include <configs/mt8189.config> + +CONFIG_PHY=y +CONFIG_PHY_MTK_UFS=y +CONFIG_SCSI=y +CONFIG_UFS=y +CONFIG_UFS_MEDIATEK=y +CONFIG_CMD_UFS=y diff --git a/configs/mt8189.config b/configs/mt8189.config index 55c2ccfc01f..ecf8c5f4b4b 100644 --- a/configs/mt8189.config +++ b/configs/mt8189.config @@ -16,21 +16,29 @@ CONFIG_CMD_CLK=y CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CLK=y # CONFIG_MMC_QUIRKS is not set CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_MTK=y +CONFIG_PHY=y +CONFIG_PHY_MTK_TPHY=y +CONFIG_PHY_MTK_XSPHY=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_PINCTRL_MT8189=y CONFIG_DM_PMIC=y CONFIG_DM_PMIC_MTK_PWRAP=y CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_MT6359=y CONFIG_BAUDRATE=921600 CONFIG_DM_SERIAL=y CONFIG_MTK_SERIAL=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MTK=y CONFIG_WDT=y CONFIG_WDT_MTK=y diff --git a/configs/mt8195.config b/configs/mt8195.config new file mode 100644 index 00000000000..ed66ea22956 --- /dev/null +++ b/configs/mt8195.config @@ -0,0 +1,28 @@ +CONFIG_ARM=y +CONFIG_COUNTER_FREQUENCY=13000000 +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_TEXT_BASE=0x4c000000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_TARGET_MT8195=y +CONFIG_SYS_LOAD_ADDR=0x60000000 +# CONFIG_BOARD_INIT is not set +CONFIG_CMD_CLK=y +CONFIG_CMD_GPT=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y +CONFIG_OF_UPSTREAM=y +CONFIG_CLK=y +CONFIG_MMC_MTK=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +CONFIG_PINCTRL_MT8195=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_MTK_PWRAP=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_MT6359=y +CONFIG_BAUDRATE=921600 +CONFIG_DM_SERIAL=y +CONFIG_MTK_SERIAL=y +CONFIG_WDT=y +CONFIG_WDT_MTK=y diff --git a/configs/mt8371_genio_520_evk_ufs_defconfig b/configs/mt8371_genio_520_evk_ufs_defconfig new file mode 100644 index 00000000000..a0b365a86a2 --- /dev/null +++ b/configs/mt8371_genio_520_evk_ufs_defconfig @@ -0,0 +1,4 @@ +#include <configs/mt8189-ufs.config> + +CONFIG_DEFAULT_DEVICE_TREE="mt8371-genio-520-evk-ufs" +CONFIG_DEFAULT_FDT_FILE="mt8371-genio-520-evk-ufs" diff --git a/configs/mt8391_genio_720_evk_ufs_defconfig b/configs/mt8391_genio_720_evk_ufs_defconfig new file mode 100644 index 00000000000..f1de9d5fa1e --- /dev/null +++ b/configs/mt8391_genio_720_evk_ufs_defconfig @@ -0,0 +1,4 @@ +#include <configs/mt8189-ufs.config> + +CONFIG_DEFAULT_DEVICE_TREE="mt8391-genio-720-evk-ufs" +CONFIG_DEFAULT_FDT_FILE="mt8391-genio-720-evk-ufs" diff --git a/configs/mt8395_genio_1200_evk_defconfig b/configs/mt8395_genio_1200_evk_defconfig index 2d73af353f7..47c10757c52 100644 --- a/configs/mt8395_genio_1200_evk_defconfig +++ b/configs/mt8395_genio_1200_evk_defconfig @@ -1,26 +1,4 @@ -CONFIG_ARM=y -CONFIG_COUNTER_FREQUENCY=13000000 -CONFIG_POSITION_INDEPENDENT=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_TEXT_BASE=0x4c000000 -CONFIG_NR_DRAM_BANKS=1 +#include <configs/mt8195.config> + CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8395-genio-1200-evk" -CONFIG_TARGET_MT8195=y -CONFIG_SYS_LOAD_ADDR=0x60000000 CONFIG_IDENT_STRING="mt8395-genio-1200-evk" -# CONFIG_BOARD_INIT is not set -CONFIG_CMD_CLK=y -CONFIG_CMD_GPT=y -CONFIG_CMD_MMC=y -CONFIG_CMD_PART=y -CONFIG_OF_UPSTREAM=y -CONFIG_CLK=y -CONFIG_MMC_MTK=y -CONFIG_PINCTRL=y -CONFIG_PINCONF=y -CONFIG_PINCTRL_MT8195=y -CONFIG_BAUDRATE=921600 -CONFIG_DM_SERIAL=y -CONFIG_MTK_SERIAL=y -CONFIG_WDT=y -CONFIG_WDT_MTK=y diff --git a/configs/mt8395_genio_1200_evk_ufs_defconfig b/configs/mt8395_genio_1200_evk_ufs_defconfig new file mode 100644 index 00000000000..e927365a03a --- /dev/null +++ b/configs/mt8395_genio_1200_evk_ufs_defconfig @@ -0,0 +1,9 @@ +#include <configs/mt8195.config> + +CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8395-genio-1200-evk-ufs" +CONFIG_IDENT_STRING=" mt8395-genio-1200-evk-ufs" +CONFIG_CMD_UFS=y +CONFIG_PHY=y +CONFIG_SCSI=y +CONFIG_UFS=y +CONFIG_UFS_MEDIATEK=y diff --git a/drivers/clk/mediatek/clk-mt8189.c b/drivers/clk/mediatek/clk-mt8189.c index 9e640059f11..d11947ee461 100644 --- a/drivers/clk/mediatek/clk-mt8189.c +++ b/drivers/clk/mediatek/clk-mt8189.c @@ -1641,6 +1641,46 @@ static const struct mtk_gate mminfra_config_clks[] = { GATE_MMINFRA_CONFIG1(CLK_MMINFRA_GCE_26M, CLK_TOP_MMINFRA_SEL, 17), }; +static const struct mtk_gate_regs ufscfg_ao_reg_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x4, +}; + +#define GATE_UFSCFG_AO_REG_EXT(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &ufscfg_ao_reg_cg_regs, _shift, \ + CLK_GATE_SETCLR | CLK_PARENT_EXT) + +#define GATE_UFSCFG_AO_REG_TOP(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &ufscfg_ao_reg_cg_regs, _shift, \ + CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN) + +static const struct mtk_gate ufs_config_ao_clks[] = { + GATE_UFSCFG_AO_REG_EXT(CLK_UFSCFG_AO_REG_UNIPRO_TX_SYM, CLK_PAD_CLK26M, 1), + GATE_UFSCFG_AO_REG_EXT(CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM0, CLK_PAD_CLK26M, 2), + GATE_UFSCFG_AO_REG_EXT(CLK_UFSCFG_AO_REG_UNIPRO_RX_SYM1, CLK_PAD_CLK26M, 3), + GATE_UFSCFG_AO_REG_TOP(CLK_UFSCFG_AO_REG_UNIPRO_SYS, CLK_TOP_U_SEL, 4), + GATE_UFSCFG_AO_REG_EXT(CLK_UFSCFG_AO_REG_U_SAP_CFG, CLK_PAD_CLK26M, 5), + GATE_UFSCFG_AO_REG_TOP(CLK_UFSCFG_AO_REG_U_PHY_TOP_AHB_S_BUS, CLK_TOP_AXI_U_SEL, 6), +}; + +static const struct mtk_gate_regs ufscfg_pdn_reg_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x4, +}; + +#define GATE_UFSCFG_PDN_REG(_id, _parent, _shift) \ + GATE_FLAGS(_id, _parent, &ufscfg_pdn_reg_cg_regs, _shift, \ + CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN) + +static const struct mtk_gate ufs_config_pdn_clks[] = { + GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_UFS, CLK_TOP_U_SEL, 0), + GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_AES, CLK_TOP_AES_UFSFDE_SEL, 1), + GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_U_AHB, CLK_TOP_AXI_U_SEL, 3), + GATE_UFSCFG_PDN_REG(CLK_UFSCFG_REG_UFSHCI_U_AXI, CLK_TOP_MEM_SUB_U_SEL, 5), +}; + static const struct mtk_parent vlp_26m_oscd10_parents[] = { EXT_PARENT(CLK_PAD_CLK26M), TOP_PARENT(CLK_TOP_OSC_D10), @@ -1955,6 +1995,8 @@ GATE_CLK_DATA(perao_clks); GATE_CLK_DATA(imp_clks); GATE_CLK_DATA(mm_clks); GATE_CLK_DATA(mminfra_config_clks); +GATE_CLK_DATA(ufs_config_ao_clks); +GATE_CLK_DATA(ufs_config_pdn_clks); GATE_CLK_DATA(vlpcfg_ao_clks); static const struct udevice_id of_match_mt8189_clk_gate[] = { @@ -1962,6 +2004,8 @@ static const struct udevice_id of_match_mt8189_clk_gate[] = { { .compatible = "mediatek,mt8189-iic-wrap", .data = (ulong)&imp_clks_data }, { .compatible = "mediatek,mt8189-dispsys", .data = (ulong)&mm_clks_data }, { .compatible = "mediatek,mt8189-mm-infra", .data = (ulong)&mminfra_config_clks_data }, + { .compatible = "mediatek,mt8189-ufscfg-ao", .data = (ulong)&ufs_config_ao_clks_data }, + { .compatible = "mediatek,mt8189-ufscfg-pdn", .data = (ulong)&ufs_config_pdn_clks_data }, { .compatible = "mediatek,mt8189-vlpcfg-ao", .data = (ulong)&vlpcfg_ao_clks_data }, { } }; diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 3557aeac3d5..9d0a6cd79cf 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -204,10 +204,6 @@ static ulong mtk_clk_find_parent_rate(struct clk *clk, int id, return clk_get_rate(&parent); } -const struct clk_ops mtk_clk_apmixedsys_ops; -const struct clk_ops mtk_clk_topckgen_ops; -const struct clk_ops mtk_clk_infrasys_ops; - static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk, const int parent, u16 flags) { @@ -216,15 +212,21 @@ static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk, switch (flags & CLK_PARENT_MASK) { case CLK_PARENT_APMIXED: /* APMIXEDSYS can be parent or grandparent. */ - if (dev_get_driver_ops(clk->dev) == &mtk_clk_apmixedsys_ops) + if (dev_get_driver_ops(clk->dev) == &mtk_clk_apmixedsys_ops || + dev_get_driver_ops(clk->dev) == &mtk_clk_fixed_pll_ops) { parent_dev = clk->dev; - else if (dev_get_driver_ops(priv->parent) == &mtk_clk_apmixedsys_ops) + } else if (dev_get_driver_ops(priv->parent) == &mtk_clk_apmixedsys_ops || + dev_get_driver_ops(priv->parent) == &mtk_clk_fixed_pll_ops) { parent_dev = priv->parent; - else if (dev_get_driver_ops(dev_get_parent(priv->parent)) == &mtk_clk_apmixedsys_ops) - parent_dev = dev_get_parent(priv->parent); - else - return -EINVAL; - + } else { + struct udevice *grandparent_dev = dev_get_parent(priv->parent); + + if (dev_get_driver_ops(grandparent_dev) == &mtk_clk_apmixedsys_ops || + dev_get_driver_ops(grandparent_dev) == &mtk_clk_fixed_pll_ops) + parent_dev = grandparent_dev; + else + return -EINVAL; + } break; case CLK_PARENT_TOPCKGEN: if (dev_get_driver_ops(clk->dev) == &mtk_clk_topckgen_ops) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 09810b62b51..fc4daa00661 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -292,6 +292,17 @@ config PHY_MTK_UFS initialization, power on and power off flow of specified M-PHYs. +config PHY_MTK_XSPHY + bool "MediaTek XS-PHY Driver" + depends on PHY + depends on ARCH_MEDIATEK + select REGMAP + select SYSCON + help + Enable this to support the SuperSpeedPlus XS-PHY transceiver for + USB3.1 GEN2 controllers on MediaTek chips. The driver supports + multiple USB2.0, USB3.1 GEN2 ports. + config PHY_NPCM_USB bool "Nuvoton NPCM USB PHY support" depends on PHY diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 83102349669..684e9a99af8 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o obj-$(CONFIG_PHY_EXYNOS_USBDRD) += phy-exynos-usbdrd.o obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o +obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o obj-$(CONFIG_PHY_NPCM_USB) += phy-npcm-usb.o obj-$(CONFIG_$(PHASE_)PHY_IMX8MQ_USB) += phy-imx8mq-usb.o obj-$(CONFIG_PHY_IMX8M_PCIE) += phy-imx8m-pcie.o diff --git a/drivers/phy/phy-mtk-ufs.c b/drivers/phy/phy-mtk-ufs.c index 1eda3df858d..c4c214dcde0 100644 --- a/drivers/phy/phy-mtk-ufs.c +++ b/drivers/phy/phy-mtk-ufs.c @@ -6,52 +6,41 @@ * Copyright (c) 2025, Igor Belwon <[email protected]> */ -#include "dm/ofnode.h" -#include "dm/read.h" -#include <clk.h> -#include <dm.h> -#include <generic-phy.h> -#include <malloc.h> -#include <mapmem.h> -#include <regmap.h> -#include <syscon.h> #include <asm/io.h> +#include <clk.h> +#include <dm/device.h> #include <dm/device_compat.h> -#include <dm/devres.h> -#include <linux/bitfield.h> +#include <dm/read.h> +#include <generic-phy.h> #include <linux/bitops.h> #include <linux/delay.h> - -#include <dt-bindings/phy/phy.h> +#include <mapmem.h> /* mphy register and offsets */ -#define MP_GLB_DIG_8C 0x008C -#define FRC_PLL_ISO_EN BIT(8) -#define PLL_ISO_EN BIT(9) -#define FRC_FRC_PWR_ON BIT(10) -#define PLL_PWR_ON BIT(11) - -#define MP_LN_DIG_RX_9C 0xA09C -#define FSM_DIFZ_FRC BIT(18) +#define MP_GLB_DIG_8C 0x008C +#define FRC_PLL_ISO_EN BIT(8) +#define PLL_ISO_EN BIT(9) +#define FRC_FRC_PWR_ON BIT(10) +#define PLL_PWR_ON BIT(11) -#define MP_LN_DIG_RX_AC 0xA0AC -#define FRC_RX_SQ_EN BIT(0) -#define RX_SQ_EN BIT(1) +#define MP_LN_DIG_RX_9C 0xA09C +#define FSM_DIFZ_FRC BIT(18) -#define MP_LN_RX_44 0xB044 -#define FRC_CDR_PWR_ON BIT(17) -#define CDR_PWR_ON BIT(18) -#define FRC_CDR_ISO_EN BIT(19) -#define CDR_ISO_EN BIT(20) +#define MP_LN_DIG_RX_AC 0xA0AC +#define FRC_RX_SQ_EN BIT(0) +#define RX_SQ_EN BIT(1) -#define UFSPHY_CLKS_CNT 2 +#define MP_LN_RX_44 0xB044 +#define FRC_CDR_PWR_ON BIT(17) +#define CDR_PWR_ON BIT(18) +#define FRC_CDR_ISO_EN BIT(19) +#define CDR_ISO_EN BIT(20) struct mtk_ufs_phy { struct udevice *dev; void __iomem *mmio; - struct clk *unipro_clk; - struct clk *mp_clk; + struct clk_bulk clk_bulk; }; static void ufs_mtk_phy_set_active(struct mtk_ufs_phy *phy) @@ -88,16 +77,9 @@ static int mtk_phy_power_on(struct phy *phy) struct mtk_ufs_phy *ufs_phy = dev_get_priv(phy->dev); int ret; - ret = clk_enable(ufs_phy->mp_clk); - if (ret < 0) { - dev_err(phy->dev, "failed to enable mp_clk\n"); - return ret; - } - - ret = clk_enable(ufs_phy->unipro_clk); - if (ret < 0) { - dev_err(phy->dev, "failed to enable unipro_clk %d\n", ret); - clk_disable(ufs_phy->unipro_clk); + ret = clk_enable_bulk(&ufs_phy->clk_bulk); + if (ret) { + dev_err(phy->dev, "failed to enable clocks (ret=%d)\n", ret); return ret; } @@ -106,34 +88,44 @@ static int mtk_phy_power_on(struct phy *phy) return 0; } -static int mtk_phy_power_off(struct phy *phy) +static void ufs_mtk_phy_set_inactive(struct mtk_ufs_phy *phy) { - struct mtk_ufs_phy *ufs_phy = dev_get_priv(phy->dev); - /* Set PHY to Deep Hibernate mode */ - setbits_le32(ufs_phy->mmio + MP_LN_DIG_RX_9C, FSM_DIFZ_FRC); + setbits_le32(phy->mmio + MP_LN_DIG_RX_9C, FSM_DIFZ_FRC); /* force DA_MP_RX0_SQ_EN */ - setbits_le32(ufs_phy->mmio + MP_LN_DIG_RX_AC, FRC_RX_SQ_EN); - clrbits_le32(ufs_phy->mmio + MP_LN_DIG_RX_AC, RX_SQ_EN); + setbits_le32(phy->mmio + MP_LN_DIG_RX_AC, FRC_RX_SQ_EN); + clrbits_le32(phy->mmio + MP_LN_DIG_RX_AC, RX_SQ_EN); /* force DA_MP_CDR_ISO_EN */ - setbits_le32(ufs_phy->mmio + MP_LN_RX_44, FRC_CDR_ISO_EN); - setbits_le32(ufs_phy->mmio + MP_LN_RX_44, CDR_ISO_EN); + setbits_le32(phy->mmio + MP_LN_RX_44, FRC_CDR_ISO_EN); + setbits_le32(phy->mmio + MP_LN_RX_44, CDR_ISO_EN); /* force DA_MP_CDR_PWR_ON */ - setbits_le32(ufs_phy->mmio + MP_LN_RX_44, FRC_CDR_PWR_ON); - clrbits_le32(ufs_phy->mmio + MP_LN_RX_44, CDR_PWR_ON); + setbits_le32(phy->mmio + MP_LN_RX_44, FRC_CDR_PWR_ON); + clrbits_le32(phy->mmio + MP_LN_RX_44, CDR_PWR_ON); /* force DA_MP_PLL_ISO_EN */ - setbits_le32(ufs_phy->mmio + MP_GLB_DIG_8C, FRC_PLL_ISO_EN); - setbits_le32(ufs_phy->mmio + MP_GLB_DIG_8C, PLL_ISO_EN); + setbits_le32(phy->mmio + MP_GLB_DIG_8C, FRC_PLL_ISO_EN); + setbits_le32(phy->mmio + MP_GLB_DIG_8C, PLL_ISO_EN); /* force DA_MP_PLL_PWR_ON */ - setbits_le32(ufs_phy->mmio + MP_GLB_DIG_8C, FRC_FRC_PWR_ON); - clrbits_le32(ufs_phy->mmio + MP_GLB_DIG_8C, PLL_PWR_ON); + setbits_le32(phy->mmio + MP_GLB_DIG_8C, FRC_FRC_PWR_ON); + clrbits_le32(phy->mmio + MP_GLB_DIG_8C, PLL_PWR_ON); +} - return 0; +static int mtk_phy_power_off(struct phy *phy) +{ + struct mtk_ufs_phy *ufs_phy = dev_get_priv(phy->dev); + int ret; + + ufs_mtk_phy_set_inactive(ufs_phy); + + ret = clk_disable_bulk(&ufs_phy->clk_bulk); + if (ret) + dev_err(phy->dev, "failed to disable clocks (ret=%d)\n", ret); + + return ret; } static const struct phy_ops mtk_ufs_phy_ops = { @@ -147,10 +139,6 @@ static int mtk_ufs_phy_probe(struct udevice *dev) fdt_addr_t addr; int ret; - phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) - return -ENOMEM; - addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -ENOMEM; @@ -158,21 +146,11 @@ static int mtk_ufs_phy_probe(struct udevice *dev) phy->dev = dev; phy->mmio = map_sysmem(addr, 0); - phy->mp_clk = devm_clk_get(dev, "mp"); - if (IS_ERR(phy->mp_clk)) { - ret = PTR_ERR(phy->mp_clk); - dev_err(dev, "Failed to get mp clock (ret=%d)\n", ret); - return ret; - } + ret = clk_get_bulk(dev, &phy->clk_bulk); + if (ret) + dev_err(dev, "Failed to get clocks (ret=%d)\n", ret); - phy->unipro_clk = devm_clk_get(dev, "unipro"); - if (IS_ERR(phy->unipro_clk)) { - ret = PTR_ERR(phy->unipro_clk); - dev_err(dev, "Failed to get unipro clock (ret=%d)\n", ret); - return ret; - } - - return 0; + return ret; } static const struct udevice_id mtk_ufs_phy_id_table[] = { diff --git a/drivers/phy/phy-mtk-xsphy.c b/drivers/phy/phy-mtk-xsphy.c new file mode 100644 index 00000000000..d3418ffb101 --- /dev/null +++ b/drivers/phy/phy-mtk-xsphy.c @@ -0,0 +1,600 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MediaTek USB3.1 gen2 xsphy Driver + * + * Copyright (c) 2026 MediaTek Inc. + * Copyright (c) 2026 BayLibre, SAS + * + * Based on Linux mtk-xsphy driver: + * Copyright (c) 2018 MediaTek Inc. + * Author: Chunfeng Yun <[email protected]> + * + * And U-Boot mtk-tphy driver: + * Copyright (c) 2015 - 2019 MediaTek Inc. + * Author: Chunfeng Yun <[email protected]> + * Ryder Lee <[email protected]> + */ + +#include <clk.h> +#include <dm.h> +#include <generic-phy.h> +#include <malloc.h> +#include <mapmem.h> +#include <regmap.h> +#include <syscon.h> + +#include <asm/io.h> +#include <dm/device_compat.h> +#include <dm/devres.h> +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/iopoll.h> + +#include <dt-bindings/phy/phy.h> + +/* u2 phy banks */ +#define SSUSB_SIFSLV_MISC 0x000 +#define SSUSB_SIFSLV_U2FREQ 0x100 +#define SSUSB_SIFSLV_U2PHY_COM 0x300 + +/* u3 phy shared banks */ +#define SSPXTP_SIFSLV_DIG_GLB 0x000 +#define SSPXTP_SIFSLV_PHYA_GLB 0x100 + +/* u3 phy banks */ +#define SSPXTP_SIFSLV_DIG_LN_TOP 0x000 +#define SSPXTP_SIFSLV_DIG_LN_TX0 0x100 +#define SSPXTP_SIFSLV_DIG_LN_RX0 0x200 +#define SSPXTP_SIFSLV_DIG_LN_DAIF 0x300 +#define SSPXTP_SIFSLV_PHYA_LN 0x400 + +#define XSP_U2FREQ_FMCR0 ((SSUSB_SIFSLV_U2FREQ) + 0x00) +#define P2F_RG_FREQDET_EN BIT(24) +#define P2F_RG_CYCLECNT GENMASK(23, 0) + +#define XSP_U2FREQ_MMONR0 ((SSUSB_SIFSLV_U2FREQ) + 0x0c) + +#define XSP_U2FREQ_FMMONR1 ((SSUSB_SIFSLV_U2FREQ) + 0x10) +#define P2F_RG_FRCK_EN BIT(8) +#define P2F_USB_FM_VALID BIT(0) + +#define XSP_USBPHYACR0 ((SSUSB_SIFSLV_U2PHY_COM) + 0x00) +#define P2A0_RG_INTR_EN BIT(5) + +#define XSP_USBPHYACR1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x04) +#define P2A1_RG_INTR_CAL GENMASK(23, 19) +#define P2A1_RG_VRT_SEL GENMASK(14, 12) +#define P2A1_RG_TERM_SEL GENMASK(10, 8) + +#define XSP_USBPHYACR5 ((SSUSB_SIFSLV_U2PHY_COM) + 0x014) +#define P2A5_RG_HSTX_SRCAL_EN BIT(15) +#define P2A5_RG_HSTX_SRCTRL GENMASK(14, 12) + +#define XSP_USBPHYACR6 ((SSUSB_SIFSLV_U2PHY_COM) + 0x018) +#define P2A6_RG_BC11_SW_EN BIT(23) +#define P2A6_RG_OTG_VBUSCMP_EN BIT(20) + +#define XSP_U2PHYDTM1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x06C) +#define P2D_FORCE_IDDIG BIT(9) +#define P2D_RG_VBUSVALID BIT(5) +#define P2D_RG_SESSEND BIT(4) +#define P2D_RG_AVALID BIT(2) +#define P2D_RG_IDDIG BIT(1) + +#define SSPXTP_PHYA_GLB_00 ((SSPXTP_SIFSLV_PHYA_GLB) + 0x00) +#define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(21, 16) + +#define SSPXTP_PHYA_LN_04 ((SSPXTP_SIFSLV_PHYA_LN) + 0x04) +#define RG_XTP_LN0_TX_IMPSEL GENMASK(4, 0) + +#define SSPXTP_PHYA_LN_14 ((SSPXTP_SIFSLV_PHYA_LN) + 0x014) +#define RG_XTP_LN0_RX_IMPSEL GENMASK(4, 0) + +#define XSP_REF_CLK_MHZ 26 +#define XSP_SLEW_RATE_COEF 17 +#define XSP_SR_COEF_DIVISOR 1000 +#define XSP_FM_DET_CYCLE_CNT 1024 + +/* PHY switch between pcie/usb3/sgmii */ +#define USB_PHY_SWITCH_CTRL 0x0 +#define RG_PHY_SW_TYPE GENMASK(3, 0) +#define RG_PHY_SW_PCIE 0x0 +#define RG_PHY_SW_USB3 0x1 +#define RG_PHY_SW_SGMII 0x2 + +struct mtk_xsphy_instance { + void __iomem *port_base; + struct device_node *np; + struct clk ref_clk; /* reference clock of analog phy */ + u32 index; + u32 type; + struct regmap *type_sw; + u32 type_sw_reg; + u32 type_sw_index; + /* only for HQA test */ + u32 efuse_intr; + u32 efuse_tx_imp; + u32 efuse_rx_imp; + /* u2 eye diagram */ + u32 eye_src; + u32 eye_vrt; + u32 eye_term; +}; + +struct mtk_xsphy { + struct udevice *dev; + void __iomem *sif_base; + struct mtk_xsphy_instance **phys; + u32 nphys; + u32 src_ref_clk_mhz; /* reference clock for slew rate calibrate */ + u32 src_coef; /* coefficient for slew rate calibrate */ +}; + +static void mtk_xsphy_u2_slew_rate_calibrate(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance) +{ + void __iomem *pbase = instance->port_base; + u32 calib_val; + u32 fm_out; + u32 tmp; + + /* use force value */ + if (instance->eye_src) + return; + + /* enable USB ring oscillator */ + setbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCAL_EN); + /* wait for clock to become stable */ + udelay(1); + + /* enable free run clock */ + setbits_le32(pbase + XSP_U2FREQ_FMMONR1, P2F_RG_FRCK_EN); + + /* set cycle count as 1024 */ + clrsetbits_le32(pbase + XSP_U2FREQ_FMCR0, P2F_RG_CYCLECNT, + FIELD_PREP(P2F_RG_CYCLECNT, XSP_FM_DET_CYCLE_CNT)); + + /* enable frequency meter */ + setbits_le32(pbase + XSP_U2FREQ_FMCR0, P2F_RG_FREQDET_EN); + + /* ignore return value */ + readl_poll_sleep_timeout(pbase + XSP_U2FREQ_FMMONR1, tmp, + (tmp & P2F_USB_FM_VALID), 10, 200); + + fm_out = readl(pbase + XSP_U2FREQ_MMONR0); + + /* disable frequency meter */ + clrbits_le32(pbase + XSP_U2FREQ_FMCR0, P2F_RG_FREQDET_EN); + + /* disable free run clock */ + clrbits_le32(pbase + XSP_U2FREQ_FMMONR1, P2F_RG_FRCK_EN); + + if (fm_out) { + /* (1024 / FM_OUT) x reference clock frequency x coefficient */ + tmp = xsphy->src_ref_clk_mhz * xsphy->src_coef; + tmp = (tmp * XSP_FM_DET_CYCLE_CNT) / fm_out; + calib_val = DIV_ROUND_CLOSEST(tmp, XSP_SR_COEF_DIVISOR); + } else { + /* if FM detection fail, set default value */ + calib_val = 3; + } + dev_dbg(xsphy->dev, "phy.%u, fm_out:%u, calib:%u (clk:%u, coef:%u)\n", + instance->index, fm_out, calib_val, xsphy->src_ref_clk_mhz, + xsphy->src_coef); + + /* set HS slew rate */ + clrsetbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL, + FIELD_PREP(P2A5_RG_HSTX_SRCTRL, calib_val)); + + /* disable USB ring oscillator */ + clrbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCAL_EN); +} + +static void mtk_xsphy_u2_instance_init(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance) +{ + void __iomem *pbase = instance->port_base; + + /* DP/DM BC1.1 path Disable */ + clrbits_le32(pbase + XSP_USBPHYACR6, P2A6_RG_BC11_SW_EN); + + setbits_le32(pbase + XSP_USBPHYACR0, P2A0_RG_INTR_EN); +} + +static void mtk_xsphy_u2_instance_power_on(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance) +{ + void __iomem *pbase = instance->port_base; + + setbits_le32(pbase + XSP_USBPHYACR6, P2A6_RG_OTG_VBUSCMP_EN); + + clrsetbits_le32(pbase + XSP_U2PHYDTM1, + P2D_RG_VBUSVALID | P2D_RG_AVALID | P2D_RG_SESSEND, + P2D_RG_VBUSVALID | P2D_RG_AVALID); + + dev_dbg(xsphy->dev, "%s(%u)\n", __func__, instance->index); +} + +static void mtk_xsphy_u2_instance_power_off(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance) +{ + void __iomem *pbase = instance->port_base; + + clrbits_le32(pbase + XSP_USBPHYACR6, P2A6_RG_OTG_VBUSCMP_EN); + + clrsetbits_le32(pbase + XSP_U2PHYDTM1, + P2D_RG_VBUSVALID | P2D_RG_AVALID | P2D_RG_SESSEND, + P2D_RG_SESSEND); + + dev_dbg(xsphy->dev, "%s(%u)\n", __func__, instance->index); +} + +static void mtk_xsphy_u2_instance_set_mode(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance, + enum phy_mode mode) +{ + u32 tmp; + + tmp = readl(instance->port_base + XSP_U2PHYDTM1); + + switch (mode) { + case PHY_MODE_USB_DEVICE: + tmp |= P2D_FORCE_IDDIG | P2D_RG_IDDIG; + break; + case PHY_MODE_USB_HOST: + tmp |= P2D_FORCE_IDDIG; + tmp &= ~P2D_RG_IDDIG; + break; + case PHY_MODE_USB_OTG: + tmp &= ~(P2D_FORCE_IDDIG | P2D_RG_IDDIG); + break; + default: + return; + } + + writel(tmp, instance->port_base + XSP_U2PHYDTM1); +} + +static void mtk_xsphy_parse_property(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance) +{ + ofnode node = np_to_ofnode(instance->np); + + switch (instance->type) { + case PHY_TYPE_USB2: + ofnode_read_u32(node, "mediatek,efuse-intr", &instance->efuse_intr); + ofnode_read_u32(node, "mediatek,eye-src", &instance->eye_src); + ofnode_read_u32(node, "mediatek,eye-vrt", &instance->eye_vrt); + ofnode_read_u32(node, "mediatek,eye-term", &instance->eye_term); + + dev_dbg(xsphy->dev, "intr:%u, src:%u, vrt:%u, term:%u\n", + instance->efuse_intr, instance->eye_src, + instance->eye_vrt, instance->eye_term); + return; + case PHY_TYPE_USB3: + ofnode_read_u32(node, "mediatek,efuse-intr", &instance->efuse_intr); + ofnode_read_u32(node, "mediatek,efuse-tx-imp", &instance->efuse_tx_imp); + ofnode_read_u32(node, "mediatek,efuse-rx-imp", &instance->efuse_rx_imp); + + dev_dbg(xsphy->dev, "intr:%u, tx-imp:%u, rx-imp:%u\n", + instance->efuse_intr, instance->efuse_tx_imp, + instance->efuse_rx_imp); + return; + case PHY_TYPE_PCIE: + case PHY_TYPE_SGMII: + /* nothing to do */ + return; + default: + dev_err(xsphy->dev, "incompatible PHY type\n"); + return; + } +} + +static void mtk_xsphy_u2_props_set(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance) +{ + void __iomem *pbase = instance->port_base; + + if (instance->efuse_intr) + clrsetbits_le32(pbase + XSP_USBPHYACR1, P2A1_RG_INTR_CAL, + FIELD_PREP(P2A1_RG_INTR_CAL, instance->efuse_intr)); + + if (instance->eye_src) + clrsetbits_le32(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL, + FIELD_PREP(P2A5_RG_HSTX_SRCTRL, instance->eye_src)); + + if (instance->eye_vrt) + clrsetbits_le32(pbase + XSP_USBPHYACR1, P2A1_RG_VRT_SEL, + FIELD_PREP(P2A1_RG_VRT_SEL, instance->eye_vrt)); + + if (instance->eye_term) + clrsetbits_le32(pbase + XSP_USBPHYACR1, P2A1_RG_TERM_SEL, + FIELD_PREP(P2A1_RG_TERM_SEL, instance->eye_term)); +} + +static void mtk_xsphy_u3_props_set(struct mtk_xsphy *xsphy, + struct mtk_xsphy_instance *instance) +{ + void __iomem *pbase = instance->port_base; + + if (instance->efuse_intr) + clrsetbits_le32(xsphy->sif_base + SSPXTP_PHYA_GLB_00, + RG_XTP_GLB_BIAS_INTR_CTRL, + FIELD_PREP(RG_XTP_GLB_BIAS_INTR_CTRL, instance->efuse_intr)); + + if (instance->efuse_tx_imp) + clrsetbits_le32(pbase + SSPXTP_PHYA_LN_04, RG_XTP_LN0_TX_IMPSEL, + FIELD_PREP(RG_XTP_LN0_TX_IMPSEL, instance->efuse_tx_imp)); + + if (instance->efuse_rx_imp) + clrsetbits_le32(pbase + SSPXTP_PHYA_LN_14, RG_XTP_LN0_RX_IMPSEL, + FIELD_PREP(RG_XTP_LN0_RX_IMPSEL, instance->efuse_rx_imp)); +} + +/* type switch for usb3/pcie/sgmii */ +static int mtk_xsphy_type_syscon_get(struct udevice *dev, + struct mtk_xsphy_instance *instance, + ofnode dn) +{ + struct ofnode_phandle_args args; + int ret; + + if (!ofnode_read_bool(dn, "mediatek,syscon-type")) + return 0; + + ret = ofnode_parse_phandle_with_args(dn, "mediatek,syscon-type", + NULL, 2, 0, &args); + if (ret) + return ret; + + instance->type_sw_reg = args.args[0]; + instance->type_sw_index = args.args[1] & 0x3; /* <=3 */ + instance->type_sw = syscon_node_to_regmap(args.node); + if (IS_ERR(instance->type_sw)) + return PTR_ERR(instance->type_sw); + + dev_dbg(dev, "phy-%s.%d: type_sw - reg %#x, index %d\n", + dev->name, instance->index, instance->type_sw_reg, + instance->type_sw_index); + + return 0; +} + +static int mtk_xsphy_type_set(struct mtk_xsphy_instance *instance) +{ + int type; + u32 offset; + + if (!instance->type_sw) + return 0; + + switch (instance->type) { + case PHY_TYPE_USB3: + type = RG_PHY_SW_USB3; + break; + case PHY_TYPE_PCIE: + type = RG_PHY_SW_PCIE; + break; + case PHY_TYPE_SGMII: + type = RG_PHY_SW_SGMII; + break; + case PHY_TYPE_USB2: + default: + return 0; + } + + offset = instance->type_sw_index * BITS_PER_BYTE; + regmap_update_bits(instance->type_sw, instance->type_sw_reg, + RG_PHY_SW_TYPE << offset, type << offset); + + return 0; +} + +static int mtk_xsphy_init(struct phy *phy) +{ + struct mtk_xsphy *xsphy = dev_get_priv(phy->dev); + struct mtk_xsphy_instance *instance = xsphy->phys[phy->id]; + int ret; + + ret = clk_enable(&instance->ref_clk); + if (ret) { + dev_err(xsphy->dev, "failed to enable ref_clk\n"); + return ret; + } + + switch (instance->type) { + case PHY_TYPE_USB2: + mtk_xsphy_u2_instance_init(xsphy, instance); + mtk_xsphy_u2_props_set(xsphy, instance); + break; + case PHY_TYPE_USB3: + mtk_xsphy_u3_props_set(xsphy, instance); + break; + case PHY_TYPE_PCIE: + case PHY_TYPE_SGMII: + /* nothing to do, only used to set type */ + break; + default: + dev_err(xsphy->dev, "incompatible PHY type\n"); + clk_disable(&instance->ref_clk); + return -EINVAL; + } + + return 0; +} + +static int mtk_xsphy_power_on(struct phy *phy) +{ + struct mtk_xsphy *xsphy = dev_get_priv(phy->dev); + struct mtk_xsphy_instance *instance = xsphy->phys[phy->id]; + + if (instance->type == PHY_TYPE_USB2) { + mtk_xsphy_u2_instance_power_on(xsphy, instance); + mtk_xsphy_u2_slew_rate_calibrate(xsphy, instance); + } + + return 0; +} + +static int mtk_xsphy_power_off(struct phy *phy) +{ + struct mtk_xsphy *xsphy = dev_get_priv(phy->dev); + struct mtk_xsphy_instance *instance = xsphy->phys[phy->id]; + + if (instance->type == PHY_TYPE_USB2) + mtk_xsphy_u2_instance_power_off(xsphy, instance); + + return 0; +} + +static int mtk_xsphy_exit(struct phy *phy) +{ + struct mtk_xsphy *xsphy = dev_get_priv(phy->dev); + struct mtk_xsphy_instance *instance = xsphy->phys[phy->id]; + + clk_disable(&instance->ref_clk); + + return 0; +} + +static int mtk_xsphy_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct mtk_xsphy *xsphy = dev_get_priv(phy->dev); + struct mtk_xsphy_instance *instance = xsphy->phys[phy->id]; + + if (instance->type == PHY_TYPE_USB2) + mtk_xsphy_u2_instance_set_mode(xsphy, instance, mode); + + return 0; +} + +static int mtk_xsphy_xlate(struct phy *phy, struct ofnode_phandle_args *args) +{ + struct mtk_xsphy *xsphy = dev_get_priv(phy->dev); + struct mtk_xsphy_instance *instance = NULL; + const struct device_node *phy_np = ofnode_to_np(args->node); + u32 index; + + if (!phy_np) { + dev_err(phy->dev, "null pointer phy node\n"); + return -EINVAL; + } + + if (args->args_count != 2) { + dev_err(phy->dev, "invalid number of cells in 'phy' property\n"); + return -EINVAL; + } + + for (index = 0; index < xsphy->nphys; index++) + if (phy_np == xsphy->phys[index]->np) { + instance = xsphy->phys[index]; + break; + } + + if (!instance) { + dev_err(phy->dev, "failed to find appropriate phy\n"); + return -EINVAL; + } + + phy->id = index; + instance->type = args->args[1]; + if (!(instance->type == PHY_TYPE_USB2 || + instance->type == PHY_TYPE_USB3 || + instance->type == PHY_TYPE_PCIE || + instance->type == PHY_TYPE_SGMII)) { + dev_err(phy->dev, "unsupported PHY type\n"); + return -EINVAL; + } + + mtk_xsphy_parse_property(xsphy, instance); + mtk_xsphy_type_set(instance); + + return 0; +} + +static const struct phy_ops mtk_xsphy_ops = { + .init = mtk_xsphy_init, + .exit = mtk_xsphy_exit, + .power_on = mtk_xsphy_power_on, + .power_off = mtk_xsphy_power_off, + .set_mode = mtk_xsphy_set_mode, + .of_xlate = mtk_xsphy_xlate, +}; + +static int mtk_xsphy_probe(struct udevice *dev) +{ + struct mtk_xsphy *xsphy = dev_get_priv(dev); + fdt_addr_t sif_addr; + ofnode subnode; + int index = 0; + + xsphy->nphys = dev_get_child_count(dev); + + xsphy->phys = devm_kcalloc(dev, xsphy->nphys, sizeof(*xsphy->phys), + GFP_KERNEL); + if (!xsphy->phys) + return -ENOMEM; + + xsphy->dev = dev; + + sif_addr = ofnode_get_addr(dev_ofnode(dev)); + /* optional, may not exist if no u3 phys */ + if (sif_addr != FDT_ADDR_T_NONE) + xsphy->sif_base = map_sysmem(sif_addr, 0); + + xsphy->src_ref_clk_mhz = XSP_REF_CLK_MHZ; + xsphy->src_coef = XSP_SLEW_RATE_COEF; + /* update parameters of slew rate calibrate if exist */ + ofnode_read_u32(dev_ofnode(dev), "mediatek,src-ref-clk-mhz", + &xsphy->src_ref_clk_mhz); + ofnode_read_u32(dev_ofnode(dev), "mediatek,src-coef", &xsphy->src_coef); + + dev_for_each_subnode(subnode, dev) { + struct mtk_xsphy_instance *inst; + fdt_addr_t addr; + int ret; + + inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + xsphy->phys[index] = inst; + + addr = ofnode_get_addr(subnode); + if (addr == FDT_ADDR_T_NONE) + return -EADDRNOTAVAIL; + + inst->port_base = map_sysmem(addr, 0); + inst->index = index; + inst->np = ofnode_to_np(subnode); + + ret = clk_get_by_name_nodev(subnode, "ref", &inst->ref_clk); + if (ret) { + dev_err(dev, "failed to get ref_clk(id-%d)\n", index); + return ret; + } + + ret = mtk_xsphy_type_syscon_get(dev, inst, subnode); + if (ret) + return ret; + + index++; + } + + return 0; +} + +static const struct udevice_id mtk_xsphy_id_table[] = { + { .compatible = "mediatek,xsphy" }, + { } +}; + +U_BOOT_DRIVER(mtk_xsphy) = { + .name = "mtk-xsphy", + .id = UCLASS_PHY, + .of_match = mtk_xsphy_id_table, + .ops = &mtk_xsphy_ops, + .probe = mtk_xsphy_probe, + .priv_auto = sizeof(struct mtk_xsphy), +}; diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/drivers/pinctrl/mediatek/pinctrl-mt7981.c index 8875c276f36..5219b147797 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c @@ -106,7 +106,7 @@ static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = { PIN_FIELD_BASE(9, 9, 5, 0x20, 0x10, 9, 1), PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1), - PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), + PIN_FIELD_BASE(11, 11, 5, 0x20, 0x10, 10, 1), PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1), PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1), @@ -215,7 +215,7 @@ static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = { PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1), PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1), PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1), - PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), + PIN_FIELD_BASE(44, 44, 7, 0x70, 0x10, 8, 1), PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1), PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1), PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1), @@ -279,8 +279,8 @@ static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1), - PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1), + PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 3), + PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 3), PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3), PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3), PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3), @@ -288,9 +288,9 @@ static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { PIN_FIELD_BASE(9, 9, 5, 0x00, 0x10, 27, 3), PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(11, 11, 5, 0x10, 0x10, 0, 3), PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(13, 13, 5, 0x10, 0x10, 3, 3), PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3), @@ -302,7 +302,7 @@ static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3), PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3), PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(23, 23, 2, 0x10, 0x10, 0, 3), PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3), PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3), @@ -368,7 +368,7 @@ static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = { PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1), PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1), PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), + PIN_FIELD_BASE(20, 20, 2, 0x30, 0x10, 3, 1), PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1), PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1), PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1), diff --git a/drivers/ufs/ufs-mediatek.c b/drivers/ufs/ufs-mediatek.c index e860d765eea..268627d5863 100644 --- a/drivers/ufs/ufs-mediatek.c +++ b/drivers/ufs/ufs-mediatek.c @@ -182,19 +182,15 @@ static int ufs_mtk_bind_mphy(struct ufs_hba *hba) struct ufs_mtk_host *host = dev_get_priv(hba->dev); int err = 0; - err = generic_phy_get_by_index(hba->dev, 0, host->mphy); + err = generic_phy_get_by_index(hba->dev, 0, &host->mphy); - if (IS_ERR(host->mphy)) { - err = PTR_ERR(host->mphy); - if (err != -ENODEV) { - dev_info(hba->dev, "%s: Could NOT get a valid PHY %d\n", __func__, - err); - } + if (err) { + if (err == -ENOENT) + return 0; /* no PHY, nothing to do */ + dev_err(hba->dev, "Failed to get PHY: %d.\n", err); + return err; } - if (err) - host->mphy = NULL; - return err; } @@ -321,19 +317,35 @@ static int ufs_mtk_init(struct ufs_hba *hba) ufs_mtk_init_reset(hba); - // TODO: Clocking + err = clk_get_bulk(hba->dev, &priv->clks); + if (err) { + dev_err(hba->dev, "failed to initialize clocks, err:%d\n", err); + return err; + } + + err = clk_enable_bulk(&priv->clks); + if (err) { + dev_err(hba->dev, "failed to enable clocks, err:%d\n", err); + goto err_clk_enable; + } - err = generic_phy_power_on(priv->mphy); + err = generic_phy_power_on(&priv->mphy); if (err) { dev_err(hba->dev, "%s: phy init failed, err = %d\n", __func__, err); - return err; + goto err_phy_power_on; } ufs_mtk_setup_ref_clk(hba, true); ufs_mtk_get_hw_ip_version(hba); return 0; + +err_phy_power_on: + clk_disable_bulk(&priv->clks); +err_clk_enable: + clk_release_bulk(&priv->clks); + return err; } static int ufs_mtk_device_reset(struct ufs_hba *hba) @@ -383,7 +395,9 @@ static int ufs_mtk_probe(struct udevice *dev) static const struct udevice_id ufs_mtk_ids[] = { { .compatible = "mediatek,mt6878-ufshci" }, - {}, + { .compatible = "mediatek,mt8183-ufshci" }, + { .compatible = "mediatek,mt8195-ufshci" }, + { } }; U_BOOT_DRIVER(mediatek_ufshci) = { diff --git a/drivers/ufs/ufs-mediatek.h b/drivers/ufs/ufs-mediatek.h index 11a83d34c5b..0ffd0483eff 100644 --- a/drivers/ufs/ufs-mediatek.h +++ b/drivers/ufs/ufs-mediatek.h @@ -154,7 +154,7 @@ struct ufs_mtk_mcq_intr_info { }; struct ufs_mtk_host { - struct phy *mphy; + struct phy mphy; struct reset_ctl *unipro_reset; struct reset_ctl *crypto_reset; struct reset_ctl *hci_reset; |
