[][openwrt][mt7988][integration][Add basic Filogic 880 SoC support]

[Description]
Add basic filogic 880 SoC support to openwrt 21.02

[Release-log]

Change-Id: I57791df2e9f9f4729cb2d32f734090de52c370f2
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6592143
Build: srv_hbgsm110
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988-clkitg.dtsi b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988-clkitg.dtsi
new file mode 100644
index 0000000..48ed6c0
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988-clkitg.dtsi
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&clkitg {
+	bring-up {
+		compatible = "mediatek,clk-bring-up";
+		clocks =
+			<&apmixedsys CK_APMIXED_NETSYSPLL>,
+			<&apmixedsys CK_APMIXED_MPLL>,
+			<&apmixedsys CK_APMIXED_MMPLL>,
+			<&apmixedsys CK_APMIXED_APLL2>,
+			<&apmixedsys CK_APMIXED_NET1PLL>,
+			<&apmixedsys CK_APMIXED_NET2PLL>,
+			<&apmixedsys CK_APMIXED_WEDMCUPLL>,
+			<&apmixedsys CK_APMIXED_SGMPLL>,
+			<&apmixedsys CK_APMIXED_ARM_B>,
+			<&apmixedsys CK_APMIXED_CCIPLL2_B>,
+			<&apmixedsys CK_APMIXED_USXGMIIPLL>,
+			<&apmixedsys CK_APMIXED_MSDCPLL>,
+			<&topckgen CK_TOP_CB_CKSQ_40M>,
+			<&topckgen CK_TOP_CB_M_416M>,
+			<&topckgen CK_TOP_CB_M_D2>,
+			<&topckgen CK_TOP_M_D3_D2>,
+			<&topckgen CK_TOP_CB_M_D4>,
+			<&topckgen CK_TOP_CB_M_D8>,
+			<&topckgen CK_TOP_M_D8_D2>,
+			<&topckgen CK_TOP_CB_MM_720M>,
+			<&topckgen CK_TOP_CB_MM_D2>,
+			<&topckgen CK_TOP_CB_MM_D3_D5>,
+			<&topckgen CK_TOP_CB_MM_D4>,
+			<&topckgen CK_TOP_MM_D6_D2>,
+			<&topckgen CK_TOP_CB_MM_D8>,
+			<&topckgen CK_TOP_CB_APLL2_196M>,
+			<&topckgen CK_TOP_CB_APLL2_D4>,
+			<&topckgen CK_TOP_CB_NET1_D4>,
+			<&topckgen CK_TOP_CB_NET1_D5>,
+			<&topckgen CK_TOP_NET1_D5_D2>,
+			<&topckgen CK_TOP_NET1_D5_D4>,
+			<&topckgen CK_TOP_CB_NET1_D8>,
+			<&topckgen CK_TOP_NET1_D8_D2>,
+			<&topckgen CK_TOP_NET1_D8_D4>,
+			<&topckgen CK_TOP_NET1_D8_D8>,
+			<&topckgen CK_TOP_NET1_D8_D16>,
+			<&topckgen CK_TOP_CB_NET2_800M>,
+			<&topckgen CK_TOP_CB_NET2_D2>,
+			<&topckgen CK_TOP_CB_NET2_D4>,
+			<&topckgen CK_TOP_NET2_D4_D4>,
+			<&topckgen CK_TOP_NET2_D4_D8>,
+			<&topckgen CK_TOP_CB_NET2_D6>,
+			<&topckgen CK_TOP_CB_NET2_D8>,
+			<&topckgen CK_TOP_CB_WEDMCU_208M>,
+			<&topckgen CK_TOP_CB_SGM_325M>,
+			<&topckgen CK_TOP_CB_NETSYS_850M>,
+			<&topckgen CK_TOP_CB_MSDC_400M>,
+			<&topckgen CK_TOP_CKSQ_40M_D2>,
+			<&topckgen CK_TOP_CB_RTC_32K>,
+			<&topckgen CK_TOP_CB_RTC_32P7K>,
+			<&topckgen CK_TOP_INFRA_F32K>,
+			<&topckgen CK_TOP_CKSQ_SRC>,
+			<&topckgen CK_TOP_NETSYS_2X>,
+			<&topckgen CK_TOP_NETSYS_GSW>,
+			<&topckgen CK_TOP_NETSYS_WED_MCU>,
+			<&topckgen CK_TOP_EIP197>,
+			<&topckgen CK_TOP_EMMC_250M>,
+			<&topckgen CK_TOP_EMMC_400M>,
+			<&topckgen CK_TOP_SPI>,
+			<&topckgen CK_TOP_SPIM_MST>,
+			<&topckgen CK_TOP_NFI1X>,
+			<&topckgen CK_TOP_SPINFI_BCK>,
+			<&topckgen CK_TOP_I2C_BCK>,
+			<&topckgen CK_TOP_USB_SYS>,
+			<&topckgen CK_TOP_USB_SYS_P1>,
+			<&topckgen CK_TOP_USB_XHCI>,
+			<&topckgen CK_TOP_USB_XHCI_P1>,
+			<&topckgen CK_TOP_USB_FRMCNT>,
+			<&topckgen CK_TOP_USB_FRMCNT_P1>,
+			<&topckgen CK_TOP_AUD>,
+			<&topckgen CK_TOP_A1SYS>,
+			<&topckgen CK_TOP_AUD_L>,
+			<&topckgen CK_TOP_A_TUNER>,
+			<&topckgen CK_TOP_SYSAXI>,
+			<&topckgen CK_TOP_INFRA_F26M>,
+			<&topckgen CK_TOP_USB_REF>,
+			<&topckgen CK_TOP_USB_CK_P1>,
+			<&topckgen CK_TOP_AUD_I2S_M>,
+			<&topckgen CK_TOP_NETSYS_SEL>,
+			<&topckgen CK_TOP_NETSYS_500M_SEL>,
+			<&topckgen CK_TOP_NETSYS_2X_SEL>,
+			<&topckgen CK_TOP_NETSYS_GSW_SEL>,
+			<&topckgen CK_TOP_ETH_GMII_SEL>,
+			<&topckgen CK_TOP_NETSYS_MCU_SEL>,
+			<&topckgen CK_TOP_NETSYS_PAO_2X_SEL>,
+			<&topckgen CK_TOP_EIP197_SEL>,
+			<&topckgen CK_TOP_AXI_INFRA_SEL>,
+			<&topckgen CK_TOP_UART_SEL>,
+			<&topckgen CK_TOP_EMMC_250M_SEL>,
+			<&topckgen CK_TOP_EMMC_400M_SEL>,
+			<&topckgen CK_TOP_SPI_SEL>,
+			<&topckgen CK_TOP_SPIM_MST_SEL>,
+			<&topckgen CK_TOP_NFI1X_SEL>,
+			<&topckgen CK_TOP_SPINFI_SEL>,
+			<&topckgen CK_TOP_PWM_SEL>,
+			<&topckgen CK_TOP_I2C_SEL>,
+			<&topckgen CK_TOP_PCIE_MBIST_250M_SEL>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&topckgen CK_TOP_USB_SYS_SEL>,
+			<&topckgen CK_TOP_USB_SYS_P1_SEL>,
+			<&topckgen CK_TOP_USB_XHCI_SEL>,
+			<&topckgen CK_TOP_USB_XHCI_P1_SEL>,
+			<&topckgen CK_TOP_USB_FRMCNT_SEL>,
+			<&topckgen CK_TOP_USB_FRMCNT_P1_SEL>,
+			<&topckgen CK_TOP_AUD_SEL>,
+			<&topckgen CK_TOP_A1SYS_SEL>,
+			<&topckgen CK_TOP_AUD_L_SEL>,
+			<&topckgen CK_TOP_A_TUNER_SEL>,
+			<&topckgen CK_TOP_SSPXTP_SEL>,
+			<&topckgen CK_TOP_USB_PHY_SEL>,
+			<&topckgen CK_TOP_USXGMII_SBUS_0_SEL>,
+			<&topckgen CK_TOP_USXGMII_SBUS_1_SEL>,
+			<&topckgen CK_TOP_SGM_0_SEL>,
+			<&topckgen CK_TOP_SGM_SBUS_0_SEL>,
+			<&topckgen CK_TOP_SGM_1_SEL>,
+			<&topckgen CK_TOP_SGM_SBUS_1_SEL>,
+			<&topckgen CK_TOP_XFI_PHY_0_XTAL_SEL>,
+			<&topckgen CK_TOP_XFI_PHY_1_XTAL_SEL>,
+			<&topckgen CK_TOP_SYSAXI_SEL>,
+			<&topckgen CK_TOP_SYSAPB_SEL>,
+			<&topckgen CK_TOP_ETH_REFCK_50M_SEL>,
+			<&topckgen CK_TOP_ETH_SYS_200M_SEL>,
+			<&topckgen CK_TOP_ETH_SYS_SEL>,
+			<&topckgen CK_TOP_ETH_XGMII_SEL>,
+			<&topckgen CK_TOP_BUS_TOPS_SEL>,
+			<&topckgen CK_TOP_NPU_TOPS_SEL>,
+			<&topckgen CK_TOP_DRAMC_SEL>,
+			<&topckgen CK_TOP_DRAMC_MD32_SEL>,
+			<&topckgen CK_TOP_INFRA_F26M_SEL>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&topckgen CK_TOP_DA_XTP_GLB_P0_SEL>,
+			<&topckgen CK_TOP_DA_XTP_GLB_P1_SEL>,
+			<&topckgen CK_TOP_DA_XTP_GLB_P2_SEL>,
+			<&topckgen CK_TOP_DA_XTP_GLB_P3_SEL>,
+			<&topckgen CK_TOP_CKM_SEL>,
+			<&topckgen CK_TOP_DA_SELM_XTAL_SEL>,
+			<&topckgen CK_TOP_PEXTP_SEL>,
+			<&topckgen CK_TOP_TOPS_P2_26M_SEL>,
+			<&topckgen CK_TOP_MCUSYS_BACKUP_625M_SEL>,
+			<&topckgen CK_TOP_NETSYS_SYNC_250M_SEL>,
+			<&topckgen CK_TOP_MACSEC_SEL>,
+			<&topckgen CK_TOP_NETSYS_TOPS_400M_SEL>,
+			<&topckgen CK_TOP_NETSYS_PPEFB_250M_SEL>,
+			<&topckgen CK_TOP_NETSYS_WARP_SEL>,
+			<&topckgen CK_TOP_ETH_MII_SEL>,
+			<&topckgen CK_TOP_CK_NPU_SEL_CM_TOPS_SEL>,
+			<&infracfg CK_INFRA_CK_F26M>,
+			<&infracfg CK_INFRA_PWM_O>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&infracfg CK_INFRA_133M_HCK>,
+			<&infracfg CK_INFRA_133M_PHCK>,
+			<&infracfg CK_INFRA_66M_PHCK>,
+			<&infracfg CK_INFRA_FAUD_L_O>,
+			<&infracfg CK_INFRA_FAUD_AUD_O>,
+			<&infracfg CK_INFRA_FAUD_EG2_O>,
+			<&infracfg CK_INFRA_I2C_O>,
+			<&infracfg CK_INFRA_UART_O0>,
+			<&infracfg CK_INFRA_UART_O1>,
+			<&infracfg CK_INFRA_UART_O2>,
+			<&infracfg CK_INFRA_NFI_O>,
+			<&infracfg CK_INFRA_SPINFI_O>,
+			<&infracfg CK_INFRA_SPI0_O>,
+			<&infracfg CK_INFRA_SPI1_O>,
+			<&infracfg CK_INFRA_LB_MUX_FRTC>,
+			<&infracfg CK_INFRA_FRTC>,
+			<&infracfg CK_INFRA_FMSDC400_O>,
+			<&infracfg CK_INFRA_FMSDC2_HCK_OCC>,
+			<&infracfg CK_INFRA_PERI_133M>,
+			<&infracfg CK_INFRA_USB_O>,
+			<&infracfg CK_INFRA_USB_O_P1>,
+			<&infracfg CK_INFRA_USB_FRMCNT_O>,
+			<&infracfg CK_INFRA_USB_FRMCNT_O_P1>,
+			<&infracfg CK_INFRA_USB_XHCI_O>,
+			<&infracfg CK_INFRA_USB_XHCI_O_P1>,
+			<&infracfg CK_INFRA_USB_PIPE_O>,
+			<&infracfg CK_INFRA_USB_PIPE_O_P1>,
+			<&infracfg CK_INFRA_USB_UTMI_O>,
+			<&infracfg CK_INFRA_USB_UTMI_O_P1>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&infracfg CK_INFRA_F26M_O0>,
+			<&infracfg CK_INFRA_F26M_O1>,
+			<&infracfg CK_INFRA_133M_MCK>,
+			<&infracfg CK_INFRA_66M_MCK>,
+			<&infracfg CK_INFRA_PERI_66M_O>,
+			<&infracfg CK_INFRA_USB_SYS_O>,
+			<&infracfg CK_INFRA_USB_SYS_O_P1>,
+			<&infracfg_ao CK_INFRA_66M_GPT_BCK>,
+			<&infracfg_ao CK_INFRA_66M_PWM_HCK>,
+			<&infracfg_ao CK_INFRA_66M_PWM_BCK>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK1>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK2>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK3>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK4>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK5>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK6>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK7>,
+			<&infracfg_ao CK_INFRA_66M_PWM_CK8>,
+			<&infracfg_ao CK_INFRA_133M_CQDMA_BCK>,
+			<&infracfg_ao CK_INFRA_66M_AUD_SLV_BCK>,
+			<&infracfg_ao CK_INFRA_AUD_26M>,
+			<&infracfg_ao CK_INFRA_AUD_L>,
+			<&infracfg_ao CK_INFRA_AUD_AUD>,
+			<&infracfg_ao CK_INFRA_AUD_EG2>,
+			<&infracfg_ao CK_INFRA_DRAMC_F26M>,
+			<&infracfg_ao CK_INFRA_133M_DBG_ACKM>,
+			<&infracfg_ao CK_INFRA_66M_AP_DMA_BCK>,
+			<&infracfg_ao CK_INFRA_66M_SEJ_BCK>,
+			<&infracfg_ao CK_INFRA_PRE_CK_SEJ_F13M>,
+			<&infracfg_ao CK_INFRA_66M_TRNG>,
+			<&infracfg_ao CK_INFRA_26M_THERM_SYSTEM>,
+			<&infracfg_ao CK_INFRA_I2C_BCK>,
+			<&infracfg_ao CK_INFRA_66M_UART0_PCK>,
+			<&infracfg_ao CK_INFRA_66M_UART1_PCK>,
+			<&infracfg_ao CK_INFRA_66M_UART2_PCK>,
+			<&infracfg_ao CK_INFRA_52M_UART0_CK>,
+			<&infracfg_ao CK_INFRA_52M_UART1_CK>,
+			<&infracfg_ao CK_INFRA_52M_UART2_CK>,
+			<&infracfg_ao CK_INFRA_NFI>,
+			<&infracfg_ao CK_INFRA_SPINFI>,
+			<&infracfg_ao CK_INFRA_66M_NFI_HCK>,
+			<&infracfg_ao CK_INFRA_104M_SPI0>,
+			<&infracfg_ao CK_INFRA_104M_SPI1>,
+			<&infracfg_ao CK_INFRA_104M_SPI2_BCK>,
+			<&infracfg_ao CK_INFRA_66M_SPI0_HCK>,
+			<&infracfg_ao CK_INFRA_66M_SPI1_HCK>,
+			<&infracfg_ao CK_INFRA_66M_SPI2_HCK>,
+			<&infracfg_ao CK_INFRA_66M_FLASHIF_AXI>,
+			<&infracfg_ao CK_INFRA_RTC>,
+			<&infracfg_ao CK_INFRA_26M_ADC_BCK>,
+			<&infracfg_ao CK_INFRA_RC_ADC>,
+			<&infracfg_ao CK_INFRA_MSDC400>,
+			<&infracfg_ao CK_INFRA_MSDC2_HCK>,
+			<&infracfg_ao CK_INFRA_133M_MSDC_0_HCK>,
+			<&infracfg_ao CK_INFRA_66M_MSDC_0_HCK>,
+			<&infracfg_ao CK_INFRA_133M_CPUM_BCK>,
+			<&infracfg_ao CK_INFRA_BIST2FPC>,
+			<&infracfg_ao CK_INFRA_I2C_X16W_MCK_CK_P1>,
+			<&infracfg_ao CK_INFRA_I2C_X16W_PCK_CK_P1>,
+			<&infracfg_ao CK_INFRA_133M_USB_HCK>,
+			<&infracfg_ao CK_INFRA_133M_USB_HCK_CK_P1>,
+			<&infracfg_ao CK_INFRA_66M_USB_HCK>,
+			<&infracfg_ao CK_INFRA_66M_USB_HCK_CK_P1>,
+			<&infracfg_ao CK_INFRA_USB_SYS>,
+			<&infracfg_ao CK_INFRA_USB_SYS_CK_P1>,
+			<&infracfg_ao CK_INFRA_USB_REF>,
+			<&infracfg_ao CK_INFRA_USB_CK_P1>,
+			<&infracfg_ao CK_INFRA_USB_FRMCNT>,
+			<&infracfg_ao CK_INFRA_USB_FRMCNT_CK_P1>,
+			<&infracfg_ao CK_INFRA_USB_PIPE>,
+			<&infracfg_ao CK_INFRA_USB_PIPE_CK_P1>,
+			<&infracfg_ao CK_INFRA_USB_UTMI>,
+			<&infracfg_ao CK_INFRA_USB_UTMI_CK_P1>,
+			<&infracfg_ao CK_INFRA_USB_XHCI>,
+			<&infracfg_ao CK_INFRA_USB_XHCI_CK_P1>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&infracfg_ao CK_INFRA_MUX_UART0_SEL>,
+			<&infracfg_ao CK_INFRA_MUX_UART1_SEL>,
+			<&infracfg_ao CK_INFRA_MUX_UART2_SEL>,
+			<&infracfg_ao CK_INFRA_MUX_SPI0_SEL>,
+			<&infracfg_ao CK_INFRA_MUX_SPI1_SEL>,
+			<&infracfg_ao CK_INFRA_MUX_SPI2_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK1_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK2_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK3_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK4_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK5_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK6_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK7_SEL>,
+			<&infracfg_ao CK_INFRA_PWM_CK8_SEL>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&ethsys CK_ETHDMA_XGP1_EN>,
+			<&ethsys CK_ETHDMA_XGP2_EN>,
+			<&ethsys CK_ETHDMA_XGP3_EN>,
+			<&ethsys CK_ETHDMA_FE_EN>,
+			<&ethsys CK_ETHDMA_GP2_EN>,
+			<&ethsys CK_ETHDMA_GP1_EN>,
+			<&ethsys CK_ETHDMA_GP3_EN>,
+			<&ethsys CK_ETHDMA_ESW_EN>,
+			<&ethsys CK_ETHDMA_CRYPT0_EN>,
+			<&ethwarp CK_ETHWARP_WOCPU2_EN>,
+			<&ethwarp CK_ETHWARP_WOCPU1_EN>,
+			<&ethwarp CK_ETHWARP_WOCPU0_EN>,
+			<&sgmiisys0 CK_SGM0_TX_EN>,
+			<&sgmiisys0 CK_SGM0_RX_EN>,
+			<&sgmiisys1 CK_SGM1_TX_EN>,
+			<&sgmiisys1 CK_SGM1_RX_EN>,
+			<&mcusys CK_MCU_BUS_DIV_SEL>,
+			<&mcusys CK_MCU_ARM_DIV_SEL>;
+
+		clock-names = "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+			      "10", "11", "12", "13", "14", "15", "16", "17",
+			      "18", "19", "20", "21", "22", "23", "24", "25",
+			      "26", "27", "28", "29", "30", "31", "32", "33",
+			      "34", "35", "36", "37", "38", "39", "40", "41",
+			      "42", "43", "44", "45", "46", "47", "48", "49",
+			      "50", "51", "52", "53", "54", "55", "56", "57",
+			      "58", "59", "60", "61", "62", "63", "64", "65",
+			      "66", "67", "68", "69", "70", "71", "72", "73",
+			      "74", "75", "76", "77", "78", "79", "80", "81",
+			      "82", "83", "84", "85", "86", "87", "88", "89",
+			      "90", "91", "92", "93", "94", "95", "96", "97",
+			      "98", "99", "100", "101", "102", "103", "104",
+			      "105", "106", "107", "108", "109", "110", "111",
+			      "112", "113", "114", "115", "116", "117", "118",
+			      "119", "120", "121", "122", "123", "124", "125",
+			      "126", "127", "128", "129", "130", "131", "132",
+			      "133", "134", "135", "136", "137", "138", "139",
+			      "140", "141", "142", "143", "144", "145", "146",
+			      "147", "148", "149", "150", "151", "152", "153",
+			      "154", "155", "156", "157", "158", "159", "160",
+			      "161", "162", "163", "164", "165", "166", "167",
+			      "168", "169", "170", "171", "172", "173", "174",
+			      "175", "176", "177", "178", "179", "180", "181",
+			      "182", "183", "184", "185", "186", "187", "188",
+			      "189", "190", "191", "192", "193", "194", "195",
+			      "196", "197", "198", "199", "200", "201", "202",
+			      "203", "204", "205", "206", "207", "208", "209",
+			      "210", "211", "212", "213", "214", "215", "216",
+			      "217", "218", "219", "220", "221", "222", "223",
+			      "224", "225", "226", "227", "228", "229", "230",
+			      "231", "232", "233", "234", "235", "236", "237",
+			      "238", "239", "240", "241", "242", "243", "244",
+			      "245", "246", "247", "248", "249", "250", "251",
+			      "252", "253", "254", "255", "256", "257", "258",
+			      "259", "260", "261", "262", "263", "264", "265",
+			      "266", "267", "268", "269", "270", "271", "272",
+			      "273", "274", "275", "276", "277", "278", "279",
+			      "280", "281", "282", "283", "284", "285", "286",
+			      "287", "288", "289", "290", "291", "292", "293",
+			      "294", "295", "296", "297", "298", "299", "300",
+			      "301", "302", "303", "304", "305", "306", "307",
+			      "308", "309", "310", "311", "312", "313", "314",
+			      "315", "316", "317", "318", "319", "320", "321",
+			      "322", "323";
+	};
+};
+
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
new file mode 100644
index 0000000..16b872e
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -0,0 +1,1096 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+#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>
+#include <dt-bindings/clock/mt7988-clk.h>
+#include <dt-bindings/pinctrl/mt65xx.h>
+#include <dt-bindings/thermal/thermal.h>
+#include <dt-bindings/regulator/richtek,rt5190a-regulator.h>
+#include <dt-bindings/power/mt7988-power.h>
+
+/ {
+	compatible = "mediatek,mt7988-rfb";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			enable-method = "psci";
+			reg = <0x0>;
+			clocks = <&mcusys CK_MCU_ARM_DIV_SEL>,
+				 <&topckgen CK_TOP_CB_NET1_D4>,
+				 <&apmixedsys CK_APMIXED_ARM_B>,
+				 <&mcusys CK_MCU_BUS_DIV_SEL>,
+				 <&apmixedsys CK_APMIXED_CCIPLL2_B>;
+			clock-names = "cpu", "intermediate", "armpll", "cci",
+				      "ccipll";
+			operating-points-v2 = <&cluster0_opp>;
+			nvmem-cells = <&cpufreq_calibration>;
+			nvmem-cell-names = "calibration-data";
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			enable-method = "psci";
+			reg = <0x1>;
+			clocks = <&mcusys CK_MCU_ARM_DIV_SEL>,
+				 <&topckgen CK_TOP_CB_NET1_D4>,
+				 <&apmixedsys CK_APMIXED_ARM_B>,
+				 <&mcusys CK_MCU_BUS_DIV_SEL>,
+				 <&apmixedsys CK_APMIXED_CCIPLL2_B>;
+			clock-names = "cpu", "intermediate", "armpll", "cci",
+				      "ccipll";
+			operating-points-v2 = <&cluster0_opp>;
+			nvmem-cells = <&cpufreq_calibration>;
+			nvmem-cell-names = "calibration-data";
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			enable-method = "psci";
+			reg = <0x2>;
+			clocks = <&mcusys CK_MCU_ARM_DIV_SEL>,
+				 <&topckgen CK_TOP_CB_NET1_D4>,
+				 <&apmixedsys CK_APMIXED_ARM_B>,
+				 <&mcusys CK_MCU_BUS_DIV_SEL>,
+				 <&apmixedsys CK_APMIXED_CCIPLL2_B>;
+			clock-names = "cpu", "intermediate", "armpll", "cci",
+				      "ccipll";
+			operating-points-v2 = <&cluster0_opp>;
+			nvmem-cells = <&cpufreq_calibration>;
+			nvmem-cell-names = "calibration-data";
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a73";
+			enable-method = "psci";
+			reg = <0x3>;
+			clocks = <&mcusys CK_MCU_ARM_DIV_SEL>,
+				 <&topckgen CK_TOP_CB_NET1_D4>,
+				 <&apmixedsys CK_APMIXED_ARM_B>,
+				 <&mcusys CK_MCU_BUS_DIV_SEL>,
+				 <&apmixedsys CK_APMIXED_CCIPLL2_B>;
+			clock-names = "cpu", "intermediate", "armpll", "cci",
+				      "ccipll";
+			operating-points-v2 = <&cluster0_opp>;
+			nvmem-cells = <&cpufreq_calibration>;
+			nvmem-cell-names = "calibration-data";
+		};
+
+		cluster0_opp: opp_table0 {
+			compatible = "operating-points-v2";
+			opp-shared;
+			opp00 {
+				opp-hz = /bits/ 64 <800000000>;
+				opp-microvolt = <850000>;
+			};
+			opp01 {
+				opp-hz = /bits/ 64 <1100000000>;
+				opp-microvolt = <850000>;
+			};
+			opp02 {
+				opp-hz = /bits/ 64 <1500000000>;
+				opp-microvolt = <850000>;
+			};
+			opp03 {
+				opp-hz = /bits/ 64 <1800000000>;
+				opp-microvolt = <900000>;
+			};
+		};
+	};
+
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+			thermal-sensors = <&lvts 0>;
+			trips {
+				cpu_trip_crit: crit {
+					temperature = <125000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+
+				cpu_trip_hot: hot {
+					temperature = <120000>;
+					hysteresis = <2000>;
+					type = "hot";
+				};
+
+				cpu_trip_active_high: active-high {
+					temperature = <115000>;
+					hysteresis = <2000>;
+					type = "active";
+				};
+
+				cpu_trip_active_low: active-low {
+					temperature = <85000>;
+					hysteresis = <2000>;
+					type = "active";
+				};
+
+				cpu_trip_passive: passive {
+					temperature = <40000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+			};
+
+			cooling-maps {
+				cpu-active-high {
+				/* active: set fan to cooling level 2 */
+					cooling-device = <&fan 2 2>;
+					trip = <&cpu_trip_active_high>;
+				};
+
+				cpu-active-low {
+				/* active: set fan to cooling level 1 */
+					cooling-device = <&fan 1 1>;
+					trip = <&cpu_trip_active_low>;
+				};
+
+				cpu-passive {
+				/* passive: set fan to cooling level 0 */
+					cooling-device = <&fan 0 0>;
+					trip = <&cpu_trip_passive>;
+				};
+			};
+
+		};
+	};
+
+	mmc0: mmc@11230000 {
+		compatible = "mediatek,mt7986-mmc";
+		reg = <0 0x11230000 0 0x1000>,
+		      <0 0x11D60000 0 0x1000>;
+		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg_ao CK_INFRA_MSDC400>,
+			 <&infracfg_ao CK_INFRA_MSDC2_HCK>,
+			 <&infracfg_ao CK_INFRA_133M_MSDC_0_HCK>,
+			 <&infracfg_ao CK_INFRA_66M_MSDC_0_HCK>;
+		clock-names = "source", "hclk", "ahb_cg", "axi_cg";
+		status = "disabled";
+	};
+
+	wed: wed@15010000 {
+		compatible = "mediatek,wed";
+		wed_num = <3>;
+		/* add this property for wed get the pci slot number. */
+		pci_slot_map = <0>, <1>, <2>;
+		reg = <0 0x15010000 0 0x2000>,
+		      <0 0x15012000 0 0x2000>,
+		      <0 0x15014000 0 0x2000>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	wed2: wed2@15012000 {
+		compatible = "mediatek,wed2";
+		wed_num = <3>;
+		/* add this property for wed get the pci slot number. */
+		reg = <0 0x15010000 0 0x2000>,
+		      <0 0x15012000 0 0x2000>,
+		      <0 0x15014000 0 0x2000>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	wed3: wed3@15014000 {
+		compatible = "mediatek,wed3";
+		wed_num = <3>;
+		/* add this property for wed get the pci slot number. */
+		reg = <0 0x15010000 0 0x2000>,
+		      <0 0x15012000 0 0x2000>,
+		      <0 0x15014000 0 0x2000>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	wdma: wdma@15104800 {
+		compatible = "mediatek,wed-wdma";
+		reg = <0 0x15104800 0 0x400>,
+		      <0 0x15104c00 0 0x400>,
+		      <0 0x15105000 0 0x400>;
+	};
+
+	ap2woccif: ap2woccif@151A5000 {
+		compatible = "mediatek,ap2woccif";
+		reg = <0 0x151A5000 0 0x1000>,
+		      <0 0x152A5000 0 0x1000>,
+		      <0 0x153A5000 0 0x1000>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	wocpu0_ilm: wocpu0_ilm@151E0000 {
+		compatible = "mediatek,wocpu0_ilm";
+		reg = <0 0x151E0000 0 0x8000>;
+	};
+
+	wocpu1_ilm: wocpu1_ilm@152E0000 {
+		compatible = "mediatek,wocpu1_ilm";
+		reg = <0 0x152E0000 0 0x8000>;
+	};
+
+	wocpu2_ilm: wocpu2_ilm@153E0000 {
+		compatible = "mediatek,wocpu2_ilm";
+		reg = <0 0x153E0000 0 0x8000>;
+	};
+
+	wocpu_dlm: wocpu_dlm@151E8000 {
+		compatible = "mediatek,wocpu_dlm";
+		reg = <0 0x151E8000 0 0x2000>,
+		      <0 0x152E8000 0 0x2000>,
+		      <0 0x153E8000 0 0x2000>;
+
+		resets = <&ethsysrst 0>;
+		reset-names = "wocpu_rst";
+	};
+
+	cpu_boot: wocpu_boot@15194000 {
+		compatible = "mediatek,wocpu_boot";
+		reg = <0 0x15194000 0 0x1000>,
+		      <0 0x15294000 0 0x1000>,
+		      <0 0x15394000 0 0x1000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+		secmon_reserved: secmon@43000000 {
+			reg = <0 0x43000000 0 0x30000>;
+			no-map;
+		};
+
+		wmcpu_emi: wmcpu-reserved@47CC0000 {
+			compatible = "mediatek,wmcpu-reserved";
+			no-map;
+			reg = <0 0x47CC0000 0 0x00100000>;
+		};
+
+		wocpu0_emi: wocpu0_emi@4F600000 {
+			compatible = "mediatek,wocpu0_emi";
+			no-map;
+			reg = <0 0x4F600000 0 0x40000>;
+			shared = <0>;
+		};
+
+		wocpu1_emi: wocpu1_emi@4F640000 {
+			compatible = "mediatek,wocpu1_emi";
+			no-map;
+			reg = <0 0x4F640000 0 0x40000>;
+			shared = <0>;
+		};
+
+		wocpu2_emi: wocpu2_emi@4F680000 {
+			compatible = "mediatek,wocpu2_emi";
+			no-map;
+			reg = <0 0x4F680000 0 0x40000>;
+			shared = <0>;
+		};
+
+		wocpu_data: wocpu_data@4F700000 {
+			compatible = "mediatek,wocpu_data";
+			no-map;
+			reg = <0 0x4F700000 0 0x800000>;
+			shared = <1>;
+		};
+	};
+
+	psci {
+		compatible  = "arm,psci-0.2";
+		method      = "smc";
+	};
+
+	system_clk: dummy_system_clk {
+		compatible = "fixed-clock";
+		clock-frequency = <40000000>;
+		#clock-cells = <0>;
+	};
+
+	uart_clk: dummy_uart_clk {
+		compatible = "fixed-clock";
+		clock-frequency = <40000000>;
+		#clock-cells = <0>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+
+	};
+
+	tops: tops@09100000 {
+		compatible = "mediatek,tops";
+		reg = <0 0x09100000 0 0x01000000>;
+		reg-names = "tops-base";
+		clocks = <&topckgen CK_TOP_BUS_TOPS_SEL>,
+			 <&topckgen CK_TOP_TOPS_P2_26M_SEL>,
+			 <&topckgen CK_TOP_NETSYS_TOPS_400M_SEL>,
+			 <&topckgen CK_TOP_NPU_TOPS_SEL>,
+			 <&topckgen CK_TOP_CK_NPU_SEL_CM_TOPS_SEL>;
+		clock-names = "bus", "sram", "xdma", "offload", "mgmt";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tdma-tx-pause", "mbox";
+		topmisc = <&topmisc>;
+		fe_mem = <&eth>;
+		topckgen = <&topckgen>;
+	};
+	hpdma1: hpdma@09106000 {
+		compatible = "mediatek,hpdma-top";
+		reg = <0 0x09106000 0 0x1000>;
+		reg-names = "base";
+	};
+	hpdma2: hpdma@09606000 {
+		compatible = "mediatek,hpdma-sub";
+		reg = <0 0x09606000 0 0x1000>;
+		reg-names = "base";
+	};
+
+	watchdog: watchdog@1001c000 {
+		compatible = "mediatek,mt7622-wdt",
+			     "mediatek,mt6589-wdt",
+			     "syscon";
+		reg = <0 0x1001c000 0 0x1000>;
+		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		#reset-cells = <1>;
+	};
+
+	phyfw: phy-firmware@f000000 {
+		compatible = "mediatek,2p5gphy-fw";
+		reg = <0 0x0f000000 0 0x8000>,
+		      <0 0x0f100000 0 0x20000>,
+		      <0 0x0f0f0000 0 0x200>;
+	};
+
+	gic: interrupt-controller@c000000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+		interrupt-controller;
+		reg = <0 0x0c000000 0 0x40000>,  /* GICD */
+		      <0 0x0c080000 0 0x200000>; /* GICR */
+
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	trng: trng@1020f000 {
+		compatible = "mediatek,mt7988-rng";
+	};
+
+	uart0: serial@11000000 {
+		compatible = "mediatek,mt7986-uart",
+			     "mediatek,mt6577-uart";
+		reg = <0 0x11000000 0 0x100>;
+		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&uart_clk>;
+		status = "disabled";
+	};
+
+	uart1: serial@11000100 {
+		compatible = "mediatek,mt7986-uart",
+			     "mediatek,mt6577-uart";
+		reg = <0 0x11000100 0 0x100>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&uart_clk>;
+		status = "disabled";
+	};
+
+	uart2: serial@11000200 {
+		compatible = "mediatek,mt7986-uart",
+			     "mediatek,mt6577-uart";
+		reg = <0 0x11000200 0 0x100>;
+		interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&uart_clk>;
+		status = "disabled";
+	};
+
+	i2c0: i2c@11003000 {
+		compatible = "mediatek,mt7988-i2c",
+			"mediatek,mt7981-i2c";
+		reg = <0 0x11003000 0 0x1000>,
+		      <0 0x10217080 0 0x80>;
+		interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+		clock-div = <1>;
+		clocks = <&system_clk>,
+			 <&system_clk>;
+		clock-names = "main", "dma";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@11004000 {
+		compatible = "mediatek,mt7988-i2c",
+			"mediatek,mt7981-i2c";
+		reg = <0 0x11004000 0 0x1000>,
+		      <0 0x10217100 0 0x80>;
+		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+		clock-div = <1>;
+		clocks = <&system_clk>,
+			 <&system_clk>;
+		clock-names = "main", "dma";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@11005000 {
+		compatible = "mediatek,mt7988-i2c",
+			"mediatek,mt7981-i2c";
+		reg = <0 0x11005000 0 0x1000>,
+		      <0 0x10217180 0 0x80>;
+		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+		clock-div = <1>;
+		clocks = <&system_clk>,
+			 <&system_clk>;
+		clock-names = "main", "dma";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	pwm: pwm@10048000 {
+		compatible = "mediatek,mt7988-pwm";
+		reg = <0 0x10048000 0 0x1000>;
+		#pwm-cells = <2>;
+		clocks = <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>;
+		clock-names = "top", "main", "pwm1", "pwm2", "pwm3",
+			      "pwm4","pwm5","pwm6","pwm7","pwm8";
+		status = "disabled";
+	};
+
+	fan: pwm-fan {
+		compatible = "pwm-fan";
+		/* cooling level (0, 1, 2) : (0% duty, 50% duty, 100% duty) */
+		cooling-levels = <0 128 255>;
+		#cooling-cells = <2>;
+		#thermal-sensor-cells = <1>;
+		status = "disabled";
+	};
+
+	lvts: lvts@1100a000 {
+		compatible = "mediatek,mt7988-lvts";
+		#thermal-sensor-cells = <1>;
+		reg = <0 0x1100a000 0 0x1000>;
+		clocks = <&system_clk>;
+		clock-names = "lvts_clk";
+		nvmem-cells = <&lvts_calibration>;
+		nvmem-cell-names = "e_data1";
+	};
+
+	crypto: crypto@15600000 {
+		compatible = "inside-secure,safexcel-eip197b";
+		reg = <0 0x15600000 0 0x180000>;
+		interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "ring0", "ring1", "ring2", "ring3";
+		status = "okay";
+	};
+
+	pcie0: pcie@11300000 {
+		compatible = "mediatek,mt7988-pcie",
+			     "mediatek,mt7986-pcie";
+		device_type = "pci";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		reg = <0 0x11300000 0 0x2000>;
+		reg-names = "pcie-mac";
+		linux,pci-domain = <0>;
+		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x81000000 0x00 0x30000000 0x00
+			  0x30000000 0x00 0x00200000>,
+			 <0x82000000 0x00 0x30200000 0x00
+			  0x30200000 0x00 0x07e00000>;
+		status = "disabled";
+
+		clocks = <&topckgen CK_TOP_PEXTP_P0_SEL>,
+			 <&infracfg_ao CK_INFRA_PCIE_GFMUX_TL_P0>,
+			 <&infracfg_ao CK_INFRA_PCIE_PIPE_P0>,
+			 <&infracfg_ao CK_INFRA_133M_PCIE_CK_P0>,
+			 <&infracfg_ao CK_INFRA_PCIE_PERI_26M_CK_P0>;
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0x7>;
+		interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+				<0 0 0 2 &pcie_intc0 1>,
+				<0 0 0 3 &pcie_intc0 2>,
+				<0 0 0 4 &pcie_intc0 3>;
+		pcie_intc0: interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+		};
+	};
+
+	pcie1: pcie@11310000 {
+		compatible = "mediatek,mt7988-pcie",
+			     "mediatek,mt7986-pcie";
+		device_type = "pci";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		reg = <0 0x11310000 0 0x2000>;
+		reg-names = "pcie-mac";
+		linux,pci-domain = <1>;
+		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x81000000 0x00 0x38000000 0x00
+			  0x38000000 0x00 0x00200000>,
+			 <0x82000000 0x00 0x38200000 0x00
+			  0x38200000 0x00 0x07e00000>;
+		status = "disabled";
+
+		clocks = <&topckgen CK_TOP_PEXTP_P1_SEL>,
+			 <&infracfg_ao CK_INFRA_PCIE_GFMUX_TL_P1>,
+			 <&infracfg_ao CK_INFRA_PCIE_PIPE_P1>,
+			 <&infracfg_ao CK_INFRA_133M_PCIE_CK_P1>,
+			 <&infracfg_ao CK_INFRA_PCIE_PERI_26M_CK_P1>;
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0x7>;
+		interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+				<0 0 0 2 &pcie_intc1 1>,
+				<0 0 0 3 &pcie_intc1 2>,
+				<0 0 0 4 &pcie_intc1 3>;
+		pcie_intc1: interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+		};
+	};
+
+	pcie2: pcie@11280000 {
+		compatible = "mediatek,mt7988-pcie",
+			     "mediatek,mt7986-pcie";
+		device_type = "pci";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		reg = <0 0x11280000 0 0x2000>;
+		reg-names = "pcie-mac";
+		linux,pci-domain = <3>;
+		interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x81000000 0x00 0x20000000 0x00
+			  0x20000000 0x00 0x00200000>,
+			 <0x82000000 0x00 0x20200000 0x00
+			  0x20200000 0x00 0x07e00000>;
+		status = "disabled";
+
+		clocks = <&topckgen CK_TOP_PEXTP_P2_SEL>,
+			 <&infracfg_ao CK_INFRA_PCIE_GFMUX_TL_P2>,
+			 <&infracfg_ao CK_INFRA_PCIE_PIPE_P2>,
+			 <&infracfg_ao CK_INFRA_133M_PCIE_CK_P2>,
+			 <&infracfg_ao CK_INFRA_PCIE_PERI_26M_CK_P2>,
+			 <&infracfg_ao CK_INFRA_PCIE_PERI_26M_CK_P3>;
+
+		phys = <&xphyu3port0 PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0x7>;
+		interrupt-map = <0 0 0 1 &pcie_intc2 0>,
+				<0 0 0 2 &pcie_intc2 1>,
+				<0 0 0 3 &pcie_intc2 2>,
+				<0 0 0 4 &pcie_intc2 3>;
+		pcie_intc2: interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+		};
+	};
+
+	pcie3: pcie@11290000 {
+		compatible = "mediatek,mt7988-pcie",
+			     "mediatek,mt7986-pcie";
+		device_type = "pci";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		reg = <0 0x11290000 0 0x2000>;
+		reg-names = "pcie-mac";
+		linux,pci-domain = <2>;
+		interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+		bus-range = <0x00 0xff>;
+		ranges = <0x81000000 0x00 0x28000000 0x00
+			  0x28000000 0x00 0x00200000>,
+			 <0x82000000 0x00 0x28200000 0x00
+			  0x28200000 0x00 0x07e00000>;
+		status = "disabled";
+
+		clocks = <&topckgen CK_TOP_PEXTP_P3_SEL>,
+			 <&infracfg_ao CK_INFRA_PCIE_GFMUX_TL_P3>,
+			 <&infracfg_ao CK_INFRA_PCIE_PIPE_P3>,
+			 <&infracfg_ao CK_INFRA_133M_PCIE_CK_P3>,
+			 <&infracfg_ao CK_INFRA_PCIE_PERI_26M_CK_P3>;
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0x7>;
+		interrupt-map = <0 0 0 1 &pcie_intc3 0>,
+				<0 0 0 2 &pcie_intc3 1>,
+				<0 0 0 3 &pcie_intc3 2>,
+				<0 0 0 4 &pcie_intc3 3>;
+		pcie_intc3: interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+		};
+	};
+
+	pio: pinctrl@1001f000 {
+		compatible = "mediatek,mt7988-pinctrl";
+		reg = <0 0x1001f000 0 0x1000>,
+		      <0 0x11c10000 0 0x1000>,
+		      <0 0x11d00000 0 0x1000>,
+		      <0 0x11d20000 0 0x1000>,
+		      <0 0x11e00000 0 0x1000>,
+		      <0 0x11f00000 0 0x1000>,
+		      <0 0x1000b000 0 0x1000>;
+		reg-names = "gpio_base", "iocfg_tr_base", "iocfg_br_base",
+			    "iocfg_rb_base", "iocfg_lb_base", "iocfg_tl_base",
+			    "eint";
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-ranges = <&pio 0 0 83>;
+		interrupt-controller;
+		interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-parent = <&gic>;
+		#interrupt-cells = <2>;
+	};
+
+	ethsys: syscon@15000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "mediatek,mt7988-ethsys",
+			     "syscon";
+		reg = <0 0x15000000 0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+
+		ethsysrst: reset-controller {
+			compatible = "ti,syscon-reset";
+			#reset-cells = <1>;
+			ti,reset-bits =
+				<0x34 4 0x34 4 0x34 4
+				 (ASSERT_SET | DEASSERT_CLEAR | STATUS_SET)>;
+		};
+	};
+
+	ethwarp: syscon@15031000 {
+		compatible = "mediatek,mt7988-ethwarp", "syscon";
+		reg = <0 0x15031000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	switch0: switch0@15020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "mediatek,mt7988-switch", "syscon";
+		reg = <0 0x15020000 0 0x8000>;
+	};
+
+	eth: ethernet@15100000 {
+		compatible = "mediatek,mt7988-eth";
+		reg = <0 0x15100000 0 0x80000>,
+		      <0 0x15400000 0 0x380000>;
+		interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>;
+		clock-names = "fe", "gp2", "gp1", "wocpu1", "wocpu0",
+			      "sgmii_tx250m", "sgmii_rx250m",
+			      "sgmii_cdr_ref", "sgmii_cdr_fb",
+			      "sgmii2_tx250m", "sgmii2_rx250m",
+			      "sgmii2_cdr_ref", "sgmii2_cdr_fb";
+		mediatek,ethsys = <&ethsys>;
+		mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
+		mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
+		mediatek,xfi_pextp = <&xfi_pextp0>, <&xfi_pextp1>;
+		mediatek,xfi_pll = <&xfi_pll>;
+		mediatek,infracfg = <&topmisc>;
+		mediatek,toprgu = <&watchdog>;
+		#reset-cells = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	hnat: hnat@15000000 {
+		compatible = "mediatek,mtk-hnat_v5";
+		reg = <0 0x15100000 0 0x80000>;
+		resets = <&ethsys 0>;
+		reset-names = "mtketh";
+		status = "disabled";
+	};
+
+	sgmiisys0: syscon@10060000 {
+		compatible = "mediatek,mt7988-sgmiisys",
+			     "mediatek,mt7988-sgmiisys_0",
+			     "syscon";
+		reg = <0 0x10060000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	sgmiisys1: syscon@10070000 {
+		compatible = "mediatek,mt7988-sgmiisys",
+			     "mediatek,mt7988-sgmiisys_1",
+			     "syscon";
+		reg = <0 0x10070000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	usxgmiisys0: usxgmiisys@10080000 {
+		compatible = "mediatek,mt7988-usxgmiisys",
+			     "mediatek,mt7988-usxgmiisys_0",
+			     "syscon";
+		reg = <0 0x10080000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	usxgmiisys1: usxgmiisys@10081000 {
+		compatible = "mediatek,mt7988-usxgmiisys",
+			     "mediatek,mt7988-usxgmiisys_1",
+			     "syscon";
+		reg = <0 0x10081000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	xfi_pextp0: xfi_pextp@11f20000 {
+		compatible = "mediatek,mt7988-xfi_pextp",
+			     "mediatek,mt7988-xfi_pextp_0",
+			     "syscon";
+		reg = <0 0x11f20000 0 0x10000>;
+		#clock-cells = <1>;
+	};
+
+	xfi_pextp1: xfi_pextp@11f30000 {
+		compatible = "mediatek,mt7988-xfi_pextp",
+			     "mediatek,mt7988-xfi_pextp_1",
+			     "syscon";
+		reg = <0 0x11f30000 0 0x10000>;
+		#clock-cells = <1>;
+	};
+
+	xfi_pll: xfi_pll@11f40000 {
+		compatible = "mediatek,mt7988-xfi_pll", "syscon";
+		reg = <0 0x11f40000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	topmisc: topmisc@11d10000 {
+		compatible = "mediatek,mt7988-topmisc", "syscon",
+			     "mediatek,mt7988-power-controller";
+		reg = <0 0x11d10000 0 0x10000>;
+		#clock-cells = <1>;
+		#power-domain-cells = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		/* power domain of the SoC */
+		tops0@MT7988_POWER_DOMAIN_TOPS0 {
+			reg = <MT7988_POWER_DOMAIN_TOPS0>;
+			#power-domain-cells = <0>;
+		};
+		tops1@MT7988_POWER_DOMAIN_TOPS1 {
+			reg = <MT7988_POWER_DOMAIN_TOPS1>;
+			#power-domain-cells = <0>;
+		};
+		eth2p5@MT7988_POWER_DOMAIN_ETH2P5 {
+			reg = <MT7988_POWER_DOMAIN_ETH2P5>;
+			#power-domain-cells = <0>;
+		};
+	};
+
+	snand: snfi@11001000 {
+		compatible = "mediatek,mt7986-snand";
+		reg = <0 0x11001000 0 0x1000>, <0 0x11002000 0 0x1000>;
+		reg-names = "nfi", "ecc";
+		interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>;
+		clock-names = "nfi_clk", "pad_clk", "ecc_clk", "nfi_hclk";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	wbsys: wbsys@18000000 {
+		compatible = "mediatek,wbsys";
+		reg = <0 0x18000000 0  0x1000000>;
+		linux,pci-domain = <4>;
+		interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
+		chip_id = <0x7981>;
+	};
+
+	wed_pcie: wed_pcie@10003000 {
+		compatible = "mediatek,wed_pcie";
+		reg = <0 0x10003000 0 0x10>;
+	};
+
+	spi0: spi@11007000 {
+		compatible = "mediatek,ipm-spi-quad";
+		reg = <0 0x11007000 0 0x100>;
+		interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&topckgen CK_TOP_CB_M_D2>,
+			 <&topckgen CK_TOP_SPI_SEL>,
+			 <&infracfg_ao CK_INFRA_104M_SPI0>,
+			 <&infracfg_ao CK_INFRA_66M_SPI0_HCK>;
+		clock-names = "parent-clk", "sel-clk", "spi-clk", "spi-hclk";
+		status = "disabled";
+	};
+
+	spi1: spi@11008000 {
+		compatible = "mediatek,ipm-spi-single";
+		reg = <0 0x11008000 0 0x100>;
+		interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&topckgen CK_TOP_CB_M_D2>,
+			 <&topckgen CK_TOP_SPI_SEL>,
+			 <&infracfg_ao CK_INFRA_104M_SPI1>,
+			 <&infracfg_ao CK_INFRA_66M_SPI1_HCK>;
+		clock-names = "parent-clk", "sel-clk", "spi-clk", "spi-hclk";
+		status = "disabled";
+	};
+
+	spi2: spi@11009000 {
+		compatible = "mediatek,ipm-spi-quad";
+		reg = <0 0x11009000 0 0x100>;
+		interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&topckgen CK_TOP_CB_M_D2>,
+			 <&topckgen CK_TOP_SPI_SEL>,
+			 <&infracfg_ao CK_INFRA_104M_SPI2_BCK>,
+			 <&infracfg_ao CK_INFRA_66M_SPI2_HCK>;
+		clock-names = "parent-clk", "sel-clk", "spi-clk", "spi-hclk";
+		status = "disabled";
+	};
+
+	consys: consys@10000000 {
+		compatible = "mediatek,mt7981-consys";
+		reg = <0 0x10000000 0 0x8600000>;
+		memory-region = <&wmcpu_emi>;
+	};
+
+	xhci0: xhci@11190000 {
+		compatible = "mediatek,mt7988-xhci",
+			     "mediatek,mtk-xhci";
+		reg = <0 0x11190000 0 0x2e00>,
+		      <0 0x11193e00 0 0x0100>;
+		reg-names = "mac", "ippc";
+		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&xphyu2port0 PHY_TYPE_USB2>,
+		       <&xphyu3port0 PHY_TYPE_USB3>;
+		clocks = <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>;
+		clock-names = "sys_ck",
+			      "xhci_ck",
+			      "ref_ck",
+			      "mcu_ck",
+			      "dma_ck";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		status = "okay";
+	};
+
+	usbxphy: usb-phy@11e10000 {
+		compatible = "mediatek,mt7988",
+			     "mediatek,xsphy";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		status = "okay";
+
+		xphyu2port0: usb-phy@11e10000 {
+			reg = <0 0x11e10000 0 0x400>;
+			clocks = <&system_clk>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			status = "okay";
+		};
+
+		xphyu3port0: usb-phy@11e13000 {
+			reg = <0 0x11e13400 0 0x500>;
+			clocks = <&system_clk>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			mediatek,syscon-type = <&topmisc 0x218 0>;
+			status = "okay";
+		};
+	};
+
+	xhci1: xhci@11200000 {
+		compatible = "mediatek,mt7988-xhci",
+			     "mediatek,mtk-xhci";
+		reg = <0 0x11200000 0 0x2e00>,
+		      <0 0x11203e00 0 0x0100>;
+		reg-names = "mac", "ippc";
+		interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&tphyu2port0 PHY_TYPE_USB2>,
+		       <&tphyu3port0 PHY_TYPE_USB3>;
+		clocks = <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>,
+			 <&system_clk>;
+		clock-names = "sys_ck",
+			      "xhci_ck",
+			      "ref_ck",
+			      "mcu_ck",
+			      "dma_ck";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		status = "okay";
+	};
+
+	usbtphy: usb-phy@11c50000 {
+		compatible = "mediatek,mt7988",
+			     "mediatek,generic-tphy-v2";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		status = "okay";
+
+		tphyu2port0: usb-phy@11c50000 {
+			reg = <0 0x11c50000 0 0x700>;
+			clocks = <&system_clk>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			status = "okay";
+		};
+
+		tphyu3port0: usb-phy@11c50700 {
+			reg = <0 0x11c50700 0 0x900>;
+			clocks = <&system_clk>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			status = "okay";
+		};
+	};
+
+	clk40m: oscillator@0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <40000000>;
+		clock-output-names = "clkxtal";
+	};
+
+	infracfg_ao: infracfg_ao@10001000 {
+		compatible = "mediatek,mt7988-infracfg_ao", "syscon";
+		reg = <0 0x10001000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	infracfg: infracfg@10209000 {
+		compatible = "mediatek,mt7988-infracfg", "syscon";
+		reg = <0 0x10209000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	topckgen: topckgen@1001B000 {
+		compatible = "mediatek,mt7988-topckgen", "syscon";
+		reg = <0 0x1001B000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	apmixedsys: apmixedsys@1001E000 {
+		compatible = "mediatek,mt7988-apmixedsys", "syscon";
+		reg = <0 0x1001E000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	mcusys: mcusys@100E0000 {
+	compatible = "mediatek,mt7988-mcusys", "syscon";
+	reg = <0 0x100E0000 0 0x1000>;
+	#clock-cells = <1>;
+	};
+
+	clkitg: clkitg {
+		compatible = "simple-bus";
+	};
+
+	efuse: efuse@11f50000 {
+		compatible = "mediatek,efuse";
+		reg = <0 0x11f50000 0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lvts_calibration: calib@918 {
+			reg = <0x918 0x28>;
+		};
+		phy_calibration_p0: calib@940 {
+			reg = <0x940 0x10>;
+		};
+		phy_calibration_p1: calib@954 {
+			reg = <0x954 0x10>;
+		};
+		phy_calibration_p2: calib@968 {
+			reg = <0x968 0x10>;
+		};
+		phy_calibration_p3: calib@97c {
+			reg = <0x97c 0x10>;
+		};
+		cpufreq_calibration: calib@278 {
+			reg = <0x278 0x1>;
+		};
+	};
+};
+
+#include "mt7988-clkitg.dtsi"
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
new file mode 100644
index 0000000..21eab01
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988A DSA 10G eMMC RFB";
+	compatible = "mediatek,mt7988a-dsa-10g-emmc",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    root=PARTLABEL=rootfs rootwait \
+			    rootfstype=squashfs,f2fs pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+
+	mmc0_pins_default: mmc0-pins-default {
+		mux {
+			function = "flash";
+			groups = "emmc_51";
+		};
+	};
+
+	mmc0_pins_uhs: mmc0-pins-uhs {
+		mux {
+			function = "flash";
+			groups = "emmc_51";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc0_pins_default>;
+	pinctrl-1 = <&mmc0_pins_uhs>;
+	bus-width = <8>;
+	max-frequency = <200000000>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+	hs400-ds-delay = <0x12814>;
+	vqmmc-supply = <&reg_1p8v>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	status = "okay";
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
new file mode 100644
index 0000000..bc2d427
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988A DSA 10G SD RFB";
+	compatible = "mediatek,mt7988a-dsa-10g-sd",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    root=PARTLABEL=rootfs rootwait \
+			    rootfstype=squashfs,f2fs pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+
+	mmc0_pins_default: mmc0-pins-default {
+		mux {
+			function = "flash";
+			groups = "emmc_45";
+		};
+	};
+
+	mmc0_pins_uhs: mmc0-pins-uhs {
+		mux {
+			function = "flash";
+			groups = "emmc_45";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc0_pins_default>;
+	pinctrl-1 = <&mmc0_pins_uhs>;
+	bus-width = <4>;
+	max-frequency = <52000000>;
+	cap-sd-highspeed;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_3p3v>;
+	no-mmc;
+	no-sdio;
+	status = "okay";
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
new file mode 100644
index 0000000..15d38ec
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988A DSA 10G SNFI-NAND RFB";
+	compatible = "mediatek,mt7988a-dsa-10g-snfi-snand",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_snfi {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&snand>;
+		forced-create;
+		empty-page-ecc-protected;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x4000000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	snfi_pins: snfi-pins {
+		mux {
+			function = "flash";
+			groups = "snfi";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&snand {
+	pinctrl-names = "default";
+	/* pin shared with spic */
+	pinctrl-0 = <&snfi_pins>;
+	status = "okay";
+	mediatek,quad-spi;
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
new file mode 100644
index 0000000..6a289ff
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988A DSA 10G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988a-dsa-10g-spim-snand",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x4000000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-buswidth = <4>;
+		spi-rx-buswidth = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
new file mode 100644
index 0000000..4edf1f0
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988A DSA 10G SPIM-NOR RFB";
+	compatible = "mediatek,mt7988a-dsa-10g-spim-nor",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&spi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi2_flash_pins>;
+	status = "okay";
+	spi_nor@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <
+			0x53 0x46 0x5F 0x42 0x4F 0x4F 0x54>; /* SF_BOOT */
+		spi-cal-addrlen = <1>;
+		spi-cal-addr = /bits/ 32 <0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+
+		partition@00000 {
+			label = "BL2";
+			reg = <0x00000 0x0040000>;
+		};
+		partition@40000 {
+			label = "u-boot-env";
+			reg = <0x40000 0x0010000>;
+		};
+		factory: partition@50000 {
+			label = "Factory";
+			reg = <0x50000 0x00B0000>;
+		};
+		partition@100000 {
+			label = "FIP";
+			reg = <0x100000 0x0080000>;
+		};
+		partition@180000 {
+			label = "firmware";
+			reg = <0x180000 0xE00000>;
+		};
+	};
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+
+	spi2_flash_pins: spi2-pins {
+		mux {
+			function = "spi";
+			groups = "spi2", "spi2_wp_hold";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&wed {
+	dy_txbm_enable = "true";
+	dy_txbm_budge = <8>;
+	txbm_init_sz = <10>;
+	status = "okay";
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
new file mode 100644
index 0000000..ed60643
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988 DSA external-2.5G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988a-dsa-e2p5g-spim-snand",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x4000000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	rt5190a_64: rt5190a@64 {
+		compatible = "richtek,rt5190a";
+		reg = <0x64>;
+		/*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
+		vin2-supply = <&rt5190_buck1>;
+		vin3-supply = <&rt5190_buck1>;
+		vin4-supply = <&rt5190_buck1>;
+
+		regulators {
+			rt5190_buck1: buck1 {
+				regulator-name = "rt5190a-buck1";
+				regulator-min-microvolt = <5090000>;
+				regulator-max-microvolt = <5090000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			buck2 {
+				regulator-name = "vcore";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck3 {
+				regulator-name = "proc";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck4 {
+				regulator-name = "rt5190a-buck4";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			ldo {
+				regulator-name = "rt5190a-ldo";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-buswidth = <4>;
+		spi-rx-buswidth = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	i2c1_pins: i2c1-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c1_0";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "2500base-x";
+		phy-handle = <&phy13>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "2500base-x";
+		phy-handle = <&phy5>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		phy5: phy@5 {
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reg = <5>;
+			reset-gpios = <&pio 0 1>;
+			reset-assert-us = <600>;
+			reset-deassert-us = <20000>;
+		};
+
+		phy13: phy@13 {
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reg = <13>;
+			reset-gpios = <&pio 1 1>;
+			reset-assert-us = <600>;
+			reset-deassert-us = <20000>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
new file mode 100644
index 0000000..d07634b
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988 DSA internal-2.5G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988a-dsa-i2p5g-spim-snand",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x4000000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-buswidth = <4>;
+		spi-rx-buswidth = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&usxgmiisys1 {
+	internal_2500;
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <15>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			phy-mode = "10gbase-kr";
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
new file mode 100644
index 0000000..4335fcf
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988 GSW 10G SFP SPIM-NAND RFB";
+	compatible = "mediatek,mt7988a-gsw-10g-sfp-spim-snand",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000";
+	};
+
+	gsw: gsw@0 {
+		compatible = "mediatek,mt753x";
+		mediatek,sysctrl = <&ethwarp>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x4000000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+
+	sfp_esp0: sfp@0 {
+		compatible = "sff,sfp";
+		i2c-bus = <&i2c2>;
+		tx-disable-gpios = <&pio 29 0>;
+	};
+
+	sfp_esp1: sfp@1 {
+		compatible = "sff,sfp";
+		i2c-bus = <&i2c1>;
+		tx-disable-gpios = <&pio 36 0>;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	rt5190a_64: rt5190a@64 {
+		compatible = "richtek,rt5190a";
+		reg = <0x64>;
+		/*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
+		vin2-supply = <&rt5190_buck1>;
+		vin3-supply = <&rt5190_buck1>;
+		vin4-supply = <&rt5190_buck1>;
+
+		regulators {
+			rt5190_buck1: buck1 {
+				regulator-name = "rt5190a-buck1";
+				regulator-min-microvolt = <5090000>;
+				regulator-max-microvolt = <5090000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			buck2 {
+				regulator-name = "vcore";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck3 {
+				regulator-name = "proc";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck4 {
+				regulator-name = "rt5190a-buck4";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			ldo {
+				regulator-name = "rt5190a-ldo";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-buswidth = <4>;
+		spi-rx-buswidth = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	i2c1_pins: i2c1-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c1_sfp";
+		};
+	};
+
+	i2c2_pins: i2c2-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c2_0";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		managed = "in-band-status";
+		sfp = <&sfp_esp1>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		managed = "in-band-status";
+		sfp = <&sfp_esp0>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "eth0";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&gsw {
+	mediatek,mdio = <&mdio>;
+	mediatek,portmap = "llllw";
+	mediatek,mdio_master_pinmux = <1>;
+	interrupt-parent = <&gic>;
+	interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+
+	port6: port@6 {
+		compatible = "mediatek,mt753x-port";
+		mediatek,ssc-on;
+		phy-mode = "10gbase-kr";
+		reg = <6>;
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+		};
+	};
+
+	mdio1: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gsw_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <0>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p0>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy1: ethernet-phy@1 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <1>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p1>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy2: ethernet-phy@2 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <2>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p2>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy3: ethernet-phy@3 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <3>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p3>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+	};
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
new file mode 100644
index 0000000..86221c2
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988 GSW 10G SPIM-NAND 4PCIe RFB";
+	compatible = "mediatek,mt7988a-gsw-10g-spim-snand-4pcie",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	gsw: gsw@0 {
+		compatible = "mediatek,mt753x";
+		mediatek,sysctrl = <&ethwarp>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x4000000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	rt5190a_64: rt5190a@64 {
+		compatible = "richtek,rt5190a";
+		reg = <0x64>;
+		/*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
+		vin2-supply = <&rt5190_buck1>;
+		vin3-supply = <&rt5190_buck1>;
+		vin4-supply = <&rt5190_buck1>;
+
+		regulators {
+			rt5190_buck1: buck1 {
+				regulator-name = "rt5190a-buck1";
+				regulator-min-microvolt = <5090000>;
+				regulator-max-microvolt = <5090000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			buck2 {
+				regulator-name = "vcore";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck3 {
+				regulator-name = "proc";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck4 {
+				regulator-name = "rt5190a-buck4";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			ldo {
+				regulator-name = "rt5190a-ldo";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-buswidth = <4>;
+		spi-rx-buswidth = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "okay";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	i2c1_pins: i2c1-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c1_0";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&xhci0 {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "eth0";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&gsw {
+	mediatek,mdio = <&mdio>;
+	mediatek,portmap = "llllw";
+	mediatek,mdio_master_pinmux = <1>;
+	interrupt-parent = <&gic>;
+	interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+
+	port6: port@6 {
+		compatible = "mediatek,mt753x-port";
+		mediatek,ssc-on;
+		phy-mode = "10gbase-kr";
+		reg = <6>;
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+		};
+	};
+
+	mdio1: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gsw_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <0>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p0>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy1: ethernet-phy@1 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <1>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p1>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy2: ethernet-phy@2 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <2>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p2>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy3: ethernet-phy@3 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <3>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p3>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+	};
+};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
new file mode 100644
index 0000000..ef4cd4d
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988 GSW 10G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988a-gsw-10g-spim-snand",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	gsw: gsw@0 {
+		compatible = "mediatek,mt753x";
+		mediatek,sysctrl = <&ethwarp>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x4000000>;
+			};
+		};
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	rt5190a_64: rt5190a@64 {
+		compatible = "richtek,rt5190a";
+		reg = <0x64>;
+		/*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
+		vin2-supply = <&rt5190_buck1>;
+		vin3-supply = <&rt5190_buck1>;
+		vin4-supply = <&rt5190_buck1>;
+
+		regulators {
+			rt5190_buck1: buck1 {
+				regulator-name = "rt5190a-buck1";
+				regulator-min-microvolt = <5090000>;
+				regulator-max-microvolt = <5090000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			buck2 {
+				regulator-name = "vcore";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck3 {
+				regulator-name = "proc";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck4 {
+				regulator-name = "rt5190a-buck4";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			ldo {
+				regulator-name = "rt5190a-ldo";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-buswidth = <4>;
+		spi-rx-buswidth = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "okay";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	i2c1_pins: i2c1-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c1_0";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1_1";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		phy-mode = "10gbase-kr";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <1000000>;
+			reset-deassert-us = <1000000>;
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "eth0";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&gsw {
+	mediatek,mdio = <&mdio>;
+	mediatek,portmap = "llllw";
+	mediatek,mdio_master_pinmux = <1>;
+	interrupt-parent = <&gic>;
+	interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+
+	port6: port@6 {
+		compatible = "mediatek,mt753x-port";
+		mediatek,ssc-on;
+		phy-mode = "10gbase-kr";
+		reg = <6>;
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+		};
+	};
+
+	mdio1: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gsw_phy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <0>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p0>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy1: ethernet-phy@1 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <1>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p1>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy2: ethernet-phy@2 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <2>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p2>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+
+		gsw_phy3: ethernet-phy@3 {
+			compatible = "ethernet-phy-id03a2.9481";
+			reg = <3>;
+			phy-mode = "gmii";
+			rext = "efuse";
+			tx_r50 = "efuse";
+			nvmem-cells = <&phy_calibration_p3>;
+			nvmem-cell-names = "phy-cal-data";
+		};
+	};
+};
diff --git a/target/linux/mediatek/files-5.4/drivers/clk/mediatek/clk-bringup.c b/target/linux/mediatek/files-5.4/drivers/clk/mediatek/clk-bringup.c
index ad1f092..637e2c5 100644
--- a/target/linux/mediatek/files-5.4/drivers/clk/mediatek/clk-bringup.c
+++ b/target/linux/mediatek/files-5.4/drivers/clk/mediatek/clk-bringup.c
@@ -31,7 +31,7 @@
 
 static int bring_up_probe(struct platform_device *pdev)
 {
-	const int NR_CLKS = 300;
+	const int NR_CLKS = 400;
 	char clk_name_buf[16];
 	struct clk *clk;
 	int i, r;
diff --git a/target/linux/mediatek/files-5.4/drivers/clk/mediatek/clk-mt7988.c b/target/linux/mediatek/files-5.4/drivers/clk/mediatek/clk-mt7988.c
new file mode 100644
index 0000000..86111c4
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/clk/mediatek/clk-mt7988.c
@@ -0,0 +1,1195 @@
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+#include "clk-mux.h"
+
+#include <dt-bindings/clock/mt7988-clk.h>
+
+static DEFINE_SPINLOCK(mt7988_clk_lock);
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+	FACTOR(CK_TOP_CB_CKSQ_40M, "cb_cksq_40m", "clkxtal", 1, 1),
+	FACTOR(CK_TOP_CB_M_416M, "cb_m_416m", "mpll", 1, 1),
+	FACTOR(CK_TOP_CB_M_D2, "cb_m_d2", "mpll", 1, 2),
+	FACTOR(CK_TOP_M_D3_D2, "m_d3_d2", "mpll", 1, 2),
+	FACTOR(CK_TOP_CB_M_D4, "cb_m_d4", "mpll", 1, 4),
+	FACTOR(CK_TOP_CB_M_D8, "cb_m_d8", "mpll", 1, 8),
+	FACTOR(CK_TOP_M_D8_D2, "m_d8_d2", "mpll", 1, 16),
+	FACTOR(CK_TOP_CB_MM_720M, "cb_mm_720m", "mmpll", 1, 1),
+	FACTOR(CK_TOP_CB_MM_D2, "cb_mm_d2", "mmpll", 1, 2),
+	FACTOR(CK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", "mmpll", 1, 15),
+	FACTOR(CK_TOP_CB_MM_D4, "cb_mm_d4", "mmpll", 1, 4),
+	FACTOR(CK_TOP_MM_D6_D2, "mm_d6_d2", "mmpll", 1, 12),
+	FACTOR(CK_TOP_CB_MM_D8, "cb_mm_d8", "mmpll", 1, 8),
+	FACTOR(CK_TOP_CB_APLL2_196M, "cb_apll2_196m", "apll2", 1, 1),
+	FACTOR(CK_TOP_CB_APLL2_D4, "cb_apll2_d4", "apll2", 1, 4),
+	FACTOR(CK_TOP_CB_NET1_D4, "cb_net1_d4", "net1pll", 1, 4),
+	FACTOR(CK_TOP_CB_NET1_D5, "cb_net1_d5", "net1pll", 1, 5),
+	FACTOR(CK_TOP_NET1_D5_D2, "net1_d5_d2", "net1pll", 1, 10),
+	FACTOR(CK_TOP_NET1_D5_D4, "net1_d5_d4", "net1pll", 1, 20),
+	FACTOR(CK_TOP_CB_NET1_D8, "cb_net1_d8", "net1pll", 1, 8),
+	FACTOR(CK_TOP_NET1_D8_D2, "net1_d8_d2", "net1pll", 1, 16),
+	FACTOR(CK_TOP_NET1_D8_D4, "net1_d8_d4", "net1pll", 1, 32),
+	FACTOR(CK_TOP_NET1_D8_D8, "net1_d8_d8", "net1pll", 1, 64),
+	FACTOR(CK_TOP_NET1_D8_D16, "net1_d8_d16", "net1pll", 1, 128),
+	FACTOR(CK_TOP_CB_NET2_800M, "cb_net2_800m", "net2pll", 1, 1),
+	FACTOR(CK_TOP_CB_NET2_D2, "cb_net2_d2", "net2pll", 1, 2),
+	FACTOR(CK_TOP_CB_NET2_D4, "cb_net2_d4", "net2pll", 1, 4),
+	FACTOR(CK_TOP_NET2_D4_D4, "net2_d4_d4", "net2pll", 1, 16),
+	FACTOR(CK_TOP_NET2_D4_D8, "net2_d4_d8", "net2pll", 1, 32),
+	FACTOR(CK_TOP_CB_NET2_D6, "cb_net2_d6", "net2pll", 1, 6),
+	FACTOR(CK_TOP_CB_NET2_D8, "cb_net2_d8", "net2pll", 1, 8),
+	FACTOR(CK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m", "wedmcupll", 1, 1),
+	FACTOR(CK_TOP_CB_SGM_325M, "cb_sgm_325m", "sgmpll", 1, 1),
+	FACTOR(CK_TOP_CB_NETSYS_850M, "cb_netsys_850m", "netsyspll", 1, 1),
+	FACTOR(CK_TOP_CB_MSDC_400M, "cb_msdc_400m", "msdcpll", 1, 1),
+	FACTOR(CK_TOP_CKSQ_40M_D2, "cksq_40m_d2", "cb_cksq_40m", 1, 2),
+	FACTOR(CK_TOP_CB_RTC_32K, "cb_rtc_32k", "cb_cksq_40m", 1, 1250),
+	FACTOR(CK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", "cb_cksq_40m", 1, 1220),
+	FACTOR(CK_TOP_INFRA_F32K, "csw_infra_f32k", "cb_rtc_32p7k", 1, 1),
+	FACTOR(CK_TOP_CKSQ_SRC, "cksq_src", "clkxtal", 1, 1),
+	FACTOR(CK_TOP_NETSYS_2X, "netsys_2x", "netsys_2x_sel", 1, 1),
+	FACTOR(CK_TOP_NETSYS_GSW, "netsys_gsw", "netsys_gsw_sel", 1, 1),
+	FACTOR(CK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", "netsys_mcu_sel", 1, 1),
+	FACTOR(CK_TOP_EIP197, "eip197", "eip197_sel", 1, 1),
+	FACTOR(CK_TOP_EMMC_250M, "emmc_250m", "emmc_250m_sel", 1, 1),
+	FACTOR(CK_TOP_EMMC_400M, "emmc_400m", "emmc_400m_sel", 1, 1),
+	FACTOR(CK_TOP_SPI, "spi", "spi_sel", 1, 1),
+	FACTOR(CK_TOP_SPIM_MST, "spim_mst", "spim_mst_sel", 1, 1),
+	FACTOR(CK_TOP_NFI1X, "nfi1x", "nfi1x_sel", 1, 1),
+	FACTOR(CK_TOP_SPINFI_BCK, "spinfi_bck", "spinfi_sel", 1, 1),
+	FACTOR(CK_TOP_I2C_BCK, "i2c_bck", "i2c_sel", 1, 1),
+	FACTOR(CK_TOP_USB_SYS, "usb_sys", "usb_sys_sel", 1, 1),
+	FACTOR(CK_TOP_USB_SYS_P1, "usb_sys_p1", "usb_sys_p1_sel", 1, 1),
+	FACTOR(CK_TOP_USB_XHCI, "usb_xhci", "usb_xhci_sel", 1, 1),
+	FACTOR(CK_TOP_USB_XHCI_P1, "usb_xhci_p1", "usb_xhci_p1_sel", 1, 1),
+	FACTOR(CK_TOP_USB_FRMCNT, "usb_frmcnt", "usb_frmcnt_sel", 1, 1),
+	FACTOR(CK_TOP_USB_FRMCNT_P1, "usb_frmcnt_p1", "usb_frmcnt_p1_sel", 1,
+	       1),
+	FACTOR(CK_TOP_AUD, "aud", "aud_sel", 1, 1),
+	FACTOR(CK_TOP_A1SYS, "a1sys", "a1sys_sel", 1, 1),
+	FACTOR(CK_TOP_AUD_L, "aud_l", "aud_l_sel", 1, 1),
+	FACTOR(CK_TOP_A_TUNER, "a_tuner", "a_tuner_sel", 1, 1),
+	FACTOR(CK_TOP_SYSAXI, "sysaxi", "sysaxi_sel", 1, 1),
+	FACTOR(CK_TOP_INFRA_F26M, "csw_infra_f26m", "csw_infra_f26m_sel", 1, 1),
+	FACTOR(CK_TOP_USB_REF, "usb_ref", "cksq_src", 1, 1),
+	FACTOR(CK_TOP_USB_CK_P1, "usb_ck_p1", "cksq_src", 1, 1),
+};
+
+static const struct mtk_fixed_factor infra_divs[] __initconst = {
+	FACTOR(CK_INFRA_CK_F26M, "infra_ck_f26m", "csw_infra_f26m_sel", 1, 1),
+	FACTOR(CK_INFRA_PWM_O, "infra_pwm_o", "pwm_sel", 1, 1),
+	FACTOR(CK_INFRA_PCIE_OCC_P0, "infra_pcie_ck_occ_p0", "pextp_tl_ck_sel",
+	       1, 1),
+	FACTOR(CK_INFRA_PCIE_OCC_P1, "infra_pcie_ck_occ_p1",
+	       "pextp_tl_ck_p1_sel", 1, 1),
+	FACTOR(CK_INFRA_PCIE_OCC_P2, "infra_pcie_ck_occ_p2",
+	       "pextp_tl_ck_p2_sel", 1, 1),
+	FACTOR(CK_INFRA_PCIE_OCC_P3, "infra_pcie_ck_occ_p3",
+	       "pextp_tl_ck_p3_sel", 1, 1),
+	FACTOR(CK_INFRA_133M_HCK, "infra_133m_hck", "sysaxi", 1, 1),
+	FACTOR(CK_INFRA_133M_PHCK, "infra_133m_phck", "infra_133m_hck", 1, 1),
+	FACTOR(CK_INFRA_66M_PHCK, "infra_66m_phck", "infra_133m_hck", 1, 1),
+	FACTOR(CK_INFRA_FAUD_L_O, "infra_faud_l_o", "aud_l", 1, 1),
+	FACTOR(CK_INFRA_FAUD_AUD_O, "infra_faud_aud_o", "a1sys", 1, 1),
+	FACTOR(CK_INFRA_FAUD_EG2_O, "infra_faud_eg2_o", "a_tuner", 1, 1),
+	FACTOR(CK_INFRA_I2C_O, "infra_i2c_o", "i2c_bck", 1, 1),
+	FACTOR(CK_INFRA_UART_O0, "infra_uart_o0", "uart_sel", 1, 1),
+	FACTOR(CK_INFRA_UART_O1, "infra_uart_o1", "uart_sel", 1, 1),
+	FACTOR(CK_INFRA_UART_O2, "infra_uart_o2", "uart_sel", 1, 1),
+	FACTOR(CK_INFRA_NFI_O, "infra_nfi_o", "nfi1x", 1, 1),
+	FACTOR(CK_INFRA_SPINFI_O, "infra_spinfi_o", "spinfi_bck", 1, 1),
+	FACTOR(CK_INFRA_SPI0_O, "infra_spi0_o", "spi", 1, 1),
+	FACTOR(CK_INFRA_SPI1_O, "infra_spi1_o", "spim_mst", 1, 1),
+	FACTOR(CK_INFRA_LB_MUX_FRTC, "infra_lb_mux_frtc", "infra_frtc", 1, 1),
+	FACTOR(CK_INFRA_FRTC, "infra_frtc", "cb_rtc_32k", 1, 1),
+	FACTOR(CK_INFRA_FMSDC400_O, "infra_fmsdc400_o", "emmc_400m", 1, 1),
+	FACTOR(CK_INFRA_FMSDC2_HCK_OCC, "infra_fmsdc2_hck_occ", "emmc_250m", 1,
+	       1),
+	FACTOR(CK_INFRA_PERI_133M, "infra_peri_133m", "sysaxi", 1, 1),
+	FACTOR(CK_INFRA_USB_O, "infra_usb_o", "usb_ref", 1, 1),
+	FACTOR(CK_INFRA_USB_O_P1, "infra_usb_o_p1", "usb_ck_p1", 1, 1),
+	FACTOR(CK_INFRA_USB_FRMCNT_O, "infra_usb_frmcnt_o", "usb_frmcnt", 1, 1),
+	FACTOR(CK_INFRA_USB_FRMCNT_O_P1, "infra_usb_frmcnt_o_p1",
+	       "usb_frmcnt_p1", 1, 1),
+	FACTOR(CK_INFRA_USB_XHCI_O, "infra_usb_xhci_o", "usb_xhci", 1, 1),
+	FACTOR(CK_INFRA_USB_XHCI_O_P1, "infra_usb_xhci_o_p1", "usb_xhci_p1", 1,
+	       1),
+	FACTOR(CK_INFRA_USB_PIPE_O, "infra_usb_pipe_o", "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_USB_PIPE_O_P1, "infra_usb_pipe_o_p1", "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_USB_UTMI_O, "infra_usb_utmi_o", "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_USB_UTMI_O_P1, "infra_usb_utmi_o_p1", "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_PCIE_PIPE_OCC_P0, "infra_pcie_pipe_ck_occ_p0",
+	       "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_PCIE_PIPE_OCC_P1, "infra_pcie_pipe_ck_occ_p1",
+	       "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_PCIE_PIPE_OCC_P2, "infra_pcie_pipe_ck_occ_p2",
+	       "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_PCIE_PIPE_OCC_P3, "infra_pcie_pipe_ck_occ_p3",
+	       "clkxtal", 1, 1),
+	FACTOR(CK_INFRA_F26M_O0, "infra_f26m_o0", "csw_infra_f26m", 1, 1),
+	FACTOR(CK_INFRA_F26M_O1, "infra_f26m_o1", "csw_infra_f26m", 1, 1),
+	FACTOR(CK_INFRA_133M_MCK, "infra_133m_mck", "sysaxi", 1, 1),
+	FACTOR(CK_INFRA_66M_MCK, "infra_66m_mck", "sysaxi", 1, 1),
+	FACTOR(CK_INFRA_PERI_66M_O, "infra_peri_66m_o", "sysaxi", 1, 1),
+	FACTOR(CK_INFRA_USB_SYS_O, "infra_usb_sys_o", "usb_sys", 1, 1),
+	FACTOR(CK_INFRA_USB_SYS_O_P1, "infra_usb_sys_o_p1", "usb_sys_p1", 1, 1),
+};
+
+static const char *const mcu_bus_div_parents[] = { "cb_cksq_40m", "ccipll2_b",
+						   "cb_net1_d4" };
+
+static const char *const mcu_arm_div_parents[] = { "cb_cksq_40m", "arm_b",
+						   "cb_net1_d4" };
+
+static struct mtk_composite mcu_muxes[] = {
+	/* bus_pll_divider_cfg */
+	MUX_GATE_FLAGS(CK_MCU_BUS_DIV_SEL, "mcu_bus_div_sel",
+		       mcu_bus_div_parents, 0x7C0, 9, 2, -1, CLK_IS_CRITICAL),
+	/* mp2_pll_divider_cfg */
+	MUX_GATE_FLAGS(CK_MCU_ARM_DIV_SEL, "mcu_arm_div_sel",
+		       mcu_arm_div_parents, 0x7A8, 9, 2, -1, CLK_IS_CRITICAL),
+};
+
+static const char *const netsys_parents[] = { "cb_cksq_40m", "cb_net2_d2",
+					      "cb_mm_d2" };
+
+static const char *const netsys_500m_parents[] = { "cb_cksq_40m", "cb_net1_d5",
+						   "net1_d5_d2" };
+
+static const char *const netsys_2x_parents[] = { "cb_cksq_40m", "cb_net2_800m",
+						 "cb_mm_720m" };
+
+static const char *const netsys_gsw_parents[] = { "cb_cksq_40m", "cb_net1_d4",
+						  "cb_net1_d5" };
+
+static const char *const eth_gmii_parents[] = { "cb_cksq_40m", "net1_d5_d4" };
+
+static const char *const netsys_mcu_parents[] = { "cb_cksq_40m", "cb_net2_800m",
+						  "cb_mm_720m",	 "cb_net1_d4",
+						  "cb_net1_d5",	 "cb_m_416m" };
+
+static const char *const eip197_parents[] = { "cb_cksq_40m",  "cb_netsys_850m",
+					      "cb_net2_800m", "cb_mm_720m",
+					      "cb_net1_d4",   "cb_net1_d5" };
+
+static const char *const axi_infra_parents[] = { "cb_cksq_40m", "net1_d8_d2" };
+
+static const char *const uart_parents[] = { "cb_cksq_40m", "cb_m_d8",
+					    "m_d8_d2" };
+
+static const char *const emmc_250m_parents[] = { "cb_cksq_40m", "net1_d5_d2",
+						 "cb_mm_d4" };
+
+static const char *const emmc_400m_parents[] = { "cb_cksq_40m", "cb_msdc_400m",
+						 "cb_mm_d2",	"cb_m_d2",
+						 "cb_mm_d4",	"net1_d8_d2" };
+
+static const char *const spi_parents[] = { "cb_cksq_40m", "cb_m_d2",
+					   "cb_mm_d4",	  "net1_d8_d2",
+					   "cb_net2_d6",  "net1_d5_d4",
+					   "cb_m_d4",	  "net1_d8_d4" };
+
+static const char *const nfi1x_parents[] = { "cb_cksq_40m", "cb_mm_d4",
+					     "net1_d8_d2",  "cb_net2_d6",
+					     "cb_m_d4",	    "cb_mm_d8",
+					     "net1_d8_d4",  "cb_m_d8" };
+
+static const char *const spinfi_parents[] = { "cksq_40m_d2", "cb_cksq_40m",
+					      "net1_d5_d4",  "cb_m_d4",
+					      "cb_mm_d8",    "net1_d8_d4",
+					      "mm_d6_d2",    "cb_m_d8" };
+
+static const char *const pwm_parents[] = { "cb_cksq_40m", "net1_d8_d2",
+					   "net1_d5_d4",  "cb_m_d4",
+					   "m_d8_d2",	  "cb_rtc_32k" };
+
+static const char *const i2c_parents[] = { "cb_cksq_40m", "net1_d5_d4",
+					   "cb_m_d4", "net1_d8_d4" };
+
+static const char *const pcie_mbist_250m_parents[] = { "cb_cksq_40m",
+						       "net1_d5_d2" };
+
+static const char *const pextp_tl_ck_parents[] = { "cb_cksq_40m", "cb_net2_d6",
+						   "cb_mm_d8", "m_d8_d2",
+						   "cb_rtc_32k" };
+
+static const char *const usb_frmcnt_parents[] = { "cb_cksq_40m",
+						  "cb_mm_d3_d5" };
+
+static const char *const aud_parents[] = { "cb_cksq_40m", "cb_apll2_196m" };
+
+static const char *const a1sys_parents[] = { "cb_cksq_40m", "cb_apll2_d4" };
+
+static const char *const aud_l_parents[] = { "cb_cksq_40m", "cb_apll2_196m",
+					     "m_d8_d2" };
+
+static const char *const sspxtp_parents[] = { "cksq_40m_d2", "m_d8_d2" };
+
+static const char *const usxgmii_sbus_0_parents[] = { "cb_cksq_40m",
+						      "net1_d8_d4" };
+
+static const char *const sgm_0_parents[] = { "cb_cksq_40m", "cb_sgm_325m" };
+
+static const char *const sysapb_parents[] = { "cb_cksq_40m", "m_d3_d2" };
+
+static const char *const eth_refck_50m_parents[] = { "cb_cksq_40m",
+						     "net2_d4_d4" };
+
+static const char *const eth_sys_200m_parents[] = { "cb_cksq_40m",
+						    "cb_net2_d4" };
+
+static const char *const eth_xgmii_parents[] = { "cksq_40m_d2", "net1_d8_d8",
+						 "net1_d8_d16" };
+
+static const char *const bus_tops_parents[] = { "cb_cksq_40m", "cb_net1_d5",
+						"cb_net2_d2" };
+
+static const char *const npu_tops_parents[] = { "cb_cksq_40m", "cb_net2_800m" };
+
+static const char *const dramc_md32_parents[] = { "cb_cksq_40m", "cb_m_d2",
+						  "cb_wedmcu_208m" };
+
+static const char *const da_xtp_glb_p0_parents[] = { "cb_cksq_40m",
+						     "cb_net2_d8" };
+
+static const char *const mcusys_backup_625m_parents[] = { "cb_cksq_40m",
+							  "cb_net1_d4" };
+
+static const char *const macsec_parents[] = { "cb_cksq_40m", "cb_sgm_325m",
+					      "cb_net1_d8" };
+
+static const char *const netsys_tops_400m_parents[] = { "cb_cksq_40m",
+							"cb_net2_d2" };
+
+static const char *const eth_mii_parents[] = { "cksq_40m_d2", "net2_d4_d8" };
+
+static struct mtk_mux top_muxes[] = {
+	/* CLK_CFG_0 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents,
+			     0x000, 0x004, 0x008, 0, 2, 7, 0x1C0, 0),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_500M_SEL, "netsys_500m_sel",
+			     netsys_500m_parents, 0x000, 0x004, 0x008, 8, 2, 15,
+			     0x1C0, 1),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_2X_SEL, "netsys_2x_sel",
+			     netsys_2x_parents, 0x000, 0x004, 0x008, 16, 2, 23,
+			     0x1C0, 2),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_GSW_SEL, "netsys_gsw_sel",
+			     netsys_gsw_parents, 0x000, 0x004, 0x008, 24, 2, 31,
+			     0x1C0, 3),
+	/* CLK_CFG_1 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_GMII_SEL, "eth_gmii_sel",
+			     eth_gmii_parents, 0x010, 0x014, 0x018, 0, 1, 7,
+			     0x1C0, 4),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel",
+			     netsys_mcu_parents, 0x010, 0x014, 0x018, 8, 3, 15,
+			     0x1C0, 5),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_PAO_2X_SEL, "netsys_pao_2x_sel",
+			     netsys_mcu_parents, 0x010, 0x014, 0x018, 16, 3, 23,
+			     0x1C0, 6),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_EIP197_SEL, "eip197_sel", eip197_parents,
+			     0x010, 0x014, 0x018, 24, 3, 31, 0x1C0, 7),
+	/* CLK_CFG_2 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_AXI_INFRA_SEL, "axi_infra_sel",
+			     axi_infra_parents, 0x020, 0x024, 0x028, 0, 1, 7,
+			     0x1C0, 8),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_UART_SEL, "uart_sel", uart_parents, 0x020,
+			     0x024, 0x028, 8, 2, 15, 0x1C0, 9),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_EMMC_250M_SEL, "emmc_250m_sel",
+			     emmc_250m_parents, 0x020, 0x024, 0x028, 16, 2, 23,
+			     0x1C0, 10),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_EMMC_400M_SEL, "emmc_400m_sel",
+			     emmc_400m_parents, 0x020, 0x024, 0x028, 24, 3, 31,
+			     0x1C0, 11),
+	/* CLK_CFG_3 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x030,
+			     0x034, 0x038, 0, 3, 7, 0x1C0, 12),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents,
+			     0x030, 0x034, 0x038, 8, 3, 15, 0x1C0, 13),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents,
+			     0x030, 0x034, 0x038, 16, 3, 23, 0x1C0, 14),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents,
+			     0x030, 0x034, 0x038, 24, 3, 31, 0x1C0, 15),
+	/* CLK_CFG_4 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x040,
+			     0x044, 0x048, 0, 3, 7, 0x1C0, 16),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x040,
+			     0x044, 0x048, 8, 2, 15, 0x1C0, 17),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PCIE_MBIST_250M_SEL, "pcie_mbist_250m_sel",
+			     pcie_mbist_250m_parents, 0x040, 0x044, 0x048, 16,
+			     1, 23, 0x1C0, 18),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel",
+			     pextp_tl_ck_parents, 0x040, 0x044, 0x048, 24, 3,
+			     31, 0x1C0, 19),
+	/* CLK_CFG_5 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_TL_P1_SEL, "pextp_tl_ck_p1_sel",
+			     pextp_tl_ck_parents, 0x050, 0x054, 0x058, 0, 3, 7,
+			     0x1C0, 20),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_TL_P2_SEL, "pextp_tl_ck_p2_sel",
+			     pextp_tl_ck_parents, 0x050, 0x054, 0x058, 8, 3, 15,
+			     0x1C0, 21),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_TL_P3_SEL, "pextp_tl_ck_p3_sel",
+			     pextp_tl_ck_parents, 0x050, 0x054, 0x058, 16, 3,
+			     23, 0x1C0, 22),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USB_SYS_SEL, "usb_sys_sel",
+			     eth_gmii_parents, 0x050, 0x054, 0x058, 24, 1, 31,
+			     0x1C0, 23),
+	/* CLK_CFG_6 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USB_SYS_P1_SEL, "usb_sys_p1_sel",
+			     eth_gmii_parents, 0x060, 0x064, 0x068, 0, 1, 7,
+			     0x1C0, 24),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USB_XHCI_SEL, "usb_xhci_sel",
+			     eth_gmii_parents, 0x060, 0x064, 0x068, 8, 1, 15,
+			     0x1C0, 25),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USB_XHCI_P1_SEL, "usb_xhci_p1_sel",
+			     eth_gmii_parents, 0x060, 0x064, 0x068, 16, 1, 23,
+			     0x1C0, 26),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel",
+			     usb_frmcnt_parents, 0x060, 0x064, 0x068, 24, 1, 31,
+			     0x1C0, 27),
+	/* CLK_CFG_7 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USB_FRMCNT_P1_SEL, "usb_frmcnt_p1_sel",
+			     usb_frmcnt_parents, 0x070, 0x074, 0x078, 0, 1, 7,
+			     0x1C0, 28),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x070,
+			     0x074, 0x078, 8, 1, 15, 0x1C0, 29),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents,
+			     0x070, 0x074, 0x078, 16, 1, 23, 0x1C0, 30),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents,
+			     0x070, 0x074, 0x078, 24, 2, 31, 0x1C4, 0),
+	/* CLK_CFG_8 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_A_TUNER_SEL, "a_tuner_sel", a1sys_parents,
+			     0x080, 0x084, 0x088, 0, 1, 7, 0x1C4, 1),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SSPXTP_SEL, "sspxtp_sel", sspxtp_parents,
+			     0x080, 0x084, 0x088, 8, 1, 15, 0x1C4, 2),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USB_PHY_SEL, "usb_phy_sel", sspxtp_parents,
+			     0x080, 0x084, 0x088, 16, 1, 23, 0x1C4, 3),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USXGMII_SBUS_0_SEL, "usxgmii_sbus_0_sel",
+			     usxgmii_sbus_0_parents, 0x080, 0x084, 0x088, 24, 1,
+			     31, 0x1C4, 4),
+	/* CLK_CFG_9 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_USXGMII_SBUS_1_SEL, "usxgmii_sbus_1_sel",
+			     usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, 0, 1,
+			     7, 0x1C4, 5),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SGM_0_SEL, "sgm_0_sel", sgm_0_parents,
+			     0x090, 0x094, 0x098, 8, 1, 15, 0x1C4, 6),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SGM_SBUS_0_SEL, "sgm_sbus_0_sel",
+			     usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, 16, 1,
+			     23, 0x1C4, 7),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SGM_1_SEL, "sgm_1_sel", sgm_0_parents,
+			     0x090, 0x094, 0x098, 24, 1, 31, 0x1C4, 8),
+	/* CLK_CFG_10 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SGM_SBUS_1_SEL, "sgm_sbus_1_sel",
+			     usxgmii_sbus_0_parents, 0x0A0, 0x0A4, 0x0A8, 0, 1,
+			     7, 0x1C4, 9),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_XFI_PHY_0_XTAL_SEL, "xfi_phy_0_xtal_sel",
+			     sspxtp_parents, 0x0A0, 0x0A4, 0x0A8, 8, 1, 15,
+			     0x1C4, 10),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_XFI_PHY_1_XTAL_SEL, "xfi_phy_1_xtal_sel",
+			     sspxtp_parents, 0x0A0, 0x0A4, 0x0A8, 16, 1, 23,
+			     0x1C4, 11),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SYSAXI_SEL, "sysaxi_sel", axi_infra_parents,
+			     0x0A0, 0x0A4, 0x0A8, 24, 1, 31, 0x1C4, 12),
+	/* CLK_CFG_11 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents,
+			     0x0B0, 0x0B4, 0x0B8, 0, 1, 7, 0x1C4, 13),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_REFCK_50M_SEL, "eth_refck_50m_sel",
+			     eth_refck_50m_parents, 0x0B0, 0x0B4, 0x0B8, 8, 1,
+			     15, 0x1C4, 14),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_SYS_200M_SEL, "eth_sys_200m_sel",
+			     eth_sys_200m_parents, 0x0B0, 0x0B4, 0x0B8, 16, 1,
+			     23, 0x1C4, 15),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_SYS_SEL, "eth_sys_sel",
+			     pcie_mbist_250m_parents, 0x0B0, 0x0B4, 0x0B8, 24,
+			     1, 31, 0x1C4, 16),
+	/* CLK_CFG_12 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_XGMII_SEL, "eth_xgmii_sel",
+			     eth_xgmii_parents, 0x0C0, 0x0C4, 0x0C8, 0, 2, 7,
+			     0x1C4, 17),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_BUS_TOPS_SEL, "bus_tops_sel",
+			     bus_tops_parents, 0x0C0, 0x0C4, 0x0C8, 8, 2, 15,
+			     0x1C4, 18),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NPU_TOPS_SEL, "npu_tops_sel",
+			     npu_tops_parents, 0x0C0, 0x0C4, 0x0C8, 16, 1, 23,
+			     0x1C4, 19),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_DRAMC_SEL, "dramc_sel", sspxtp_parents,
+			     0x0C0, 0x0C4, 0x0C8, 24, 1, 31, 0x1C4, 20),
+	/* CLK_CFG_13 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel",
+			     dramc_md32_parents, 0x0D0, 0x0D4, 0x0D8, 0, 2, 7,
+			     0x1C4, 21),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_INFRA_F26M_SEL, "csw_infra_f26m_sel",
+			     sspxtp_parents, 0x0D0, 0x0D4, 0x0D8, 8, 1, 15,
+			     0x1C4, 22),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_P0_SEL, "pextp_p0_sel",
+			     sspxtp_parents, 0x0D0, 0x0D4, 0x0D8, 16, 1, 23,
+			     0x1C4, 23),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_P1_SEL, "pextp_p1_sel",
+			     sspxtp_parents, 0x0D0, 0x0D4, 0x0D8, 24, 1, 31,
+			     0x1C4, 24),
+	/* CLK_CFG_14 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_P2_SEL, "pextp_p2_sel",
+			     sspxtp_parents, 0x0E0, 0x0E4, 0x0E8, 0, 1, 7,
+			     0x1C4, 25),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_P3_SEL, "pextp_p3_sel",
+			     sspxtp_parents, 0x0E0, 0x0E4, 0x0E8, 8, 1, 15,
+			     0x1C4, 26),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_DA_XTP_GLB_P0_SEL, "da_xtp_glb_p0_sel",
+			     da_xtp_glb_p0_parents, 0x0E0, 0x0E4, 0x0E8, 16, 1,
+			     23, 0x1C4, 27),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_DA_XTP_GLB_P1_SEL, "da_xtp_glb_p1_sel",
+			     da_xtp_glb_p0_parents, 0x0E0, 0x0E4, 0x0E8, 24, 1,
+			     31, 0x1C4, 28),
+	/* CLK_CFG_15 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_DA_XTP_GLB_P2_SEL, "da_xtp_glb_p2_sel",
+			     da_xtp_glb_p0_parents, 0x0F0, 0x0F4, 0x0F8, 0, 1,
+			     7, 0x1C4, 29),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_DA_XTP_GLB_P3_SEL, "da_xtp_glb_p3_sel",
+			     da_xtp_glb_p0_parents, 0x0F0, 0x0F4, 0x0F8, 8, 1,
+			     15, 0x1C4, 30),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_CKM_SEL, "ckm_sel", sspxtp_parents, 0x0F0,
+			     0x0F4, 0x0F8, 16, 1, 23, 0x1C8, 0),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_DA_SELM_XTAL_SEL, "da_selm_xtal_sel",
+			     sspxtp_parents, 0x0F0, 0x0F4, 0x0F8, 24, 1, 31,
+			     0x1C8, 1),
+	/* CLK_CFG_16 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_PEXTP_SEL, "pextp_sel", sspxtp_parents,
+			     0x0100, 0x104, 0x108, 0, 1, 7, 0x1C8, 2),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_TOPS_P2_26M_SEL, "tops_p2_26m_sel",
+			     sspxtp_parents, 0x0100, 0x104, 0x108, 8, 1, 15,
+			     0x1C8, 3),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_MCUSYS_BACKUP_625M_SEL,
+			     "mcusys_backup_625m_sel",
+			     mcusys_backup_625m_parents, 0x0100, 0x104, 0x108,
+			     16, 1, 23, 0x1C8, 4),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_SYNC_250M_SEL,
+			     "netsys_sync_250m_sel", pcie_mbist_250m_parents,
+			     0x0100, 0x104, 0x108, 24, 1, 31, 0x1C8, 5),
+	/* CLK_CFG_17 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_MACSEC_SEL, "macsec_sel", macsec_parents,
+			     0x0110, 0x114, 0x118, 0, 2, 7, 0x1C8, 6),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_TOPS_400M_SEL,
+			     "netsys_tops_400m_sel", netsys_tops_400m_parents,
+			     0x0110, 0x114, 0x118, 8, 1, 15, 0x1C8, 7),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_PPEFB_250M_SEL,
+			     "netsys_ppefb_250m_sel", pcie_mbist_250m_parents,
+			     0x0110, 0x114, 0x118, 16, 1, 23, 0x1C8, 8),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_NETSYS_WARP_SEL, "netsys_warp_sel",
+			     netsys_parents, 0x0110, 0x114, 0x118, 24, 2, 31,
+			     0x1C8, 9),
+	/* CLK_CFG_18 */
+	MUX_GATE_CLR_SET_UPD(CK_TOP_ETH_MII_SEL, "eth_mii_sel", eth_mii_parents,
+			     0x0120, 0x124, 0x128, 0, 1, 7, 0x1C8, 10),
+	MUX_GATE_CLR_SET_UPD(CK_TOP_CK_NPU_SEL_CM_TOPS_SEL,
+			     "ck_npu_sel_cm_tops_sel", netsys_2x_parents,
+			     0x0120, 0x124, 0x128, 8, 2, 15, 0x1C8, 11),
+};
+
+static const char *const infra_mux_uart0_parents[] __initconst = {
+	"infra_ck_f26m", "infra_uart_o0"
+};
+
+static const char *const infra_mux_uart1_parents[] __initconst = {
+	"infra_ck_f26m", "infra_uart_o1"
+};
+
+static const char *const infra_mux_uart2_parents[] __initconst = {
+	"infra_ck_f26m", "infra_uart_o2"
+};
+
+static const char *const infra_mux_spi0_parents[] __initconst = {
+	"infra_i2c_o", "infra_spi0_o"
+};
+
+static const char *const infra_mux_spi1_parents[] __initconst = {
+	"infra_i2c_o", "infra_spi1_o"
+};
+
+static const char *const infra_pwm_bck_parents[] __initconst = {
+	"csw_infra_f32k", "infra_ck_f26m", "infra_66m_mck", "infra_pwm_o"
+};
+
+static const char *const infra_pcie_gfmux_tl_ck_o_p0_parents[] __initconst = {
+	"csw_infra_f32k", "infra_ck_f26m", "infra_ck_f26m",
+	"infra_pcie_ck_occ_p0"
+};
+
+static const char *const infra_pcie_gfmux_tl_ck_o_p1_parents[] __initconst = {
+	"csw_infra_f32k", "infra_ck_f26m", "infra_ck_f26m",
+	"infra_pcie_ck_occ_p1"
+};
+
+static const char *const infra_pcie_gfmux_tl_ck_o_p2_parents[] __initconst = {
+	"csw_infra_f32k", "infra_ck_f26m", "infra_ck_f26m",
+	"infra_pcie_ck_occ_p2"
+};
+
+static const char *const infra_pcie_gfmux_tl_ck_o_p3_parents[] __initconst = {
+	"csw_infra_f32k", "infra_ck_f26m", "infra_ck_f26m",
+	"infra_pcie_ck_occ_p3"
+};
+
+static const struct mtk_mux infra_muxes[] = {
+	/* MODULE_CLK_SEL_0 */
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_UART0_SEL, "infra_mux_uart0_sel",
+			     infra_mux_uart0_parents, 0x0018, 0x0010, 0x0014, 0,
+			     1, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_UART1_SEL, "infra_mux_uart1_sel",
+			     infra_mux_uart1_parents, 0x0018, 0x0010, 0x0014, 1,
+			     1, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_UART2_SEL, "infra_mux_uart2_sel",
+			     infra_mux_uart2_parents, 0x0018, 0x0010, 0x0014, 2,
+			     1, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_SPI0_SEL, "infra_mux_spi0_sel",
+			     infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 4,
+			     1, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_SPI1_SEL, "infra_mux_spi1_sel",
+			     infra_mux_spi1_parents, 0x0018, 0x0010, 0x0014, 5,
+			     1, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_MUX_SPI2_SEL, "infra_mux_spi2_sel",
+			     infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 6,
+			     1, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_SEL, "infra_pwm_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 14,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK1_SEL, "infra_pwm_ck1_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 16,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK2_SEL, "infra_pwm_ck2_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 18,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK3_SEL, "infra_pwm_ck3_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 20,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK4_SEL, "infra_pwm_ck4_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 22,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK5_SEL, "infra_pwm_ck5_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 24,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK6_SEL, "infra_pwm_ck6_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 26,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK7_SEL, "infra_pwm_ck7_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 28,
+			     2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PWM_CK8_SEL, "infra_pwm_ck8_sel",
+			     infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 30,
+			     2, -1, -1, -1),
+	/* MODULE_CLK_SEL_1 */
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PCIE_GFMUX_TL_O_P0_SEL,
+			     "infra_pcie_gfmux_tl_o_p0_sel",
+			     infra_pcie_gfmux_tl_ck_o_p0_parents, 0x0028,
+			     0x0020, 0x0024, 0, 2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PCIE_GFMUX_TL_O_P1_SEL,
+			     "infra_pcie_gfmux_tl_o_p1_sel",
+			     infra_pcie_gfmux_tl_ck_o_p1_parents, 0x0028,
+			     0x0020, 0x0024, 2, 2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PCIE_GFMUX_TL_O_P2_SEL,
+			     "infra_pcie_gfmux_tl_o_p2_sel",
+			     infra_pcie_gfmux_tl_ck_o_p2_parents, 0x0028,
+			     0x0020, 0x0024, 4, 2, -1, -1, -1),
+	MUX_GATE_CLR_SET_UPD(CK_INFRA_PCIE_GFMUX_TL_O_P3_SEL,
+			     "infra_pcie_gfmux_tl_o_p3_sel",
+			     infra_pcie_gfmux_tl_ck_o_p3_parents, 0x0028,
+			     0x0020, 0x0024, 6, 2, -1, -1, -1),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+	DIV_ADJ(CK_TOP_AUD_I2S_M, "aud_i2s_m", "aud", 0x0420, 8, 8),
+};
+
+static const struct mtk_gate_regs infra0_cg_regs = {
+	.set_ofs = 0x10,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x18,
+};
+
+static const struct mtk_gate_regs infra1_cg_regs = {
+	.set_ofs = 0x40,
+	.clr_ofs = 0x44,
+	.sta_ofs = 0x48,
+};
+
+static const struct mtk_gate_regs infra2_cg_regs = {
+	.set_ofs = 0x50,
+	.clr_ofs = 0x54,
+	.sta_ofs = 0x58,
+};
+
+static const struct mtk_gate_regs infra3_cg_regs = {
+	.set_ofs = 0x60,
+	.clr_ofs = 0x64,
+	.sta_ofs = 0x68,
+};
+
+#define GATE_INFRA0(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &infra0_cg_regs, .shift = _shift,                      \
+		.ops = &mtk_clk_gate_ops_setclr,                               \
+	}
+
+#define GATE_INFRA1(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &infra1_cg_regs, .shift = _shift,                      \
+		.ops = &mtk_clk_gate_ops_setclr,                               \
+	}
+
+#define GATE_INFRA2(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &infra2_cg_regs, .shift = _shift,                      \
+		.ops = &mtk_clk_gate_ops_setclr,                               \
+	}
+
+#define GATE_INFRA3(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &infra3_cg_regs, .shift = _shift,                      \
+		.ops = &mtk_clk_gate_ops_setclr,                               \
+	}
+
+static const struct mtk_gate infra_clks[] __initconst = {
+	/* INFRA0 */
+	GATE_INFRA0(CK_INFRA_PCIE_PERI_26M_CK_P0,
+		    "infra_pcie_peri_ck_26m_ck_p0", "infra_f26m_o0", 7),
+	GATE_INFRA0(CK_INFRA_PCIE_PERI_26M_CK_P1,
+		    "infra_pcie_peri_ck_26m_ck_p1", "infra_f26m_o0", 8),
+	GATE_INFRA0(CK_INFRA_PCIE_PERI_26M_CK_P2,
+		    "infra_pcie_peri_ck_26m_ck_p2", "infra_f26m_o0", 9),
+	GATE_INFRA0(CK_INFRA_PCIE_PERI_26M_CK_P3,
+		    "infra_pcie_peri_ck_26m_ck_p3", "infra_f26m_o0", 10),
+	/* INFRA1 */
+	GATE_INFRA1(CK_INFRA_66M_GPT_BCK, "infra_hf_66m_gpt_bck",
+		    "infra_66m_mck", 0),
+	GATE_INFRA1(CK_INFRA_66M_PWM_HCK, "infra_hf_66m_pwm_hck",
+		    "infra_66m_mck", 1),
+	GATE_INFRA1(CK_INFRA_66M_PWM_BCK, "infra_hf_66m_pwm_bck",
+		    "infra_pwm_sel", 2),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK1, "infra_hf_66m_pwm_ck1",
+		    "infra_pwm_ck1_sel", 3),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK2, "infra_hf_66m_pwm_ck2",
+		    "infra_pwm_ck2_sel", 4),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK3, "infra_hf_66m_pwm_ck3",
+		    "infra_pwm_ck3_sel", 5),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK4, "infra_hf_66m_pwm_ck4",
+		    "infra_pwm_ck4_sel", 6),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK5, "infra_hf_66m_pwm_ck5",
+		    "infra_pwm_ck5_sel", 7),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK6, "infra_hf_66m_pwm_ck6",
+		    "infra_pwm_ck6_sel", 8),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK7, "infra_hf_66m_pwm_ck7",
+		    "infra_pwm_ck7_sel", 9),
+	GATE_INFRA1(CK_INFRA_66M_PWM_CK8, "infra_hf_66m_pwm_ck8",
+		    "infra_pwm_ck8_sel", 10),
+	GATE_INFRA1(CK_INFRA_133M_CQDMA_BCK, "infra_hf_133m_cqdma_bck",
+		    "infra_133m_mck", 12),
+	GATE_INFRA1(CK_INFRA_66M_AUD_SLV_BCK, "infra_66m_aud_slv_bck",
+		    "infra_66m_phck", 13),
+	GATE_INFRA1(CK_INFRA_AUD_26M, "infra_f_faud_26m", "infra_ck_f26m", 14),
+	GATE_INFRA1(CK_INFRA_AUD_L, "infra_f_faud_l", "infra_faud_l_o", 15),
+	GATE_INFRA1(CK_INFRA_AUD_AUD, "infra_f_aud_aud", "infra_faud_aud_o",
+		    16),
+	GATE_INFRA1(CK_INFRA_AUD_EG2, "infra_f_faud_eg2", "infra_faud_eg2_o",
+		    18),
+	GATE_INFRA1(CK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "infra_ck_f26m",
+		    19),
+	GATE_INFRA1(CK_INFRA_133M_DBG_ACKM, "infra_hf_133m_dbg_ackm",
+		    "infra_133m_mck", 20),
+	GATE_INFRA1(CK_INFRA_66M_AP_DMA_BCK, "infra_66m_ap_dma_bck",
+		    "infra_66m_mck", 21),
+	GATE_INFRA1(CK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck",
+		    "infra_66m_mck", 29),
+	GATE_INFRA1(CK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m",
+		    "infra_ck_f26m", 30),
+	GATE_INFRA1(CK_INFRA_66M_TRNG, "infra_hf_66m_trng", "infra_peri_66m_o",
+		    31),
+	/* INFRA2 */
+	GATE_INFRA2(CK_INFRA_26M_THERM_SYSTEM, "infra_hf_26m_therm_system",
+		    "infra_ck_f26m", 0),
+	GATE_INFRA2(CK_INFRA_I2C_BCK, "infra_i2c_bck", "infra_i2c_o", 1),
+	GATE_INFRA2(CK_INFRA_66M_UART0_PCK, "infra_hf_66m_uart0_pck",
+		    "infra_66m_mck", 3),
+	GATE_INFRA2(CK_INFRA_66M_UART1_PCK, "infra_hf_66m_uart1_pck",
+		    "infra_66m_mck", 4),
+	GATE_INFRA2(CK_INFRA_66M_UART2_PCK, "infra_hf_66m_uart2_pck",
+		    "infra_66m_mck", 5),
+	GATE_INFRA2(CK_INFRA_52M_UART0_CK, "infra_f_52m_uart0",
+		    "infra_mux_uart0_sel", 3),
+	GATE_INFRA2(CK_INFRA_52M_UART1_CK, "infra_f_52m_uart1",
+		    "infra_mux_uart1_sel", 4),
+	GATE_INFRA2(CK_INFRA_52M_UART2_CK, "infra_f_52m_uart2",
+		    "infra_mux_uart2_sel", 5),
+	GATE_INFRA2(CK_INFRA_NFI, "infra_f_fnfi", "infra_nfi_o", 9),
+	GATE_INFRA2(CK_INFRA_SPINFI, "infra_f_fspinfi", "infra_spinfi_o", 10),
+	GATE_INFRA2(CK_INFRA_66M_NFI_HCK, "infra_hf_66m_nfi_hck",
+		    "infra_66m_mck", 11),
+	GATE_INFRA2(CK_INFRA_104M_SPI0, "infra_hf_104m_spi0",
+		    "infra_mux_spi0_sel", 12),
+	GATE_INFRA2(CK_INFRA_104M_SPI1, "infra_hf_104m_spi1",
+		    "infra_mux_spi1_sel", 13),
+	GATE_INFRA2(CK_INFRA_104M_SPI2_BCK, "infra_hf_104m_spi2_bck",
+		    "infra_mux_spi2_sel", 14),
+	GATE_INFRA2(CK_INFRA_66M_SPI0_HCK, "infra_hf_66m_spi0_hck",
+		    "infra_66m_mck", 15),
+	GATE_INFRA2(CK_INFRA_66M_SPI1_HCK, "infra_hf_66m_spi1_hck",
+		    "infra_66m_mck", 16),
+	GATE_INFRA2(CK_INFRA_66M_SPI2_HCK, "infra_hf_66m_spi2_hck",
+		    "infra_66m_mck", 17),
+	GATE_INFRA2(CK_INFRA_66M_FLASHIF_AXI, "infra_hf_66m_flashif_axi",
+		    "infra_66m_mck", 18),
+	GATE_INFRA2(CK_INFRA_RTC, "infra_f_frtc", "infra_lb_mux_frtc", 19),
+	GATE_INFRA2(CK_INFRA_26M_ADC_BCK, "infra_f_26m_adc_bck",
+		    "infra_f26m_o1", 20),
+	GATE_INFRA2(CK_INFRA_RC_ADC, "infra_f_frc_adc", "infra_f_26m_adc_bck",
+		    21),
+	GATE_INFRA2(CK_INFRA_MSDC400, "infra_f_fmsdc400", "infra_fmsdc400_o",
+		    22),
+	GATE_INFRA2(CK_INFRA_MSDC2_HCK, "infra_f_fmsdc2_hck",
+		    "infra_fmsdc2_hck_occ", 23),
+	GATE_INFRA2(CK_INFRA_133M_MSDC_0_HCK, "infra_hf_133m_msdc_0_hck",
+		    "infra_peri_133m", 24),
+	GATE_INFRA2(CK_INFRA_66M_MSDC_0_HCK, "infra_66m_msdc_0_hck",
+		    "infra_66m_phck", 25),
+	GATE_INFRA2(CK_INFRA_133M_CPUM_BCK, "infra_hf_133m_cpum_bck",
+		    "infra_133m_mck", 26),
+	GATE_INFRA2(CK_INFRA_BIST2FPC, "infra_hf_fbist2fpc", "infra_nfi_o", 27),
+	GATE_INFRA2(CK_INFRA_I2C_X16W_MCK_CK_P1, "infra_hf_i2c_x16w_mck_ck_p1",
+		    "infra_133m_mck", 29),
+	GATE_INFRA2(CK_INFRA_I2C_X16W_PCK_CK_P1, "infra_hf_i2c_x16w_pck_ck_p1",
+		    "infra_66m_phck", 31),
+	/* INFRA3 */
+	GATE_INFRA3(CK_INFRA_133M_USB_HCK, "infra_133m_usb_hck",
+		    "infra_133m_phck", 0),
+	GATE_INFRA3(CK_INFRA_133M_USB_HCK_CK_P1, "infra_133m_usb_hck_ck_p1",
+		    "infra_133m_phck", 1),
+	GATE_INFRA3(CK_INFRA_66M_USB_HCK, "infra_66m_usb_hck", "infra_66m_phck",
+		    2),
+	GATE_INFRA3(CK_INFRA_66M_USB_HCK_CK_P1, "infra_66m_usb_hck_ck_p1",
+		    "infra_66m_phck", 3),
+	GATE_INFRA3(CK_INFRA_USB_SYS, "infra_usb_sys", "infra_usb_sys_o", 4),
+	GATE_INFRA3(CK_INFRA_USB_SYS_CK_P1, "infra_usb_sys_ck_p1",
+		    "infra_usb_sys_o_p1", 5),
+	GATE_INFRA3(CK_INFRA_USB_REF, "infra_usb_ref", "infra_usb_o", 6),
+	GATE_INFRA3(CK_INFRA_USB_CK_P1, "infra_usb_ck_p1", "infra_usb_o_p1", 7),
+	GATE_INFRA3(CK_INFRA_USB_FRMCNT, "infra_usb_frmcnt",
+		    "infra_usb_frmcnt_o", 8),
+	GATE_INFRA3(CK_INFRA_USB_FRMCNT_CK_P1, "infra_usb_frmcnt_ck_p1",
+		    "infra_usb_frmcnt_o_p1", 9),
+	GATE_INFRA3(CK_INFRA_USB_PIPE, "infra_usb_pipe", "infra_usb_pipe_o",
+		    10),
+	GATE_INFRA3(CK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1",
+		    "infra_usb_pipe_o_p1", 11),
+	GATE_INFRA3(CK_INFRA_USB_UTMI, "infra_usb_utmi", "infra_usb_utmi_o",
+		    12),
+	GATE_INFRA3(CK_INFRA_USB_UTMI_CK_P1, "infra_usb_utmi_ck_p1",
+		    "infra_usb_utmi_o_p1", 13),
+	GATE_INFRA3(CK_INFRA_USB_XHCI, "infra_usb_xhci", "infra_usb_xhci_o",
+		    14),
+	GATE_INFRA3(CK_INFRA_USB_XHCI_CK_P1, "infra_usb_xhci_ck_p1",
+		    "infra_usb_xhci_o_p1", 15),
+	GATE_INFRA3(CK_INFRA_PCIE_GFMUX_TL_P0, "infra_pcie_gfmux_tl_ck_p0",
+		    "infra_pcie_gfmux_tl_o_p0_sel", 20),
+	GATE_INFRA3(CK_INFRA_PCIE_GFMUX_TL_P1, "infra_pcie_gfmux_tl_ck_p1",
+		    "infra_pcie_gfmux_tl_o_p1_sel", 21),
+	GATE_INFRA3(CK_INFRA_PCIE_GFMUX_TL_P2, "infra_pcie_gfmux_tl_ck_p2",
+		    "infra_pcie_gfmux_tl_o_p2_sel", 22),
+	GATE_INFRA3(CK_INFRA_PCIE_GFMUX_TL_P3, "infra_pcie_gfmux_tl_ck_p3",
+		    "infra_pcie_gfmux_tl_o_p3_sel", 23),
+	GATE_INFRA3(CK_INFRA_PCIE_PIPE_P0, "infra_pcie_pipe_ck_p0",
+		    "infra_pcie_pipe_ck_occ_p0", 24),
+	GATE_INFRA3(CK_INFRA_PCIE_PIPE_P1, "infra_pcie_pipe_ck_p1",
+		    "infra_pcie_pipe_ck_occ_p1", 25),
+	GATE_INFRA3(CK_INFRA_PCIE_PIPE_P2, "infra_pcie_pipe_ck_p2",
+		    "infra_pcie_pipe_ck_occ_p2", 26),
+	GATE_INFRA3(CK_INFRA_PCIE_PIPE_P3, "infra_pcie_pipe_ck_p3",
+		    "infra_pcie_pipe_ck_occ_p3", 27),
+	GATE_INFRA3(CK_INFRA_133M_PCIE_CK_P0, "infra_133m_pcie_ck_p0",
+		    "infra_133m_phck", 28),
+	GATE_INFRA3(CK_INFRA_133M_PCIE_CK_P1, "infra_133m_pcie_ck_p1",
+		    "infra_133m_phck", 29),
+	GATE_INFRA3(CK_INFRA_133M_PCIE_CK_P2, "infra_133m_pcie_ck_p2",
+		    "infra_133m_phck", 30),
+	GATE_INFRA3(CK_INFRA_133M_PCIE_CK_P3, "infra_133m_pcie_ck_p3",
+		    "infra_133m_phck", 31),
+};
+
+static const struct mtk_gate_regs sgmii0_cg_regs = {
+	.set_ofs = 0xE4,
+	.clr_ofs = 0xE4,
+	.sta_ofs = 0xE4,
+};
+
+#define GATE_SGMII0(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &sgmii0_cg_regs, .shift = _shift,                      \
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,                        \
+	}
+
+static const struct mtk_gate sgmii0_clks[] __initconst = {
+	GATE_SGMII0(CK_SGM0_TX_EN, "sgm0_tx_en", "clkxtal", 2),
+	GATE_SGMII0(CK_SGM0_RX_EN, "sgm0_rx_en", "clkxtal", 3),
+};
+
+static const struct mtk_gate_regs sgmii1_cg_regs = {
+	.set_ofs = 0xE4,
+	.clr_ofs = 0xE4,
+	.sta_ofs = 0xE4,
+};
+
+#define GATE_SGMII1(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &sgmii1_cg_regs, .shift = _shift,                      \
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,                        \
+	}
+
+static const struct mtk_gate sgmii1_clks[] __initconst = {
+	GATE_SGMII1(CK_SGM1_TX_EN, "sgm1_tx_en", "clkxtal", 2),
+	GATE_SGMII1(CK_SGM1_RX_EN, "sgm1_rx_en", "clkxtal", 3),
+};
+
+static const struct mtk_gate_regs ethdma_cg_regs = {
+	.set_ofs = 0x30,
+	.clr_ofs = 0x30,
+	.sta_ofs = 0x30,
+};
+
+#define GATE_ETHDMA(_id, _name, _parent, _shift)                               \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &ethdma_cg_regs, .shift = _shift,                      \
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,                        \
+	}
+
+static const struct mtk_gate ethdma_clks[] __initconst = {
+	GATE_ETHDMA(CK_ETHDMA_XGP1_EN, "ethdma_xgp1_en", "clkxtal", 0),
+	GATE_ETHDMA(CK_ETHDMA_XGP2_EN, "ethdma_xgp2_en", "clkxtal", 1),
+	GATE_ETHDMA(CK_ETHDMA_XGP3_EN, "ethdma_xgp3_en", "clkxtal", 2),
+	GATE_ETHDMA(CK_ETHDMA_FE_EN, "ethdma_fe_en", "netsys_2x", 6),
+	GATE_ETHDMA(CK_ETHDMA_GP2_EN, "ethdma_gp2_en", "clkxtal", 7),
+	GATE_ETHDMA(CK_ETHDMA_GP1_EN, "ethdma_gp1_en", "clkxtal", 8),
+	GATE_ETHDMA(CK_ETHDMA_GP3_EN, "ethdma_gp3_en", "clkxtal", 10),
+	GATE_ETHDMA(CK_ETHDMA_ESW_EN, "ethdma_esw_en", "netsys_gsw", 16),
+	GATE_ETHDMA(CK_ETHDMA_CRYPT0_EN, "ethdma_crypt0_en", "eip197", 29),
+};
+
+static const struct mtk_gate_regs ethwarp_cg_regs = {
+	.set_ofs = 0x14,
+	.clr_ofs = 0x14,
+	.sta_ofs = 0x14,
+};
+
+#define GATE_ETHWARP(_id, _name, _parent, _shift)                              \
+	{                                                                      \
+		.id = _id, .name = _name, .parent_name = _parent,              \
+		.regs = &ethwarp_cg_regs, .shift = _shift,                     \
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,                        \
+	}
+
+static const struct mtk_gate ethwarp_clks[] __initconst = {
+	GATE_ETHWARP(CK_ETHWARP_WOCPU2_EN, "ethwarp_wocpu2_en",
+		     "netsys_wed_mcu", 13),
+	GATE_ETHWARP(CK_ETHWARP_WOCPU1_EN, "ethwarp_wocpu1_en",
+		     "netsys_wed_mcu", 14),
+	GATE_ETHWARP(CK_ETHWARP_WOCPU0_EN, "ethwarp_wocpu0_en",
+		     "netsys_wed_mcu", 15),
+};
+
+#define MT7988_PLL_FMAX	     (2500UL * MHZ)
+#define MT7988_PCW_CHG_SHIFT 2
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask,     \
+	      _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,         \
+	      _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, _div_table,   \
+	      _parent_name)                                                    \
+	{                                                                      \
+		.id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg,    \
+		.en_mask = _en_mask, .flags = _flags,                          \
+		.rst_bar_mask = BIT(_rst_bar_mask), .fmax = MT7988_PLL_FMAX,   \
+		.pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \
+		.tuner_reg = _tuner_reg, .tuner_en_reg = _tuner_en_reg,        \
+		.tuner_en_bit = _tuner_en_bit, .pcw_reg = _pcw_reg,            \
+		.pcw_shift = _pcw_shift, .pcw_chg_reg = _pcw_chg_reg,          \
+		.pcw_chg_shift = MT7988_PCW_CHG_SHIFT,                         \
+		.div_table = _div_table, .parent_name = _parent_name,          \
+	}
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask,       \
+	    _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,           \
+	    _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, _parent_name)   \
+	PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask,     \
+	      _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,         \
+	      _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, NULL,         \
+	      _parent_name)
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CK_APMIXED_NETSYSPLL, "netsyspll", 0x0104, 0x0110, 0x00000001, 0, 0,
+	    32, 0x0104, 4, 0, 0, 0, 0x0108, 0, 0x0104, "clkxtal"),
+	PLL(CK_APMIXED_MPLL, "mpll", 0x0114, 0x0120, 0xff000001, HAVE_RST_BAR,
+	    23, 32, 0x0114, 4, 0, 0, 0, 0x0118, 0, 0x0114, "clkxtal"),
+	PLL(CK_APMIXED_MMPLL, "mmpll", 0x0124, 0x0130, 0xff000001, HAVE_RST_BAR,
+	    23, 32, 0x0124, 4, 0, 0, 0, 0x0128, 0, 0x0124, "clkxtal"),
+	PLL(CK_APMIXED_APLL2, "apll2", 0x0134, 0x0140, 0x00000001, 0, 0, 32,
+	    0x0134, 4, 0x0704, 0x0700, 1, 0x0138, 0, 0x0134, "clkxtal"),
+	PLL(CK_APMIXED_NET1PLL, "net1pll", 0x0144, 0x0150, 0xff000001,
+	    HAVE_RST_BAR, 23, 32, 0x0144, 4, 0, 0, 0, 0x0148, 0, 0x0144,
+	    "clkxtal"),
+	PLL(CK_APMIXED_NET2PLL, "net2pll", 0x0154, 0x0160, 0xff000001,
+	    HAVE_RST_BAR, 23, 32, 0x0154, 4, 0, 0, 0, 0x0158, 0, 0x0154,
+	    "clkxtal"),
+	PLL(CK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0164, 0x0170, 0x00000001, 0, 0,
+	    32, 0x0164, 4, 0, 0, 0, 0x0168, 0, 0x0164, "clkxtal"),
+	PLL(CK_APMIXED_SGMPLL, "sgmpll", 0x0174, 0x0180, 0x00000001, 0, 0, 32,
+	    0x0174, 4, 0, 0, 0, 0x0178, 0, 0x0174, "clkxtal"),
+	PLL(CK_APMIXED_ARM_B, "arm_b", 0x0204, 0x0210, 0xff000001, HAVE_RST_BAR,
+	    23, 32, 0x0204, 4, 0, 0, 0, 0x0208, 0, 0x0204, "clkxtal"),
+	PLL(CK_APMIXED_CCIPLL2_B, "ccipll2_b", 0x0214, 0x0220, 0xff000001,
+	    HAVE_RST_BAR, 23, 32, 0x0214, 4, 0, 0, 0, 0x0218, 0, 0x0214,
+	    "clkxtal"),
+	PLL(CK_APMIXED_USXGMIIPLL, "usxgmiipll", 0x0304, 0x0310, 0xff000001,
+	    HAVE_RST_BAR, 23, 32, 0x0304, 4, 0, 0, 0, 0x0308, 0, 0x0304,
+	    "clkxtal"),
+	PLL(CK_APMIXED_MSDCPLL, "msdcpll", 0x0314, 0x0320, 0x00000001, 0, 0, 32,
+	    0x0314, 4, 0, 0, 0, 0x0318, 0, 0x0314, "clkxtal"),
+};
+
+static struct clk_onecell_data *mt7988_top_clk_data __initdata;
+static struct clk_onecell_data *mt7988_pll_clk_data __initdata;
+
+static void __init mtk_clk_enable_critical(void)
+{
+	if (!mt7988_top_clk_data || !mt7988_pll_clk_data)
+		return;
+
+	clk_prepare_enable(mt7988_pll_clk_data->clks[CK_APMIXED_ARM_B]);
+	clk_prepare_enable(mt7988_top_clk_data->clks[CK_TOP_SYSAXI_SEL]);
+	clk_prepare_enable(mt7988_top_clk_data->clks[CK_TOP_SYSAPB_SEL]);
+	clk_prepare_enable(mt7988_top_clk_data->clks[CK_TOP_DRAMC_SEL]);
+	clk_prepare_enable(mt7988_top_clk_data->clks[CK_TOP_DRAMC_MD32_SEL]);
+	clk_prepare_enable(mt7988_top_clk_data->clks[CK_TOP_INFRA_F26M_SEL]);
+}
+
+static void __init mtk_infracfg_init(struct device_node *node)
+{
+	int r;
+
+	mt7988_top_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs),
+				 mt7988_top_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get,
+				mt7988_top_clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+
+	mtk_clk_enable_critical();
+}
+CLK_OF_DECLARE(mtk_infracfg, "mediatek,mt7988-infracfg", mtk_infracfg_init);
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	mt7988_top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs),
+				 mt7988_top_clk_data);
+	mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
+			       &mt7988_clk_lock, mt7988_top_clk_data);
+	mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base,
+				  &mt7988_clk_lock, mt7988_top_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get,
+				mt7988_top_clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+
+	mtk_clk_enable_critical();
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt7988-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infracfg_ao_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_AO_NR_CLK);
+
+	mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node,
+			       &mt7988_clk_lock, clk_data);
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+			       clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+}
+CLK_OF_DECLARE(mtk_infracfg_ao, "mediatek,mt7988-infracfg_ao",
+	       mtk_infracfg_ao_init);
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	int r;
+
+	mt7988_pll_clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls),
+			      mt7988_pll_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get,
+				mt7988_pll_clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+
+	mtk_clk_enable_critical();
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt7988-apmixedsys",
+	       mtk_apmixedsys_init);
+
+static void __init mtk_mcusys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK);
+	mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base,
+				    &mt7988_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+}
+CLK_OF_DECLARE(mtk_mcusys, "mediatek,mt7988-mcusys", mtk_mcusys_init);
+
+static void __init mtk_sgmiisys_0_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_SGMII0_NR_CLK);
+
+	mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks),
+			       clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+}
+CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7988-sgmiisys_0",
+	       mtk_sgmiisys_0_init);
+
+static void __init mtk_sgmiisys_1_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_SGMII1_NR_CLK);
+
+	mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks),
+			       clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+}
+CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7988-sgmiisys_1",
+	       mtk_sgmiisys_1_init);
+
+static void __init mtk_ethdma_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_ETHDMA_NR_CLK);
+
+	mtk_clk_register_gates(node, ethdma_clks, ARRAY_SIZE(ethdma_clks),
+			       clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+}
+CLK_OF_DECLARE(mtk_ethdma, "mediatek,mt7988-ethsys", mtk_ethdma_init);
+
+static void __init mtk_ethwarp_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_ETHWARP_NR_CLK);
+
+	mtk_clk_register_gates(node, ethwarp_clks, ARRAY_SIZE(ethwarp_clks),
+			       clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+		       __func__, r);
+}
+CLK_OF_DECLARE(mtk_ethwarp, "mediatek,mt7988-ethwarp", mtk_ethwarp_init);
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
new file mode 100644
index 0000000..251a412
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <linux/bitfield.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+
+#define MEDAITEK_2P5GE_PHY_DMB_FW "mediatek-2p5ge-phy-dmb.bin"
+#define MEDIATEK_2P5GE_PHY_PMB_FW "mediatek-2p5ge-phy-pmb.bin"
+
+#define MD32_EN_CFG	0x18
+#define   MD32_EN	BIT(0)
+
+static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
+{
+	int ret;
+	int i;
+	const struct firmware *fw;
+	struct device *dev = &phydev->mdio.dev;
+	struct device_node *np;
+	void __iomem *dmb_addr;
+	void __iomem *pmb_addr;
+	void __iomem *mcucsr_base;
+	u16 reg;
+
+	np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
+	if (!np)
+		return -ENOENT;
+
+	dmb_addr = of_iomap(np, 0);
+	if (!dmb_addr)
+		return -ENOMEM;
+	pmb_addr = of_iomap(np, 1);
+	if (!pmb_addr)
+		return -ENOMEM;
+	mcucsr_base = of_iomap(np, 2);
+	if (!mcucsr_base)
+		return -ENOMEM;
+
+	ret = request_firmware(&fw, MEDAITEK_2P5GE_PHY_DMB_FW, dev);
+	if (ret) {
+		dev_err(dev, "failed to load firmware: %s, ret: %d\n",
+			MEDAITEK_2P5GE_PHY_DMB_FW, ret);
+		return ret;
+	}
+	for (i = 0; i < fw->size - 1; i += 4)
+		writel(*((uint32_t *)(fw->data + i)), dmb_addr + i);
+	release_firmware(fw);
+
+	ret = request_firmware(&fw, MEDIATEK_2P5GE_PHY_PMB_FW, dev);
+	if (ret) {
+		dev_err(dev, "failed to load firmware: %s, ret: %d\n",
+			MEDIATEK_2P5GE_PHY_PMB_FW, ret);
+		return ret;
+	}
+	for (i = 0; i < fw->size - 1; i += 4)
+		writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
+	release_firmware(fw);
+
+	reg = readw(mcucsr_base + MD32_EN_CFG);
+	writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG);
+	dev_info(dev, "Firmware loading/trigger ok.\n");
+
+	return 0;
+}
+
+static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = genphy_read_abilities(phydev);
+	if (ret)
+		return ret;
+
+	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+			 phydev->supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+			 phydev->supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+			 phydev->supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+			 phydev->supported);
+	linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
+
+	return 0;
+}
+
+static struct phy_driver mtk_gephy_driver[] = {
+	{
+		PHY_ID_MATCH_EXACT(0x00339c11),
+		.name		= "MediaTek MT798x 2.5GbE PHY",
+		.config_init	= mt798x_2p5ge_phy_config_init,
+		.config_aneg    = genphy_c45_config_aneg,
+		.get_features	= mt798x_2p5ge_phy_get_features,
+		//.config_intr	= genphy_no_config_intr,
+		//.handle_interrupt = genphy_no_ack_interrupt,
+		//.suspend	= genphy_suspend,
+		//.resume		= genphy_resume,
+	},
+};
+
+module_phy_driver(mtk_gephy_driver);
+
+static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = {
+	{ PHY_ID_MATCH_VENDOR(0x00339c00) },
+	{ }
+};
+
+MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver");
+MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl);
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/Makefile b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/Makefile
old mode 100755
new mode 100644
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7530.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7530.c
old mode 100755
new mode 100644
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
index 7253042..854a586 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
@@ -7,6 +7,10 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/hrtimer.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/of_address.h>
 
 #include "mt753x.h"
 #include "mt753x_regs.h"
@@ -682,6 +686,24 @@
 	return -ENODEV;
 }
 
+static int mt7988_sw_detect(struct gsw_mt753x *gsw, struct chip_rev *crev)
+{
+	const char *model;
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "mediatek,mt7988-switch");
+	if (!np)
+		return -ENODEV;
+
+	of_node_put(np);
+
+	crev->rev = 0;
+	crev->name = "MT7988";
+	gsw->direct_access = true;
+
+	return 0;
+}
+
 static void pinmux_set_mux_7531(struct gsw_mt753x *gsw, u32 pin, u32 mode)
 {
 	u32 val;
@@ -810,7 +832,8 @@
 	u32 val;
 
 	for (i = 0; i < MT753X_NUM_PHYS; i++) {
-		mt7531_phy_100m_eye_diag_setting(gsw, i);
+		if (!gsw->direct_access)
+			mt7531_phy_100m_eye_diag_setting(gsw, i);
 
 		/* Enable HW auto downshift */
 		gsw->mii_write(gsw, i, 0x1f, 0x1);
@@ -834,10 +857,14 @@
 		val |= PHY_LINKDOWN_POWER_SAVING_EN;
 		gsw->mii_write(gsw, i, PHY_EXT_REG_17, val);
 
-		val = gsw->mmd_read(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6);
-		val &= ~PHY_POWER_SAVING_M;
-		val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S;
-		gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6, val);
+		if (!gsw->direct_access) {
+			val = gsw->mmd_read(gsw, i, PHY_DEV1E,
+					    PHY_DEV1E_REG_0C6);
+			val &= ~PHY_POWER_SAVING_M;
+			val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S;
+			gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6,
+				       val);
+		}
 
 		/* Timing Recovery for GbE slave mode */
 		mt753x_tr_write(gsw, i, PMA_CH, PMA_NOD, PMA_01, 0x6fb90a);
@@ -952,7 +979,8 @@
 	gsw->mmd_read = mt753x_mmd_read;
 	gsw->mmd_write = mt753x_mmd_write;
 
-	gsw->hw_phy_cal = of_property_read_bool(gsw->dev->of_node, "mediatek,hw_phy_cal");
+	gsw->hw_phy_cal = of_property_read_bool(gsw->dev->of_node,
+						"mediatek,hw_phy_cal");
 
 	for (i = 0; i < MT753X_NUM_PHYS; i++) {
 		val = gsw->mii_read(gsw, i, MII_BMCR);
@@ -966,7 +994,7 @@
 
 	/* Switch soft reset */
 	mt753x_reg_write(gsw, SYS_CTRL, SW_SYS_RST | SW_REG_RST);
-	usleep_range(10, 20);
+	udelay(20);
 
 	/* Enable MDC input Schmitt Trigger */
 	val = mt753x_reg_read(gsw, SMT0_IOLB);
@@ -976,6 +1004,7 @@
 	mt7531_set_gpio_pinmux(gsw);
 
 	mt7531_core_pll_setup(gsw);
+
 	mt7531_mac_port_setup(gsw, 5, &gsw->port5_cfg);
 	mt7531_mac_port_setup(gsw, 6, &gsw->port6_cfg);
 
@@ -999,6 +1028,89 @@
 	return 0;
 }
 
+static int mt7988_sw_init(struct gsw_mt753x *gsw)
+{
+	struct device_node *switch_node = NULL;
+	struct platform_device *pdev;
+	int i;
+	u32 val;
+	u32 pmcr;
+	u32 speed;
+
+	switch_node = of_find_node_by_name(NULL, "switch0");
+	if (switch_node == NULL) {
+		dev_err(&pdev->dev, "switch node invaild\n");
+		return -ENOENT;
+	}
+
+	gsw->base = of_iomap(switch_node, 0);
+	if (IS_ERR(gsw->base)) {
+		dev_err(&pdev->dev, "switch ioremap failed\n");
+		return -EIO;
+	}
+
+	pdev = container_of(gsw->dev, struct platform_device, dev);
+	gsw->sysctrl_base = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+							"mediatek,sysctrl");
+	if (IS_ERR(gsw->sysctrl_base)) {
+		dev_err(&pdev->dev, "no sysctl regmap found\n");
+		return -ENODEV;
+	}
+
+	/* reset control */
+	regmap_write(gsw->sysctrl_base, ETH_RESET, 0x200);
+	udelay(20);
+	regmap_write(gsw->sysctrl_base, ETH_RESET, 0);
+	udelay(20);
+
+	gsw->phy_base = (gsw->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
+
+	gsw->mii_read = mt753x_mii_read;
+	gsw->mii_write = mt753x_mii_write;
+	gsw->mmd_read = mt753x_mmd_read;
+	gsw->mmd_write = mt753x_mmd_write;
+
+	for (i = 0; i < MT753X_NUM_PHYS; i++) {
+		val = gsw->mii_read(gsw, i, MII_BMCR);
+		val |= BMCR_ISOLATE;
+		gsw->mii_write(gsw, i, MII_BMCR, val);
+	}
+
+	speed = MAC_SPD_1000;
+	pmcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
+		MAC_MODE | MAC_TX_EN | MAC_RX_EN | BKOFF_EN |
+		BACKPR_EN | FORCE_MODE_LNK | FORCE_LINK | FORCE_MODE_SPD |
+		FORCE_MODE_DPX | FORCE_MODE_RX_FC | FORCE_MODE_TX_FC |
+		FORCE_RX_FC | FORCE_TX_FC | (speed << FORCE_SPD_S) | FORCE_DPX;
+
+	mt753x_reg_write(gsw, PMCR(6), pmcr);
+
+	/* Global mac control settings */
+	mt753x_reg_write(gsw, GMACCR,
+			 (15 << MTCC_LMT_S) | (15 << MAX_RX_JUMBO_S) |
+			 RX_PKT_LEN_MAX_JUMBO);
+
+	/* Enable Collision Poll */
+	val = mt753x_reg_read(gsw, CPGC_CTRL);
+	val |= COL_CLK_EN;
+	mt753x_reg_write(gsw, CPGC_CTRL, val);
+	val |= COL_RST_N;
+	mt753x_reg_write(gsw, CPGC_CTRL, val);
+	val |= COL_EN;
+	mt753x_reg_write(gsw, CPGC_CTRL, val);
+
+	/* Disable AFIFO reset for extra short IPG */
+	mt7531_afifo_reset(gsw, 0);
+
+	/* PHY force slave 1G*/
+	for (i = 0; i < MT753X_NUM_PHYS; i++) {
+		gsw->mii_write(gsw, i, MII_CTRL1000, 0x1200);
+		gsw->mii_write(gsw, i, MII_BMCR, 0x140);
+	}
+
+	return 0;
+}
+
 static int mt7531_sw_post_init(struct gsw_mt753x *gsw)
 {
 	int i;
@@ -1016,7 +1128,8 @@
 	val |= POWER_ON_OFF;
 	gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
 
-	mt7531_phy_pll_setup(gsw);
+	if (!gsw->direct_access)
+		mt7531_phy_pll_setup(gsw);
 
 	/* Enable Internal PHYs before phy setting */
 	val = gsw->mmd_read(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403);
@@ -1041,7 +1154,14 @@
 	for (i = 0; i < MT753X_NUM_PHYS; i++)
 		gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_141, 0x0);
 
-	mt7531_internal_phy_calibration(gsw);
+	if (!gsw->direct_access)
+		mt7531_internal_phy_calibration(gsw);
+
+	/* PHY force slave disable, restart AN*/
+	for (i = 0; i < MT753X_NUM_PHYS; i++) {
+		gsw->mii_write(gsw, i, MII_CTRL1000, 0x200);
+		gsw->mii_write(gsw, i, MII_BMCR, 0x1240);
+	}
 
 	return 0;
 }
@@ -1053,6 +1173,13 @@
 	.post_init = mt7531_sw_post_init
 };
 
+struct mt753x_sw_id mt7988_id = {
+	.model = MT7988,
+	.detect = mt7988_sw_detect,
+	.init = mt7988_sw_init,
+	.post_init = mt7531_sw_post_init
+};
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Zhanguo Ju <zhanguo.ju@mediatek.com>");
 MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch");
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.h b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.h
new file mode 100644
index 0000000..2167722
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+#ifndef _MT7531_H_
+#define _MT7531_H_
+#include "mt753x.h"
+extern struct mt753x_sw_id mt7531_id;
+extern struct mt753x_sw_id mt7988_id;
+#endif /* _MT7531_H_ */
+
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x.h b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x.h
old mode 100755
new mode 100644
index 732bda1..344d2b0
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x.h
@@ -13,6 +13,7 @@
 #include <linux/of_mdio.h>
 #include <linux/workqueue.h>
 #include <linux/gpio/consumer.h>
+#include <linux/phy.h>
 
 #ifdef CONFIG_SWCONFIG
 #include <linux/switch.h>
@@ -30,12 +31,13 @@
 
 enum mt753x_model {
 	MT7530 = 0x7530,
-	MT7531 = 0x7531
+	MT7531 = 0x7531,
+	MT7988 = 0x7988,
 };
 
 struct mt753x_port_cfg {
 	struct device_node *np;
-	int phy_mode;
+	phy_interface_t phy_mode;
 	u32 enabled: 1;
 	u32 force_link: 1;
 	u32 speed: 2;
@@ -60,6 +62,10 @@
 	u32 smi_addr;
 	u32 phy_base;
 	int direct_phy_access;
+	bool direct_access;
+
+	void __iomem *base;
+	struct regmap *sysctrl_base;
 
 	enum mt753x_model model;
 	const char *name;
@@ -70,7 +76,7 @@
 	bool hw_phy_cal;
 	bool phy_status_poll;
 	struct mt753x_phy phys[MT753X_NUM_PHYS];
-//	int phy_irqs[PHY_MAX_ADDR]; //FIXME 
+//	int phy_irqs[PHY_MAX_ADDR]; //FIXME
 
 	int phy_link_sts;
 
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
old mode 100755
new mode 100644
index 3639df1..c57a5a2
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
@@ -33,19 +33,24 @@
 static struct mt753x_sw_id *mt753x_sw_ids[] = {
 	&mt7530_id,
 	&mt7531_id,
+	&mt7988_id,
 };
 
 u32 mt753x_reg_read(struct gsw_mt753x *gsw, u32 reg)
 {
 	u32 high, low;
 
-	mutex_lock(&gsw->host_bus->mdio_lock);
+	if (gsw->direct_access)
+		return __raw_readl(gsw->base + reg);
 
+	mutex_lock(&gsw->host_bus->mdio_lock);
 	gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f,
-		(reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S);
+			     (reg & MT753X_REG_PAGE_ADDR_M) >>
+				     MT753X_REG_PAGE_ADDR_S);
 
 	low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr,
-		(reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S);
+				  (reg & MT753X_REG_ADDR_M) >>
+					  MT753X_REG_ADDR_S);
 
 	high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x10);
 
@@ -56,17 +61,24 @@
 
 void mt753x_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val)
 {
-	mutex_lock(&gsw->host_bus->mdio_lock);
-
-	gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f,
-		(reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S);
+	if (gsw->direct_access) {
+		__raw_writel(val, gsw->base + reg);
+	} else {
+		mutex_lock(&gsw->host_bus->mdio_lock);
+		gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f,
+				     (reg & MT753X_REG_PAGE_ADDR_M) >>
+					     MT753X_REG_PAGE_ADDR_S);
 
-	gsw->host_bus->write(gsw->host_bus, gsw->smi_addr,
-		(reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S, val & 0xffff);
+		gsw->host_bus->write(gsw->host_bus, gsw->smi_addr,
+				     (reg & MT753X_REG_ADDR_M) >>
+					     MT753X_REG_ADDR_S,
+				     val & 0xffff);
 
-	gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, val >> 16);
+		gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10,
+				     val >> 16);
 
-	mutex_unlock(&gsw->host_bus->mdio_lock);
+		mutex_unlock(&gsw->host_bus->mdio_lock);
+	}
 }
 
 /* Indirect MDIO clause 22/45 access */
@@ -89,8 +101,7 @@
 			return -ETIMEDOUT;
 	}
 
-	val = (st << MDIO_ST_S) |
-	      ((cmd << MDIO_CMD_S) & MDIO_CMD_M) |
+	val = (st << MDIO_ST_S) | ((cmd << MDIO_CMD_S) & MDIO_CMD_M) |
 	      ((phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) |
 	      ((reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M);
 
@@ -182,19 +193,19 @@
 
 	mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
 		      (MMD_ADDR << MMD_CMD_S) |
-		      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
 		      MDIO_CMD_WRITE, MDIO_ST_C22);
 
-	mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg,
-		      MDIO_CMD_WRITE, MDIO_ST_C22);
+	mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, MDIO_CMD_WRITE,
+		      MDIO_ST_C22);
 
 	mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
 		      (MMD_DATA << MMD_CMD_S) |
-		      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
 		      MDIO_CMD_WRITE, MDIO_ST_C22);
 
-	val = mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, 0,
-			    MDIO_CMD_READ, MDIO_ST_C22);
+	val = mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, 0, MDIO_CMD_READ,
+			    MDIO_ST_C22);
 
 	mutex_unlock(&gsw->mii_lock);
 
@@ -211,19 +222,19 @@
 
 	mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
 		      (MMD_ADDR << MMD_CMD_S) |
-		      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
 		      MDIO_CMD_WRITE, MDIO_ST_C22);
 
-	mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg,
-		      MDIO_CMD_WRITE, MDIO_ST_C22);
+	mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, MDIO_CMD_WRITE,
+		      MDIO_ST_C22);
 
 	mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
 		      (MMD_DATA << MMD_CMD_S) |
-		      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
+			      ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
 		      MDIO_CMD_WRITE, MDIO_ST_C22);
 
-	mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, val,
-		      MDIO_CMD_WRITE, MDIO_ST_C22);
+	mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, val, MDIO_CMD_WRITE,
+		      MDIO_ST_C22);
 
 	mutex_unlock(&gsw->mii_lock);
 }
@@ -239,6 +250,7 @@
 	struct device_node *fixed_link_node;
 	struct mt753x_port_cfg *port_cfg;
 	u32 port;
+	int ret;
 
 	for_each_child_of_node(gsw->dev->of_node, port_np) {
 		if (!of_device_is_compatible(port_np, "mediatek,mt753x-port"))
@@ -269,8 +281,8 @@
 
 		port_cfg->np = port_np;
 
-		port_cfg->phy_mode = of_get_phy_mode(port_np);
-		if (port_cfg->phy_mode < 0) {
+		ret = of_get_phy_mode(port_cfg->np);
+		if (ret < 0) {
 			dev_info(gsw->dev, "incorrect phy-mode %d\n", port);
 			continue;
 		}
@@ -303,6 +315,7 @@
 			case 2500:
 				port_cfg->speed = MAC_SPD_2500;
 				break;
+
 			default:
 				dev_info(gsw->dev, "incorrect speed %d\n",
 					 speed);
@@ -310,10 +323,10 @@
 			}
 		}
 
-		port_cfg->ssc_on = of_property_read_bool(port_cfg->np,
-							 "mediatek,ssc-on");
-		port_cfg->stag_on = of_property_read_bool(port_cfg->np,
-							  "mediatek,stag-on");
+		port_cfg->ssc_on =
+			of_property_read_bool(port_cfg->np, "mediatek,ssc-on");
+		port_cfg->stag_on =
+			of_property_read_bool(port_cfg->np, "mediatek,stag-on");
 		port_cfg->enabled = 1;
 	}
 }
@@ -438,7 +451,6 @@
 	mutex_unlock(&mt753x_devs_lock);
 }
 
-
 struct gsw_mt753x *mt753x_get_gsw(u32 id)
 {
 	struct gsw_mt753x *dev;
@@ -505,8 +517,8 @@
 
 	gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
 	if (gsw->reset_pin < 0) {
-		dev_err(gsw->dev, "Missing reset pin of switch\n");
-		return ret;
+		dev_info(gsw->dev, "No reset pin of switch\n");
+		return 0;
 	}
 
 	ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "mt753x-reset");
@@ -523,7 +535,7 @@
 
 	return 0;
 }
-#if 1 //XDXDXDXD
+
 static int mt753x_mdio_read(struct mii_bus *bus, int addr, int reg)
 {
 	struct gsw_mt753x *gsw = bus->priv;
@@ -540,8 +552,7 @@
 	return 0;
 }
 
-static const struct net_device_ops mt753x_dummy_netdev_ops = {
-};
+static const struct net_device_ops mt753x_dummy_netdev_ops = {};
 
 static void mt753x_phy_link_handler(struct net_device *dev)
 {
@@ -552,8 +563,8 @@
 
 	if (phydev->link) {
 		dev_info(gsw->dev,
-			 "Port %d Link is Up - %s/%s - flow control %s\n",
-			 port, phy_speed_to_str(phydev->speed),
+			 "Port %d Link is Up - %s/%s - flow control %s\n", port,
+			 phy_speed_to_str(phydev->speed),
 			 (phydev->duplex == DUPLEX_FULL) ? "Full" : "Half",
 			 phydev->pause ? "rx/tx" : "off");
 	} else {
@@ -566,7 +577,8 @@
 {
 	struct device_node *phy_np;
 	struct mt753x_phy *phy;
-	int phy_mode;
+	phy_interface_t iface;
+	int ret;
 	u32 phyad;
 
 	if (!mii_np)
@@ -579,10 +591,10 @@
 		if (phyad >= MT753X_NUM_PHYS)
 			continue;
 
-		phy_mode = of_get_phy_mode(phy_np);
-		if (phy_mode < 0) {
+		ret = of_get_phy_mode(phy_np);
+		if (ret < 0) {
 			dev_info(gsw->dev, "incorrect phy-mode %d for PHY %d\n",
-				 phy_mode, phyad);
+				 iface, phyad);
 			continue;
 		}
 
@@ -593,7 +605,7 @@
 		phy->netdev.netdev_ops = &mt753x_dummy_netdev_ops;
 
 		phy->phydev = of_phy_connect(&phy->netdev, phy_np,
-					mt753x_phy_link_handler, 0, phy_mode);
+					     mt753x_phy_link_handler, 0, iface);
 		if (!phy->phydev) {
 			dev_info(gsw->dev, "could not connect to PHY %d\n",
 				 phyad);
@@ -640,7 +652,7 @@
 	gsw->gphy_bus->priv = gsw;
 	gsw->gphy_bus->parent = gsw->dev;
 	gsw->gphy_bus->phy_mask = BIT(MT753X_NUM_PHYS) - 1;
-//	gsw->gphy_bus->irq = gsw->phy_irqs;
+	//	gsw->gphy_bus->irq = gsw->phy_irqs;
 
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		gsw->gphy_bus->irq[i] = PHY_POLL;
@@ -655,7 +667,6 @@
 	ret = of_mdiobus_register(gsw->gphy_bus, mii_np);
 
 	if (ret) {
-		devm_mdiobus_free(gsw->dev, gsw->gphy_bus);
 		gsw->gphy_bus = NULL;
 	} else {
 		if (gsw->phy_status_poll)
@@ -668,7 +679,6 @@
 
 	return ret;
 }
-#endif
 
 static irqreturn_t mt753x_irq_handler(int irq, void *dev)
 {
@@ -710,8 +720,10 @@
 	mutex_init(&gsw->mii_lock);
 
 	/* Switch hard reset */
-	if (mt753x_hw_reset(gsw))
+	if (mt753x_hw_reset(gsw)) {
+		dev_info(&pdev->dev, "reset switch fail.\n");
 		goto fail;
+	}
 
 	/* Fetch the SMI address dirst */
 	if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr))
@@ -768,8 +780,8 @@
 
 	platform_set_drvdata(pdev, gsw);
 
-	gsw->phy_status_poll = of_property_read_bool(gsw->dev->of_node,
-						     "mediatek,phy-poll");
+	gsw->phy_status_poll =
+		of_property_read_bool(gsw->dev->of_node, "mediatek,phy-poll");
 
 	mt753x_add_gsw(gsw);
 #if 1 //XDXD
@@ -825,7 +837,7 @@
 
 static const struct of_device_id mt753x_ids[] = {
 	{ .compatible = "mediatek,mt753x" },
-	{ },
+	{},
 };
 
 MODULE_DEVICE_TABLE(of, mt753x_ids);
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.c
old mode 100755
new mode 100644
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.h b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.h
old mode 100755
new mode 100644
index 7a2a992..e36b6f3
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.h
@@ -38,7 +38,6 @@
 #ifdef __KERNEL__
 int mt753x_nl_init(void);
 void mt753x_nl_exit(void);
-
 #endif /* __KERNEL__ */
 
 #endif /* _MT753X_NL_H_ */
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_regs.h b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_regs.h
old mode 100755
new mode 100644
index 1784873..733da63
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_regs.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_regs.h
@@ -9,6 +9,9 @@
 
 #include <linux/bitops.h>
 
+/* ethernet wrap register */
+#define ETH_RESET		0x8
+
 /* Values of Egress TAG Control */
 #define ETAG_CTRL_UNTAG			0
 #define ETAG_CTRL_TAG			2
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c
old mode 100755
new mode 100644
diff --git a/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7988.c
new file mode 100644
index 0000000..3be91dd
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/pinctrl/mediatek/pinctrl-mt7988.c
@@ -0,0 +1,1467 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The MT7988 driver based on Linux generic pinctrl binding.
+ *
+ * Copyright (C) 2020 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include "pinctrl-moore.h"
+
+enum MT7988_PINCTRL_REG_PAGE {
+	GPIO_BASE,
+	IOCFG_TR_BASE,
+	IOCFG_BR_BASE,
+	IOCFG_RB_BASE,
+	IOCFG_LB_BASE,
+	IOCFG_TL_BASE,
+};
+
+#define MT7988_PIN(_number, _name) MTK_PIN(_number, _name, 0, _number, DRV_GRP4)
+
+#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,     \
+		       _x_bits)                                                \
+	PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,     \
+		       _x_bits, 32, 0)
+
+#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,    \
+			_x_bits)                                               \
+	PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit,     \
+		       _x_bits, 32, 1)
+
+static const struct mtk_pin_field_calc mt7988_pin_mode_range[] = {
+	PIN_FIELD(0, 83, 0x300, 0x10, 0, 4),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_dir_range[] = {
+	PIN_FIELD(0, 83, 0x0, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_di_range[] = {
+	PIN_FIELD(0, 83, 0x200, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_do_range[] = {
+	PIN_FIELD(0, 83, 0x100, 0x10, 0, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_ies_range[] = {
+	PIN_FIELD_BASE(0, 0, 5, 0x30, 0x10, 13, 1),
+	PIN_FIELD_BASE(1, 1, 5, 0x30, 0x10, 14, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 11, 1),
+	PIN_FIELD_BASE(3, 3, 5, 0x30, 0x10, 12, 1),
+	PIN_FIELD_BASE(4, 4, 5, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 5, 5, 0x30, 0x10, 9, 1),
+	PIN_FIELD_BASE(6, 6, 5, 0x30, 0x10, 10, 1),
+
+	PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 8, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 6, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(10, 10, 4, 0x30, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(11, 11, 1, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(12, 12, 1, 0x40, 0x10, 21, 1),
+	PIN_FIELD_BASE(13, 13, 1, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(14, 14, 1, 0x40, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(15, 15, 5, 0x30, 0x10, 7, 1),
+	PIN_FIELD_BASE(16, 16, 5, 0x30, 0x10, 8, 1),
+	PIN_FIELD_BASE(17, 17, 5, 0x30, 0x10, 3, 1),
+	PIN_FIELD_BASE(18, 18, 5, 0x30, 0x10, 4, 1),
+
+	PIN_FIELD_BASE(19, 19, 4, 0x30, 0x10, 7, 1),
+	PIN_FIELD_BASE(20, 20, 4, 0x30, 0x10, 4, 1),
+
+	PIN_FIELD_BASE(21, 21, 3, 0x50, 0x10, 17, 1),
+	PIN_FIELD_BASE(22, 22, 3, 0x50, 0x10, 23, 1),
+	PIN_FIELD_BASE(23, 23, 3, 0x50, 0x10, 20, 1),
+	PIN_FIELD_BASE(24, 24, 3, 0x50, 0x10, 19, 1),
+	PIN_FIELD_BASE(25, 25, 3, 0x50, 0x10, 21, 1),
+	PIN_FIELD_BASE(26, 26, 3, 0x50, 0x10, 22, 1),
+	PIN_FIELD_BASE(27, 27, 3, 0x50, 0x10, 18, 1),
+	PIN_FIELD_BASE(28, 28, 3, 0x50, 0x10, 25, 1),
+	PIN_FIELD_BASE(29, 29, 3, 0x50, 0x10, 26, 1),
+	PIN_FIELD_BASE(30, 30, 3, 0x50, 0x10, 27, 1),
+	PIN_FIELD_BASE(31, 31, 3, 0x50, 0x10, 24, 1),
+	PIN_FIELD_BASE(32, 32, 3, 0x50, 0x10, 28, 1),
+	PIN_FIELD_BASE(33, 33, 3, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(34, 34, 3, 0x50, 0x10, 31, 1),
+	PIN_FIELD_BASE(35, 35, 3, 0x50, 0x10, 29, 1),
+	PIN_FIELD_BASE(36, 36, 3, 0x50, 0x10, 30, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 1, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x50, 0x10, 11, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x50, 0x10, 10, 1),
+	PIN_FIELD_BASE(40, 40, 3, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(41, 41, 3, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(42, 42, 3, 0x50, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 3, 0x50, 0x10, 8, 1),
+	PIN_FIELD_BASE(44, 44, 3, 0x50, 0x10, 7, 1),
+	PIN_FIELD_BASE(45, 45, 3, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(46, 46, 3, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(47, 47, 3, 0x50, 0x10, 4, 1),
+	PIN_FIELD_BASE(48, 48, 3, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(49, 49, 3, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(50, 50, 3, 0x50, 0x10, 15, 1),
+	PIN_FIELD_BASE(51, 51, 3, 0x50, 0x10, 12, 1),
+	PIN_FIELD_BASE(52, 52, 3, 0x50, 0x10, 13, 1),
+	PIN_FIELD_BASE(53, 53, 3, 0x50, 0x10, 14, 1),
+	PIN_FIELD_BASE(54, 54, 3, 0x50, 0x10, 16, 1),
+
+	PIN_FIELD_BASE(55, 55, 1, 0x40, 0x10, 14, 1),
+	PIN_FIELD_BASE(56, 56, 1, 0x40, 0x10, 15, 1),
+	PIN_FIELD_BASE(57, 57, 1, 0x40, 0x10, 13, 1),
+	PIN_FIELD_BASE(58, 58, 1, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(59, 59, 1, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(60, 60, 1, 0x40, 0x10, 6, 1),
+	PIN_FIELD_BASE(61, 61, 1, 0x40, 0x10, 3, 1),
+	PIN_FIELD_BASE(62, 62, 1, 0x40, 0x10, 7, 1),
+	PIN_FIELD_BASE(63, 63, 1, 0x40, 0x10, 20, 1),
+	PIN_FIELD_BASE(64, 64, 1, 0x40, 0x10, 8, 1),
+	PIN_FIELD_BASE(65, 65, 1, 0x40, 0x10, 9, 1),
+	PIN_FIELD_BASE(66, 66, 1, 0x40, 0x10, 10, 1),
+	PIN_FIELD_BASE(67, 67, 1, 0x40, 0x10, 11, 1),
+	PIN_FIELD_BASE(68, 68, 1, 0x40, 0x10, 12, 1),
+
+	PIN_FIELD_BASE(69, 69, 5, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, 5, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(71, 71, 5, 0x30, 0x10, 5, 1),
+	PIN_FIELD_BASE(72, 72, 5, 0x30, 0x10, 6, 1),
+
+	PIN_FIELD_BASE(73, 73, 4, 0x30, 0x10, 10, 1),
+	PIN_FIELD_BASE(74, 74, 4, 0x30, 0x10, 1, 1),
+	PIN_FIELD_BASE(75, 75, 4, 0x30, 0x10, 11, 1),
+	PIN_FIELD_BASE(76, 76, 4, 0x30, 0x10, 9, 1),
+	PIN_FIELD_BASE(77, 77, 4, 0x30, 0x10, 2, 1),
+	PIN_FIELD_BASE(78, 78, 4, 0x30, 0x10, 0, 1),
+	PIN_FIELD_BASE(79, 79, 4, 0x30, 0x10, 12, 1),
+
+	PIN_FIELD_BASE(80, 80, 1, 0x40, 0x10, 18, 1),
+	PIN_FIELD_BASE(81, 81, 1, 0x40, 0x10, 19, 1),
+	PIN_FIELD_BASE(82, 82, 1, 0x40, 0x10, 16, 1),
+	PIN_FIELD_BASE(83, 83, 1, 0x40, 0x10, 17, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_smt_range[] = {
+	PIN_FIELD_BASE(0, 0, 5, 0xc0, 0x10, 13, 1),
+	PIN_FIELD_BASE(1, 1, 5, 0xc0, 0x10, 14, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0xc0, 0x10, 11, 1),
+	PIN_FIELD_BASE(3, 3, 5, 0xc0, 0x10, 12, 1),
+	PIN_FIELD_BASE(4, 4, 5, 0xc0, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 5, 5, 0xc0, 0x10, 9, 1),
+	PIN_FIELD_BASE(6, 6, 5, 0xc0, 0x10, 10, 1),
+
+	PIN_FIELD_BASE(7, 7, 4, 0xb0, 0x10, 8, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0xb0, 0x10, 6, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0xb0, 0x10, 5, 1),
+	PIN_FIELD_BASE(10, 10, 4, 0xb0, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(11, 11, 1, 0xe0, 0x10, 0, 1),
+	PIN_FIELD_BASE(12, 12, 1, 0xe0, 0x10, 21, 1),
+	PIN_FIELD_BASE(13, 13, 1, 0xe0, 0x10, 1, 1),
+	PIN_FIELD_BASE(14, 14, 1, 0xe0, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(15, 15, 5, 0xc0, 0x10, 7, 1),
+	PIN_FIELD_BASE(16, 16, 5, 0xc0, 0x10, 8, 1),
+	PIN_FIELD_BASE(17, 17, 5, 0xc0, 0x10, 3, 1),
+	PIN_FIELD_BASE(18, 18, 5, 0xc0, 0x10, 4, 1),
+
+	PIN_FIELD_BASE(19, 19, 4, 0xb0, 0x10, 7, 1),
+	PIN_FIELD_BASE(20, 20, 4, 0xb0, 0x10, 4, 1),
+
+	PIN_FIELD_BASE(21, 21, 3, 0x140, 0x10, 17, 1),
+	PIN_FIELD_BASE(22, 22, 3, 0x140, 0x10, 23, 1),
+	PIN_FIELD_BASE(23, 23, 3, 0x140, 0x10, 20, 1),
+	PIN_FIELD_BASE(24, 24, 3, 0x140, 0x10, 19, 1),
+	PIN_FIELD_BASE(25, 25, 3, 0x140, 0x10, 21, 1),
+	PIN_FIELD_BASE(26, 26, 3, 0x140, 0x10, 22, 1),
+	PIN_FIELD_BASE(27, 27, 3, 0x140, 0x10, 18, 1),
+	PIN_FIELD_BASE(28, 28, 3, 0x140, 0x10, 25, 1),
+	PIN_FIELD_BASE(29, 29, 3, 0x140, 0x10, 26, 1),
+	PIN_FIELD_BASE(30, 30, 3, 0x140, 0x10, 27, 1),
+	PIN_FIELD_BASE(31, 31, 3, 0x140, 0x10, 24, 1),
+	PIN_FIELD_BASE(32, 32, 3, 0x140, 0x10, 28, 1),
+	PIN_FIELD_BASE(33, 33, 3, 0x150, 0x10, 0, 1),
+	PIN_FIELD_BASE(34, 34, 3, 0x140, 0x10, 31, 1),
+	PIN_FIELD_BASE(35, 35, 3, 0x140, 0x10, 29, 1),
+	PIN_FIELD_BASE(36, 36, 3, 0x140, 0x10, 30, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x150, 0x10, 1, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x140, 0x10, 11, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x140, 0x10, 10, 1),
+	PIN_FIELD_BASE(40, 40, 3, 0x140, 0x10, 0, 1),
+	PIN_FIELD_BASE(41, 41, 3, 0x140, 0x10, 1, 1),
+	PIN_FIELD_BASE(42, 42, 3, 0x140, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 3, 0x140, 0x10, 8, 1),
+	PIN_FIELD_BASE(44, 44, 3, 0x140, 0x10, 7, 1),
+	PIN_FIELD_BASE(45, 45, 3, 0x140, 0x10, 6, 1),
+	PIN_FIELD_BASE(46, 46, 3, 0x140, 0x10, 5, 1),
+	PIN_FIELD_BASE(47, 47, 3, 0x140, 0x10, 4, 1),
+	PIN_FIELD_BASE(48, 48, 3, 0x140, 0x10, 3, 1),
+	PIN_FIELD_BASE(49, 49, 3, 0x140, 0x10, 2, 1),
+	PIN_FIELD_BASE(50, 50, 3, 0x140, 0x10, 15, 1),
+	PIN_FIELD_BASE(51, 51, 3, 0x140, 0x10, 12, 1),
+	PIN_FIELD_BASE(52, 52, 3, 0x140, 0x10, 13, 1),
+	PIN_FIELD_BASE(53, 53, 3, 0x140, 0x10, 14, 1),
+	PIN_FIELD_BASE(54, 54, 3, 0x140, 0x10, 16, 1),
+
+	PIN_FIELD_BASE(55, 55, 1, 0xe0, 0x10, 14, 1),
+	PIN_FIELD_BASE(56, 56, 1, 0xe0, 0x10, 15, 1),
+	PIN_FIELD_BASE(57, 57, 1, 0xe0, 0x10, 13, 1),
+	PIN_FIELD_BASE(58, 58, 1, 0xe0, 0x10, 4, 1),
+	PIN_FIELD_BASE(59, 59, 1, 0xe0, 0x10, 5, 1),
+	PIN_FIELD_BASE(60, 60, 1, 0xe0, 0x10, 6, 1),
+	PIN_FIELD_BASE(61, 61, 1, 0xe0, 0x10, 3, 1),
+	PIN_FIELD_BASE(62, 62, 1, 0xe0, 0x10, 7, 1),
+	PIN_FIELD_BASE(63, 63, 1, 0xe0, 0x10, 20, 1),
+	PIN_FIELD_BASE(64, 64, 1, 0xe0, 0x10, 8, 1),
+	PIN_FIELD_BASE(65, 65, 1, 0xe0, 0x10, 9, 1),
+	PIN_FIELD_BASE(66, 66, 1, 0xe0, 0x10, 10, 1),
+	PIN_FIELD_BASE(67, 67, 1, 0xe0, 0x10, 11, 1),
+	PIN_FIELD_BASE(68, 68, 1, 0xe0, 0x10, 12, 1),
+
+	PIN_FIELD_BASE(69, 69, 5, 0xc0, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, 5, 0xc0, 0x10, 2, 1),
+	PIN_FIELD_BASE(71, 71, 5, 0xc0, 0x10, 5, 1),
+	PIN_FIELD_BASE(72, 72, 5, 0xc0, 0x10, 6, 1),
+
+	PIN_FIELD_BASE(73, 73, 4, 0xb0, 0x10, 10, 1),
+	PIN_FIELD_BASE(74, 74, 4, 0xb0, 0x10, 1, 1),
+	PIN_FIELD_BASE(75, 75, 4, 0xb0, 0x10, 11, 1),
+	PIN_FIELD_BASE(76, 76, 4, 0xb0, 0x10, 9, 1),
+	PIN_FIELD_BASE(77, 77, 4, 0xb0, 0x10, 2, 1),
+	PIN_FIELD_BASE(78, 78, 4, 0xb0, 0x10, 0, 1),
+	PIN_FIELD_BASE(79, 79, 4, 0xb0, 0x10, 12, 1),
+
+	PIN_FIELD_BASE(80, 80, 1, 0xe0, 0x10, 18, 1),
+	PIN_FIELD_BASE(81, 81, 1, 0xe0, 0x10, 19, 1),
+	PIN_FIELD_BASE(82, 82, 1, 0xe0, 0x10, 16, 1),
+	PIN_FIELD_BASE(83, 83, 1, 0xe0, 0x10, 17, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_pu_range[] = {
+	PIN_FIELD_BASE(7, 7, 4, 0x60, 0x10, 5, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x60, 0x10, 4, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x60, 0x10, 3, 1),
+	PIN_FIELD_BASE(10, 10, 4, 0x60, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(13, 13, 1, 0x70, 0x10, 0, 1),
+	PIN_FIELD_BASE(14, 14, 1, 0x70, 0x10, 1, 1),
+	PIN_FIELD_BASE(63, 63, 1, 0x70, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(75, 75, 4, 0x60, 0x10, 7, 1),
+	PIN_FIELD_BASE(76, 76, 4, 0x60, 0x10, 6, 1),
+	PIN_FIELD_BASE(77, 77, 4, 0x60, 0x10, 1, 1),
+	PIN_FIELD_BASE(78, 78, 4, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(79, 79, 4, 0x60, 0x10, 8, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_pd_range[] = {
+	PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(9, 9, 4, 0x40, 0x10, 3, 1),
+	PIN_FIELD_BASE(10, 10, 4, 0x40, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(13, 13, 1, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(14, 14, 1, 0x50, 0x10, 1, 1),
+
+	PIN_FIELD_BASE(15, 15, 5, 0x40, 0x10, 4, 1),
+	PIN_FIELD_BASE(16, 16, 5, 0x40, 0x10, 5, 1),
+	PIN_FIELD_BASE(17, 17, 5, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(18, 18, 5, 0x40, 0x10, 1, 1),
+
+	PIN_FIELD_BASE(63, 63, 1, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(71, 71, 5, 0x40, 0x10, 2, 1),
+	PIN_FIELD_BASE(72, 72, 5, 0x40, 0x10, 3, 1),
+
+	PIN_FIELD_BASE(75, 75, 4, 0x40, 0x10, 7, 1),
+	PIN_FIELD_BASE(76, 76, 4, 0x40, 0x10, 6, 1),
+	PIN_FIELD_BASE(77, 77, 4, 0x40, 0x10, 1, 1),
+	PIN_FIELD_BASE(78, 78, 4, 0x40, 0x10, 0, 1),
+	PIN_FIELD_BASE(79, 79, 4, 0x40, 0x10, 8, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_drv_range[] = {
+	PIN_FIELD_BASE(0, 0, 5, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(1, 1, 5, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(3, 3, 5, 0x00, 0x10, 18, 3),
+	PIN_FIELD_BASE(4, 4, 5, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(5, 5, 5, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(6, 6, 5, 0x00, 0x10, 12, 3),
+
+	PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 28, 3),
+	PIN_FIELD_BASE(9, 9, 4, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(10, 10, 4, 0x00, 0x10, 9, 3),
+
+	PIN_FIELD_BASE(11, 11, 1, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(12, 12, 1, 0x20, 0x10, 3, 3),
+	PIN_FIELD_BASE(13, 13, 1, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(14, 14, 1, 0x00, 0x10, 6, 3),
+
+	PIN_FIELD_BASE(19, 19, 4, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(20, 20, 4, 0x00, 0x10, 12, 3),
+
+	PIN_FIELD_BASE(21, 21, 3, 0x10, 0x10, 21, 3),
+	PIN_FIELD_BASE(22, 22, 3, 0x20, 0x10, 9, 3),
+	PIN_FIELD_BASE(23, 23, 3, 0x20, 0x10, 0, 3),
+	PIN_FIELD_BASE(24, 24, 3, 0x10, 0x10, 27, 3),
+	PIN_FIELD_BASE(25, 25, 3, 0x20, 0x10, 3, 3),
+	PIN_FIELD_BASE(26, 26, 3, 0x20, 0x10, 6, 3),
+	PIN_FIELD_BASE(27, 27, 3, 0x10, 0x10, 24, 3),
+	PIN_FIELD_BASE(28, 28, 3, 0x20, 0x10, 15, 3),
+	PIN_FIELD_BASE(29, 29, 3, 0x20, 0x10, 18, 3),
+	PIN_FIELD_BASE(30, 30, 3, 0x20, 0x10, 21, 3),
+	PIN_FIELD_BASE(31, 31, 3, 0x20, 0x10, 12, 3),
+	PIN_FIELD_BASE(32, 32, 3, 0x20, 0x10, 24, 3),
+	PIN_FIELD_BASE(33, 33, 3, 0x30, 0x10, 6, 3),
+	PIN_FIELD_BASE(34, 34, 3, 0x30, 0x10, 3, 3),
+	PIN_FIELD_BASE(35, 35, 3, 0x20, 0x10, 27, 3),
+	PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 0, 3),
+	PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 9, 3),
+	PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 3, 3),
+	PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 0, 3),
+	PIN_FIELD_BASE(40, 40, 3, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(41, 41, 3, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(42, 42, 3, 0x00, 0x10, 27, 3),
+	PIN_FIELD_BASE(43, 43, 3, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(44, 44, 3, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(45, 45, 3, 0x00, 0x10, 18, 3),
+	PIN_FIELD_BASE(46, 46, 3, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(47, 47, 3, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(48, 48, 3, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(49, 49, 3, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(50, 50, 3, 0x10, 0x10, 15, 3),
+	PIN_FIELD_BASE(51, 51, 3, 0x10, 0x10, 6, 3),
+	PIN_FIELD_BASE(52, 52, 3, 0x10, 0x10, 9, 3),
+	PIN_FIELD_BASE(53, 53, 3, 0x10, 0x10, 12, 3),
+	PIN_FIELD_BASE(54, 54, 3, 0x10, 0x10, 18, 3),
+
+	PIN_FIELD_BASE(55, 55, 1, 0x10, 0x10, 12, 3),
+	PIN_FIELD_BASE(56, 56, 1, 0x10, 0x10, 15, 3),
+	PIN_FIELD_BASE(57, 57, 1, 0x10, 0x10, 9, 3),
+	PIN_FIELD_BASE(58, 58, 1, 0x00, 0x10, 12, 3),
+	PIN_FIELD_BASE(59, 59, 1, 0x00, 0x10, 15, 3),
+	PIN_FIELD_BASE(60, 60, 1, 0x00, 0x10, 18, 3),
+	PIN_FIELD_BASE(61, 61, 1, 0x00, 0x10, 9, 3),
+	PIN_FIELD_BASE(62, 62, 1, 0x00, 0x10, 21, 3),
+	PIN_FIELD_BASE(63, 63, 1, 0x20, 0x10, 0, 3),
+	PIN_FIELD_BASE(64, 64, 1, 0x00, 0x10, 24, 3),
+	PIN_FIELD_BASE(65, 65, 1, 0x00, 0x10, 27, 3),
+	PIN_FIELD_BASE(66, 66, 1, 0x10, 0x10, 0, 3),
+	PIN_FIELD_BASE(67, 67, 1, 0x10, 0x10, 3, 3),
+	PIN_FIELD_BASE(68, 68, 1, 0x10, 0x10, 6, 3),
+
+	PIN_FIELD_BASE(69, 69, 5, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(70, 70, 5, 0x00, 0x10, 6, 3),
+
+	PIN_FIELD_BASE(73, 73, 4, 0x10, 0x10, 0, 3),
+	PIN_FIELD_BASE(74, 74, 4, 0x00, 0x10, 3, 3),
+	PIN_FIELD_BASE(75, 75, 4, 0x10, 0x10, 3, 3),
+	PIN_FIELD_BASE(76, 76, 4, 0x00, 0x10, 27, 3),
+	PIN_FIELD_BASE(77, 77, 4, 0x00, 0x10, 6, 3),
+	PIN_FIELD_BASE(78, 78, 4, 0x00, 0x10, 0, 3),
+	PIN_FIELD_BASE(79, 79, 4, 0x10, 0x10, 6, 3),
+
+	PIN_FIELD_BASE(80, 80, 1, 0x10, 0x10, 24, 3),
+	PIN_FIELD_BASE(81, 81, 1, 0x10, 0x10, 27, 3),
+	PIN_FIELD_BASE(82, 82, 1, 0x10, 0x10, 18, 3),
+	PIN_FIELD_BASE(83, 83, 1, 0x10, 0x10, 21, 3),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_pupd_range[] = {
+	PIN_FIELD_BASE(0, 0, 5, 0x50, 0x10, 7, 1),
+	PIN_FIELD_BASE(1, 1, 5, 0x50, 0x10, 8, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 5, 1),
+	PIN_FIELD_BASE(3, 3, 5, 0x50, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 5, 0x50, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 5, 5, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(6, 6, 5, 0x50, 0x10, 4, 1),
+
+	PIN_FIELD_BASE(11, 11, 1, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(12, 12, 1, 0x60, 0x10, 18, 1),
+
+	PIN_FIELD_BASE(19, 19, 4, 0x50, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 4, 0x50, 0x10, 1, 1),
+
+	PIN_FIELD_BASE(21, 21, 3, 0x70, 0x10, 17, 1),
+	PIN_FIELD_BASE(22, 22, 3, 0x70, 0x10, 23, 1),
+	PIN_FIELD_BASE(23, 23, 3, 0x70, 0x10, 20, 1),
+	PIN_FIELD_BASE(24, 24, 3, 0x70, 0x10, 19, 1),
+	PIN_FIELD_BASE(25, 25, 3, 0x70, 0x10, 21, 1),
+	PIN_FIELD_BASE(26, 26, 3, 0x70, 0x10, 22, 1),
+	PIN_FIELD_BASE(27, 27, 3, 0x70, 0x10, 18, 1),
+	PIN_FIELD_BASE(28, 28, 3, 0x70, 0x10, 25, 1),
+	PIN_FIELD_BASE(29, 29, 3, 0x70, 0x10, 26, 1),
+	PIN_FIELD_BASE(30, 30, 3, 0x70, 0x10, 27, 1),
+	PIN_FIELD_BASE(31, 31, 3, 0x70, 0x10, 24, 1),
+	PIN_FIELD_BASE(32, 32, 3, 0x70, 0x10, 28, 1),
+	PIN_FIELD_BASE(33, 33, 3, 0x80, 0x10, 0, 1),
+	PIN_FIELD_BASE(34, 34, 3, 0x70, 0x10, 31, 1),
+	PIN_FIELD_BASE(35, 35, 3, 0x70, 0x10, 29, 1),
+	PIN_FIELD_BASE(36, 36, 3, 0x70, 0x10, 30, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0x80, 0x10, 1, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x70, 0x10, 11, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x70, 0x10, 10, 1),
+	PIN_FIELD_BASE(40, 40, 3, 0x70, 0x10, 0, 1),
+	PIN_FIELD_BASE(41, 41, 3, 0x70, 0x10, 1, 1),
+	PIN_FIELD_BASE(42, 42, 3, 0x70, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 3, 0x70, 0x10, 8, 1),
+	PIN_FIELD_BASE(44, 44, 3, 0x70, 0x10, 7, 1),
+	PIN_FIELD_BASE(45, 45, 3, 0x70, 0x10, 6, 1),
+	PIN_FIELD_BASE(46, 46, 3, 0x70, 0x10, 5, 1),
+	PIN_FIELD_BASE(47, 47, 3, 0x70, 0x10, 4, 1),
+	PIN_FIELD_BASE(48, 48, 3, 0x70, 0x10, 3, 1),
+	PIN_FIELD_BASE(49, 49, 3, 0x70, 0x10, 2, 1),
+	PIN_FIELD_BASE(50, 50, 3, 0x70, 0x10, 15, 1),
+	PIN_FIELD_BASE(51, 51, 3, 0x70, 0x10, 12, 1),
+	PIN_FIELD_BASE(52, 52, 3, 0x70, 0x10, 13, 1),
+	PIN_FIELD_BASE(53, 53, 3, 0x70, 0x10, 14, 1),
+	PIN_FIELD_BASE(54, 54, 3, 0x70, 0x10, 16, 1),
+
+	PIN_FIELD_BASE(55, 55, 1, 0x60, 0x10, 12, 1),
+	PIN_FIELD_BASE(56, 56, 1, 0x60, 0x10, 13, 1),
+	PIN_FIELD_BASE(57, 57, 1, 0x60, 0x10, 11, 1),
+	PIN_FIELD_BASE(58, 58, 1, 0x60, 0x10, 2, 1),
+	PIN_FIELD_BASE(59, 59, 1, 0x60, 0x10, 3, 1),
+	PIN_FIELD_BASE(60, 60, 1, 0x60, 0x10, 4, 1),
+	PIN_FIELD_BASE(61, 61, 1, 0x60, 0x10, 1, 1),
+	PIN_FIELD_BASE(62, 62, 1, 0x60, 0x10, 5, 1),
+	PIN_FIELD_BASE(64, 64, 1, 0x60, 0x10, 6, 1),
+	PIN_FIELD_BASE(65, 65, 1, 0x60, 0x10, 7, 1),
+	PIN_FIELD_BASE(66, 66, 1, 0x60, 0x10, 8, 1),
+	PIN_FIELD_BASE(67, 67, 1, 0x60, 0x10, 9, 1),
+	PIN_FIELD_BASE(68, 68, 1, 0x60, 0x10, 10, 1),
+
+	PIN_FIELD_BASE(69, 69, 5, 0x50, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, 5, 0x50, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(73, 73, 4, 0x50, 0x10, 3, 1),
+	PIN_FIELD_BASE(74, 74, 4, 0x50, 0x10, 0, 1),
+
+	PIN_FIELD_BASE(80, 80, 1, 0x60, 0x10, 16, 1),
+	PIN_FIELD_BASE(81, 81, 1, 0x60, 0x10, 17, 1),
+	PIN_FIELD_BASE(82, 82, 1, 0x60, 0x10, 14, 1),
+	PIN_FIELD_BASE(83, 83, 1, 0x60, 0x10, 15, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_r0_range[] = {
+	PIN_FIELD_BASE(0, 0, 5, 0x60, 0x10, 7, 1),
+	PIN_FIELD_BASE(1, 1, 5, 0x60, 0x10, 8, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x60, 0x10, 5, 1),
+	PIN_FIELD_BASE(3, 3, 5, 0x60, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 5, 0x60, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 5, 5, 0x60, 0x10, 3, 1),
+	PIN_FIELD_BASE(6, 6, 5, 0x60, 0x10, 4, 1),
+
+	PIN_FIELD_BASE(11, 11, 1, 0x80, 0x10, 0, 1),
+	PIN_FIELD_BASE(12, 12, 1, 0x80, 0x10, 18, 1),
+
+	PIN_FIELD_BASE(19, 19, 4, 0x70, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 4, 0x70, 0x10, 1, 1),
+
+	PIN_FIELD_BASE(21, 21, 3, 0x90, 0x10, 17, 1),
+	PIN_FIELD_BASE(22, 22, 3, 0x90, 0x10, 23, 1),
+	PIN_FIELD_BASE(23, 23, 3, 0x90, 0x10, 20, 1),
+	PIN_FIELD_BASE(24, 24, 3, 0x90, 0x10, 19, 1),
+	PIN_FIELD_BASE(25, 25, 3, 0x90, 0x10, 21, 1),
+	PIN_FIELD_BASE(26, 26, 3, 0x90, 0x10, 22, 1),
+	PIN_FIELD_BASE(27, 27, 3, 0x90, 0x10, 18, 1),
+	PIN_FIELD_BASE(28, 28, 3, 0x90, 0x10, 25, 1),
+	PIN_FIELD_BASE(29, 29, 3, 0x90, 0x10, 26, 1),
+	PIN_FIELD_BASE(30, 30, 3, 0x90, 0x10, 27, 1),
+	PIN_FIELD_BASE(31, 31, 3, 0x90, 0x10, 24, 1),
+	PIN_FIELD_BASE(32, 32, 3, 0x90, 0x10, 28, 1),
+	PIN_FIELD_BASE(33, 33, 3, 0xa0, 0x10, 0, 1),
+	PIN_FIELD_BASE(34, 34, 3, 0x90, 0x10, 31, 1),
+	PIN_FIELD_BASE(35, 35, 3, 0x90, 0x10, 29, 1),
+	PIN_FIELD_BASE(36, 36, 3, 0x90, 0x10, 30, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0xa0, 0x10, 1, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0x90, 0x10, 11, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0x90, 0x10, 10, 1),
+	PIN_FIELD_BASE(40, 40, 3, 0x90, 0x10, 0, 1),
+	PIN_FIELD_BASE(41, 41, 3, 0x90, 0x10, 1, 1),
+	PIN_FIELD_BASE(42, 42, 3, 0x90, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 3, 0x90, 0x10, 8, 1),
+	PIN_FIELD_BASE(44, 44, 3, 0x90, 0x10, 7, 1),
+	PIN_FIELD_BASE(45, 45, 3, 0x90, 0x10, 6, 1),
+	PIN_FIELD_BASE(46, 46, 3, 0x90, 0x10, 5, 1),
+	PIN_FIELD_BASE(47, 47, 3, 0x90, 0x10, 4, 1),
+	PIN_FIELD_BASE(48, 48, 3, 0x90, 0x10, 3, 1),
+	PIN_FIELD_BASE(49, 49, 3, 0x90, 0x10, 2, 1),
+	PIN_FIELD_BASE(50, 50, 3, 0x90, 0x10, 15, 1),
+	PIN_FIELD_BASE(51, 51, 3, 0x90, 0x10, 12, 1),
+	PIN_FIELD_BASE(52, 52, 3, 0x90, 0x10, 13, 1),
+	PIN_FIELD_BASE(53, 53, 3, 0x90, 0x10, 14, 1),
+	PIN_FIELD_BASE(54, 54, 3, 0x90, 0x10, 16, 1),
+
+	PIN_FIELD_BASE(55, 55, 1, 0x80, 0x10, 12, 1),
+	PIN_FIELD_BASE(56, 56, 1, 0x80, 0x10, 13, 1),
+	PIN_FIELD_BASE(57, 57, 1, 0x80, 0x10, 11, 1),
+	PIN_FIELD_BASE(58, 58, 1, 0x80, 0x10, 2, 1),
+	PIN_FIELD_BASE(59, 59, 1, 0x80, 0x10, 3, 1),
+	PIN_FIELD_BASE(60, 60, 1, 0x80, 0x10, 4, 1),
+	PIN_FIELD_BASE(61, 61, 1, 0x80, 0x10, 1, 1),
+	PIN_FIELD_BASE(62, 62, 1, 0x80, 0x10, 5, 1),
+	PIN_FIELD_BASE(64, 64, 1, 0x80, 0x10, 6, 1),
+	PIN_FIELD_BASE(65, 65, 1, 0x80, 0x10, 7, 1),
+	PIN_FIELD_BASE(66, 66, 1, 0x80, 0x10, 8, 1),
+	PIN_FIELD_BASE(67, 67, 1, 0x80, 0x10, 9, 1),
+	PIN_FIELD_BASE(68, 68, 1, 0x80, 0x10, 10, 1),
+
+	PIN_FIELD_BASE(69, 69, 5, 0x60, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, 5, 0x60, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(73, 73, 4, 0x70, 0x10, 3, 1),
+	PIN_FIELD_BASE(74, 74, 4, 0x70, 0x10, 0, 1),
+
+	PIN_FIELD_BASE(80, 80, 1, 0x80, 0x10, 16, 1),
+	PIN_FIELD_BASE(81, 81, 1, 0x80, 0x10, 17, 1),
+	PIN_FIELD_BASE(82, 82, 1, 0x80, 0x10, 14, 1),
+	PIN_FIELD_BASE(83, 83, 1, 0x80, 0x10, 15, 1),
+};
+
+static const struct mtk_pin_field_calc mt7988_pin_r1_range[] = {
+	PIN_FIELD_BASE(0, 0, 5, 0x70, 0x10, 7, 1),
+	PIN_FIELD_BASE(1, 1, 5, 0x70, 0x10, 8, 1),
+	PIN_FIELD_BASE(2, 2, 5, 0x70, 0x10, 5, 1),
+	PIN_FIELD_BASE(3, 3, 5, 0x70, 0x10, 6, 1),
+	PIN_FIELD_BASE(4, 4, 5, 0x70, 0x10, 0, 1),
+	PIN_FIELD_BASE(5, 5, 5, 0x70, 0x10, 3, 1),
+	PIN_FIELD_BASE(6, 6, 5, 0x70, 0x10, 4, 1),
+
+	PIN_FIELD_BASE(11, 11, 1, 0x90, 0x10, 0, 1),
+	PIN_FIELD_BASE(12, 12, 1, 0x90, 0x10, 18, 1),
+
+	PIN_FIELD_BASE(19, 19, 4, 0x80, 0x10, 2, 1),
+	PIN_FIELD_BASE(20, 20, 4, 0x80, 0x10, 1, 1),
+
+	PIN_FIELD_BASE(21, 21, 3, 0xb0, 0x10, 17, 1),
+	PIN_FIELD_BASE(22, 22, 3, 0xb0, 0x10, 23, 1),
+	PIN_FIELD_BASE(23, 23, 3, 0xb0, 0x10, 20, 1),
+	PIN_FIELD_BASE(24, 24, 3, 0xb0, 0x10, 19, 1),
+	PIN_FIELD_BASE(25, 25, 3, 0xb0, 0x10, 21, 1),
+	PIN_FIELD_BASE(26, 26, 3, 0xb0, 0x10, 22, 1),
+	PIN_FIELD_BASE(27, 27, 3, 0xb0, 0x10, 18, 1),
+	PIN_FIELD_BASE(28, 28, 3, 0xb0, 0x10, 25, 1),
+	PIN_FIELD_BASE(29, 29, 3, 0xb0, 0x10, 26, 1),
+	PIN_FIELD_BASE(30, 30, 3, 0xb0, 0x10, 27, 1),
+	PIN_FIELD_BASE(31, 31, 3, 0xb0, 0x10, 24, 1),
+	PIN_FIELD_BASE(32, 32, 3, 0xb0, 0x10, 28, 1),
+	PIN_FIELD_BASE(33, 33, 3, 0xc0, 0x10, 0, 1),
+	PIN_FIELD_BASE(34, 34, 3, 0xb0, 0x10, 31, 1),
+	PIN_FIELD_BASE(35, 35, 3, 0xb0, 0x10, 29, 1),
+	PIN_FIELD_BASE(36, 36, 3, 0xb0, 0x10, 30, 1),
+	PIN_FIELD_BASE(37, 37, 3, 0xc0, 0x10, 1, 1),
+	PIN_FIELD_BASE(38, 38, 3, 0xb0, 0x10, 11, 1),
+	PIN_FIELD_BASE(39, 39, 3, 0xb0, 0x10, 10, 1),
+	PIN_FIELD_BASE(40, 40, 3, 0xb0, 0x10, 0, 1),
+	PIN_FIELD_BASE(41, 41, 3, 0xb0, 0x10, 1, 1),
+	PIN_FIELD_BASE(42, 42, 3, 0xb0, 0x10, 9, 1),
+	PIN_FIELD_BASE(43, 43, 3, 0xb0, 0x10, 8, 1),
+	PIN_FIELD_BASE(44, 44, 3, 0xb0, 0x10, 7, 1),
+	PIN_FIELD_BASE(45, 45, 3, 0xb0, 0x10, 6, 1),
+	PIN_FIELD_BASE(46, 46, 3, 0xb0, 0x10, 5, 1),
+	PIN_FIELD_BASE(47, 47, 3, 0xb0, 0x10, 4, 1),
+	PIN_FIELD_BASE(48, 48, 3, 0xb0, 0x10, 3, 1),
+	PIN_FIELD_BASE(49, 49, 3, 0xb0, 0x10, 2, 1),
+	PIN_FIELD_BASE(50, 50, 3, 0xb0, 0x10, 15, 1),
+	PIN_FIELD_BASE(51, 51, 3, 0xb0, 0x10, 12, 1),
+	PIN_FIELD_BASE(52, 52, 3, 0xb0, 0x10, 13, 1),
+	PIN_FIELD_BASE(53, 53, 3, 0xb0, 0x10, 14, 1),
+	PIN_FIELD_BASE(54, 54, 3, 0xb0, 0x10, 16, 1),
+
+	PIN_FIELD_BASE(55, 55, 1, 0x90, 0x10, 12, 1),
+	PIN_FIELD_BASE(56, 56, 1, 0x90, 0x10, 13, 1),
+	PIN_FIELD_BASE(57, 57, 1, 0x90, 0x10, 11, 1),
+	PIN_FIELD_BASE(58, 58, 1, 0x90, 0x10, 2, 1),
+	PIN_FIELD_BASE(59, 59, 1, 0x90, 0x10, 3, 1),
+	PIN_FIELD_BASE(60, 60, 1, 0x90, 0x10, 4, 1),
+	PIN_FIELD_BASE(61, 61, 1, 0x90, 0x10, 1, 1),
+	PIN_FIELD_BASE(62, 62, 1, 0x90, 0x10, 5, 1),
+	PIN_FIELD_BASE(64, 64, 1, 0x90, 0x10, 6, 1),
+	PIN_FIELD_BASE(65, 65, 1, 0x90, 0x10, 7, 1),
+	PIN_FIELD_BASE(66, 66, 1, 0x90, 0x10, 8, 1),
+	PIN_FIELD_BASE(67, 67, 1, 0x90, 0x10, 9, 1),
+	PIN_FIELD_BASE(68, 68, 1, 0x90, 0x10, 10, 1),
+
+	PIN_FIELD_BASE(69, 69, 5, 0x70, 0x10, 1, 1),
+	PIN_FIELD_BASE(70, 70, 5, 0x70, 0x10, 2, 1),
+
+	PIN_FIELD_BASE(73, 73, 4, 0x80, 0x10, 3, 1),
+	PIN_FIELD_BASE(74, 74, 4, 0x80, 0x10, 0, 1),
+
+	PIN_FIELD_BASE(80, 80, 1, 0x90, 0x10, 16, 1),
+	PIN_FIELD_BASE(81, 81, 1, 0x90, 0x10, 17, 1),
+	PIN_FIELD_BASE(82, 82, 1, 0x90, 0x10, 14, 1),
+	PIN_FIELD_BASE(83, 83, 1, 0x90, 0x10, 15, 1),
+};
+
+static const struct mtk_pin_reg_calc mt7988_reg_cals[] = {
+	[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7988_pin_mode_range),
+	[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7988_pin_dir_range),
+	[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7988_pin_di_range),
+	[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7988_pin_do_range),
+	[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7988_pin_smt_range),
+	[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7988_pin_ies_range),
+	[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7988_pin_pu_range),
+	[PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7988_pin_pd_range),
+	[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7988_pin_drv_range),
+	[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7988_pin_pupd_range),
+	[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7988_pin_r0_range),
+	[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7988_pin_r1_range),
+};
+
+static const struct mtk_pin_desc mt7988_pins[] = {
+	MT7988_PIN(0, "UART2_RXD"),
+	MT7988_PIN(1, "UART2_TXD"),
+	MT7988_PIN(2, "UART2_CTS"),
+	MT7988_PIN(3, "UART2_RTS"),
+	MT7988_PIN(4, "GPIO_A"),
+	MT7988_PIN(5, "SMI_0_MDC"),
+	MT7988_PIN(6, "SMI_0_MDIO"),
+	MT7988_PIN(7, "PCIE30_2L_0_WAKE_N"),
+	MT7988_PIN(8, "PCIE30_2L_0_CLKREQ_N"),
+	MT7988_PIN(9, "PCIE30_1L_1_WAKE_N"),
+	MT7988_PIN(10, "PCIE30_1L_1_CLKREQ_N"),
+	MT7988_PIN(11, "GPIO_P"),
+	MT7988_PIN(12, "WATCHDOG"),
+	MT7988_PIN(13, "GPIO_RESET"),
+	MT7988_PIN(14, "GPIO_WPS"),
+	MT7988_PIN(15, "PMIC_I2C_SCL"),
+	MT7988_PIN(16, "PMIC_I2C_SDA"),
+	MT7988_PIN(17, "I2C_1_SCL"),
+	MT7988_PIN(18, "I2C_1_SDA"),
+	MT7988_PIN(19, "PCIE30_2L_0_PRESET_N"),
+	MT7988_PIN(20, "PCIE30_1L_1_PRESET_N"),
+	MT7988_PIN(21, "PWMD1"),
+	MT7988_PIN(22, "SPI0_WP"),
+	MT7988_PIN(23, "SPI0_HOLD"),
+	MT7988_PIN(24, "SPI0_CSB"),
+	MT7988_PIN(25, "SPI0_MISO"),
+	MT7988_PIN(26, "SPI0_MOSI"),
+	MT7988_PIN(27, "SPI0_CLK"),
+	MT7988_PIN(28, "SPI1_CSB"),
+	MT7988_PIN(29, "SPI1_MISO"),
+	MT7988_PIN(30, "SPI1_MOSI"),
+	MT7988_PIN(31, "SPI1_CLK"),
+	MT7988_PIN(32, "SPI2_CLK"),
+	MT7988_PIN(33, "SPI2_MOSI"),
+	MT7988_PIN(34, "SPI2_MISO"),
+	MT7988_PIN(35, "SPI2_CSB"),
+	MT7988_PIN(36, "SPI2_HOLD"),
+	MT7988_PIN(37, "SPI2_WP"),
+	MT7988_PIN(38, "EMMC_RSTB"),
+	MT7988_PIN(39, "EMMC_DSL"),
+	MT7988_PIN(40, "EMMC_CK"),
+	MT7988_PIN(41, "EMMC_CMD"),
+	MT7988_PIN(42, "EMMC_DATA_7"),
+	MT7988_PIN(43, "EMMC_DATA_6"),
+	MT7988_PIN(44, "EMMC_DATA_5"),
+	MT7988_PIN(45, "EMMC_DATA_4"),
+	MT7988_PIN(46, "EMMC_DATA_3"),
+	MT7988_PIN(47, "EMMC_DATA_2"),
+	MT7988_PIN(48, "EMMC_DATA_1"),
+	MT7988_PIN(49, "EMMC_DATA_0"),
+	MT7988_PIN(50, "PCM_FS_I2S_LRCK"),
+	MT7988_PIN(51, "PCM_CLK_I2S_BCLK"),
+	MT7988_PIN(52, "PCM_DRX_I2S_DIN"),
+	MT7988_PIN(53, "PCM_DTX_I2S_DOUT"),
+	MT7988_PIN(54, "PCM_MCK_I2S_MCLK"),
+	MT7988_PIN(55, "UART0_RXD"),
+	MT7988_PIN(56, "UART0_TXD"),
+	MT7988_PIN(57, "PWMD0"),
+	MT7988_PIN(58, "JTAG_JTDI"),
+	MT7988_PIN(59, "JTAG_JTDO"),
+	MT7988_PIN(60, "JTAG_JTMS"),
+	MT7988_PIN(61, "JTAG_JTCLK"),
+	MT7988_PIN(62, "JTAG_JTRST_N"),
+	MT7988_PIN(63, "USB_DRV_VBUS_P1"),
+	MT7988_PIN(64, "LED_A"),
+	MT7988_PIN(65, "LED_B"),
+	MT7988_PIN(66, "LED_C"),
+	MT7988_PIN(67, "LED_D"),
+	MT7988_PIN(68, "LED_E"),
+	MT7988_PIN(69, "GPIO_B"),
+	MT7988_PIN(70, "GPIO_C"),
+	MT7988_PIN(71, "I2C_2_SCL"),
+	MT7988_PIN(72, "I2C_2_SDA"),
+	MT7988_PIN(73, "PCIE30_2L_1_PRESET_N"),
+	MT7988_PIN(74, "PCIE30_1L_0_PRESET_N"),
+	MT7988_PIN(75, "PCIE30_2L_1_WAKE_N"),
+	MT7988_PIN(76, "PCIE30_2L_1_CLKREQ_N"),
+	MT7988_PIN(77, "PCIE30_1L_0_WAKE_N"),
+	MT7988_PIN(78, "PCIE30_1L_0_CLKREQ_N"),
+	MT7988_PIN(79, "USB_DRV_VBUS_P0"),
+	MT7988_PIN(80, "UART1_RXD"),
+	MT7988_PIN(81, "UART1_TXD"),
+	MT7988_PIN(82, "UART1_CTS"),
+	MT7988_PIN(83, "UART1_RTS"),
+};
+
+/* jtag */
+static int mt7988_tops_jtag0_0_pins[] = { 0, 1, 2, 3, 4 };
+static int mt7988_tops_jtag0_0_funcs[] = { 2, 2, 2, 2, 2 };
+
+static int mt7988_wo0_jtag_pins[] = { 50, 51, 52, 53, 54 };
+static int mt7988_wo0_jtag_funcs[] = { 3, 3, 3, 3, 3 };
+
+static int mt7988_wo1_jtag_pins[] = { 50, 51, 52, 53, 54 };
+static int mt7988_wo1_jtag_funcs[] = { 4, 4, 4, 4, 4 };
+
+static int mt7988_wo2_jtag_pins[] = { 50, 51, 52, 53, 54 };
+static int mt7988_wo2_jtag_funcs[] = { 5, 5, 5, 5, 5 };
+
+static int mt7988_jtag_pins[] = { 58, 59, 60, 61, 62 };
+static int mt7988_jtag_funcs[] = { 1, 1, 1, 1, 1 };
+
+static int mt7988_tops_jtag0_1_pins[] = { 58, 59, 60, 61, 62 };
+static int mt7988_tops_jtag0_1_funcs[] = { 4, 4, 4, 4, 4 };
+
+/* int_usxgmii */
+static int mt7988_int_usxgmii_pins[] = { 2, 3 };
+static int mt7988_int_usxgmii_funcs[] = { 3, 3 };
+
+/* pwm */
+static int mt7988_pwm7_0_pins[] = { 4 };
+static int mt7988_pwm7_0_funcs[] = { 3 };
+
+static int mt7988_pwm1_pins[] = { 21 };
+static int mt7988_pwm1_funcs[] = { 1 };
+
+static int mt7988_pwm0_pins[] = { 57 };
+static int mt7988_pwm0_funcs[] = { 1 };
+
+static int mt7988_pwm2_pins[] = { 58 };
+static int mt7988_pwm2_funcs[] = { 5 };
+
+static int mt7988_pwm3_pins[] = { 59 };
+static int mt7988_pwm3_funcs[] = { 5 };
+
+static int mt7988_pwm4_pins[] = { 60 };
+static int mt7988_pwm4_funcs[] = { 5 };
+
+static int mt7988_pwm5_pins[] = { 61 };
+static int mt7988_pwm5_funcs[] = { 5 };
+
+static int mt7988_pwm6_0_pins[] = { 62 };
+static int mt7988_pwm6_0_funcs[] = { 5 };
+
+static int mt7988_pwm6_1_pins[] = { 69 };
+static int mt7988_pwm6_1_funcs[] = { 3 };
+
+static int mt7988_pwm7_pins[] = { 70 };
+static int mt7988_pwm7_funcs[] = { 3 };
+
+static int mt7988_pwm2_1_pins[] = { 80 };
+static int mt7988_pwm2_1_funcs[] = { 2 };
+
+static int mt7988_pwm3_1_pins[] = { 81 };
+static int mt7988_pwm3_1_funcs[] = { 2 };
+
+static int mt7988_pwm4_1_pins[] = { 82 };
+static int mt7988_pwm4_1_funcs[] = { 2 };
+
+static int mt7988_pwm5_1_pins[] = { 83 };
+static int mt7988_pwm5_1_funcs[] = { 2 };
+
+/* dfd */
+static int mt7988_dfd_pins[] = { 0, 1, 2, 3, 4 };
+static int mt7988_dfd_funcs[] = { 4, 4, 4, 4, 4 };
+
+/* i2c */
+static int mt7988_xfi_phy0_i2c0_pins[] = { 0, 1 };
+static int mt7988_xfi_phy0_i2c0_funcs[] = { 5, 5 };
+
+static int mt7988_xfi_phy1_i2c0_pins[] = { 0, 1 };
+static int mt7988_xfi_phy1_i2c0_funcs[] = { 6, 6 };
+
+static int mt7988_xfi_phy_pll_i2c0_pins[] = { 3, 4 };
+static int mt7988_xfi_phy_pll_i2c0_funcs[] = { 5, 5 };
+
+static int mt7988_xfi_phy_pll_i2c1_pins[] = { 3, 4 };
+static int mt7988_xfi_phy_pll_i2c1_funcs[] = { 6, 6 };
+
+static int mt7988_i2c0_0_pins[] = { 5, 6 };
+static int mt7988_i2c0_0_funcs[] = { 2, 2 };
+
+static int mt7988_i2c1_sfp_pins[] = { 5, 6 };
+static int mt7988_i2c1_sfp_funcs[] = { 4, 4 };
+
+static int mt7988_xfi_pextp_phy0_i2c_pins[] = { 5, 6 };
+static int mt7988_xfi_pextp_phy0_i2c_funcs[] = { 5, 5 };
+
+static int mt7988_xfi_pextp_phy1_i2c_pins[] = { 5, 6 };
+static int mt7988_xfi_pextp_phy1_i2c_funcs[] = { 6, 6 };
+
+static int mt7988_i2c0_1_pins[] = { 15, 16 };
+static int mt7988_i2c0_1_funcs[] = { 1, 1 };
+
+static int mt7988_u30_phy_i2c0_pins[] = { 15, 16 };
+static int mt7988_u30_phy_i2c0_funcs[] = { 2, 2 };
+
+static int mt7988_u32_phy_i2c0_pins[] = { 15, 16 };
+static int mt7988_u32_phy_i2c0_funcs[] = { 3, 3 };
+
+static int mt7988_xfi_phy0_i2c1_pins[] = { 15, 16 };
+static int mt7988_xfi_phy0_i2c1_funcs[] = { 5, 5 };
+
+static int mt7988_xfi_phy1_i2c1_pins[] = { 15, 16 };
+static int mt7988_xfi_phy1_i2c1_funcs[] = { 6, 6 };
+
+static int mt7988_xfi_phy_pll_i2c2_pins[] = { 15, 16 };
+static int mt7988_xfi_phy_pll_i2c2_funcs[] = { 7, 7 };
+
+static int mt7988_i2c1_0_pins[] = { 17, 18 };
+static int mt7988_i2c1_0_funcs[] = { 1, 1 };
+
+static int mt7988_u30_phy_i2c1_pins[] = { 17, 18 };
+static int mt7988_u30_phy_i2c1_funcs[] = { 2, 2 };
+
+static int mt7988_u32_phy_i2c1_pins[] = { 17, 18 };
+static int mt7988_u32_phy_i2c1_funcs[] = { 3, 3 };
+
+static int mt7988_xfi_phy_pll_i2c3_pins[] = { 17, 18 };
+static int mt7988_xfi_phy_pll_i2c3_funcs[] = { 4, 4 };
+
+static int mt7988_sgmii0_i2c_pins[] = { 17, 18 };
+static int mt7988_sgmii0_i2c_funcs[] = { 5, 5 };
+
+static int mt7988_sgmii1_i2c_pins[] = { 17, 18 };
+static int mt7988_sgmii1_i2c_funcs[] = { 6, 6 };
+
+static int mt7988_i2c1_2_pins[] = { 69, 70 };
+static int mt7988_i2c1_2_funcs[] = { 2, 2 };
+
+static int mt7988_i2c2_0_pins[] = { 69, 70 };
+static int mt7988_i2c2_0_funcs[] = { 4, 4 };
+
+static int mt7988_i2c2_1_pins[] = { 70, 71 };
+static int mt7988_i2c2_1_funcs[] = { 1, 1 };
+
+/* eth */
+static int mt7988_mdc_mdio0_pins[] = { 5, 6 };
+static int mt7988_mdc_mdio0_funcs[] = { 1, 1 };
+
+static int mt7988_2p5g_ext_mdio_pins[] = { 28, 29 };
+static int mt7988_2p5g_ext_mdio_funcs[] = { 6, 6 };
+
+static int mt7988_gbe_ext_mdio_pins[] = { 30, 31 };
+static int mt7988_gbe_ext_mdio_funcs[] = { 6, 6 };
+
+static int mt7988_mdc_mdio1_pins[] = { 69, 70 };
+static int mt7988_mdc_mdio1_funcs[] = { 1, 1 };
+
+/* pcie */
+static int mt7988_pcie_wake_n0_0_pins[] = { 7 };
+static int mt7988_pcie_wake_n0_0_funcs[] = { 1 };
+
+static int mt7988_pcie_clk_req_n0_0_pins[] = { 8 };
+static int mt7988_pcie_clk_req_n0_0_funcs[] = { 1 };
+
+static int mt7988_pcie_wake_n3_0_pins[] = { 9 };
+static int mt7988_pcie_wake_n3_0_funcs[] = { 1 };
+
+static int mt7988_pcie_clk_req_n3_pins[] = { 10 };
+static int mt7988_pcie_clk_req_n3_funcs[] = { 1 };
+
+static int mt7988_pcie_clk_req_n0_1_pins[] = { 10 };
+static int mt7988_pcie_clk_req_n0_1_funcs[] = { 2 };
+
+static int mt7988_pcie_p0_phy_i2c_pins[] = { 7, 8 };
+static int mt7988_pcie_p0_phy_i2c_funcs[] = { 3, 3 };
+
+static int mt7988_pcie_p1_phy_i2c_pins[] = { 7, 8 };
+static int mt7988_pcie_p1_phy_i2c_funcs[] = { 4, 4 };
+
+static int mt7988_pcie_p3_phy_i2c_pins[] = { 9, 10 };
+static int mt7988_pcie_p3_phy_i2c_funcs[] = { 4, 4 };
+
+static int mt7988_pcie_p2_phy_i2c_pins[] = { 7, 8 };
+static int mt7988_pcie_p2_phy_i2c_funcs[] = { 5, 5 };
+
+static int mt7988_ckm_phy_i2c_pins[] = { 9, 10 };
+static int mt7988_ckm_phy_i2c_funcs[] = { 5, 5 };
+
+static int mt7988_pcie_wake_n0_1_pins[] = { 13 };
+static int mt7988_pcie_wake_n0_1_funcs[] = { 2 };
+
+static int mt7988_pcie_wake_n3_1_pins[] = { 14 };
+static int mt7988_pcie_wake_n3_1_funcs[] = { 2 };
+
+static int mt7988_pcie_2l_0_pereset_pins[] = { 19 };
+static int mt7988_pcie_2l_0_pereset_funcs[] = { 1 };
+
+static int mt7988_pcie_1l_1_pereset_pins[] = { 20 };
+static int mt7988_pcie_1l_1_pereset_funcs[] = { 1 };
+
+static int mt7988_pcie_clk_req_n2_1_pins[] = { 63 };
+static int mt7988_pcie_clk_req_n2_1_funcs[] = { 2 };
+
+static int mt7988_pcie_2l_1_pereset_pins[] = { 73 };
+static int mt7988_pcie_2l_1_pereset_funcs[] = { 1 };
+
+static int mt7988_pcie_1l_0_pereset_pins[] = { 74 };
+static int mt7988_pcie_1l_0_pereset_funcs[] = { 1 };
+
+static int mt7988_pcie_wake_n1_0_pins[] = { 75 };
+static int mt7988_pcie_wake_n1_0_funcs[] = { 1 };
+
+static int mt7988_pcie_clk_req_n1_pins[] = { 76 };
+static int mt7988_pcie_clk_req_n1_funcs[] = { 1 };
+
+static int mt7988_pcie_wake_n2_0_pins[] = { 77 };
+static int mt7988_pcie_wake_n2_0_funcs[] = { 1 };
+
+static int mt7988_pcie_clk_req_n2_0_pins[] = { 78 };
+static int mt7988_pcie_clk_req_n2_0_funcs[] = { 1 };
+
+static int mt7988_pcie_wake_n2_1_pins[] = { 79 };
+static int mt7988_pcie_wake_n2_1_funcs[] = { 2 };
+
+/* pmic */
+static int mt7988_pmic_pins[] = { 11 };
+static int mt7988_pmic_funcs[] = { 1 };
+
+/* watchdog */
+static int mt7988_watchdog_pins[] = { 12 };
+static int mt7988_watchdog_funcs[] = { 1 };
+
+/* spi */
+static int mt7988_spi0_wp_hold_pins[] = { 22, 23 };
+static int mt7988_spi0_wp_hold_funcs[] = { 1, 1 };
+
+static int mt7988_spi0_pins[] = { 24, 25, 26, 27 };
+static int mt7988_spi0_funcs[] = { 1, 1, 1, 1 };
+
+static int mt7988_spi1_pins[] = { 28, 29, 30, 31 };
+static int mt7988_spi1_funcs[] = { 1, 1, 1, 1 };
+
+static int mt7988_spi2_pins[] = { 32, 33, 34, 35 };
+static int mt7988_spi2_funcs[] = { 1, 1, 1, 1 };
+
+static int mt7988_spi2_wp_hold_pins[] = { 36, 37 };
+static int mt7988_spi2_wp_hold_funcs[] = { 1, 1 };
+
+/* flash */
+static int mt7988_snfi_pins[] = { 22, 23, 24, 25, 26, 27 };
+static int mt7988_snfi_funcs[] = { 2, 2, 2, 2, 2, 2 };
+
+static int mt7988_emmc_45_pins[] = {
+	21, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37
+};
+static int mt7988_emmc_45_funcs[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
+
+static int mt7988_emmc_51_pins[] = { 38, 39, 40, 41, 42, 43,
+				     44, 45, 46, 47, 48, 49 };
+static int mt7988_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+
+/* uart */
+static int mt7988_uart2_pins[] = { 0, 1, 2, 3 };
+static int mt7988_uart2_funcs[] = { 1, 1, 1, 1 };
+
+static int mt7988_tops_uart0_0_pins[] = { 22, 23 };
+static int mt7988_tops_uart0_0_funcs[] = { 3, 3 };
+
+static int mt7988_uart2_0_pins[] = { 28, 29, 30, 31 };
+static int mt7988_uart2_0_funcs[] = { 2, 2, 2, 2 };
+
+static int mt7988_uart1_0_pins[] = { 32, 33, 34, 35 };
+static int mt7988_uart1_0_funcs[] = { 2, 2, 2, 2 };
+
+static int mt7988_uart2_1_pins[] = { 32, 33, 34, 35 };
+static int mt7988_uart2_1_funcs[] = { 3, 3, 3, 3 };
+
+static int mt7988_net_wo0_uart_txd_0_pins[] = { 28 };
+static int mt7988_net_wo0_uart_txd_0_funcs[] = { 3 };
+
+static int mt7988_net_wo1_uart_txd_0_pins[] = { 29 };
+static int mt7988_net_wo1_uart_txd_0_funcs[] = { 3 };
+
+static int mt7988_net_wo2_uart_txd_0_pins[] = { 30 };
+static int mt7988_net_wo2_uart_txd_0_funcs[] = { 3 };
+
+static int mt7988_tops_uart1_0_pins[] = { 28, 29 };
+static int mt7988_tops_uart1_0_funcs[] = { 4, 4 };
+
+static int mt7988_tops_uart0_1_pins[] = { 30, 31 };
+static int mt7988_tops_uart0_1_funcs[] = { 4, 4 };
+
+static int mt7988_tops_uart1_1_pins[] = { 36, 37 };
+static int mt7988_tops_uart1_1_funcs[] = { 3, 3 };
+
+static int mt7988_uart0_pins[] = { 55, 56 };
+static int mt7988_uart0_funcs[] = { 1, 1 };
+
+static int mt7988_tops_uart0_2_pins[] = { 55, 56 };
+static int mt7988_tops_uart0_2_funcs[] = { 2, 2 };
+
+static int mt7988_uart2_2_pins[] = { 50, 51, 52, 53 };
+static int mt7988_uart2_2_funcs[] = { 2, 2, 2, 2 };
+
+static int mt7988_uart1_1_pins[] = { 58, 59, 60, 61 };
+static int mt7988_uart1_1_funcs[] = { 2, 2, 2, 2 };
+
+static int mt7988_uart2_3_pins[] = { 58, 59, 60, 61 };
+static int mt7988_uart2_3_funcs[] = { 3, 3, 3, 3 };
+
+static int mt7988_uart1_2_pins[] = { 80, 81, 82, 83 };
+static int mt7988_uart1_2_funcs[] = { 1, 1, 1, 1 };
+
+static int mt7988_tops_uart1_2_pins[] = { 80, 81 };
+static int mt7988_tops_uart1_2_funcs[] = {
+	4,
+	4,
+};
+
+static int mt7988_net_wo0_uart_txd_1_pins[] = { 80 };
+static int mt7988_net_wo0_uart_txd_1_funcs[] = { 3 };
+
+static int mt7988_net_wo1_uart_txd_1_pins[] = { 81 };
+static int mt7988_net_wo1_uart_txd_1_funcs[] = { 3 };
+
+static int mt7988_net_wo2_uart_txd_1_pins[] = { 82 };
+static int mt7988_net_wo2_uart_txd_1_funcs[] = { 3 };
+
+/* udi */
+static int mt7988_udi_pins[] = { 32, 33, 34, 35, 36 };
+static int mt7988_udi_funcs[] = { 4, 4, 4, 4, 4 };
+
+/* pcm */
+static int mt7988_pcm_pins[] = { 50, 51, 52, 53, 54 };
+static int mt7988_pcm_funcs[] = { 1, 1, 1, 1, 1 };
+
+/* led */
+static int mt7988_gbe_led1_pins[] = { 58, 59, 60, 61 };
+static int mt7988_gbe_led1_funcs[] = { 6, 6, 6, 6 };
+
+static int mt7988_2p5gbe_led1_pins[] = { 62 };
+static int mt7988_2p5gbe_led1_funcs[] = { 6 };
+
+static int mt7988_gbe_led0_pins[] = { 64, 65, 66, 67 };
+static int mt7988_gbe_led0_funcs[] = { 1, 1, 1, 1 };
+
+static int mt7988_2p5gbe_led0_pins[] = { 68 };
+static int mt7988_2p5gbe_led0_funcs[] = { 1 };
+
+/* usb */
+static int mt7988_drv_vbus_p1_pins[] = { 63 };
+static int mt7988_drv_vbus_p1_funcs[] = { 1 };
+
+static int mt7988_drv_vbus_pins[] = { 79 };
+static int mt7988_drv_vbus_funcs[] = { 1 };
+
+static const struct group_desc mt7988_groups[] = {
+	/*  @GPIO(0,1,2,3): uart2 */
+	PINCTRL_PIN_GROUP("uart2", mt7988_uart2),
+	/*  @GPIO(0,1,2,3,4): tops_jtag0_0 */
+	PINCTRL_PIN_GROUP("tops_jtag0_0", mt7988_tops_jtag0_0),
+	/*  @GPIO(2,3): int_usxgmii */
+	PINCTRL_PIN_GROUP("int_usxgmii", mt7988_int_usxgmii),
+	/*  @GPIO(4): pwm7_0 */
+	PINCTRL_PIN_GROUP("pwm7_0", mt7988_pwm7_0),
+	/*  @GPIO(0,1,2,3,4): dfd */
+	PINCTRL_PIN_GROUP("dfd", mt7988_dfd),
+	/*  @GPIO(0,1): xfi_phy0_i2c0 */
+	PINCTRL_PIN_GROUP("xfi_phy0_i2c0", mt7988_xfi_phy0_i2c0),
+	/*  @GPIO(0,1): xfi_phy1_i2c0 */
+	PINCTRL_PIN_GROUP("xfi_phy1_i2c0", mt7988_xfi_phy1_i2c0),
+	/*  @GPIO(3,4): xfi_phy_pll_i2c0 */
+	PINCTRL_PIN_GROUP("xfi_phy_pll_i2c0", mt7988_xfi_phy_pll_i2c0),
+	/*  @GPIO(3,4): xfi_phy_pll_i2c1 */
+	PINCTRL_PIN_GROUP("xfi_phy_pll_i2c1", mt7988_xfi_phy_pll_i2c1),
+	/*  @GPIO(5,6) i2c0_0 */
+	PINCTRL_PIN_GROUP("i2c0_0", mt7988_i2c0_0),
+	/*  @GPIO(5,6) i2c1_sfp */
+	PINCTRL_PIN_GROUP("i2c1_sfp", mt7988_i2c1_sfp),
+	/*  @GPIO(5,6) xfi_pextp_phy0_i2c */
+	PINCTRL_PIN_GROUP("xfi_pextp_phy0_i2c", mt7988_xfi_pextp_phy0_i2c),
+	/*  @GPIO(5,6) xfi_pextp_phy1_i2c */
+	PINCTRL_PIN_GROUP("xfi_pextp_phy1_i2c", mt7988_xfi_pextp_phy1_i2c),
+	/*  @GPIO(5,6) mdc_mdio0 */
+	PINCTRL_PIN_GROUP("mdc_mdio0", mt7988_mdc_mdio0),
+	/*  @GPIO(7): pcie_wake_n0_0 */
+	PINCTRL_PIN_GROUP("pcie_wake_n0_0", mt7988_pcie_wake_n0_0),
+	/*  @GPIO(8): pcie_clk_req_n0_0 */
+	PINCTRL_PIN_GROUP("pcie_clk_req_n0_0", mt7988_pcie_clk_req_n0_0),
+	/*  @GPIO(9): pcie_wake_n3_0 */
+	PINCTRL_PIN_GROUP("pcie_wake_n3_0", mt7988_pcie_wake_n3_0),
+	/*  @GPIO(10): pcie_clk_req_n3 */
+	PINCTRL_PIN_GROUP("pcie_clk_req_n3", mt7988_pcie_clk_req_n3),
+	/*  @GPIO(10): pcie_clk_req_n0_1 */
+	PINCTRL_PIN_GROUP("pcie_clk_req_n0_1", mt7988_pcie_clk_req_n0_1),
+	/*  @GPIO(7,8) pcie_p0_phy_i2c */
+	PINCTRL_PIN_GROUP("pcie_p0_phy_i2c", mt7988_pcie_p0_phy_i2c),
+	/*  @GPIO(7,8) pcie_p1_phy_i2c */
+	PINCTRL_PIN_GROUP("pcie_p1_phy_i2c", mt7988_pcie_p1_phy_i2c),
+	/*  @GPIO(7,8) pcie_p2_phy_i2c */
+	PINCTRL_PIN_GROUP("pcie_p2_phy_i2c", mt7988_pcie_p2_phy_i2c),
+	/*  @GPIO(9,10) pcie_p3_phy_i2c */
+	PINCTRL_PIN_GROUP("pcie_p3_phy_i2c", mt7988_pcie_p3_phy_i2c),
+	/*  @GPIO(9,10) ckm_phy_i2c */
+	PINCTRL_PIN_GROUP("ckm_phy_i2c", mt7988_ckm_phy_i2c),
+	/*  @GPIO(11): pmic */
+	PINCTRL_PIN_GROUP("pcie_pmic", mt7988_pmic),
+	/*  @GPIO(12): watchdog */
+	PINCTRL_PIN_GROUP("watchdog", mt7988_watchdog),
+	/*  @GPIO(13): pcie_wake_n0_1 */
+	PINCTRL_PIN_GROUP("pcie_wake_n0_1", mt7988_pcie_wake_n0_1),
+	/*  @GPIO(14): pcie_wake_n3_1 */
+	PINCTRL_PIN_GROUP("pcie_wake_n3_1", mt7988_pcie_wake_n3_1),
+	/*  @GPIO(15,16) i2c0_1 */
+	PINCTRL_PIN_GROUP("i2c0_1", mt7988_i2c0_1),
+	/*  @GPIO(15,16) u30_phy_i2c0 */
+	PINCTRL_PIN_GROUP("u30_phy_i2c0", mt7988_u30_phy_i2c0),
+	/*  @GPIO(15,16) u32_phy_i2c0 */
+	PINCTRL_PIN_GROUP("u32_phy_i2c0", mt7988_u32_phy_i2c0),
+	/*  @GPIO(15,16) xfi_phy0_i2c1 */
+	PINCTRL_PIN_GROUP("xfi_phy0_i2c1", mt7988_xfi_phy0_i2c1),
+	/*  @GPIO(15,16) xfi_phy1_i2c1 */
+	PINCTRL_PIN_GROUP("xfi_phy1_i2c1", mt7988_xfi_phy1_i2c1),
+	/*  @GPIO(15,16) xfi_phy_pll_i2c2 */
+	PINCTRL_PIN_GROUP("xfi_phy_pll_i2c2", mt7988_xfi_phy_pll_i2c2),
+	/*  @GPIO(17,18) i2c1_0 */
+	PINCTRL_PIN_GROUP("i2c1_0", mt7988_i2c1_0),
+	/*  @GPIO(17,18) u30_phy_i2c1 */
+	PINCTRL_PIN_GROUP("u30_phy_i2c1", mt7988_u30_phy_i2c1),
+	/*  @GPIO(17,18) u32_phy_i2c1 */
+	PINCTRL_PIN_GROUP("u32_phy_i2c1", mt7988_u32_phy_i2c1),
+	/*  @GPIO(17,18) xfi_phy_pll_i2c3 */
+	PINCTRL_PIN_GROUP("xfi_phy_pll_i2c3", mt7988_xfi_phy_pll_i2c3),
+	/*  @GPIO(17,18) sgmii0_i2c */
+	PINCTRL_PIN_GROUP("sgmii0_i2c", mt7988_sgmii0_i2c),
+	/*  @GPIO(17,18) sgmii1_i2c */
+	PINCTRL_PIN_GROUP("sgmii1_i2c", mt7988_sgmii1_i2c),
+	/*  @GPIO(19): pcie_2l_0_pereset */
+	PINCTRL_PIN_GROUP("pcie_2l_0_pereset", mt7988_pcie_2l_0_pereset),
+	/*  @GPIO(20): pcie_1l_1_pereset */
+	PINCTRL_PIN_GROUP("pcie_1l_1_pereset", mt7988_pcie_1l_1_pereset),
+	/*  @GPIO(21): pwm1 */
+	PINCTRL_PIN_GROUP("pwm1", mt7988_pwm1),
+	/*  @GPIO(22,23) spi0_wp_hold */
+	PINCTRL_PIN_GROUP("spi0_wp_hold", mt7988_spi0_wp_hold),
+	/*  @GPIO(24,25,26,27) spi0 */
+	PINCTRL_PIN_GROUP("spi0", mt7988_spi0),
+	/*  @GPIO(28,29,30,31) spi1 */
+	PINCTRL_PIN_GROUP("spi1", mt7988_spi1),
+	/*  @GPIO(32,33,34,35) spi2 */
+	PINCTRL_PIN_GROUP("spi2", mt7988_spi2),
+	/*  @GPIO(36,37) spi2_wp_hold */
+	PINCTRL_PIN_GROUP("spi2_wp_hold", mt7988_spi2_wp_hold),
+	/*  @GPIO(22,23,24,25,26,27) snfi */
+	PINCTRL_PIN_GROUP("snfi", mt7988_snfi),
+	/*  @GPIO(22,23) tops_uart0_0 */
+	PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart0_0),
+	/*  @GPIO(28,29,30,31) uart2_0 */
+	PINCTRL_PIN_GROUP("uart2_0", mt7988_uart2_0),
+	/*  @GPIO(32,33,34,35) uart1_0 */
+	PINCTRL_PIN_GROUP("uart1_0", mt7988_uart1_0),
+	/*  @GPIO(32,33,34,35) uart2_1 */
+	PINCTRL_PIN_GROUP("uart2_1", mt7988_uart2_1),
+	/*  @GPIO(28) net_wo0_uart_txd_0 */
+	PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0),
+	/*  @GPIO(29) net_wo1_uart_txd_0 */
+	PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0),
+	/*  @GPIO(30) net_wo2_uart_txd_0 */
+	PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0),
+	/*  @GPIO(28,29) tops_uart1_0 */
+	PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart1_0),
+	/*  @GPIO(30,31) tops_uart0_1 */
+	PINCTRL_PIN_GROUP("tops_uart0_1", mt7988_tops_uart0_1),
+	/*  @GPIO(36,37) tops_uart1_1 */
+	PINCTRL_PIN_GROUP("tops_uart1_1", mt7988_tops_uart1_1),
+	/*  @GPIO(32,33,34,35,36) udi */
+	PINCTRL_PIN_GROUP("udi", mt7988_udi),
+	/*  @GPIO(21,28,29,30,31,32,33,34,35,36,37) emmc_45 */
+	PINCTRL_PIN_GROUP("emmc_45", mt7988_emmc_45),
+	/*  @GPIO(38,39,40,41,42,43,44,45,46,47,48,49) emmc_51 */
+	PINCTRL_PIN_GROUP("emmc_51", mt7988_emmc_51),
+	/*  @GPIO(28,29) 2p5g_ext_mdio */
+	PINCTRL_PIN_GROUP("2p5g_ext_mdio", mt7988_2p5g_ext_mdio),
+	/*  @GPIO(30,31) gbe_ext_mdio */
+	PINCTRL_PIN_GROUP("gbe_ext_mdio", mt7988_gbe_ext_mdio),
+	/*  @GPIO(50,51,52,53,54) pcm */
+	PINCTRL_PIN_GROUP("pcm", mt7988_pcm),
+	/*  @GPIO(55,56) uart0 */
+	PINCTRL_PIN_GROUP("uart0", mt7988_uart0),
+	/*  @GPIO(55,56) tops_uart0_2 */
+	PINCTRL_PIN_GROUP("tops_uart0_2", mt7988_tops_uart0_2),
+	/*  @GPIO(50,51,52,53) uart2_2 */
+	PINCTRL_PIN_GROUP("uart2_2", mt7988_uart2_2),
+	/*  @GPIO(50,51,52,53,54) wo0_jtag */
+	PINCTRL_PIN_GROUP("wo0_jtag", mt7988_wo0_jtag),
+	/*  @GPIO(50,51,52,53,54) wo1-wo1_jtag */
+	PINCTRL_PIN_GROUP("wo1_jtag", mt7988_wo1_jtag),
+	/*  @GPIO(50,51,52,53,54) wo2_jtag */
+	PINCTRL_PIN_GROUP("wo2_jtag", mt7988_wo2_jtag),
+	/*  @GPIO(57) pwm0 */
+	PINCTRL_PIN_GROUP("pwm0", mt7988_pwm0),
+	/*  @GPIO(58,59,60,61,62) jtag */
+	PINCTRL_PIN_GROUP("jtag", mt7988_jtag),
+	/*  @GPIO(58,59,60,61,62) tops_jtag0_1 */
+	PINCTRL_PIN_GROUP("tops_jtag0_1", mt7988_tops_jtag0_1),
+	/*  @GPIO(58,59,60,61) uart2_3 */
+	PINCTRL_PIN_GROUP("uart2_3", mt7988_uart2_3),
+	/*  @GPIO(58,59,60,61) uart1_1 */
+	PINCTRL_PIN_GROUP("uart1_1", mt7988_uart1_1),
+	/*  @GPIO(58) pwm2 */
+	PINCTRL_PIN_GROUP("pwm2", mt7988_pwm2),
+	/*  @GPIO(59) pwm3 */
+	PINCTRL_PIN_GROUP("pwm3", mt7988_pwm3),
+	/*  @GPIO(60) pwm4 */
+	PINCTRL_PIN_GROUP("pwm4", mt7988_pwm4),
+	/*  @GPIO(61) pwm5 */
+	PINCTRL_PIN_GROUP("pwm5", mt7988_pwm5),
+	/*  @GPIO(62) pwm6_0 */
+	PINCTRL_PIN_GROUP("pwm6_0", mt7988_pwm6_0),
+	/*  @GPIO(58,59,60,61) gbe_led1 */
+	PINCTRL_PIN_GROUP("gbe_led1", mt7988_gbe_led1),
+	/*  @GPIO(62) 2p5gbe_led1 */
+	PINCTRL_PIN_GROUP("2p5gbe_led1", mt7988_2p5gbe_led1),
+	/*  @GPIO(64,65,66,67) gbe_led0 */
+	PINCTRL_PIN_GROUP("gbe_led0", mt7988_gbe_led0),
+	/*  @GPIO(68) 2p5gbe_led0 */
+	PINCTRL_PIN_GROUP("2p5gbe_led0", mt7988_2p5gbe_led0),
+	/*  @GPIO(63) drv_vbus_p1 */
+	PINCTRL_PIN_GROUP("drv_vbus_p1", mt7988_drv_vbus_p1),
+	/*  @GPIO(63) pcie_clk_req_n2_1 */
+	PINCTRL_PIN_GROUP("pcie_clk_req_n2_1", mt7988_pcie_clk_req_n2_1),
+	/*  @GPIO(69, 70) mdc_mdio1 */
+	PINCTRL_PIN_GROUP("mdc_mdio1", mt7988_mdc_mdio1),
+	/*  @GPIO(69, 70) i2c1_2 */
+	PINCTRL_PIN_GROUP("i2c1_2", mt7988_i2c1_2),
+	/*  @GPIO(69) pwm6_1 */
+	PINCTRL_PIN_GROUP("pwm6_1", mt7988_pwm6_1),
+	/*  @GPIO(70) pwm7 */
+	PINCTRL_PIN_GROUP("pwm7", mt7988_pwm7),
+	/*  @GPIO(69,70) i2c2_0 */
+	PINCTRL_PIN_GROUP("i2c2_0", mt7988_i2c2_0),
+	/*  @GPIO(71,72) i2c2_1 */
+	PINCTRL_PIN_GROUP("i2c2_1", mt7988_i2c2_1),
+	/*  @GPIO(73) pcie_2l_1_pereset */
+	PINCTRL_PIN_GROUP("pcie_2l_1_pereset", mt7988_pcie_2l_1_pereset),
+	/*  @GPIO(74) pcie_1l_0_pereset */
+	PINCTRL_PIN_GROUP("pcie_1l_0_pereset", mt7988_pcie_1l_0_pereset),
+	/*  @GPIO(75) pcie_wake_n1_0 */
+	PINCTRL_PIN_GROUP("pcie_wake_n1_0", mt7988_pcie_wake_n1_0),
+	/*  @GPIO(76) pcie_clk_req_n1 */
+	PINCTRL_PIN_GROUP("pcie_clk_req_n1", mt7988_pcie_clk_req_n1),
+	/*  @GPIO(77) pcie_wake_n2_0 */
+	PINCTRL_PIN_GROUP("pcie_wake_n2_0", mt7988_pcie_wake_n2_0),
+	/*  @GPIO(78) pcie_clk_req_n2_0 */
+	PINCTRL_PIN_GROUP("pcie_clk_req_n2_0", mt7988_pcie_clk_req_n2_0),
+	/*  @GPIO(79) drv_vbus */
+	PINCTRL_PIN_GROUP("drv_vbus", mt7988_drv_vbus),
+	/*  @GPIO(79) pcie_wake_n2_1 */
+	PINCTRL_PIN_GROUP("pcie_wake_n2_1", mt7988_pcie_wake_n2_1),
+	/*  @GPIO(80,81,82,83) uart1_2 */
+	PINCTRL_PIN_GROUP("uart1_2", mt7988_uart1_2),
+	/*  @GPIO(80) pwm2_1 */
+	PINCTRL_PIN_GROUP("pwm2_1", mt7988_pwm2_1),
+	/*  @GPIO(81) pwm3_1 */
+	PINCTRL_PIN_GROUP("pwm3_1", mt7988_pwm3_1),
+	/*  @GPIO(82) pwm4_1 */
+	PINCTRL_PIN_GROUP("pwm4_1", mt7988_pwm4_1),
+	/*  @GPIO(83) pwm5_1 */
+	PINCTRL_PIN_GROUP("pwm5_1", mt7988_pwm5_1),
+	/*  @GPIO(80) net_wo0_uart_txd_0 */
+	PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0),
+	/*  @GPIO(81) net_wo1_uart_txd_0 */
+	PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0),
+	/*  @GPIO(82) net_wo2_uart_txd_0 */
+	PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0),
+	/*  @GPIO(80,81) tops_uart1_2 */
+	PINCTRL_PIN_GROUP("tops_uart1_2", mt7988_tops_uart1_2),
+	/*  @GPIO(80) net_wo0_uart_txd_1 */
+	PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7988_net_wo0_uart_txd_1),
+	/*  @GPIO(81) net_wo1_uart_txd_1 */
+	PINCTRL_PIN_GROUP("net_wo1_uart_txd_1", mt7988_net_wo1_uart_txd_1),
+	/*  @GPIO(82) net_wo2_uart_txd_1 */
+	PINCTRL_PIN_GROUP("net_wo2_uart_txd_1", mt7988_net_wo2_uart_txd_1),
+};
+
+/* Joint those groups owning the same capability in user point of view which
+ * allows that people tend to use through the device tree.
+ */
+static const char * const mt7988_jtag_groups[] = {
+	"tops_jtag0_0", "wo0_jtag", "wo1_jtag",
+	"wo2_jtag",	"jtag",	    "tops_jtag0_1",
+};
+static const char * const mt7988_int_usxgmii_groups[] = {
+	"int_usxgmii",
+};
+static const char * const mt7988_pwm_groups[] = {
+	"pwm7_0", "pwm1",   "pwm0", "pwm2",   "pwm3",	"pwm4",	  "pwm5",
+	"pwm6_0", "pwm6_1", "pwm7", "pwm2_1", "pwm3_1", "pwm4_1", "pwm5_1"
+};
+static const char * const mt7988_dfd_groups[] = {
+	"dfd",
+};
+static const char * const mt7988_i2c_groups[] = {
+	"xfi_phy0_i2c0",
+	"xfi_phy1_i2c0",
+	"xfi_phy_pll_i2c0",
+	"xfi_phy_pll_i2c1",
+	"i2c0_0",
+	"i2c1_sfp",
+	"xfi_pextp_phy0_i2c",
+	"xfi_pextp_phy1_i2c",
+	"i2c0_1",
+	"u30_phy_i2c0",
+	"u32_phy_i2c0",
+	"xfi_phy0_i2c1",
+	"xfi_phy1_i2c1",
+	"xfi_phy_pll_i2c2",
+	"i2c1_0",
+	"u30_phy_i2c1",
+	"u32_phy_i2c1",
+	"xfi_phy_pll_i2c3",
+	"sgmii0_i2c",
+	"sgmii1_i2c",
+	"i2c1_2",
+	"i2c2_0",
+	"i2c2_1",
+};
+static const char * const mt7988_ethernet_groups[] = {
+	"mdc_mdio0",
+	"2p5g_ext_mdio",
+	"gbe_ext_mdio",
+	"mdc_mdio1",
+};
+static const char * const mt7988_pcie_groups[] = {
+	"pcie_wake_n0_0",    "pcie_clk_req_n0_0", "pcie_wake_n3_0",
+	"pcie_clk_req_n3",   "pcie_p0_phy_i2c",	  "pcie_p1_phy_i2c",
+	"pcie_p3_phy_i2c",   "pcie_p2_phy_i2c",	  "ckm_phy_i2c",
+	"pcie_wake_n0_1",    "pcie_wake_n3_1",	  "pcie_2l_0_pereset",
+	"pcie_1l_1_pereset", "pcie_clk_req_n2_1", "pcie_2l_1_pereset",
+	"pcie_1l_0_pereset", "pcie_wake_n1_0",	  "pcie_clk_req_n1",
+	"pcie_wake_n2_0",    "pcie_clk_req_n2_0", "pcie_wake_n2_1",
+	"pcie_clk_req_n0_1"
+};
+static const char * const mt7988_pmic_groups[] = {
+	"pmic",
+};
+static const char * const mt7988_wdt_groups[] = {
+	"watchdog",
+};
+static const char * const mt7988_spi_groups[] = {
+	"spi0", "spi0_wp_hold", "spi1", "spi2", "spi2_wp_hold",
+};
+static const char * const mt7988_flash_groups[] = { "emmc_45", "snfi",
+						    "emmc_51" };
+static const char * const mt7988_uart_groups[] = {
+	"uart2",
+	"tops_uart0_0",
+	"uart2_0",
+	"uart1_0",
+	"uart2_1",
+	"net_wo0_uart_txd_0",
+	"net_wo1_uart_txd_0",
+	"net_wo2_uart_txd_0",
+	"tops_uart1_0",
+	"ops_uart0_1",
+	"ops_uart1_1",
+	"uart0",
+	"tops_uart0_2",
+	"uart1_1",
+	"uart2_3",
+	"uart1_2",
+	"tops_uart1_2",
+	"net_wo0_uart_txd_1",
+	"net_wo1_uart_txd_1",
+	"net_wo2_uart_txd_1",
+};
+static const char * const mt7988_udi_groups[] = {
+	"udi",
+};
+static const char * const mt7988_pcm_groups[] = {
+	"pcm",
+};
+static const char * const mt7988_led_groups[] = {
+	"gbe_led1",    "2p5gbe_led1", "gbe_led0",
+	"2p5gbe_led0", "wf5g_led0",   "wf5g_led1",
+};
+static const char * const mt7988_usb_groups[] = {
+	"drv_vbus",
+	"drv_vbus_p1",
+};
+
+static const struct function_desc mt7988_functions[] = {
+	{ "jtag", mt7988_jtag_groups, ARRAY_SIZE(mt7988_jtag_groups) },
+	{ "int_usxgmii", mt7988_int_usxgmii_groups,
+	  ARRAY_SIZE(mt7988_int_usxgmii_groups) },
+	{ "pwm", mt7988_pwm_groups, ARRAY_SIZE(mt7988_pwm_groups) },
+	{ "dfd", mt7988_dfd_groups, ARRAY_SIZE(mt7988_dfd_groups) },
+	{ "i2c", mt7988_i2c_groups, ARRAY_SIZE(mt7988_i2c_groups) },
+	{ "eth", mt7988_ethernet_groups, ARRAY_SIZE(mt7988_ethernet_groups) },
+	{ "pcie", mt7988_pcie_groups, ARRAY_SIZE(mt7988_pcie_groups) },
+	{ "pmic", mt7988_pmic_groups, ARRAY_SIZE(mt7988_pmic_groups) },
+	{ "watchdog", mt7988_wdt_groups, ARRAY_SIZE(mt7988_wdt_groups) },
+	{ "spi", mt7988_spi_groups, ARRAY_SIZE(mt7988_spi_groups) },
+	{ "flash", mt7988_flash_groups, ARRAY_SIZE(mt7988_flash_groups) },
+	{ "uart", mt7988_uart_groups, ARRAY_SIZE(mt7988_uart_groups) },
+	{ "udi", mt7988_udi_groups, ARRAY_SIZE(mt7988_udi_groups) },
+	{ "pcm", mt7988_pcm_groups, ARRAY_SIZE(mt7988_pcm_groups) },
+	{ "usb", mt7988_usb_groups, ARRAY_SIZE(mt7988_usb_groups) },
+	{ "led", mt7988_led_groups, ARRAY_SIZE(mt7988_led_groups) },
+};
+
+static const struct mtk_eint_hw mt7988_eint_hw = {
+	.port_mask = 7,
+	.ports = 7,
+	.ap_num = ARRAY_SIZE(mt7988_pins),
+	.db_cnt = 16,
+};
+
+static const char * const mt7988_pinctrl_register_base_names[] = {
+	"gpio_base",	 "iocfg_tr_base", "iocfg_br_base",
+	"iocfg_rb_base", "iocfg_lb_base", "iocfg_tl_base",
+};
+
+static struct mtk_pin_soc mt7988_data = {
+	.reg_cal = mt7988_reg_cals,
+	.pins = mt7988_pins,
+	.npins = ARRAY_SIZE(mt7988_pins),
+	.grps = mt7988_groups,
+	.ngrps = ARRAY_SIZE(mt7988_groups),
+	.funcs = mt7988_functions,
+	.nfuncs = ARRAY_SIZE(mt7988_functions),
+	.eint_hw = &mt7988_eint_hw,
+	.gpio_m = 0,
+	.ies_present = false,
+	.base_names = mt7988_pinctrl_register_base_names,
+	.nbase_names = ARRAY_SIZE(mt7988_pinctrl_register_base_names),
+	.bias_disable_set = mtk_pinconf_bias_disable_set,
+	.bias_disable_get = mtk_pinconf_bias_disable_get,
+	.bias_set = mtk_pinconf_bias_set,
+	.bias_get = mtk_pinconf_bias_get,
+	.drive_set = mtk_pinconf_drive_set_rev1,
+	.drive_get = mtk_pinconf_drive_get_rev1,
+	.adv_pull_get = mtk_pinconf_adv_pull_get,
+	.adv_pull_set = mtk_pinconf_adv_pull_set,
+};
+
+static const struct of_device_id mt7988_pinctrl_of_match[] = {
+	{
+		.compatible = "mediatek,mt7988-pinctrl",
+	},
+	{}
+};
+
+static int mt7988_pinctrl_probe(struct platform_device *pdev)
+{
+	return mtk_moore_pinctrl_probe(pdev, &mt7988_data);
+}
+
+static struct platform_driver mt7988_pinctrl_driver = {
+	.driver = {
+		.name = "mt7988-pinctrl",
+		.of_match_table = mt7988_pinctrl_of_match,
+	},
+	.probe = mt7988_pinctrl_probe,
+};
+
+static int __init mt7988_pinctrl_init(void)
+{
+	return platform_driver_register(&mt7988_pinctrl_driver);
+}
+arch_initcall(mt7988_pinctrl_init);
diff --git a/target/linux/mediatek/files-5.4/drivers/regulator/rt5190a-regulator.c b/target/linux/mediatek/files-5.4/drivers/regulator/rt5190a-regulator.c
new file mode 100644
index 0000000..c616a46
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/regulator/rt5190a-regulator.c
@@ -0,0 +1,557 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <dt-bindings/regulator/richtek,rt5190a-regulator.h>
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#define RT5190A_REG_MANUFACTURE 0x00
+#define RT5190A_REG_BUCK2VSEL	0x04
+#define RT5190A_REG_BUCK3VSEL	0x05
+#define RT5190A_REG_DCDCCNTL	0x06
+#define RT5190A_REG_ENABLE	0x07
+#define RT5190A_REG_DISCHARGE	0x09
+#define RT5190A_REG_PROTMODE	0x0A
+#define RT5190A_REG_MUTECNTL	0x0B
+#define RT5190A_REG_PGSTAT	0x0F
+#define RT5190A_REG_OVINT	0x10
+#define RT5190A_REG_HOTDIEMASK	0x17
+
+#define RT5190A_VSEL_MASK	   GENMASK(6, 0)
+#define RT5190A_RID_BITMASK(rid)   BIT(rid + 1)
+#define RT5190A_BUCK1_DISCHG_MASK  GENMASK(1, 0)
+#define RT5190A_BUCK1_DISCHG_ONVAL 0x01
+#define RT5190A_OVERVOLT_MASK	   GENMASK(7, 0)
+#define RT5190A_UNDERVOLT_MASK	   GENMASK(15, 8)
+#define RT5190A_CH234OT_MASK	   BIT(29)
+#define RT5190A_CHIPOT_MASK	   BIT(28)
+
+#define RT5190A_BUCK23_MINUV   600000
+#define RT5190A_BUCK23_MAXUV   1400000
+#define RT5190A_BUCK23_STEPUV  10000
+#define RT5190A_BUCK23_STEPNUM ((1400000 - 600000) / 10000 + 1)
+
+enum {
+	RT5190A_IDX_BUCK1 = 0,
+	RT5190A_IDX_BUCK2,
+	RT5190A_IDX_BUCK3,
+	RT5190A_IDX_BUCK4,
+	RT5190A_IDX_LDO,
+	RT5190A_MAX_IDX
+};
+
+struct rt5190a_priv {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regulator_desc rdesc[RT5190A_MAX_IDX];
+	struct regulator_dev *rdev[RT5190A_MAX_IDX];
+};
+
+static int rt5190a_get_error_flags(struct regulator_dev *rdev,
+				   unsigned int *flags)
+{
+	struct regmap *regmap = rdev_get_regmap(rdev);
+	int rid = rdev_get_id(rdev);
+	unsigned int pgood_stat;
+	int ret;
+
+	ret = regmap_read(regmap, RT5190A_REG_PGSTAT, &pgood_stat);
+	if (ret)
+		return ret;
+
+	if (!(pgood_stat & RT5190A_RID_BITMASK(rid)))
+		*flags = REGULATOR_ERROR_FAIL;
+	else
+		*flags = 0;
+
+	return 0;
+}
+
+static int rt5190a_fixed_buck_set_mode(struct regulator_dev *rdev,
+				       unsigned int mode)
+{
+	struct regmap *regmap = rdev_get_regmap(rdev);
+	int rid = rdev_get_id(rdev);
+	unsigned int mask = RT5190A_RID_BITMASK(rid), val;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = mask;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(regmap, RT5190A_REG_DCDCCNTL, mask, val);
+}
+
+static unsigned int rt5190a_fixed_buck_get_mode(struct regulator_dev *rdev)
+{
+	struct regmap *regmap = rdev_get_regmap(rdev);
+	int rid = rdev_get_id(rdev);
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(regmap, RT5190A_REG_DCDCCNTL, &val);
+	if (ret) {
+		dev_err(&rdev->dev, "Failed to get mode [%d]\n", ret);
+		return ret;
+	}
+
+	if (val & RT5190A_RID_BITMASK(rid))
+		return REGULATOR_MODE_FAST;
+
+	return REGULATOR_MODE_NORMAL;
+}
+
+static const struct regulator_ops rt5190a_ranged_buck_ops = {
+	.enable = regulator_enable_regmap,
+	/*.disable = regulator_disable_regmap,*/
+	.is_enabled = regulator_is_enabled_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.set_active_discharge = regulator_set_active_discharge_regmap,
+	.get_error_flags = rt5190a_get_error_flags,
+};
+
+static const struct regulator_ops rt5190a_fixed_buck_ops = {
+	.enable = regulator_enable_regmap,
+	/*.disable = regulator_disable_regmap,*/
+	.is_enabled = regulator_is_enabled_regmap,
+	.set_active_discharge = regulator_set_active_discharge_regmap,
+	.set_mode = rt5190a_fixed_buck_set_mode,
+	.get_mode = rt5190a_fixed_buck_get_mode,
+	.get_error_flags = rt5190a_get_error_flags,
+};
+
+static const struct regulator_ops rt5190a_fixed_ldo_ops = {
+	.enable = regulator_enable_regmap,
+	/*.disable = regulator_disable_regmap,*/
+	.is_enabled = regulator_is_enabled_regmap,
+	.set_active_discharge = regulator_set_active_discharge_regmap,
+	.get_error_flags = rt5190a_get_error_flags,
+};
+
+static const struct event {
+	unsigned int bitmask;
+	unsigned int report;
+};
+
+static const struct event event_tbl[] = {
+	{ RT5190A_OVERVOLT_MASK, REGULATOR_ERROR_REGULATION_OUT },
+	{ RT5190A_UNDERVOLT_MASK, REGULATOR_ERROR_UNDER_VOLTAGE }
+};
+
+static irqreturn_t rt5190a_irq_handler(int irq, void *data)
+{
+	struct rt5190a_priv *priv = data;
+	__le32 raws;
+	unsigned int events, fields;
+	int i, j, ret;
+
+	ret = regmap_raw_read(priv->regmap, RT5190A_REG_OVINT, &raws,
+			      sizeof(raws));
+	if (ret) {
+		dev_err(priv->dev, "Failed to read events\n");
+		return IRQ_NONE;
+	}
+
+	events = le32_to_cpu(raws);
+
+	ret = regmap_raw_write(priv->regmap, RT5190A_REG_OVINT, &raws,
+			       sizeof(raws));
+	if (ret)
+		dev_err(priv->dev, "Failed to write-clear events\n");
+
+	/* Handle OV,UV events */
+	for (i = 0; i < ARRAY_SIZE(event_tbl); i++) {
+		fields = events & event_tbl[i].bitmask;
+		fields >>= ffs(event_tbl[i].bitmask) - 1;
+
+		for (j = 0; j < RT5190A_MAX_IDX; j++) {
+			if (!(fields & RT5190A_RID_BITMASK(j)))
+				continue;
+
+			regulator_notifier_call_chain(
+				priv->rdev[j], event_tbl[i].report, NULL);
+		}
+	}
+
+	/* Handle CH234 OT event */
+	if (events & RT5190A_CH234OT_MASK) {
+		for (j = RT5190A_IDX_BUCK2; j < RT5190A_IDX_LDO; j++) {
+			regulator_notifier_call_chain(
+				priv->rdev[j], REGULATOR_ERROR_OVER_TEMP, NULL);
+		}
+	}
+
+	/* Warning if CHIP OT occur */
+	if (events & RT5190A_CHIPOT_MASK)
+		dev_warn(priv->dev, "CHIP overheat\n");
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int rt5190a_of_map_mode(unsigned int mode)
+{
+	switch (mode) {
+	case RT5190A_OPMODE_AUTO:
+		return REGULATOR_MODE_NORMAL;
+	case RT5190A_OPMODE_FPWM:
+		return REGULATOR_MODE_FAST;
+	default:
+		return REGULATOR_MODE_INVALID;
+	}
+}
+
+static int rt5190a_of_parse_cb(struct rt5190a_priv *priv, int rid,
+			       struct of_regulator_match *match)
+{
+	struct regulator_desc *desc = priv->rdesc + rid;
+	struct regulator_init_data *init_data = match->init_data;
+	struct device_node *np = match->of_node;
+	bool latchup_enable;
+	unsigned int mask = RT5190A_RID_BITMASK(rid), val;
+
+	switch (rid) {
+	case RT5190A_IDX_BUCK1:
+	case RT5190A_IDX_BUCK4:
+	case RT5190A_IDX_LDO:
+		init_data->constraints.apply_uV = 0;
+
+		if (init_data->constraints.min_uV ==
+		    init_data->constraints.max_uV)
+			desc->fixed_uV = init_data->constraints.min_uV;
+		else {
+			dev_err(priv->dev,
+				"Variable voltage for fixed regulator\n");
+			return -EINVAL;
+		}
+		break;
+	default:
+		break;
+	}
+
+	latchup_enable = of_property_read_bool(np, "richtek,latchup-enable");
+
+	/* latchup: 0, default hiccup: 1 */
+	val = !latchup_enable ? mask : 0;
+
+	return regmap_update_bits(priv->regmap, RT5190A_REG_PROTMODE, mask,
+				  val);
+}
+
+static void rt5190a_fillin_regulator_desc(struct regulator_desc *desc, int rid)
+{
+	static const char *const regu_name[] = { "buck1", "buck2", "buck3",
+						 "buck4", "ldo" };
+	static const char *const supply[] = { NULL, "vin2", "vin3", "vin4",
+					      "vinldo" };
+
+	desc->name = regu_name[rid];
+	desc->supply_name = supply[rid];
+	desc->owner = THIS_MODULE;
+	desc->type = REGULATOR_VOLTAGE;
+	desc->id = rid;
+	desc->enable_reg = RT5190A_REG_ENABLE;
+	desc->enable_mask = RT5190A_RID_BITMASK(rid);
+	desc->active_discharge_reg = RT5190A_REG_DISCHARGE;
+	desc->active_discharge_mask = RT5190A_RID_BITMASK(rid);
+	desc->active_discharge_on = RT5190A_RID_BITMASK(rid);
+
+	switch (rid) {
+	case RT5190A_IDX_BUCK1:
+		desc->active_discharge_mask = RT5190A_BUCK1_DISCHG_MASK;
+		desc->active_discharge_on = RT5190A_BUCK1_DISCHG_ONVAL;
+		desc->n_voltages = 1;
+		desc->ops = &rt5190a_fixed_buck_ops;
+		desc->of_map_mode = rt5190a_of_map_mode;
+		break;
+	case RT5190A_IDX_BUCK2:
+		desc->vsel_reg = RT5190A_REG_BUCK2VSEL;
+		desc->vsel_mask = RT5190A_VSEL_MASK;
+		desc->min_uV = RT5190A_BUCK23_MINUV;
+		desc->uV_step = RT5190A_BUCK23_STEPUV;
+		desc->n_voltages = RT5190A_BUCK23_STEPNUM;
+		desc->ops = &rt5190a_ranged_buck_ops;
+		break;
+	case RT5190A_IDX_BUCK3:
+		desc->vsel_reg = RT5190A_REG_BUCK3VSEL;
+		desc->vsel_mask = RT5190A_VSEL_MASK;
+		desc->min_uV = RT5190A_BUCK23_MINUV;
+		desc->uV_step = RT5190A_BUCK23_STEPUV;
+		desc->n_voltages = RT5190A_BUCK23_STEPNUM;
+		desc->ops = &rt5190a_ranged_buck_ops;
+		break;
+	case RT5190A_IDX_BUCK4:
+		desc->n_voltages = 1;
+		desc->ops = &rt5190a_fixed_buck_ops;
+		desc->of_map_mode = rt5190a_of_map_mode;
+		break;
+	case RT5190A_IDX_LDO:
+		desc->n_voltages = 1;
+		desc->ops = &rt5190a_fixed_ldo_ops;
+		break;
+	}
+}
+
+static struct of_regulator_match rt5190a_regulator_match[] = {
+	{
+		.name = "buck1",
+	},
+	{
+		.name = "buck2",
+	},
+	{
+		.name = "buck3",
+	},
+	{
+		.name = "buck4",
+	},
+	{
+		.name = "ldo",
+	}
+};
+
+static int rt5190a_parse_regulator_dt_data(struct rt5190a_priv *priv)
+{
+	struct device_node *regulator_np;
+	struct regulator_desc *reg_desc;
+	struct of_regulator_match *match;
+	int i, ret;
+
+	for (i = 0; i < RT5190A_MAX_IDX; i++) {
+		reg_desc = priv->rdesc + i;
+		match = rt5190a_regulator_match + i;
+
+		rt5190a_fillin_regulator_desc(reg_desc, i);
+
+		match->desc = reg_desc;
+	}
+
+	regulator_np = of_get_child_by_name(priv->dev->of_node, "regulators");
+	if (!regulator_np) {
+		dev_err(priv->dev, "Could not find 'regulators' node\n");
+		return -ENODEV;
+	}
+
+	ret = of_regulator_match(priv->dev, regulator_np,
+				 rt5190a_regulator_match,
+				 ARRAY_SIZE(rt5190a_regulator_match));
+
+	of_node_put(regulator_np);
+
+	if (ret < 0) {
+		dev_err(priv->dev, "Error parsing regulator init data: %d\n",
+			ret);
+		return ret;
+	}
+
+	for (i = 0; i < RT5190A_MAX_IDX; i++) {
+		match = rt5190a_regulator_match + i;
+
+		ret = rt5190a_of_parse_cb(priv, i, match);
+		if (ret) {
+			dev_err(priv->dev, "Failed in [%d] of_parse_cb\n", i);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct reg_sequence rt5190a_init_patch[] = { {
+								  0x09,
+								  0x3d,
+							  },
+							{
+								  0x0a,
+								  0x3e,
+							  },
+							{
+								  0x0b,
+								  0x01,
+							  },
+							{
+								  0x10,
+								  0xff,
+							  },
+							{
+								  0x11,
+								  0xff,
+							  },
+							{
+								  0x12,
+								  0xff,
+							  },
+							{
+								  0x13,
+								  0xff,
+							  },
+							{
+								  0x14,
+								  0,
+							  },
+							{
+								  0x15,
+								  0,
+							  },
+							{
+								  0x16,
+								  0x3e,
+							  },
+							{
+								  0x17,
+								  0,
+							  } };
+
+static int rt5190a_device_initialize(struct rt5190a_priv *priv)
+{
+	bool mute_enable;
+	int ret;
+
+	ret = regmap_register_patch(priv->regmap, rt5190a_init_patch,
+				    ARRAY_SIZE(rt5190a_init_patch));
+	if (ret) {
+		dev_err(priv->dev, "Failed to do register patch\n");
+		return ret;
+	}
+
+	mute_enable =
+		device_property_read_bool(priv->dev, "richtek,mute-enable");
+
+	if (mute_enable) {
+		ret = regmap_write(priv->regmap, RT5190A_REG_MUTECNTL, 0x00);
+		if (ret) {
+			dev_err(priv->dev, "Failed to enable mute function\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int rt5190a_device_check(struct rt5190a_priv *priv)
+{
+	u16 devid;
+	int ret;
+
+	ret = regmap_raw_read(priv->regmap, RT5190A_REG_MANUFACTURE, &devid,
+			      sizeof(devid));
+	if (ret)
+		return ret;
+
+	if (devid) {
+		dev_err(priv->dev, "Incorrect device id 0x%04x\n", devid);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static const struct regmap_config rt5190a_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = RT5190A_REG_HOTDIEMASK,
+};
+
+static int rt5190a_probe(struct i2c_client *i2c)
+{
+	struct rt5190a_priv *priv;
+	struct regulator_config cfg = {};
+	int i, ret;
+
+	priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = &i2c->dev;
+
+	priv->regmap = devm_regmap_init_i2c(i2c, &rt5190a_regmap_config);
+	if (IS_ERR(priv->regmap)) {
+		dev_err(&i2c->dev, "Failed to allocate regmap\n");
+		return PTR_ERR(priv->regmap);
+	}
+
+	ret = rt5190a_device_check(priv);
+	if (ret) {
+		dev_err(&i2c->dev, "Failed to check device %d\n", ret);
+		return ret;
+	}
+
+	ret = rt5190a_device_initialize(priv);
+	if (ret) {
+		dev_err(&i2c->dev, "Failed to initialize the device\n");
+		return ret;
+	}
+
+	ret = rt5190a_parse_regulator_dt_data(priv);
+	if (ret) {
+		dev_err(&i2c->dev, "Failed to parse regulator dt\n");
+		return ret;
+	}
+
+	cfg.dev = &i2c->dev;
+	cfg.regmap = priv->regmap;
+
+	for (i = 0; i < RT5190A_MAX_IDX; i++) {
+		struct regulator_desc *desc = priv->rdesc + i;
+		struct of_regulator_match *match = rt5190a_regulator_match + i;
+
+		cfg.init_data = match->init_data;
+		cfg.of_node = match->of_node;
+
+		priv->rdev[i] = devm_regulator_register(&i2c->dev, desc, &cfg);
+		if (IS_ERR(priv->rdev[i])) {
+			dev_err(&i2c->dev, "Failed to register regulator %s\n",
+				desc->name);
+			return PTR_ERR(priv->rdev[i]);
+		}
+	}
+
+	if (i2c->irq) {
+		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+						rt5190a_irq_handler,
+						IRQF_ONESHOT,
+						dev_name(&i2c->dev), priv);
+		if (ret) {
+			dev_err(&i2c->dev, "Failed to register interrupt\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct of_device_id __maybe_unused rt5190a_device_table[] = {
+	{
+		.compatible = "richtek,rt5190a",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, rt5190a_device_table);
+
+static struct i2c_driver rt5190a_driver = {
+	.driver = {
+		.name = "rt5190a",
+		.of_match_table = rt5190a_device_table,
+	},
+	.probe_new = rt5190a_probe,
+};
+module_i2c_driver(rt5190a_driver);
+
+MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Richtek RT5190A Regulator Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mt7988-pm-domains.h b/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mt7988-pm-domains.h
new file mode 100644
index 0000000..f7db02c
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mt7988-pm-domains.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ */
+
+#ifndef __SOC_MEDIATEK_MT7988_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT7988_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+//#include "mt7988-power.h"
+#include <dt-bindings/power/mt7988-power.h>
+
+/*
+ * MT8139 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt7988[] = {
+	[MT7988_POWER_DOMAIN_TOPS0] = {
+		.sta_mask = BIT(30),
+		.sta_2nd_mask = BIT(31),
+		.pwr_sta_offs = 0x040,
+		.pwr_sta_2nd_offs = 0x040,
+		.pwr_on_bit = BIT(1),
+		.pwr_on_2nd_bit = BIT(2),
+		.pwr_on_offs  = 0x040,
+		.pwr_on_2nd_offs = 0x040,
+		.pwr_clamp_bit = BIT(4),
+		.pwr_rst_bit = BIT(0),
+		.sram_pdn_bit = BIT(2),
+		.sram_pdn_ack_bit = BIT(28),
+		.sram_clk_iso_bit = BIT(0),
+		.sram_ctrl_offs = 0x048,
+		.sram_2nd_pdn_bit = BIT(8),
+		.sram_2nd_pdn_ack_bit = BIT(24),
+		.sram_2nd_clk_iso_bit = BIT(5),
+		.sram_2nd_clk_dis_bit = BIT(3),
+		.sram_2nd_ctrl_offs = 0x040,
+		.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+	},
+	[MT7988_POWER_DOMAIN_TOPS1] = {
+		.sta_mask = BIT(30),
+		.sta_2nd_mask = BIT(31),
+		.pwr_sta_offs = 0x044,
+		.pwr_sta_2nd_offs = 0x044,
+		.pwr_on_bit = BIT(1),
+		.pwr_on_2nd_bit = BIT(2),
+		.pwr_on_offs  = 0x044,
+		.pwr_on_2nd_offs = 0x044,
+		.pwr_clamp_bit = BIT(4),
+		.pwr_rst_bit = BIT(0),
+		.sram_pdn_bit = BIT(6),
+		.sram_pdn_ack_bit = BIT(30),
+		.sram_clk_iso_bit = BIT(4),
+		.sram_ctrl_offs = 0x048,
+		.sram_2nd_pdn_bit = BIT(8),
+		.sram_2nd_pdn_ack_bit = BIT(24),
+		.sram_2nd_clk_iso_bit = BIT(5),
+		.sram_2nd_clk_dis_bit = BIT(3),
+		.sram_2nd_ctrl_offs = 0x044,
+		.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+
+	},
+	[MT7988_POWER_DOMAIN_ETH2P5] = {
+		.sta_mask = BIT(30),
+		.sta_2nd_mask = BIT(31),
+		.pwr_sta_offs = 0x060,
+		.pwr_sta_2nd_offs = 0x060,
+		.pwr_on_bit = BIT(1),
+		.pwr_on_2nd_bit = BIT(2),
+		.pwr_on_offs  = 0x060,
+		.pwr_on_2nd_offs = 0x060,
+		.pwr_clamp_bit = BIT(4),
+	    .pwr_rst_bit = BIT(0),
+		.sram_2nd_pdn_bit = BIT(8),
+		.sram_2nd_clk_dis_bit = BIT(5),
+		.sram_2nd_ctrl_offs = 0x060,
+		.caps = MTK_SCPD_CLAMP_PROTECTION,
+
+	},
+
+};
+
+static const struct scpsys_soc_data mt7988_scpsys_data = {
+	.domains_data = scpsys_domain_data_mt7988,
+	.num_domains = ARRAY_SIZE(scpsys_domain_data_mt7988),
+};
+
+#endif /* __SOC_MEDIATEK_MT7988_PM_DOMAINS_H */
diff --git a/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mtk-pm-domains.c b/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mtk-pm-domains.c
new file mode 100644
index 0000000..fc6b5ff
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mtk-pm-domains.c
@@ -0,0 +1,630 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020 Collabora Ltd.
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_clk.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/soc/mediatek/infracfg.h>
+#include <linux/regulator/consumer.h>
+
+#include "mt7988-pm-domains.h"
+
+#define MTK_POLL_DELAY_US 30
+#define MTK_POLL_TIMEOUT  USEC_PER_SEC
+
+struct scpsys_domain {
+	struct generic_pm_domain genpd;
+	const struct scpsys_domain_data *data;
+	struct scpsys *scpsys;
+	int num_clks;
+	struct clk_bulk_data *clks;
+	int num_subsys_clks;
+	struct clk_bulk_data *subsys_clks;
+	struct regmap *infracfg;
+	struct regulator *supply;
+};
+
+struct scpsys {
+	struct device *dev;
+	struct regmap *base;
+	const struct scpsys_soc_data *soc_data;
+	struct genpd_onecell_data pd_data;
+	struct generic_pm_domain *domains[];
+};
+
+static inline int mtk_regmap_set_bits(struct regmap *map, unsigned int reg,
+				      unsigned int bits)
+{
+	return regmap_update_bits_base(map, reg, bits, bits, NULL, false,
+				       false);
+}
+
+static inline int mtk_regmap_clear_bits(struct regmap *map, unsigned int reg,
+					unsigned int bits)
+{
+	return regmap_update_bits_base(map, reg, bits, 0, NULL, false, false);
+}
+
+#define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd)
+
+static bool scpsys_domain_is_on(struct scpsys_domain *pd)
+{
+	struct scpsys *scpsys = pd->scpsys;
+	u32 status = 0, status2 = 0;
+
+	regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status);
+	status &= pd->data->sta_mask;
+
+	regmap_read(scpsys->base, pd->data->pwr_sta_2nd_offs, &status2);
+	status2 &= pd->data->sta_2nd_mask;
+
+	/* A domain is on when both status bits are set. */
+	return status && status2;
+}
+
+static int scpsys_sram_enable(struct scpsys_domain *pd)
+{
+	u32 pdn_ack = pd->data->sram_pdn_ack_bit;
+	u32 pdn_2nd_ack = pd->data->sram_2nd_pdn_ack_bit;
+	struct scpsys *scpsys = pd->scpsys;
+	unsigned int tmp = 0;
+	int ret;
+
+	if (pd->data->sram_pdn_bit) {
+		mtk_regmap_clear_bits(scpsys->base, pd->data->sram_ctrl_offs,
+				      pd->data->sram_pdn_bit);
+
+		/* Either wait until SRAM_PDN_ACK all 1 or 0 */
+		ret = regmap_read_poll_timeout(scpsys->base,
+					       pd->data->sram_ctrl_offs, tmp,
+					       (tmp & pdn_ack) == 0,
+					       MTK_POLL_DELAY_US,
+					       MTK_POLL_TIMEOUT);
+		if (ret < 0)
+			return ret;
+	}
+	if (pd->data->sram_2nd_pdn_bit) {
+		/* sram pdn 2nd for special mtcmos */
+		mtk_regmap_clear_bits(scpsys->base,
+				      pd->data->sram_2nd_ctrl_offs,
+				      pd->data->sram_2nd_pdn_bit);
+
+		ret = regmap_read_poll_timeout(scpsys->base,
+					       pd->data->sram_2nd_ctrl_offs,
+					       tmp, (tmp & pdn_2nd_ack) == 0,
+					       MTK_POLL_DELAY_US,
+					       MTK_POLL_TIMEOUT);
+		if (ret < 0)
+			return ret;
+	}
+	if (pd->data->sram_clk_iso_bit) {
+		mtk_regmap_clear_bits(scpsys->base, pd->data->sram_ctrl_offs,
+				      pd->data->sram_clk_iso_bit);
+	}
+	if (pd->data->sram_clk_dis_bit) {
+		mtk_regmap_clear_bits(scpsys->base, pd->data->sram_ctrl_offs,
+				      pd->data->sram_clk_dis_bit);
+	}
+	if (pd->data->sram_2nd_clk_iso_bit) {
+		mtk_regmap_clear_bits(scpsys->base,
+				      pd->data->sram_2nd_ctrl_offs,
+				      pd->data->sram_2nd_clk_iso_bit);
+	}
+	if (pd->data->sram_2nd_clk_dis_bit) {
+		mtk_regmap_clear_bits(scpsys->base,
+				      pd->data->sram_2nd_ctrl_offs,
+				      pd->data->sram_2nd_clk_dis_bit);
+	}
+
+	return 0;
+}
+
+static int scpsys_sram_disable(struct scpsys_domain *pd)
+{
+	u32 pdn_ack = pd->data->sram_pdn_ack_bit;
+	u32 pdn_2nd_ack = pd->data->sram_2nd_pdn_ack_bit;
+	struct scpsys *scpsys = pd->scpsys;
+	unsigned int tmp = 0;
+	int ret;
+
+	if (pd->data->sram_2nd_clk_dis_bit) {
+		mtk_regmap_set_bits(scpsys->base, pd->data->sram_2nd_ctrl_offs,
+				    pd->data->sram_2nd_clk_dis_bit);
+	}
+	if (pd->data->sram_clk_iso_bit) {
+		mtk_regmap_set_bits(scpsys->base, pd->data->sram_ctrl_offs,
+				    pd->data->sram_clk_iso_bit);
+		udelay(1);
+	}
+	if (pd->data->sram_pdn_bit) {
+		mtk_regmap_set_bits(scpsys->base, pd->data->sram_ctrl_offs,
+				    pd->data->sram_pdn_bit);
+	}
+
+	if (pd->data->sram_2nd_clk_iso_bit) {
+		mtk_regmap_set_bits(scpsys->base, pd->data->sram_2nd_ctrl_offs,
+				    pd->data->sram_2nd_clk_iso_bit);
+		udelay(1);
+	}
+	if (pd->data->sram_2nd_pdn_bit) {
+		mtk_regmap_set_bits(scpsys->base, pd->data->sram_2nd_ctrl_offs,
+				    pd->data->sram_2nd_pdn_bit);
+	}
+
+	return 0;
+}
+
+static int scpsys_regulator_get(struct generic_pm_domain *genpd)
+{
+	struct scpsys_domain *pd =
+		container_of(genpd, struct scpsys_domain, genpd);
+	struct device_node *node;
+	struct device_node *root;
+
+	if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY) && !pd->supply) {
+		root = pd->scpsys->dev->of_node;
+		node = of_find_node_by_name(root, genpd->name);
+		if (node) {
+			pd->scpsys->dev->of_node = node;
+			pd->supply =
+				devm_regulator_get(pd->scpsys->dev, "domain");
+			pd->scpsys->dev->of_node = root;
+			if (IS_ERR(pd->supply))
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int scpsys_regulator_enable(struct generic_pm_domain *genpd)
+{
+	struct scpsys_domain *pd =
+		container_of(genpd, struct scpsys_domain, genpd);
+	int ret = scpsys_regulator_get(genpd);
+
+	if (ret)
+		return ret;
+
+	return pd->supply ? regulator_enable(pd->supply) : 0;
+}
+
+static int scpsys_regulator_disable(struct generic_pm_domain *genpd)
+{
+	struct scpsys_domain *pd =
+		container_of(genpd, struct scpsys_domain, genpd);
+
+	return pd->supply ? regulator_disable(pd->supply) : 0;
+}
+
+static int scpsys_power_on(struct generic_pm_domain *genpd)
+{
+	struct scpsys_domain *pd =
+		container_of(genpd, struct scpsys_domain, genpd);
+	struct scpsys *scpsys = pd->scpsys;
+	bool tmp;
+	int ret;
+
+	ret = scpsys_regulator_enable(genpd);
+	if (ret)
+		return ret;
+
+	ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
+	if (ret)
+		goto err_pwr_ack;
+
+	/* subsys power on */
+	mtk_regmap_set_bits(scpsys->base, pd->data->pwr_on_offs,
+			    pd->data->pwr_on_bit);
+	mtk_regmap_set_bits(scpsys->base, pd->data->pwr_on_2nd_offs,
+			    pd->data->pwr_on_2nd_bit);
+
+	/* wait until PWR_ACK = 1 */
+	ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp,
+				 MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+	if (ret < 0)
+		goto err_pwr_ack;
+	udelay(30);
+
+	if (pd->data->pwr_clamp_bit) {
+		mtk_regmap_clear_bits(scpsys->base, pd->data->pwr_on_offs,
+				      pd->data->pwr_clamp_bit);
+		udelay(30);
+	}
+
+	if (pd->data->pwr_rst_bit)
+		mtk_regmap_set_bits(scpsys->base, pd->data->pwr_on_offs,
+				    pd->data->pwr_rst_bit);
+
+	ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks);
+	if (ret)
+		goto err_disable_subsys_clks;
+
+	ret = scpsys_sram_enable(pd);
+	if (ret < 0)
+		goto err_disable_sram;
+
+	return 0;
+
+err_disable_sram:
+	scpsys_sram_disable(pd);
+err_disable_subsys_clks:
+	clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
+err_pwr_ack:
+	clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+err_reg:
+	scpsys_regulator_disable(genpd);
+	return ret;
+}
+
+static int scpsys_power_off(struct generic_pm_domain *genpd)
+{
+	struct scpsys_domain *pd =
+		container_of(genpd, struct scpsys_domain, genpd);
+	struct scpsys *scpsys = pd->scpsys;
+	bool tmp;
+	int ret;
+
+	ret = scpsys_sram_disable(pd);
+	if (ret < 0)
+		return ret;
+
+	clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
+
+	if (pd->data->pwr_clamp_bit) {
+		mtk_regmap_set_bits(scpsys->base, pd->data->pwr_on_offs,
+				    pd->data->pwr_clamp_bit);
+		udelay(30);
+	}
+	if (pd->data->pwr_rst_bit)
+		mtk_regmap_clear_bits(scpsys->base, pd->data->pwr_on_offs,
+				      pd->data->pwr_rst_bit);
+
+	mtk_regmap_clear_bits(scpsys->base, pd->data->pwr_on_offs,
+			      pd->data->pwr_on_bit);
+	mtk_regmap_clear_bits(scpsys->base, pd->data->pwr_on_2nd_offs,
+			      pd->data->pwr_on_2nd_bit);
+
+	clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+	scpsys_regulator_disable(genpd);
+
+	return 0;
+}
+
+static struct generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys,
+						       struct device_node *node)
+{
+	const struct scpsys_domain_data *domain_data;
+	struct scpsys_domain *pd;
+	struct property *prop;
+	const char *clk_name;
+	int i, ret, num_clks;
+	struct clk *clk;
+	struct device_node *smi_node;
+	struct device_node *larb_node;
+	int clk_ind = 0;
+	u32 id;
+
+	ret = of_property_read_u32(node, "reg", &id);
+	if (ret) {
+		dev_err(scpsys->dev,
+			"%pOF: failed to retrieve domain id from reg: %d\n",
+			node, ret);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (id >= scpsys->soc_data->num_domains) {
+		dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
+		return ERR_PTR(-EINVAL);
+	}
+
+	domain_data = &scpsys->soc_data->domains_data[id];
+	if (domain_data->sta_mask == 0) {
+		dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node,
+			id);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
+	if (!pd)
+		return ERR_PTR(-ENOMEM);
+
+	pd->data = domain_data;
+	pd->scpsys = scpsys;
+
+	num_clks = of_clk_get_parent_count(node);
+	if (num_clks > 0) {
+		/* Calculate number of subsys_clks */
+		of_property_for_each_string(node, "clock-names", prop,
+					     clk_name) {
+			char *subsys;
+
+			subsys = strchr(clk_name, '-');
+			if (subsys)
+				pd->num_subsys_clks++;
+			else
+				pd->num_clks++;
+		}
+
+		pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks,
+					sizeof(*pd->clks), GFP_KERNEL);
+		if (!pd->clks)
+			return ERR_PTR(-ENOMEM);
+
+		pd->subsys_clks =
+			devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
+				     sizeof(*pd->subsys_clks), GFP_KERNEL);
+		if (!pd->subsys_clks)
+			return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0; i < pd->num_clks; i++) {
+		clk = of_clk_get(node, i);
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			dev_err(scpsys->dev,
+				"%pOF: failed to get clk at index %d: %d\n",
+				node, i, ret);
+			goto err_put_clocks;
+		}
+
+		pd->clks[clk_ind++].clk = clk;
+	}
+
+	for (i = 0; i < pd->num_subsys_clks; i++) {
+		clk = of_clk_get(node, i + clk_ind);
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			dev_err(scpsys->dev,
+				"%pOF: failed to get clk at index %d: %d\n",
+				node, i + clk_ind, ret);
+			goto err_put_subsys_clocks;
+		}
+
+		pd->subsys_clks[i].clk = clk;
+	}
+
+	/*
+	 * Initially turn on all domains to make the domains usable
+	 * with !CONFIG_PM and to get the hardware in sync with the
+	 * software.  The unused domains will be switched off during
+	 * late_init time.
+	 */
+	if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
+		if (scpsys_domain_is_on(pd))
+			dev_warn(
+				scpsys->dev,
+				"%pOF: A default off power domain has been ON\n",
+				node);
+	} else {
+		ret = scpsys_power_on(&pd->genpd);
+		if (ret < 0) {
+			dev_err(scpsys->dev,
+				"%pOF: failed to power on domain: %d\n", node,
+				ret);
+			goto err_put_subsys_clocks;
+		}
+	}
+
+	if (scpsys->domains[id]) {
+		ret = -EINVAL;
+		dev_err(scpsys->dev,
+			"power domain with id %d already exists, check your device-tree\n",
+			id);
+		goto err_put_subsys_clocks;
+	}
+
+	pd->genpd.name = node->name;
+	pd->genpd.power_off = scpsys_power_off;
+	pd->genpd.power_on = scpsys_power_on;
+
+	if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP))
+		pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+
+	if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
+		pm_genpd_init(&pd->genpd, NULL, true);
+	else
+		pm_genpd_init(&pd->genpd, NULL, false);
+
+	scpsys->domains[id] = &pd->genpd;
+
+	return scpsys->pd_data.domains[id];
+
+err_put_subsys_clocks:
+	clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
+err_put_clocks:
+	clk_bulk_put(pd->num_clks, pd->clks);
+	return ERR_PTR(ret);
+}
+
+static int scpsys_add_subdomain(struct scpsys *scpsys,
+				struct device_node *parent)
+{
+	struct generic_pm_domain *child_pd, *parent_pd;
+	struct device_node *child;
+	int ret;
+
+	for_each_child_of_node(parent, child) {
+		u32 id;
+
+		ret = of_property_read_u32(parent, "reg", &id);
+		if (ret) {
+			dev_err(scpsys->dev,
+				"%pOF: failed to get parent domain id\n",
+				child);
+			goto err_put_node;
+		}
+
+		if (!scpsys->pd_data.domains[id]) {
+			ret = -EINVAL;
+			dev_err(scpsys->dev,
+				"power domain with id %d does not exist\n", id);
+			goto err_put_node;
+		}
+
+		parent_pd = scpsys->pd_data.domains[id];
+
+		child_pd = scpsys_add_one_domain(scpsys, child);
+		if (IS_ERR(child_pd)) {
+			ret = PTR_ERR(child_pd);
+			dev_err(scpsys->dev,
+				"%pOF: failed to get child domain id\n", child);
+			goto err_put_node;
+		}
+
+		ret = pm_genpd_add_subdomain(parent_pd, child_pd);
+		if (ret) {
+			dev_err(scpsys->dev,
+				"failed to add %s subdomain to parent %s\n",
+				child_pd->name, parent_pd->name);
+			goto err_put_node;
+		} else {
+			dev_dbg(scpsys->dev, "%s add subdomain: %s\n",
+				parent_pd->name, child_pd->name);
+		}
+
+		/* recursive call to add all subdomains */
+		ret = scpsys_add_subdomain(scpsys, child);
+		if (ret)
+			goto err_put_node;
+	}
+
+	return 0;
+
+err_put_node:
+	of_node_put(child);
+	return ret;
+}
+
+static void scpsys_remove_one_domain(struct scpsys_domain *pd)
+{
+	int ret;
+
+	if (scpsys_domain_is_on(pd))
+		scpsys_power_off(&pd->genpd);
+
+	/*
+	 * We're in the error cleanup already, so we only complain,
+	 * but won't emit another error on top of the original one.
+	 */
+	ret = pm_genpd_remove(&pd->genpd);
+	if (ret < 0)
+		dev_err(pd->scpsys->dev,
+			"failed to remove domain '%s' : %d - state may be inconsistent\n",
+			pd->genpd.name, ret);
+
+	clk_bulk_put(pd->num_clks, pd->clks);
+	clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
+}
+
+static void scpsys_domain_cleanup(struct scpsys *scpsys)
+{
+	struct generic_pm_domain *genpd;
+	struct scpsys_domain *pd;
+	int i;
+
+	for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
+		genpd = scpsys->pd_data.domains[i];
+		if (genpd) {
+			pd = to_scpsys_domain(genpd);
+			scpsys_remove_one_domain(pd);
+		}
+	}
+}
+
+static const struct of_device_id scpsys_of_match[] = {
+	{
+		.compatible = "mediatek,mt7988-power-controller",
+		.data = &mt7988_scpsys_data,
+	},
+	{}
+};
+
+static int scpsys_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct scpsys_soc_data *soc;
+	struct device_node *node;
+	struct scpsys *scpsys;
+	struct resource *res;
+	int ret;
+
+	soc = of_device_get_match_data(&pdev->dev);
+	if (!soc) {
+		dev_err(&pdev->dev, "no power controller data\n");
+		return -EINVAL;
+	}
+
+	scpsys = devm_kzalloc(dev,
+			      struct_size(scpsys, domains, soc->num_domains),
+			      GFP_KERNEL);
+	if (!scpsys)
+		return -ENOMEM;
+
+	scpsys->dev = dev;
+	scpsys->soc_data = soc;
+
+	scpsys->pd_data.domains = scpsys->domains;
+	scpsys->pd_data.num_domains = soc->num_domains;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	scpsys->base = syscon_node_to_regmap(np);
+	if (IS_ERR(scpsys->base)) {
+		dev_err(dev, "no regmap available\n");
+		return PTR_ERR(scpsys->base);
+	}
+
+	ret = -ENODEV;
+	for_each_available_child_of_node(np, node) {
+		struct generic_pm_domain *domain;
+
+		domain = scpsys_add_one_domain(scpsys, node);
+		if (IS_ERR(domain)) {
+			ret = PTR_ERR(domain);
+			of_node_put(node);
+			goto err_cleanup_domains;
+		}
+
+		ret = scpsys_add_subdomain(scpsys, node);
+		if (ret) {
+			of_node_put(node);
+			goto err_cleanup_domains;
+		}
+	}
+
+	if (ret) {
+		dev_dbg(dev, "no power domains present\n");
+		return ret;
+	}
+
+	ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
+	if (ret) {
+		dev_err(dev, "failed to add provider: %d\n", ret);
+		goto err_cleanup_domains;
+	}
+
+	return 0;
+
+err_cleanup_domains:
+	scpsys_domain_cleanup(scpsys);
+	return ret;
+}
+
+static struct platform_driver scpsys_pm_domain_driver = {
+	.probe = scpsys_probe,
+	.driver = {
+		.name = "mtk-power-controller",
+		.suppress_bind_attrs = true,
+		.of_match_table = scpsys_of_match,
+	},
+};
+builtin_platform_driver(scpsys_pm_domain_driver);
diff --git a/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mtk-pm-domains.h b/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mtk-pm-domains.h
new file mode 100644
index 0000000..853f5e6
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/soc/mediatek/mtk-pm-domains.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MTK_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MTK_PM_DOMAINS_H
+
+#define MTK_SCPD_ACTIVE_WAKEUP		BIT(0)
+#define MTK_SCPD_FWAIT_SRAM		BIT(1)
+#define MTK_SCPD_SRAM_ISO		BIT(2)
+#define MTK_SCPD_KEEP_DEFAULT_OFF	BIT(3)
+#define MTK_SCPD_DOMAIN_SUPPLY		BIT(4)
+#define MTK_SCPD_CLAMP_PROTECTION	BIT(5)
+#define MTK_SCPD_CAPS(_scpd, _x)	((_scpd)->data->caps & (_x))
+
+/**
+ * struct scpsys_domain_data - scp domain data for power on/off flow
+ * @sta_mask: The mask for power on/off status bit.
+ * @sta_2nd_mask: The mask for 2nd power on/off status bit.
+ * @pwr_sta_offs: the main power status register.
+ * @pwr_sta_2nd_offs: the 2nd power status register.
+ * @pwr_on_bit: The power on/off bit.
+ * @pwr_on_2nd_bit: The 2nd power on/off bit.
+ * @pwr_on_offs: The offset for main power control register.
+ * @pwr_on_2nd_offs: The offset for 2nd power control register.
+ * @sram_pdn_bit: The mask for sram power control bit.
+ * @sram_pdn_ack_bit: The sram power control acked bit.
+ * @sram_clk_iso_bit: The sram  clk iso bit.
+ * @sram_clk_dis_bit: The sram clk disable bit.
+ * @sram_ctrl_offs: The sram power control register.
+ * @caps: The flag for active wake-up action.
+ * @bp_infracfg: bus protection for infracfg subsystem
+ */
+struct scpsys_domain_data {
+	u32 sta_mask;
+	u32 sta_2nd_mask;
+	int pwr_sta_offs;
+	int pwr_sta_2nd_offs;
+	u32 pwr_on_bit;
+	u32 pwr_on_2nd_bit;
+	int pwr_on_offs;
+	int pwr_on_2nd_offs;
+	u32 pwr_clamp_bit;
+	u32 pwr_rst_bit;
+	u32 sram_pdn_bit;
+	u32 sram_pdn_ack_bit;
+	u32 sram_clk_iso_bit;
+	u32 sram_clk_dis_bit;
+	int sram_ctrl_offs;
+	u32 sram_2nd_pdn_bit;
+	u32 sram_2nd_pdn_ack_bit;
+	u32 sram_2nd_clk_iso_bit;
+	u32 sram_2nd_clk_dis_bit;
+	int sram_2nd_ctrl_offs;
+	u8 caps;
+
+};
+
+struct scpsys_soc_data {
+	const struct scpsys_domain_data *domains_data;
+	int num_domains;
+};
+
+#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */
diff --git a/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/Kconfig b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/Kconfig
new file mode 100644
index 0000000..edc0aa4
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/Kconfig
@@ -0,0 +1,9 @@
+config MTK_SOC_THERMAL_LVTS
+        tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
+        depends on HAS_IOMEM
+        depends on NVMEM
+        help
+          Enable this option if you want to get SoC temperature
+          information for Mediatek platforms. This driver
+          configures LVTS thermal controllers to collect temperatures
+          via Analog Serial Interface(ASIF).
diff --git a/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/Makefile b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/Makefile
new file mode 100644
index 0000000..c9225cb
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)	+= soc_temp_lvts.o
diff --git a/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/soc_temp_lvts.c b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/soc_temp_lvts.c
new file mode 100644
index 0000000..570ac17
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/soc_temp_lvts.c
@@ -0,0 +1,1895 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Henry Yen <henry.yen@mediatek.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/thermal.h>
+#include "soc_temp_lvts.h"
+
+/*
+ * Definition or macro function
+ */
+#define STOP_COUNTING_V5	     (DEVICE_WRITE | RG_TSFM_CTRL_0 << 8 | 0x00)
+#define SET_RG_TSFM_LPDLY_V5	     (DEVICE_WRITE | RG_TSFM_CTRL_4 << 8 | 0xA6)
+#define SET_COUNTING_WINDOW_20US1_V5 (DEVICE_WRITE | RG_TSFM_CTRL_2 << 8 | 0x00)
+#define SET_COUNTING_WINDOW_20US2_V5 (DEVICE_WRITE | RG_TSFM_CTRL_1 << 8 | 0x20)
+#define TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V5                                       \
+	(DEVICE_WRITE | RG_TSV2F_CTRL_2 << 8 | 0x8C)
+#define TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V5                                       \
+	(DEVICE_WRITE | RG_TSV2F_CTRL_4 << 8 | 0xFC)
+#define SET_TS_RSV_V5 (DEVICE_WRITE | RG_TSV2F_CTRL_1 << 8 | 0x8D)
+#define SET_TS_EN_V5  (DEVICE_WRITE | RG_TSV2F_CTRL_0 << 8 | 0xF1)
+
+#define SET_MANUAL_RCK_V5	  (DEVICE_WRITE | RG_TSV2F_CTRL_6 << 8 | 0x00)
+#define SELECT_SENSOR_RCK_V5(id)  (DEVICE_WRITE | RG_TSV2F_CTRL_5 << 8 | (id))
+#define SET_DEVICE_SINGLE_MODE_V5 (DEVICE_WRITE | RG_TSFM_CTRL_3 << 8 | 0xB8)
+#define KICK_OFF_RCK_COUNTING_V5  (DEVICE_WRITE | RG_TSFM_CTRL_0 << 8 | 0x02)
+#define SET_SENSOR_NO_RCK_V5(id)                                               \
+	(DEVICE_WRITE | RG_TSV2F_CTRL_5 << 8 | 0x10 | (id))
+#define SET_DEVICE_LOW_POWER_SINGLE_MODE_V5                                    \
+	(DEVICE_WRITE | RG_TSFM_CTRL_3 << 8 | 0xB8)
+
+#define STOP_COUNTING_V4	     (DEVICE_WRITE | RG_TSFM_CTRL_0 << 8 | 0x00)
+#define SET_RG_TSFM_LPDLY_V4	     (DEVICE_WRITE | RG_TSFM_CTRL_4 << 8 | 0xA6)
+#define SET_COUNTING_WINDOW_20US1_V4 (DEVICE_WRITE | RG_TSFM_CTRL_2 << 8 | 0x00)
+#define SET_COUNTING_WINDOW_20US2_V4 (DEVICE_WRITE | RG_TSFM_CTRL_1 << 8 | 0x20)
+#define TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V4                                       \
+	(DEVICE_WRITE | RG_TSV2F_CTRL_2 << 8 | 0x84)
+#define TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V4                                       \
+	(DEVICE_WRITE | RG_TSV2F_CTRL_4 << 8 | 0x7C)
+#define SET_TS_RSV_V4		    (DEVICE_WRITE | RG_TSV2F_CTRL_1 << 8 | 0x8D)
+#define SET_TS_EN_V4		    (DEVICE_WRITE | RG_TSV2F_CTRL_0 << 8 | 0xF4)
+#define TOGGLE_RG_TSV2F_VCO_RST1_V4 (DEVICE_WRITE | RG_TSV2F_CTRL_0 << 8 | 0xFC)
+#define TOGGLE_RG_TSV2F_VCO_RST2_V4 (DEVICE_WRITE | RG_TSV2F_CTRL_0 << 8 | 0xF4)
+
+#define SET_LVTS_AUTO_RCK_V4	  (DEVICE_WRITE | RG_TSV2F_CTRL_6 << 8 | 0x01)
+#define SELECT_SENSOR_RCK_V4(id)  (DEVICE_WRITE | RG_TSV2F_CTRL_5 << 8 | (id))
+#define SET_DEVICE_SINGLE_MODE_V4 (DEVICE_WRITE | RG_TSFM_CTRL_3 << 8 | 0x78)
+#define KICK_OFF_RCK_COUNTING_V4  (DEVICE_WRITE | RG_TSFM_CTRL_0 << 8 | 0x02)
+#define SET_SENSOR_NO_RCK_V4	  (DEVICE_WRITE | RG_TSV2F_CTRL_5 << 8 | 0x10)
+#define SET_DEVICE_LOW_POWER_SINGLE_MODE_V4                                    \
+	(DEVICE_WRITE | RG_TSFM_CTRL_3 << 8 | 0xB8)
+
+#define ENABLE_FEATURE(feature)	 (lvts_data->feature_bitmap |= (feature))
+#define DISABLE_FEATURE(feature) (lvts_data->feature_bitmap &= (~(feature)))
+#define IS_ENABLE(feature)	 (lvts_data->feature_bitmap & (feature))
+
+#define DISABLE_THERMAL_HW_REBOOT (-274000)
+
+#define CLOCK_26MHZ_CYCLE_NS	(38)
+#define BUS_ACCESS_US		(2)
+#define GOLDEN_TEMP_MAX		(62)
+#define FEATURE_DEVICE_AUTO_RCK (BIT(0))
+#define FEATURE_CK26M_ACTIVE	(BIT(1))
+#define FEATURE_IRQ		(BIT(2))
+#define FEATURE_RESET		(BIT(3))
+#define CK26M_ACTIVE                                                           \
+	(((lvts_data->feature_bitmap & FEATURE_CK26M_ACTIVE) ? 1 : 0) << 30)
+#define GET_BASE_ADDR(tc_id)                                                   \
+	(lvts_data->domain[lvts_data->tc[tc_id].domain_index].base +           \
+	 lvts_data->tc[tc_id].addr_offset)
+
+#define SET_TC_SPEED_IN_US(pu, gd, fd, sd)                                     \
+	{                                                                      \
+		.period_unit = (((pu)*1000) / (256 * CLOCK_26MHZ_CYCLE_NS)),   \
+		.group_interval_delay = ((gd) / (pu)),                         \
+		.filter_interval_delay = ((fd) / (pu)),                        \
+		.sensor_interval_delay = ((sd) / (pu)),                        \
+	}
+
+#define GET_CAL_DATA_BITMASK(index, h, l)                                      \
+	(((index) < lvts_data->num_efuse_addr) ?                               \
+		 ((lvts_data->efuse[(index)] & GENMASK(h, l)) >> l) :          \
+		 0)
+
+#define GET_CAL_DATA_BIT(index, bit)                                           \
+	(((index) < lvts_data->num_efuse_addr) ?                               \
+		 ((lvts_data->efuse[index] & BIT(bit)) >> (bit)) :             \
+		 0)
+
+#define GET_TC_SENSOR_NUM(tc_id) (lvts_data->tc[tc_id].num_sensor)
+
+#define ONE_SAMPLE (lvts_data->counting_window_us + 2 * BUS_ACCESS_US)
+
+#define NUM_OF_SAMPLE(tc_id)                                                   \
+	((lvts_data->tc[tc_id].hw_filter < LVTS_FILTER_2) ?                    \
+		 1 :                                                           \
+		 ((lvts_data->tc[tc_id].hw_filter > LVTS_FILTER_16_OF_18) ?    \
+			  1 :                                                  \
+			  ((lvts_data->tc[tc_id].hw_filter ==                  \
+			    LVTS_FILTER_16_OF_18) ?                            \
+				   18 :                                        \
+				   ((lvts_data->tc[tc_id].hw_filter ==         \
+				     LVTS_FILTER_8_OF_10) ?                    \
+					    10 :                               \
+					    (lvts_data->tc[tc_id].hw_filter *  \
+					     2)))))
+
+#define PERIOD_UNIT_US(tc_id)                                                  \
+	((lvts_data->tc[tc_id].tc_speed.period_unit * 256 *                    \
+	  CLOCK_26MHZ_CYCLE_NS) /                                              \
+	 1000)
+#define FILTER_INT_US(tc_id)                                                   \
+	(lvts_data->tc[tc_id].tc_speed.filter_interval_delay *                 \
+	 PERIOD_UNIT_US(tc_id))
+#define SENSOR_INT_US(tc_id)                                                   \
+	(lvts_data->tc[tc_id].tc_speed.sensor_interval_delay *                 \
+	 PERIOD_UNIT_US(tc_id))
+#define GROUP_INT_US(tc_id)                                                    \
+	(lvts_data->tc[tc_id].tc_speed.group_interval_delay *                  \
+	 PERIOD_UNIT_US(tc_id))
+
+#define SENSOR_LATENCY_US(tc_id)                                               \
+	((NUM_OF_SAMPLE(tc_id) - 1) * FILTER_INT_US(tc_id) +                   \
+	 NUM_OF_SAMPLE(tc_id) * ONE_SAMPLE)
+
+#define GROUP_LATENCY_US(tc_id)                                                \
+	(GET_TC_SENSOR_NUM(tc_id) * SENSOR_LATENCY_US(tc_id) +                 \
+	 (GET_TC_SENSOR_NUM(tc_id) - 1) * SENSOR_INT_US(tc_id) +               \
+	 GROUP_INT_US(tc_id))
+
+/*
+ * LVTS local common code
+ */
+static int lvts_raw_to_temp(struct formula_coeff *co, unsigned int msr_raw)
+{
+	/* This function returns degree mC */
+
+	int temp;
+
+	msr_raw &= 0xffff;
+	temp = (co->a * ((unsigned long long)msr_raw)) >> 14;
+	temp = temp + co->golden_temp * 500 + co->b;
+
+	return temp;
+}
+
+static unsigned int lvts_temp_to_raw(struct formula_coeff *co, int temp)
+{
+	unsigned int msr_raw;
+
+	msr_raw = ((long long)((co->golden_temp * 500 + co->b - temp)) << 14) /
+		  (-1 * co->a);
+
+	return msr_raw;
+}
+
+static int lvts_read_all_tc_temperature(struct lvts_data *lvts_data)
+{
+	struct tc_settings *tc = lvts_data->tc;
+	unsigned int i, j, s_index, msr_raw;
+	int max_temp = -100000, current_temp;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+
+			msr_raw = readl(LVTSMSR0_0 + base + 0x4 * j) &
+				  MRS_RAW_MASK;
+			current_temp =
+				lvts_raw_to_temp(&lvts_data->coeff, msr_raw);
+
+			if (msr_raw == 0)
+				current_temp = THERMAL_TEMP_INVALID;
+
+			max_temp = max(max_temp, current_temp);
+
+			lvts_data->sen_data[s_index].msr_raw = msr_raw;
+			lvts_data->sen_data[s_index].temp = current_temp;
+		}
+	}
+
+	return max_temp;
+}
+
+static int soc_temp_lvts_read_temp(void *data, int *temperature)
+{
+	struct soc_temp_tz *lvts_tz = (struct soc_temp_tz *)data;
+	struct lvts_data *lvts_data = lvts_tz->lvts_data;
+
+	if (lvts_tz->id == 0)
+		*temperature = lvts_read_all_tc_temperature(lvts_data);
+	else if (lvts_tz->id - 1 < lvts_data->num_sensor)
+		*temperature = lvts_data->sen_data[lvts_tz->id - 1].temp;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops soc_temp_lvts_ops = {
+	.get_temp = soc_temp_lvts_read_temp,
+};
+
+static void lvts_write_device(struct lvts_data *lvts_data, unsigned int data,
+			      int tc_id)
+{
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(tc_id);
+
+	writel(data, LVTS_CONFIG_0 + base);
+
+	usleep_range(5, 15);
+}
+
+static unsigned int lvts_read_device(struct lvts_data *lvts_data,
+				     unsigned int reg_idx, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	void __iomem *base;
+	unsigned int data;
+	int ret;
+
+	base = GET_BASE_ADDR(tc_id);
+	writel(READ_DEVICE_REG(reg_idx), LVTS_CONFIG_0 + base);
+
+	ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
+				 !(data & DEVICE_ACCESS_STARTUS), 2, 200);
+	if (ret)
+		dev_err(dev,
+			"Error: LVTS %d DEVICE_ACCESS_START didn't ready\n",
+			tc_id);
+
+	data = readl(LVTSRDATA0_0 + base);
+
+	return data;
+}
+
+static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int mask, error_code, is_error;
+	void __iomem *base;
+	int i, cnt, ret;
+
+	mask = BIT(10) | BIT(7) | BIT(0);
+
+	for (cnt = 0; cnt < 2; cnt++) {
+		is_error = 0;
+		for (i = 0; i < lvts_data->num_tc; i++) {
+			base = GET_BASE_ADDR(i);
+			ret = readl_poll_timeout(LVTSMSRCTL1_0 + base,
+						 error_code,
+						 !(error_code & mask), 2, 200);
+			/*
+			 * Error code
+			 * 000: IDLE
+			 * 001: Write transaction
+			 * 010: Waiting for read after Write
+			 * 011: Disable Continue fetching on Device
+			 * 100: Read transaction
+			 * 101: Set Device special Register for Voltage
+			 *	threshold
+			 * 111: Set TSMCU number for Fetch
+			 */
+			error_code = ((error_code & BIT(10)) >> 8) +
+				     ((error_code & BIT(7)) >> 6) +
+				     (error_code & BIT(0));
+
+			if (ret)
+				dev_err(dev,
+					"Error LVTS %d sensing points aren't idle, error_code %d\n",
+					i, error_code);
+
+			if (error_code != 0)
+				is_error = 1;
+		}
+
+		if (is_error == 0)
+			break;
+	}
+}
+
+static void lvts_reset(struct lvts_data *lvts_data)
+{
+	int i;
+
+	for (i = 0; i < lvts_data->num_domain; i++) {
+		if (lvts_data->domain[i].reset)
+			reset_control_assert(lvts_data->domain[i].reset);
+
+		if (lvts_data->domain[i].reset)
+			reset_control_deassert(lvts_data->domain[i].reset);
+	}
+}
+
+static void device_identification(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int i, data;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+
+		writel(ENABLE_LVTS_CTRL_CLK, LVTSCLKEN_0 + base);
+
+		lvts_write_device(lvts_data, RESET_ALL_DEVICES, i);
+
+		lvts_write_device(lvts_data, READ_BACK_DEVICE_ID, i);
+
+		/* Check LVTS device ID */
+		data = (readl(LVTS_ID_0 + base) & GENMASK(7, 0));
+		if (data != (0x83 + i))
+			dev_err(dev,
+				"LVTS_TC_%d, Device ID should be 0x%x, but 0x%x\n",
+				i, (0x83 + i), data);
+	}
+}
+
+static void disable_all_sensing_points(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+		writel(DISABLE_SENSING_POINT, LVTSMONCTL0_0 + base);
+	}
+}
+
+static void enable_all_sensing_points(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	struct tc_settings *tc = lvts_data->tc;
+	unsigned int i, num;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+		num = tc[i].num_sensor;
+
+		if (num > ALL_SENSING_POINTS) {
+			dev_err(dev,
+				"%s, LVTS%d, illegal number of sensors: %d\n",
+				__func__, i, tc[i].num_sensor);
+			continue;
+		}
+
+		writel(ENABLE_SENSING_POINT(num), LVTSMONCTL0_0 + base);
+	}
+}
+
+static void set_polling_speed(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	struct tc_settings *tc = lvts_data->tc;
+	unsigned int lvts_mon_ctl_1, lvts_mon_ctl_2;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(tc_id);
+
+	lvts_mon_ctl_1 = ((tc[tc_id].tc_speed.group_interval_delay << 20) &
+			  GENMASK(29, 20)) |
+			 (tc[tc_id].tc_speed.period_unit & GENMASK(9, 0));
+	lvts_mon_ctl_2 =
+		((tc[tc_id].tc_speed.filter_interval_delay << 16) &
+		 GENMASK(25, 16)) |
+		(tc[tc_id].tc_speed.sensor_interval_delay & GENMASK(9, 0));
+	/*
+	 * Clock source of LVTS thermal controller is 26MHz.
+	 * Period unit is a base for all interval delays
+	 * All interval delays must multiply it to convert a setting to time.
+	 *
+	 * Filter interval delay:
+	 * A delay between two samples of the same sensor
+	 *
+	 * Sensor interval delay:
+	 * A delay between two samples of differnet sensors
+	 *
+	 * Group interval delay:
+	 * A delay between different rounds.
+	 *
+	 * For example:
+	 *     If Period unit = C, filter delay = 1, sensor delay = 2,
+	 *     group delay = 1, and two sensors, TS1 and TS2, are in a LVTS
+	 *     thermal controller and then
+	 *     Period unit = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us
+	 *     Filter interval delay = 1 * Period unit = 118.149us
+	 *     Sensor interval delay = 2 * Period unit = 236.298us
+	 *     Group interval delay = 1 * Period unit = 118.149us
+	 *
+	 *     TS1    TS1 ... TS1    TS2    TS2 ... TS2    TS1...
+	 *        <--> Filter interval delay
+	 *                       <--> Sensor interval delay
+	 *                                             <--> Group interval delay
+	 */
+	writel(lvts_mon_ctl_1, LVTSMONCTL1_0 + base);
+	writel(lvts_mon_ctl_2, LVTSMONCTL2_0 + base);
+
+	dev_info(dev, "%s %d, LVTSMONCTL1_0= 0x%x,LVTSMONCTL2_0= 0x%x\n",
+		 __func__, tc_id, readl(LVTSMONCTL1_0 + base),
+		 readl(LVTSMONCTL2_0 + base));
+}
+
+static void set_hw_filter(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	struct tc_settings *tc = lvts_data->tc;
+	unsigned int option;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(tc_id);
+	option = tc[tc_id].hw_filter & 0x7;
+	/* hw filter
+	 * 000: Get one sample
+	 * 001: Get 2 samples and average them
+	 * 010: Get 4 samples, drop max and min, then average the rest of 2
+	 *      samples
+	 * 011: Get 6 samples, drop max and min, then average the rest of 4
+	 *      samples
+	 * 100: Get 10 samples, drop max and min, then average the rest of 8
+	 *      samples
+	 * 101: Get 18 samples, drop max and min, then average the rest of 16
+	 * samples
+	 */
+	option = (option << 9) | (option << 6) | (option << 3) | option;
+
+	writel(option, LVTSMSRCTL0_0 + base);
+	dev_info(dev, "%s %d, LVTSMSRCTL0_0= 0x%x\n", __func__, tc_id,
+		 readl(LVTSMSRCTL0_0 + base));
+}
+
+static int get_dominator_index(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	struct tc_settings *tc = lvts_data->tc;
+	int d_index;
+
+	if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
+		d_index = ALL_SENSING_POINTS;
+	} else if (tc[tc_id].dominator_sensing_point < tc[tc_id].num_sensor) {
+		d_index = tc[tc_id].dominator_sensing_point;
+	} else {
+		dev_err(dev,
+			"Error: LVTS%d, dominator_sensing_point= %d should smaller than num_sensor= %d\n",
+			tc_id, tc[tc_id].dominator_sensing_point,
+			tc[tc_id].num_sensor);
+
+		dev_err(dev,
+			"Use the sensing point 0 as the dominated sensor\n");
+		d_index = SENSING_POINT0;
+	}
+
+	return d_index;
+}
+
+static void disable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
+{
+	unsigned int temp;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(tc_id);
+
+	/* LVTS thermal controller has two interrupts for thermal HW reboot
+	 * One is for AP SW and the other is for RGU
+	 * The interrupt of AP SW can turn off by a bit of a register, but
+	 * the other for RGU cannot.
+	 * To prevent rebooting device accidentally, we are going to add
+	 * a huge offset to LVTS and make LVTS always report extremely low
+	 * temperature.
+	 */
+
+	/* After adding the huge offset 0x3FFF, LVTS alawys adds the
+	 * offset to MSR_RAW.
+	 * When MSR_RAW is larger, SW will convert lower temperature/
+	 */
+	temp = readl(LVTSPROTCTL_0 + base);
+	writel(temp | 0x3FFF, LVTSPROTCTL_0 + base);
+
+	/* Disable the interrupt of AP SW */
+	temp = readl(LVTSMONINT_0 + base);
+	writel(temp & ~(STAGE3_INT_EN), LVTSMONINT_0 + base);
+}
+
+static void enable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
+{
+	unsigned int temp;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(tc_id);
+
+	/* Enable the interrupt of AP SW */
+	temp = readl(LVTSMONINT_0 + base);
+	writel(temp | STAGE3_INT_EN, LVTSMONINT_0 + base);
+	/* Clear the offset */
+	temp = readl(LVTSPROTCTL_0 + base);
+	writel(temp & ~PROTOFFSET, LVTSPROTCTL_0 + base);
+}
+
+static void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data,
+				       int trip_point, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int msr_raw, temp, config, d_index;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(tc_id);
+	d_index = get_dominator_index(lvts_data, tc_id);
+
+	dev_info(dev, "%s: LVTS%d, the dominator sensing point= %d\n", __func__,
+		 tc_id, d_index);
+
+	disable_hw_reboot_interrupt(lvts_data, tc_id);
+
+	temp = readl(LVTSPROTCTL_0 + base);
+	if (d_index == ALL_SENSING_POINTS) {
+		/* Maximum of 4 sensing points */
+		config = (0x1 << 16);
+		writel(config | temp, LVTSPROTCTL_0 + base);
+	} else {
+		/* Select protection sensor */
+		config = ((d_index << 2) + 0x2) << 16;
+		writel(config | temp, LVTSPROTCTL_0 + base);
+	}
+
+	msr_raw = lvts_temp_to_raw(&lvts_data->coeff, trip_point);
+	writel(msr_raw, LVTSPROTTC_0 + base);
+
+	enable_hw_reboot_interrupt(lvts_data, tc_id);
+}
+
+static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
+{
+	struct tc_settings *tc = lvts_data->tc;
+	int i, trip_point;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		trip_point = tc[i].hw_reboot_trip_point;
+
+		if (tc[i].num_sensor == 0)
+			continue;
+
+		if (trip_point == DISABLE_THERMAL_HW_REBOOT)
+			continue;
+
+		set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
+	}
+}
+
+static int lvts_init(struct lvts_data *lvts_data)
+{
+	struct platform_ops *ops = &lvts_data->ops;
+	struct device *dev = lvts_data->dev;
+	int ret;
+
+	ret = clk_prepare_enable(lvts_data->clk);
+	if (ret) {
+		dev_err(dev,
+			"Error: Failed to enable lvts controller clock: %d\n",
+			ret);
+		return ret;
+	}
+
+	if (lvts_data->feature_bitmap & FEATURE_RESET)
+		lvts_reset(lvts_data);
+
+	device_identification(lvts_data);
+	if (ops->device_enable_and_init)
+		ops->device_enable_and_init(lvts_data);
+
+	if (IS_ENABLE(FEATURE_DEVICE_AUTO_RCK)) {
+		if (ops->device_enable_auto_rck)
+			ops->device_enable_auto_rck(lvts_data);
+	} else {
+		if (ops->device_read_count_rc_n)
+			ops->device_read_count_rc_n(lvts_data);
+	}
+
+	if (ops->set_cal_data)
+		ops->set_cal_data(lvts_data);
+
+	disable_all_sensing_points(lvts_data);
+	wait_all_tc_sensing_point_idle(lvts_data);
+	if (ops->init_controller)
+		ops->init_controller(lvts_data);
+	enable_all_sensing_points(lvts_data);
+
+	set_all_tc_hw_reboot(lvts_data);
+
+	return 0;
+}
+
+static int prepare_calibration_data(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+	struct platform_ops *ops = &lvts_data->ops;
+	int i, offset, size;
+	char buffer[512];
+
+	cal_data->count_r =
+		devm_kcalloc(dev, lvts_data->num_sensor,
+			     sizeof(*cal_data->count_r), GFP_KERNEL);
+	if (!cal_data->count_r)
+		return -ENOMEM;
+
+	cal_data->count_rc =
+		devm_kcalloc(dev, lvts_data->num_sensor,
+			     sizeof(*cal_data->count_rc), GFP_KERNEL);
+	if (!cal_data->count_rc)
+		return -ENOMEM;
+
+	if (ops->efuse_to_cal_data && !cal_data->use_fake_efuse)
+		ops->efuse_to_cal_data(lvts_data);
+
+	if (cal_data->golden_temp == 0 ||
+	    cal_data->golden_temp > GOLDEN_TEMP_MAX)
+		cal_data->use_fake_efuse = 1;
+
+	if (cal_data->use_fake_efuse) {
+		/* It means all efuse data are equal to 0 */
+		dev_err(dev,
+			"[lvts_cal] This sample is not calibrated, fake !!\n");
+
+		cal_data->golden_temp = cal_data->default_golden_temp;
+		for (i = 0; i < lvts_data->num_sensor; i++) {
+			cal_data->count_r[i] = cal_data->default_count_r;
+			cal_data->count_rc[i] = cal_data->default_count_rc;
+		}
+	}
+
+	lvts_data->coeff.golden_temp = cal_data->golden_temp;
+
+	dev_info(dev, "[lvts_cal] golden_temp = %d\n", cal_data->golden_temp);
+
+	size = sizeof(buffer);
+	offset = snprintf(buffer, size, "[lvts_cal] num:g_count:g_count_rc ");
+	for (i = 0; i < lvts_data->num_sensor; i++)
+		offset +=
+			snprintf(buffer + offset, size - offset, "%d:%d:%d ", i,
+				 cal_data->count_r[i], cal_data->count_rc[i]);
+
+	buffer[offset] = '\0';
+	dev_info(dev, "%s\n", buffer);
+
+	return 0;
+}
+
+static int get_calibration_data(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	char cell_name[8];
+	struct nvmem_cell *cell;
+	u32 *buf;
+	size_t len;
+	int i, j, index = 0;
+
+	lvts_data->efuse = devm_kcalloc(dev, lvts_data->num_efuse_addr,
+					sizeof(*lvts_data->efuse), GFP_KERNEL);
+	if (!lvts_data->efuse)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_efuse_block; i++) {
+		snprintf(cell_name, sizeof(cell_name), "e_data%d", i + 1);
+		cell = nvmem_cell_get(dev, cell_name);
+		if (IS_ERR(cell)) {
+			dev_err(dev, "Error: Failed to get nvmem cell %s\n",
+				cell_name);
+			return PTR_ERR(cell);
+		}
+
+		buf = (u32 *)nvmem_cell_read(cell, &len);
+		nvmem_cell_put(cell);
+
+		if (IS_ERR(buf))
+			return PTR_ERR(buf);
+
+		for (j = 0; j < (len / sizeof(u32)); j++) {
+			if (index >= lvts_data->num_efuse_addr) {
+				dev_err(dev,
+					"Array efuse is going to overflow");
+				kfree(buf);
+				return -EINVAL;
+			}
+
+			lvts_data->efuse[index] = buf[j];
+			index++;
+		}
+
+		kfree(buf);
+	}
+
+	return 0;
+}
+
+static int of_update_lvts_data(struct lvts_data *lvts_data,
+			       struct platform_device *pdev)
+{
+	struct device *dev = lvts_data->dev;
+	struct power_domain *domain;
+	struct resource *res;
+	unsigned int i;
+	int ret;
+
+	lvts_data->clk = devm_clk_get(dev, "lvts_clk");
+	if (IS_ERR(lvts_data->clk))
+		return PTR_ERR(lvts_data->clk);
+
+	domain = devm_kcalloc(dev, lvts_data->num_domain, sizeof(*domain),
+			      GFP_KERNEL);
+	if (!domain)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_domain; i++) {
+		/* Get base address */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			dev_err(dev, "No IO resource, index %d\n", i);
+			return -ENXIO;
+		}
+
+		domain[i].base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(domain[i].base)) {
+			dev_err(dev, "Failed to remap io, index %d\n", i);
+			return PTR_ERR(domain[i].base);
+		}
+
+		/* Get interrupt number */
+		if (lvts_data->feature_bitmap & FEATURE_IRQ) {
+			res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+			if (!res) {
+				dev_err(dev, "No irq resource, index %d\n", i);
+				return -EINVAL;
+			}
+			domain[i].irq_num = res->start;
+		}
+
+		/* Get reset control */
+		if (lvts_data->feature_bitmap & FEATURE_RESET) {
+			domain[i].reset =
+				devm_reset_control_get_by_index(dev, i);
+			if (IS_ERR(domain[i].reset)) {
+				dev_err(dev, "Failed to get, index %d\n", i);
+				return PTR_ERR(domain[i].reset);
+			}
+		}
+	}
+
+	lvts_data->domain = domain;
+
+	lvts_data->sen_data =
+		devm_kcalloc(dev, lvts_data->num_sensor,
+			     sizeof(*lvts_data->sen_data), GFP_KERNEL);
+	if (!lvts_data->sen_data)
+		return -ENOMEM;
+
+	ret = get_calibration_data(lvts_data);
+	if (ret)
+		lvts_data->cal_data.use_fake_efuse = 1;
+	ret = prepare_calibration_data(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void lvts_device_close(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+		lvts_write_device(lvts_data, RESET_ALL_DEVICES, i);
+		writel(DISABLE_LVTS_CTRL_CLK, LVTSCLKEN_0 + base);
+	}
+}
+
+static void lvts_close(struct lvts_data *lvts_data)
+{
+	disable_all_sensing_points(lvts_data);
+	wait_all_tc_sensing_point_idle(lvts_data);
+	lvts_device_close(lvts_data);
+	clk_disable_unprepare(lvts_data->clk);
+}
+
+static void tc_irq_handler(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int ret = 0;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(tc_id);
+
+	ret = readl(LVTSMONINTSTS_0 + base);
+	/* Write back to clear interrupt status */
+	writel(ret, LVTSMONINTSTS_0 + base);
+
+	dev_info(
+		dev,
+		"[Thermal IRQ] LVTS thermal controller %d, LVTSMONINTSTS=0x%08x\n",
+		tc_id, ret);
+
+	if (ret & THERMAL_PROTECTION_STAGE_3)
+		dev_info(
+			dev,
+			"[Thermal IRQ]: Thermal protection stage 3 interrupt triggered\n");
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+	struct lvts_data *lvts_data = (struct lvts_data *)dev_id;
+	struct device *dev = lvts_data->dev;
+	struct tc_settings *tc = lvts_data->tc;
+	unsigned int i, *irq_bitmap;
+	void __iomem *base;
+
+	irq_bitmap =
+		kcalloc(lvts_data->num_domain, sizeof(*irq_bitmap), GFP_ATOMIC);
+
+	if (!irq_bitmap)
+		return IRQ_NONE;
+
+	for (i = 0; i < lvts_data->num_domain; i++) {
+		base = lvts_data->domain[i].base;
+		irq_bitmap[i] = readl(THERMINTST + base);
+		dev_info(dev, "%s : THERMINTST = 0x%x\n", __func__,
+			 irq_bitmap[i]);
+	}
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		if ((irq_bitmap[tc[i].domain_index] & tc[i].irq_bit) == 0)
+			tc_irq_handler(lvts_data, i);
+	}
+
+	kfree(irq_bitmap);
+
+	return IRQ_HANDLED;
+}
+
+static int lvts_register_irq_handler(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < lvts_data->num_domain; i++) {
+		ret = devm_request_irq(dev, lvts_data->domain[i].irq_num,
+				       irq_handler, IRQF_TRIGGER_HIGH,
+				       "mtk_lvts", lvts_data);
+
+		if (ret) {
+			dev_err(dev,
+				"Failed to register LVTS IRQ, ret %d, domain %d irq_num %d\n",
+				ret, i, lvts_data->domain[i].irq_num);
+			lvts_close(lvts_data);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	struct thermal_zone_device *tzdev;
+	struct soc_temp_tz *lvts_tz;
+	int i, ret;
+
+	for (i = 0; i < lvts_data->num_sensor + 1; i++) {
+		lvts_tz = devm_kzalloc(dev, sizeof(*lvts_tz), GFP_KERNEL);
+		if (!lvts_tz) {
+			lvts_close(lvts_data);
+			return -ENOMEM;
+		}
+
+		lvts_tz->id = i;
+		lvts_tz->lvts_data = lvts_data;
+
+		tzdev = devm_thermal_zone_of_sensor_register(
+			dev, lvts_tz->id, lvts_tz, &soc_temp_lvts_ops);
+
+		if (IS_ERR(tzdev)) {
+			if (lvts_tz->id != 0)
+				return 0;
+
+			ret = PTR_ERR(tzdev);
+			lvts_close(lvts_data);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int lvts_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct lvts_data *lvts_data;
+	int ret;
+
+	lvts_data = (struct lvts_data *)of_device_get_match_data(dev);
+
+	if (!lvts_data) {
+		dev_err(dev, "Error: Failed to get lvts platform data\n");
+		return -ENODATA;
+	}
+
+	lvts_data->dev = &pdev->dev;
+
+	ret = of_update_lvts_data(lvts_data, pdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, lvts_data);
+
+	ret = lvts_init(lvts_data);
+	if (ret)
+		return ret;
+
+	if (lvts_data->feature_bitmap & FEATURE_IRQ) {
+		ret = lvts_register_irq_handler(lvts_data);
+		if (ret)
+			return ret;
+	}
+
+	ret = lvts_register_thermal_zones(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int lvts_remove(struct platform_device *pdev)
+{
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	lvts_close(lvts_data);
+
+	return 0;
+}
+
+static int lvts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	lvts_close(lvts_data);
+
+	return 0;
+}
+
+static int lvts_resume(struct platform_device *pdev)
+{
+	int ret;
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	ret = lvts_init(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * LVTS v4 common code
+ */
+
+static void device_enable_and_init_v4(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		lvts_write_device(lvts_data, STOP_COUNTING_V4, i);
+		lvts_write_device(lvts_data, SET_RG_TSFM_LPDLY_V4, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US1_V4, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US2_V4, i);
+		lvts_write_device(lvts_data, TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V4,
+				  i);
+		lvts_write_device(lvts_data, TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V4,
+				  i);
+		lvts_write_device(lvts_data, SET_TS_RSV_V4, i);
+		lvts_write_device(lvts_data, SET_TS_EN_V4, i);
+		lvts_write_device(lvts_data, TOGGLE_RG_TSV2F_VCO_RST1_V4, i);
+		lvts_write_device(lvts_data, TOGGLE_RG_TSV2F_VCO_RST2_V4, i);
+	}
+
+	lvts_data->counting_window_us = 20;
+}
+
+static void device_enable_auto_rck_v4(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < lvts_data->num_tc; i++)
+		lvts_write_device(lvts_data, SET_LVTS_AUTO_RCK_V4, i);
+}
+
+static int device_read_count_rc_n_v4(struct lvts_data *lvts_data)
+{
+	/* Resistor-Capacitor Calibration */
+	/* count_RC_N: count RC now */
+	struct device *dev = lvts_data->dev;
+	struct tc_settings *tc = lvts_data->tc;
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int offset, size, s_index, data;
+	void __iomem *base;
+	int ret, i, j;
+	char buffer[512];
+
+	cal_data->count_rc_now =
+		devm_kcalloc(dev, lvts_data->num_sensor,
+			     sizeof(*cal_data->count_rc_now), GFP_KERNEL);
+	if (!cal_data->count_rc_now)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+
+			lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V4(j),
+					  i);
+			lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V4,
+					  i);
+			usleep_range(10, 20);
+
+			lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V4,
+					  i);
+			usleep_range(30, 40);
+
+			ret = readl_poll_timeout(
+				LVTS_CONFIG_0 + base, data,
+				!(data & DEVICE_SENSING_STATUS), 2, 200);
+
+			data = lvts_read_device(lvts_data, 0x00, i);
+
+			cal_data->count_rc_now[s_index] =
+				(data & GENMASK(23, 0));
+		}
+
+		/* Recover Setting for Normal Access on
+		 * temperature fetch
+		 */
+		lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V4, i);
+		lvts_write_device(lvts_data,
+				  SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
+	}
+
+	size = sizeof(buffer);
+	offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
+	for (i = 0; i < lvts_data->num_sensor; i++)
+		offset += snprintf(buffer + offset, size - offset, "%d:%d ", i,
+				   cal_data->count_rc_now[i]);
+
+	buffer[offset] = '\0';
+	dev_info(dev, "%s\n", buffer);
+
+	return 0;
+}
+
+static void set_calibration_data_v4(struct lvts_data *lvts_data)
+{
+	struct tc_settings *tc = lvts_data->tc;
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int i, j, s_index, e_data;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+			if (IS_ENABLE(FEATURE_DEVICE_AUTO_RCK))
+				e_data = cal_data->count_r[s_index];
+			else
+				e_data = (((unsigned long long)cal_data
+						   ->count_rc_now[s_index]) *
+					  cal_data->count_r[s_index]) >>
+					 14;
+
+			writel(e_data, LVTSEDATA00_0 + base + 0x4 * j);
+		}
+	}
+}
+
+static void init_controller_v4(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+
+		lvts_write_device(lvts_data,
+				  SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
+
+		writel(SET_SENSOR_INDEX, LVTSTSSEL_0 + base);
+		writel(SET_CALC_SCALE_RULES, LVTSCALSCALE_0 + base);
+
+		set_polling_speed(lvts_data, i);
+		set_hw_filter(lvts_data, i);
+
+		dev_info(dev,
+			 "lvts%d: read all %d sensors in %d us, one in %d us\n",
+			 i, GET_TC_SENSOR_NUM(i), GROUP_LATENCY_US(i),
+			 SENSOR_LATENCY_US(i));
+	}
+}
+
+/*
+ * LVTS v5 common code
+ */
+static void device_enable_and_init_v5(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		lvts_write_device(lvts_data, STOP_COUNTING_V5, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US2_V5, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US1_V5, i);
+		lvts_write_device(lvts_data, SET_RG_TSFM_LPDLY_V5, i);
+		lvts_write_device(lvts_data, TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V5,
+				  i);
+		lvts_write_device(lvts_data, TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V5,
+				  i);
+		lvts_write_device(lvts_data, SET_TS_RSV_V5, i);
+		lvts_write_device(lvts_data, SET_TS_EN_V5, i);
+	}
+
+	lvts_data->counting_window_us = 20;
+}
+
+static int device_read_count_rc_n_v5(struct lvts_data *lvts_data)
+{
+	/* Resistor-Capacitor Calibration */
+	/* count_RC_N: count RC now */
+	struct device *dev = lvts_data->dev;
+	struct tc_settings *tc = lvts_data->tc;
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int offset, size, s_index, data;
+	void __iomem *base;
+	int ret, i, j;
+	char buffer[512];
+
+	cal_data->count_rc_now =
+		devm_kcalloc(dev, lvts_data->num_sensor,
+			     sizeof(*cal_data->count_rc_now), GFP_KERNEL);
+	if (!cal_data->count_rc_now)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(i);
+		lvts_write_device(lvts_data, SET_MANUAL_RCK_V5, i);
+
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+
+			lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V5(j),
+					  i);
+			lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V5,
+					  i);
+			lvts_write_device(lvts_data,
+					  SET_COUNTING_WINDOW_20US2_V5, i);
+			lvts_write_device(lvts_data,
+					  SET_COUNTING_WINDOW_20US1_V5, i);
+			lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V5,
+					  i);
+			udelay(40);
+
+			ret = readl_poll_timeout(
+				LVTS_CONFIG_0 + base, data,
+				!(data & DEVICE_SENSING_STATUS), 2, 200);
+			if (ret)
+				dev_err(dev,
+					"Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n",
+					i);
+
+			data = lvts_read_device(lvts_data, 0x00, i);
+
+			cal_data->count_rc_now[s_index] =
+				(data & GENMASK(23, 0));
+
+			/* Recover Setting for Normal Access on
+			 * temperature fetch
+			 */
+			lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V5(j),
+					  i);
+			lvts_write_device(lvts_data,
+					  SET_DEVICE_LOW_POWER_SINGLE_MODE_V5,
+					  i);
+		}
+	}
+
+	size = sizeof(buffer);
+	offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
+	for (i = 0; i < lvts_data->num_sensor; i++)
+		offset += snprintf(buffer + offset, size - offset, "%d:%d ", i,
+				   cal_data->count_rc_now[i]);
+
+	buffer[offset] = '\0';
+	dev_info(dev, "%s\n", buffer);
+
+	return 0;
+}
+
+/*
+ * LVTS MT6873
+ */
+
+#define MT6873_NUM_LVTS (ARRAY_SIZE(mt6873_tc_settings))
+
+enum mt6873_lvts_domain {
+	MT6873_AP_DOMAIN,
+	MT6873_MCU_DOMAIN,
+	MT6873_NUM_DOMAIN
+};
+
+enum mt6873_lvts_sensor_enum {
+	MT6873_TS1_0,
+	MT6873_TS1_1,
+	MT6873_TS2_0,
+	MT6873_TS2_1,
+	MT6873_TS3_0,
+	MT6873_TS3_1,
+	MT6873_TS3_2,
+	MT6873_TS3_3,
+	MT6873_TS4_0,
+	MT6873_TS4_1,
+	MT6873_TS5_0,
+	MT6873_TS5_1,
+	MT6873_TS6_0,
+	MT6873_TS6_1,
+	MT6873_TS7_0,
+	MT6873_TS7_1,
+	MT6873_TS7_2,
+	MT6873_NUM_TS
+};
+
+static void mt6873_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, 31, 24);
+	cal_data->count_r[MT6873_TS1_0] = GET_CAL_DATA_BITMASK(1, 23, 0);
+	cal_data->count_r[MT6873_TS1_1] = GET_CAL_DATA_BITMASK(2, 23, 0);
+	cal_data->count_r[MT6873_TS2_0] = GET_CAL_DATA_BITMASK(3, 23, 0);
+	cal_data->count_r[MT6873_TS2_1] = GET_CAL_DATA_BITMASK(4, 23, 0);
+	cal_data->count_r[MT6873_TS3_0] = GET_CAL_DATA_BITMASK(5, 23, 0);
+	cal_data->count_r[MT6873_TS3_1] = GET_CAL_DATA_BITMASK(6, 23, 0);
+	cal_data->count_r[MT6873_TS3_2] = GET_CAL_DATA_BITMASK(7, 23, 0);
+	cal_data->count_r[MT6873_TS3_3] = GET_CAL_DATA_BITMASK(8, 23, 0);
+	cal_data->count_r[MT6873_TS4_0] = GET_CAL_DATA_BITMASK(9, 23, 0);
+	cal_data->count_r[MT6873_TS4_1] = GET_CAL_DATA_BITMASK(10, 23, 0);
+	cal_data->count_r[MT6873_TS5_0] = GET_CAL_DATA_BITMASK(11, 23, 0);
+	cal_data->count_r[MT6873_TS5_1] = GET_CAL_DATA_BITMASK(12, 23, 0);
+	cal_data->count_r[MT6873_TS6_0] = GET_CAL_DATA_BITMASK(13, 23, 0);
+	cal_data->count_r[MT6873_TS6_1] = GET_CAL_DATA_BITMASK(14, 23, 0);
+	cal_data->count_r[MT6873_TS7_0] = GET_CAL_DATA_BITMASK(15, 23, 0);
+	cal_data->count_r[MT6873_TS7_1] = GET_CAL_DATA_BITMASK(16, 23, 0);
+	cal_data->count_r[MT6873_TS7_2] = GET_CAL_DATA_BITMASK(17, 23, 0);
+
+	cal_data->count_rc[MT6873_TS1_0] = GET_CAL_DATA_BITMASK(21, 23, 0);
+
+	cal_data->count_rc[MT6873_TS2_0] =
+		(GET_CAL_DATA_BITMASK(1, 31, 24) << 16) +
+		(GET_CAL_DATA_BITMASK(2, 31, 24) << 8) +
+		GET_CAL_DATA_BITMASK(3, 31, 24);
+
+	cal_data->count_rc[MT6873_TS3_0] =
+		(GET_CAL_DATA_BITMASK(4, 31, 24) << 16) +
+		(GET_CAL_DATA_BITMASK(5, 31, 24) << 8) +
+		GET_CAL_DATA_BITMASK(6, 31, 24);
+
+	cal_data->count_rc[MT6873_TS4_0] =
+		(GET_CAL_DATA_BITMASK(7, 31, 24) << 16) +
+		(GET_CAL_DATA_BITMASK(8, 31, 24) << 8) +
+		GET_CAL_DATA_BITMASK(9, 31, 24);
+
+	cal_data->count_rc[MT6873_TS5_0] =
+		(GET_CAL_DATA_BITMASK(10, 31, 24) << 16) +
+		(GET_CAL_DATA_BITMASK(11, 31, 24) << 8) +
+		GET_CAL_DATA_BITMASK(12, 31, 24);
+
+	cal_data->count_rc[MT6873_TS6_0] =
+		(GET_CAL_DATA_BITMASK(13, 31, 24) << 16) +
+		(GET_CAL_DATA_BITMASK(14, 31, 24) << 8) +
+		GET_CAL_DATA_BITMASK(15, 31, 24);
+
+	cal_data->count_rc[MT6873_TS7_0] =
+		(GET_CAL_DATA_BITMASK(16, 31, 24) << 16) +
+		(GET_CAL_DATA_BITMASK(17, 31, 24) << 8) +
+		GET_CAL_DATA_BITMASK(18, 31, 24);
+}
+
+static struct tc_settings mt6873_tc_settings[] = {
+	[0] = {
+		.domain_index = MT6873_MCU_DOMAIN,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT6873_TS1_0, MT6873_TS1_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.domain_index = MT6873_MCU_DOMAIN,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT6873_TS2_0, MT6873_TS2_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.domain_index = MT6873_MCU_DOMAIN,
+		.addr_offset = 0x200,
+		.num_sensor = 4,
+		.sensor_map = {MT6873_TS3_0, MT6873_TS3_1, MT6873_TS3_2,
+			       MT6873_TS3_3},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(5),
+	},
+	[3] = {
+		.domain_index = MT6873_AP_DOMAIN,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT6873_TS4_0, MT6873_TS4_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(3),
+	},
+	[4] = {
+		.domain_index = MT6873_AP_DOMAIN,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT6873_TS5_0, MT6873_TS5_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(4),
+	},
+	[5] = {
+		.domain_index = MT6873_AP_DOMAIN,
+		.addr_offset = 0x200,
+		.num_sensor = 2,
+		.sensor_map = {MT6873_TS6_0, MT6873_TS6_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(5),
+	},
+	[6] = {
+		.domain_index = MT6873_AP_DOMAIN,
+		.addr_offset = 0x300,
+		.num_sensor = 3,
+		.sensor_map = {MT6873_TS7_0, MT6873_TS7_1, MT6873_TS7_2},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT2,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(6),
+	}
+};
+
+static struct lvts_data mt6873_lvts_data = {
+	.num_domain = MT6873_NUM_DOMAIN,
+	.num_tc = MT6873_NUM_LVTS,
+	.tc = mt6873_tc_settings,
+	.num_sensor = MT6873_NUM_TS,
+	.ops = {
+		.efuse_to_cal_data = mt6873_efuse_to_cal_data,
+		.device_enable_and_init = device_enable_and_init_v4,
+		.device_enable_auto_rck = device_enable_auto_rck_v4,
+		.device_read_count_rc_n = device_read_count_rc_n_v4,
+		.set_cal_data = set_calibration_data_v4,
+		.init_controller = init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = 22,
+	.num_efuse_block = 1,
+	.cal_data = {
+		.default_golden_temp = 50,
+		.default_count_r = 35000,
+		.default_count_rc = 2750,
+	},
+	.coeff = {
+		.a = -250460,
+		.b = 250460,
+	},
+};
+
+/*
+ * LVTS MT7988
+ */
+
+#define MT7988_NUM_LVTS (ARRAY_SIZE(mt7988_tc_settings))
+
+enum mt7988_lvts_domain { MT7988_AP_DOMAIN, MT7988_NUM_DOMAIN };
+
+enum mt7988_lvts_sensor_enum {
+	MT7988_TS2_0,
+	MT7988_TS2_1,
+	MT7988_TS2_2,
+	MT7988_TS2_3,
+	MT7988_TS3_0,
+	MT7988_TS3_1,
+	MT7988_TS3_2,
+	MT7988_TS3_3,
+	MT7988_NUM_TS
+};
+
+static void mt7988_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, 31, 24);
+
+	cal_data->count_r[MT7988_TS2_0] = GET_CAL_DATA_BITMASK(0, 23, 0);
+	cal_data->count_r[MT7988_TS2_1] = GET_CAL_DATA_BITMASK(1, 23, 0);
+	cal_data->count_r[MT7988_TS2_2] = GET_CAL_DATA_BITMASK(2, 23, 0);
+	cal_data->count_r[MT7988_TS2_3] = GET_CAL_DATA_BITMASK(3, 23, 0);
+	cal_data->count_rc[MT7988_TS2_0] = GET_CAL_DATA_BITMASK(4, 23, 0);
+
+	cal_data->count_r[MT7988_TS3_0] = GET_CAL_DATA_BITMASK(5, 23, 0);
+	cal_data->count_r[MT7988_TS3_1] = GET_CAL_DATA_BITMASK(6, 23, 0);
+	cal_data->count_r[MT7988_TS3_2] = GET_CAL_DATA_BITMASK(7, 23, 0);
+	cal_data->count_r[MT7988_TS3_3] = GET_CAL_DATA_BITMASK(8, 23, 0);
+	cal_data->count_rc[MT7988_TS3_0] = GET_CAL_DATA_BITMASK(9, 23, 0);
+}
+
+static struct tc_settings mt7988_tc_settings[] = {
+	[0] = {
+		.domain_index = MT7988_AP_DOMAIN,
+		.addr_offset = 0x0,
+		.num_sensor = 4,
+		.sensor_map = {MT7988_TS2_0, MT7988_TS2_1, MT7988_TS2_2,
+			       MT7988_TS2_3},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_16_OF_18,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(4),
+	},
+	[1] = {
+		.domain_index = MT7988_AP_DOMAIN,
+		.addr_offset = 0x100,
+		.num_sensor = 4,
+		.sensor_map = {MT7988_TS3_0, MT7988_TS3_1, MT7988_TS3_2,
+			       MT7988_TS3_3},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_16_OF_18,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(5),
+	}
+
+};
+
+static struct lvts_data mt7988_lvts_data = {
+	.num_domain = MT7988_NUM_DOMAIN,
+	.num_tc = MT7988_NUM_LVTS,
+	.tc = mt7988_tc_settings,
+	.num_sensor = MT7988_NUM_TS,
+	.ops = {
+		.efuse_to_cal_data = mt7988_efuse_to_cal_data,
+		.device_enable_and_init = device_enable_and_init_v5,
+		.device_enable_auto_rck = device_enable_auto_rck_v4,
+		.device_read_count_rc_n = device_read_count_rc_n_v5,
+		.set_cal_data = set_calibration_data_v4,
+		.init_controller = init_controller_v4,
+	},
+	.feature_bitmap = 0,
+	.num_efuse_addr = 10,
+	.num_efuse_block = 1,
+	.cal_data = {
+		.default_golden_temp = 60,
+		.default_count_r = 19380,
+		.default_count_rc = 5330,
+	},
+	.coeff = {
+		.a = -204650,
+		.b = 204650,
+	},
+};
+
+/*
+ * LVTS MT8195
+ */
+
+#define MT8195_NUM_LVTS (ARRAY_SIZE(mt8195_tc_settings))
+
+enum mt8195_lvts_domain {
+	MT8195_AP_DOMAIN,
+	MT8195_MCU_DOMAIN,
+	MT8195_NUM_DOMAIN
+};
+
+enum mt8195_lvts_sensor_enum {
+	MT8195_TS1_0,
+	MT8195_TS1_1,
+	MT8195_TS2_0,
+	MT8195_TS2_1,
+	MT8195_TS3_0,
+	MT8195_TS3_1,
+	MT8195_TS3_2,
+	MT8195_TS3_3,
+	MT8195_TS4_0,
+	MT8195_TS4_1,
+	MT8195_TS5_0,
+	MT8195_TS5_1,
+	MT8195_TS6_0,
+	MT8195_TS6_1,
+	MT8195_TS6_2,
+	MT8195_TS7_0,
+	MT8195_TS7_1,
+	MT8195_NUM_TS
+};
+
+static void mt8195_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, 31, 24);
+	cal_data->count_r[MT8195_TS1_0] = GET_CAL_DATA_BITMASK(1, 23, 0);
+	cal_data->count_r[MT8195_TS1_1] =
+		(GET_CAL_DATA_BITMASK(2, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(1, 31, 24);
+	cal_data->count_r[MT8195_TS2_0] = GET_CAL_DATA_BITMASK(3, 31, 8);
+	cal_data->count_r[MT8195_TS2_1] = GET_CAL_DATA_BITMASK(4, 23, 0);
+	cal_data->count_r[MT8195_TS3_0] =
+		(GET_CAL_DATA_BITMASK(6, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(5, 31, 16);
+	cal_data->count_r[MT8195_TS3_1] = GET_CAL_DATA_BITMASK(6, 31, 8);
+	cal_data->count_r[MT8195_TS3_2] = GET_CAL_DATA_BITMASK(7, 23, 0);
+	cal_data->count_r[MT8195_TS3_3] =
+		(GET_CAL_DATA_BITMASK(8, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(7, 31, 24);
+	cal_data->count_r[MT8195_TS4_0] = GET_CAL_DATA_BITMASK(9, 31, 8);
+	cal_data->count_r[MT8195_TS4_1] = GET_CAL_DATA_BITMASK(10, 23, 0);
+	cal_data->count_r[MT8195_TS5_0] =
+		(GET_CAL_DATA_BITMASK(12, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(11, 31, 16);
+	cal_data->count_r[MT8195_TS5_1] = GET_CAL_DATA_BITMASK(12, 31, 8);
+	cal_data->count_r[MT8195_TS6_0] =
+		(GET_CAL_DATA_BITMASK(14, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(13, 31, 24);
+	cal_data->count_r[MT8195_TS6_1] =
+		(GET_CAL_DATA_BITMASK(15, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(14, 31, 16);
+	cal_data->count_r[MT8195_TS6_2] = GET_CAL_DATA_BITMASK(15, 31, 8);
+	cal_data->count_r[MT8195_TS7_0] =
+		(GET_CAL_DATA_BITMASK(17, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(16, 31, 24);
+	cal_data->count_r[MT8195_TS7_1] =
+		(GET_CAL_DATA_BITMASK(18, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(17, 31, 16);
+	cal_data->count_rc[MT8195_TS1_0] =
+		(GET_CAL_DATA_BITMASK(3, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(2, 31, 16);
+	cal_data->count_rc[MT8195_TS2_0] =
+		(GET_CAL_DATA_BITMASK(5, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(4, 31, 24);
+	cal_data->count_rc[MT8195_TS3_0] =
+		(GET_CAL_DATA_BITMASK(9, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(8, 31, 16);
+	cal_data->count_rc[MT8195_TS4_0] =
+		(GET_CAL_DATA_BITMASK(11, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(10, 31, 24);
+	cal_data->count_rc[MT8195_TS5_0] = GET_CAL_DATA_BITMASK(13, 23, 0);
+	cal_data->count_rc[MT8195_TS6_0] = GET_CAL_DATA_BITMASK(16, 23, 0);
+	cal_data->count_rc[MT8195_TS7_0] = GET_CAL_DATA_BITMASK(18, 31, 8);
+}
+
+static struct tc_settings mt8195_tc_settings[] = {
+	[0] = {
+		.domain_index = MT8195_MCU_DOMAIN,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS1_0, MT8195_TS1_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.domain_index = MT8195_MCU_DOMAIN,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS2_0, MT8195_TS2_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.domain_index = MT8195_MCU_DOMAIN,
+		.addr_offset = 0x200,
+		.num_sensor = 4,
+		.sensor_map = {MT8195_TS3_0, MT8195_TS3_1, MT8195_TS3_2,
+			       MT8195_TS3_3},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(5),
+	},
+	[3] = {
+		.domain_index = MT8195_AP_DOMAIN,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS4_0, MT8195_TS4_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(3),
+	},
+	[4] = {
+		.domain_index = MT8195_AP_DOMAIN,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS5_0, MT8195_TS5_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(4),
+	},
+	[5] = {
+		.domain_index = MT8195_AP_DOMAIN,
+		.addr_offset = 0x200,
+		.num_sensor = 3,
+		.sensor_map = {MT8195_TS6_0, MT8195_TS6_1, MT8195_TS6_2},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(5),
+	},
+	[6] = {
+		.domain_index = MT8195_AP_DOMAIN,
+		.addr_offset = 0x300,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS7_0, MT8195_TS7_1},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(6),
+	}
+};
+
+static struct lvts_data mt8195_lvts_data = {
+	.num_domain = MT8195_NUM_DOMAIN,
+	.num_tc = MT8195_NUM_LVTS,
+	.tc = mt8195_tc_settings,
+	.num_sensor = MT8195_NUM_TS,
+	.ops = {
+		.efuse_to_cal_data = mt8195_efuse_to_cal_data,
+		.device_enable_and_init = device_enable_and_init_v4,
+		.device_enable_auto_rck = device_enable_auto_rck_v4,
+		.device_read_count_rc_n = device_read_count_rc_n_v4,
+		.set_cal_data = set_calibration_data_v4,
+		.init_controller = init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = 22,
+	.num_efuse_block = 2,
+	.cal_data = {
+		.default_golden_temp = 50,
+		.default_count_r = 35000,
+		.default_count_rc = 2750,
+	},
+	.coeff = {
+		.a = -250460,
+		.b = 250460,
+	},
+};
+
+/*
+ * LVTS MT8139
+ */
+
+#define MT8139_NUM_LVTS (ARRAY_SIZE(mt8139_tc_settings))
+
+enum mt8139_lvts_domain {
+	MT8139_AP_DOMAIN,
+	MT8139_MCU_DOMAIN,
+	MT8139_NUM_DOMAIN
+};
+
+enum mt8139_lvts_sensor_enum {
+	MT8139_TS1_0,
+	MT8139_TS1_1,
+	MT8139_TS1_2,
+	MT8139_TS1_3,
+	MT8139_TS2_0,
+	MT8139_TS2_1,
+	MT8139_TS2_2,
+	MT8139_TS2_3,
+	MT8139_TS3_0,
+	MT8139_TS3_1,
+	MT8139_TS3_2,
+	MT8139_TS3_3,
+	MT8139_NUM_TS
+};
+
+static void mt8139_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, 7, 0);
+	cal_data->count_r[MT8139_TS1_0] = GET_CAL_DATA_BITMASK(0, 31, 8);
+	cal_data->count_r[MT8139_TS1_1] = GET_CAL_DATA_BITMASK(1, 23, 0);
+	cal_data->count_r[MT8139_TS1_2] =
+		(GET_CAL_DATA_BITMASK(2, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(1, 31, 24);
+	cal_data->count_r[MT8139_TS1_3] =
+		(GET_CAL_DATA_BITMASK(3, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(2, 31, 16);
+	cal_data->count_rc[MT8139_TS1_0] = GET_CAL_DATA_BITMASK(3, 31, 8);
+
+	cal_data->count_r[MT8139_TS2_0] = GET_CAL_DATA_BITMASK(4, 23, 0);
+	cal_data->count_r[MT8139_TS2_1] =
+		(GET_CAL_DATA_BITMASK(5, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(4, 31, 24);
+	cal_data->count_r[MT8139_TS2_2] =
+		(GET_CAL_DATA_BITMASK(6, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(5, 31, 16);
+	cal_data->count_r[MT8139_TS2_3] = GET_CAL_DATA_BITMASK(6, 31, 8);
+	cal_data->count_rc[MT8139_TS2_0] = GET_CAL_DATA_BITMASK(7, 23, 0);
+
+	cal_data->count_r[MT8139_TS3_0] =
+		(GET_CAL_DATA_BITMASK(8, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(7, 31, 24);
+	cal_data->count_r[MT8139_TS3_1] =
+		(GET_CAL_DATA_BITMASK(9, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(8, 31, 16);
+	cal_data->count_r[MT8139_TS3_2] = GET_CAL_DATA_BITMASK(9, 31, 8);
+	cal_data->count_r[MT8139_TS3_3] = GET_CAL_DATA_BITMASK(10, 23, 0);
+	cal_data->count_rc[MT8139_TS3_0] =
+		(GET_CAL_DATA_BITMASK(11, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(10, 31, 24);
+}
+
+static struct tc_settings mt8139_tc_settings[] = {
+	[0] = {
+		.domain_index = MT8139_MCU_DOMAIN,
+		.addr_offset = 0x0,
+		.num_sensor = 4,
+		.sensor_map = {MT8139_TS1_0, MT8139_TS1_1, MT8139_TS1_2,
+			       MT8139_TS1_3},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.domain_index = MT8139_AP_DOMAIN,
+		.addr_offset = 0x0,
+		.num_sensor = 4,
+		.sensor_map = {MT8139_TS2_0, MT8139_TS2_1, MT8139_TS2_2,
+			       MT8139_TS2_3},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.domain_index = MT8139_AP_DOMAIN,
+		.addr_offset = 0x100,
+		.num_sensor = 4,
+		.sensor_map = {MT8139_TS3_0, MT8139_TS3_1, MT8139_TS3_2,
+			       MT8139_TS3_3},
+		.tc_speed = SET_TC_SPEED_IN_US(118, 118, 118, 118),
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = 117000,
+		.irq_bit = BIT(5),
+	}
+
+};
+
+static struct lvts_data mt8139_lvts_data = {
+	.num_domain = MT8139_NUM_DOMAIN,
+	.num_tc = MT8139_NUM_LVTS,
+	.tc = mt8139_tc_settings,
+	.num_sensor = MT8139_NUM_TS,
+	.ops = {
+		.efuse_to_cal_data = mt8139_efuse_to_cal_data,
+		.device_enable_and_init = device_enable_and_init_v4,
+		.device_enable_auto_rck = device_enable_auto_rck_v4,
+		.device_read_count_rc_n = device_read_count_rc_n_v4,
+		.set_cal_data = set_calibration_data_v4,
+		.init_controller = init_controller_v4,
+	},
+	.feature_bitmap = 0,
+	.num_efuse_addr = 48,
+	.num_efuse_block = 1,
+	.cal_data = {
+		.default_golden_temp = 50,
+		.default_count_r = 35000,
+		.default_count_rc = 2750,
+	},
+	.coeff = {
+		.a = -250460,
+		.b = 250460,
+	},
+};
+
+/*
+ * Support chips
+ */
+static const struct of_device_id lvts_of_match[] = {
+	{
+		.compatible = "mediatek,mt6873-lvts",
+		.data = (void *)&mt6873_lvts_data,
+	},
+	{
+		.compatible = "mediatek,mt8195-lvts",
+		.data = (void *)&mt8195_lvts_data,
+	},
+	{
+		.compatible = "mediatek,mt8139-lvts",
+		.data = (void *)&mt8139_lvts_data,
+	},
+	{
+		.compatible = "mediatek,mt7988-lvts",
+		.data = (void *)&mt7988_lvts_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvts_of_match);
+
+static struct platform_driver soc_temp_lvts = {
+	.probe = lvts_probe,
+	.remove = lvts_remove,
+	.suspend = lvts_suspend,
+	.resume = lvts_resume,
+	.driver = {
+		.name = "mtk-soc-temp-lvts",
+		.of_match_table = lvts_of_match,
+	},
+};
+
+module_platform_driver(soc_temp_lvts);
+MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
+MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+MODULE_AUTHOR("Henry Yen <henry.yen@mediatek.com>");
+MODULE_DESCRIPTION("Mediatek soc temperature driver");
+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/soc_temp_lvts.h b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/soc_temp_lvts.h
new file mode 100644
index 0000000..ed3d058
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/drivers/thermal/mediatek/soc_temp_lvts.h
@@ -0,0 +1,314 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+
+#ifndef __MTK_SOC_TEMP_LVTS_H__
+#define __MTK_SOC_TEMP_LVTS_H__
+
+/* LVTS HW filter settings
+ * 000: Get one sample
+ * 001: Get 2 samples and average them
+ * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
+ * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
+ * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
+ * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
+ */
+enum lvts_hw_filter {
+	LVTS_FILTER_1,
+	LVTS_FILTER_2,
+	LVTS_FILTER_2_OF_4,
+	LVTS_FILTER_4_OF_6,
+	LVTS_FILTER_8_OF_10,
+	LVTS_FILTER_16_OF_18
+};
+
+enum lvts_sensing_point {
+	SENSING_POINT0,
+	SENSING_POINT1,
+	SENSING_POINT2,
+	SENSING_POINT3,
+	ALL_SENSING_POINTS
+};
+
+/*
+ * Data structure
+ */
+struct lvts_data;
+
+struct speed_settings {
+	unsigned int period_unit;
+	unsigned int group_interval_delay;
+	unsigned int filter_interval_delay;
+	unsigned int sensor_interval_delay;
+};
+
+struct tc_settings {
+	unsigned int domain_index;
+	unsigned int addr_offset;
+	unsigned int num_sensor;
+	unsigned int sensor_map[ALL_SENSING_POINTS]; /* In sensor ID */
+	struct speed_settings tc_speed;
+	/* HW filter setting
+	 * 000: Get one sample
+	 * 001: Get 2 samples and average them
+	 * 010: Get 4 samples, drop max and min, then average the rest of 2
+	 *	samples
+	 * 011: Get 6 samples, drop max and min, then average the rest of 4
+	 *      samples
+	 * 100: Get 10 samples, drop max and min, then average the rest of 8
+	 *      samples
+	 * 101: Get 18 samples, drop max and min, then average the rest of 16
+	 *      samples
+	 */
+	unsigned int hw_filter;
+	/* Dominator_sensing point is used to select a sensing point
+	 * and reference its temperature to trigger Thermal HW Reboot
+	 * When it is ALL_SENSING_POINTS, it will select all sensing points
+	 */
+	int dominator_sensing_point;
+	int hw_reboot_trip_point; /* -274000: Disable HW reboot */
+	unsigned int irq_bit;
+};
+
+struct formula_coeff {
+	int a;
+	int b;
+	unsigned int golden_temp;
+};
+
+struct sensor_cal_data {
+	int use_fake_efuse; /* 1: Use fake efuse, 0: Use real efuse */
+	unsigned int golden_temp;
+	unsigned int *count_r;
+	unsigned int *count_rc;
+	unsigned int *count_rc_now;
+
+	unsigned int default_golden_temp;
+	unsigned int default_count_r;
+	unsigned int default_count_rc;
+};
+
+struct platform_ops {
+	void (*efuse_to_cal_data)(struct lvts_data *lvts_data);
+	void (*device_enable_and_init)(struct lvts_data *lvts_data);
+	void (*device_enable_auto_rck)(struct lvts_data *lvts_data);
+	int (*device_read_count_rc_n)(struct lvts_data *lvts_data);
+	void (*set_cal_data)(struct lvts_data *lvts_data);
+	void (*init_controller)(struct lvts_data *lvts_data);
+};
+
+struct power_domain {
+	void __iomem *base; /* LVTS base addresses */
+	unsigned int irq_num; /* LVTS interrupt numbers */
+	struct reset_control *reset;
+};
+
+struct sensor_data {
+	int temp; /* Current temperature */
+	unsigned int msr_raw; /* MSR raw data from LVTS */
+};
+
+struct lvts_data {
+	struct device *dev;
+	struct clk *clk;
+	unsigned int num_domain;
+	struct power_domain *domain;
+
+	int num_tc; /* Number of LVTS thermal controllers */
+	struct tc_settings *tc;
+	int counting_window_us; /* LVTS device counting window */
+
+	int num_sensor; /* Number of sensors in this platform */
+	struct sensor_data *sen_data;
+
+	struct platform_ops ops;
+	int feature_bitmap; /* Show what features are enabled */
+
+	unsigned int num_efuse_addr;
+	unsigned int *efuse;
+	unsigned int num_efuse_block; /* Number of contiguous efuse indexes */
+	struct sensor_cal_data cal_data;
+	struct formula_coeff coeff;
+};
+
+struct soc_temp_tz {
+	unsigned int id; /* if id is 0, get max temperature of all sensors */
+	struct lvts_data *lvts_data;
+};
+
+struct match_entry {
+	char chip[32];
+	struct lvts_data *lvts_data;
+};
+
+struct lvts_match_data {
+	unsigned int hw_version;
+	struct match_entry *table;
+	void (*set_up_common_callbacks)(struct lvts_data *lvts_data);
+	struct list_head node;
+};
+
+struct lvts_id {
+	unsigned int hw_version;
+	char chip[32];
+};
+
+/*
+ * LVTS device register
+ */
+#define RG_TSFM_DATA_0	0x00
+#define RG_TSFM_DATA_1	0x01
+#define RG_TSFM_DATA_2	0x02
+#define RG_TSFM_CTRL_0	0x03
+#define RG_TSFM_CTRL_1	0x04
+#define RG_TSFM_CTRL_2	0x05
+#define RG_TSFM_CTRL_3	0x06
+#define RG_TSFM_CTRL_4	0x07
+#define RG_TSV2F_CTRL_0 0x08
+#define RG_TSV2F_CTRL_1 0x09
+#define RG_TSV2F_CTRL_2 0x0A
+#define RG_TSV2F_CTRL_3 0x0B
+#define RG_TSV2F_CTRL_4 0x0C
+#define RG_TSV2F_CTRL_5 0x0D
+#define RG_TSV2F_CTRL_6 0x0E
+#define RG_TEMP_DATA_0	0x10
+#define RG_TEMP_DATA_1	0x11
+#define RG_TEMP_DATA_2	0x12
+#define RG_TEMP_DATA_3	0x13
+#define RG_RC_DATA_0	0x14
+#define RG_RC_DATA_1	0x15
+#define RG_RC_DATA_2	0x16
+#define RG_RC_DATA_3	0x17
+#define RG_DIV_DATA_0	0x18
+#define RG_DIV_DATA_1	0x19
+#define RG_DIV_DATA_2	0x1A
+#define RG_DIV_DATA_3	0x1B
+#define RG_TST_DATA_0	0x70
+#define RG_TST_DATA_1	0x71
+#define RG_TST_DATA_2	0x72
+#define RG_TST_CTRL	0x73
+#define RG_DBG_FQMTR	0xF0
+#define RG_DBG_LPSEQ	0xF1
+#define RG_DBG_STATE	0xF2
+#define RG_DBG_CHKSUM	0xF3
+#define RG_DID_LVTS	0xFC
+#define RG_DID_REV	0xFD
+#define RG_TSFM_RST	0xFF
+/*
+ * LVTS controller register
+ */
+#define LVTSMONCTL0_0		  0x000
+#define LVTS_SINGLE_SENSE	  BIT(9)
+#define ENABLE_SENSING_POINT(num) (LVTS_SINGLE_SENSE | GENMASK(((num)-1), 0))
+#define DISABLE_SENSING_POINT	  (LVTS_SINGLE_SENSE | 0x0)
+#define LVTSMONCTL1_0		  0x004
+#define LVTSMONCTL2_0		  0x008
+#define LVTSMONINT_0		  0x00C
+#define STAGE3_INT_EN		  BIT(31)
+#define LVTSMONINTSTS_0		  0x010
+#define LVTSMONIDET0_0		  0x014
+#define LVTSMONIDET1_0		  0x018
+#define LVTSMONIDET2_0		  0x01C
+#define LVTSMONIDET3_0		  0x020
+#define LVTSH2NTHRE_0		  0x024
+#define LVTSHTHRE_0		  0x028
+#define LVTSCTHRE_0		  0x02C
+#define LVTSOFFSETH_0		  0x030
+#define LVTSOFFSETL_0		  0x034
+#define LVTSMSRCTL0_0		  0x038
+#define LVTSMSRCTL1_0		  0x03C
+#define LVTSTSSEL_0		  0x040
+#define SET_SENSOR_INDEX	  0x13121110
+#define LVTSDEVICETO_0		  0x044
+#define LVTSCALSCALE_0		  0x048
+#define SET_CALC_SCALE_RULES	  0x00000300
+#define LVTS_ID_0		  0x04C
+#define LVTS_CONFIG_0		  0x050
+
+#define BROADCAST_ID_UPDATE	  BIT(26)
+#define DEVICE_SENSING_STATUS	  BIT(25)
+#define DEVICE_ACCESS_STARTUS	  BIT(24)
+#define WRITE_ACCESS		  BIT(16)
+#define DEVICE_WRITE                                                           \
+	(BIT(31) | CK26M_ACTIVE | DEVICE_ACCESS_STARTUS | BIT(17) |            \
+	 WRITE_ACCESS)
+#define DEVICE_READ                                                            \
+	(BIT(31) | CK26M_ACTIVE | DEVICE_ACCESS_STARTUS | 1 << 17)
+#define RESET_ALL_DEVICES                                                      \
+	(DEVICE_WRITE | RG_TSFM_RST << 8 | 0xFF)
+#define READ_BACK_DEVICE_ID                                                    \
+	(BIT(31) | CK26M_ACTIVE | BROADCAST_ID_UPDATE |                        \
+	 DEVICE_ACCESS_STARTUS | BIT(17) | RG_DID_LVTS << 8)
+#define READ_DEVICE_REG(reg_idx) (DEVICE_READ | (reg_idx) << 8 | 0x00)
+#define LVTSEDATA00_0		 0x054
+#define LVTSEDATA01_0		 0x058
+#define LVTSEDATA02_0		 0x05C
+#define LVTSEDATA03_0		 0x060
+#define LVTSMSR0_0		 0x090
+#define MRS_RAW_MASK		 GENMASK(15, 0)
+#define MRS_RAW_VALID_BIT	 BIT(16)
+#define LVTSMSR1_0		 0x094
+#define LVTSMSR2_0		 0x098
+#define LVTSMSR3_0		 0x09C
+#define LVTSIMMD0_0		 0x0A0
+#define LVTSIMMD1_0		 0x0A4
+#define LVTSIMMD2_0		 0x0A8
+#define LVTSIMMD3_0		 0x0AC
+#define LVTSRDATA0_0		 0x0B0
+#define LVTSRDATA1_0		 0x0B4
+#define LVTSRDATA2_0		 0x0B8
+#define LVTSRDATA3_0		 0x0BC
+#define LVTSPROTCTL_0		 0x0C0
+#define PROTOFFSET		 GENMASK(15, 0)
+#define LVTSPROTTA_0		 0x0C4
+#define LVTSPROTTB_0		 0x0C8
+#define LVTSPROTTC_0		 0x0CC
+#define LVTSCLKEN_0		 0x0E4
+#define ENABLE_LVTS_CTRL_CLK	 (1)
+#define DISABLE_LVTS_CTRL_CLK	 (0)
+#define LVTSDBGSEL_0		 0x0E8
+#define LVTSDBGSIG_0		 0x0EC
+#define LVTSSPARE0_0		 0x0F0
+#define LVTSSPARE1_0		 0x0F4
+#define LVTSSPARE2_0		 0x0F8
+#define LVTSSPARE3_0		 0x0FC
+
+#define THERMINTST 0xF04
+/*
+ * LVTS register mask
+ */
+#define THERMAL_COLD_INTERRUPT_0	 0x00000001
+#define THERMAL_HOT_INTERRUPT_0		 0x00000002
+#define THERMAL_LOW_OFFSET_INTERRUPT_0	 0x00000004
+#define THERMAL_HIGH_OFFSET_INTERRUPT_0	 0x00000008
+#define THERMAL_HOT2NORMAL_INTERRUPT_0	 0x00000010
+#define THERMAL_COLD_INTERRUPT_1	 0x00000020
+#define THERMAL_HOT_INTERRUPT_1		 0x00000040
+#define THERMAL_LOW_OFFSET_INTERRUPT_1	 0x00000080
+#define THERMAL_HIGH_OFFSET_INTERRUPT_1	 0x00000100
+#define THERMAL_HOT2NORMAL_INTERRUPT_1	 0x00000200
+#define THERMAL_COLD_INTERRUPT_2	 0x00000400
+#define THERMAL_HOT_INTERRUPT_2		 0x00000800
+#define THERMAL_LOW_OFFSET_INTERRUPT_2	 0x00001000
+#define THERMAL_HIGH_OFFSET_INTERRUPT_2	 0x00002000
+#define THERMAL_HOT2NORMAL_INTERRUPT_2	 0x00004000
+#define THERMAL_AHB_TIMEOUT_INTERRUPT	 0x00008000
+#define THERMAL_DEVICE_TIMEOUT_INTERRUPT 0x00008000
+#define THERMAL_IMMEDIATE_INTERRUPT_0	 0x00010000
+#define THERMAL_IMMEDIATE_INTERRUPT_1	 0x00020000
+#define THERMAL_IMMEDIATE_INTERRUPT_2	 0x00040000
+#define THERMAL_FILTER_INTERRUPT_0	 0x00080000
+#define THERMAL_FILTER_INTERRUPT_1	 0x00100000
+#define THERMAL_FILTER_INTERRUPT_2	 0x00200000
+#define THERMAL_COLD_INTERRUPT_3	 0x00400000
+#define THERMAL_HOT_INTERRUPT_3		 0x00800000
+#define THERMAL_LOW_OFFSET_INTERRUPT_3	 0x01000000
+#define THERMAL_HIGH_OFFSET_INTERRUPT_3	 0x02000000
+#define THERMAL_HOT2NORMAL_INTERRUPT_3	 0x04000000
+#define THERMAL_IMMEDIATE_INTERRUPT_3	 0x08000000
+#define THERMAL_FILTER_INTERRUPT_3	 0x10000000
+#define THERMAL_PROTECTION_STAGE_1	 0x20000000
+#define THERMAL_PROTECTION_STAGE_2	 0x40000000
+#define THERMAL_PROTECTION_STAGE_3	 0x80000000
+#endif /* __MTK_SOC_TEMP_LVTS_H__ */
diff --git a/target/linux/mediatek/files-5.4/include/dt-bindings/clock/mt7988-clk.h b/target/linux/mediatek/files-5.4/include/dt-bindings/clock/mt7988-clk.h
new file mode 100644
index 0000000..fb97122
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/include/dt-bindings/clock/mt7988-clk.h
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT7988_H
+#define _DT_BINDINGS_CLK_MT7988_H
+
+/* INFRACFG */
+
+#define CK_INFRA_CK_F26M		0
+#define CK_INFRA_PWM_O			1
+#define CK_INFRA_PCIE_OCC_P0		2
+#define CK_INFRA_PCIE_OCC_P1		3
+#define CK_INFRA_PCIE_OCC_P2		4
+#define CK_INFRA_PCIE_OCC_P3		5
+#define CK_INFRA_133M_HCK		6
+#define CK_INFRA_133M_PHCK		7
+#define CK_INFRA_66M_PHCK		8
+#define CK_INFRA_FAUD_L_O		9
+#define CK_INFRA_FAUD_AUD_O		10
+#define CK_INFRA_FAUD_EG2_O		11
+#define CK_INFRA_I2C_O			12
+#define CK_INFRA_UART_O0		13
+#define CK_INFRA_UART_O1		14
+#define CK_INFRA_UART_O2		15
+#define CK_INFRA_NFI_O			16
+#define CK_INFRA_SPINFI_O		17
+#define CK_INFRA_SPI0_O			18
+#define CK_INFRA_SPI1_O			19
+#define CK_INFRA_LB_MUX_FRTC		20
+#define CK_INFRA_FRTC			21
+#define CK_INFRA_FMSDC400_O		22
+#define CK_INFRA_FMSDC2_HCK_OCC		23
+#define CK_INFRA_PERI_133M		24
+#define CK_INFRA_USB_O			25
+#define CK_INFRA_USB_O_P1		26
+#define CK_INFRA_USB_FRMCNT_O		27
+#define CK_INFRA_USB_FRMCNT_O_P1	28
+#define CK_INFRA_USB_XHCI_O		29
+#define CK_INFRA_USB_XHCI_O_P1		30
+#define CK_INFRA_USB_PIPE_O		31
+#define CK_INFRA_USB_PIPE_O_P1		32
+#define CK_INFRA_USB_UTMI_O		33
+#define CK_INFRA_USB_UTMI_O_P1		34
+#define CK_INFRA_PCIE_PIPE_OCC_P0	35
+#define CK_INFRA_PCIE_PIPE_OCC_P1	36
+#define CK_INFRA_PCIE_PIPE_OCC_P2	37
+#define CK_INFRA_PCIE_PIPE_OCC_P3	38
+#define CK_INFRA_F26M_O0		39
+#define CK_INFRA_F26M_O1		40
+#define CK_INFRA_133M_MCK		41
+#define CK_INFRA_66M_MCK		42
+#define CK_INFRA_PERI_66M_O		43
+#define CK_INFRA_USB_SYS_O		44
+#define CK_INFRA_USB_SYS_O_P1		45
+#define CLK_INFRA_NR_CLK		46
+
+
+/* INFRACFG_AO */
+
+#define CK_INFRA_MUX_UART0_SEL		0
+#define CK_INFRA_MUX_UART1_SEL		1
+#define CK_INFRA_MUX_UART2_SEL		2
+#define CK_INFRA_MUX_SPI0_SEL		3
+#define CK_INFRA_MUX_SPI1_SEL		4
+#define CK_INFRA_MUX_SPI2_SEL		5
+#define CK_INFRA_PWM_SEL		6
+#define CK_INFRA_PWM_CK1_SEL		7
+#define CK_INFRA_PWM_CK2_SEL		8
+#define CK_INFRA_PWM_CK3_SEL		9
+#define CK_INFRA_PWM_CK4_SEL		10
+#define CK_INFRA_PWM_CK5_SEL		11
+#define CK_INFRA_PWM_CK6_SEL		12
+#define CK_INFRA_PWM_CK7_SEL		13
+#define CK_INFRA_PWM_CK8_SEL		14
+#define CK_INFRA_PCIE_GFMUX_TL_O_P0_SEL	15
+#define CK_INFRA_PCIE_GFMUX_TL_O_P1_SEL	16
+#define CK_INFRA_PCIE_GFMUX_TL_O_P2_SEL	17
+#define CK_INFRA_PCIE_GFMUX_TL_O_P3_SEL	18
+#define CK_INFRA_66M_GPT_BCK		19
+#define CK_INFRA_66M_PWM_HCK		20
+#define CK_INFRA_66M_PWM_BCK		21
+#define CK_INFRA_66M_PWM_CK1		22
+#define CK_INFRA_66M_PWM_CK2		23
+#define CK_INFRA_66M_PWM_CK3		24
+#define CK_INFRA_66M_PWM_CK4		25
+#define CK_INFRA_66M_PWM_CK5		26
+#define CK_INFRA_66M_PWM_CK6		27
+#define CK_INFRA_66M_PWM_CK7		28
+#define CK_INFRA_66M_PWM_CK8		29
+#define CK_INFRA_133M_CQDMA_BCK		30
+#define CK_INFRA_66M_AUD_SLV_BCK	31
+#define CK_INFRA_AUD_26M		32
+#define CK_INFRA_AUD_L			33
+#define CK_INFRA_AUD_AUD		34
+#define CK_INFRA_AUD_EG2		35
+#define CK_INFRA_DRAMC_F26M		36
+#define CK_INFRA_133M_DBG_ACKM		37
+#define CK_INFRA_66M_AP_DMA_BCK		38
+#define CK_INFRA_66M_SEJ_BCK		39
+#define CK_INFRA_PRE_CK_SEJ_F13M	40
+#define CK_INFRA_66M_TRNG		41
+#define CK_INFRA_26M_THERM_SYSTEM	42
+#define CK_INFRA_I2C_BCK		43
+#define CK_INFRA_66M_UART0_PCK		44
+#define CK_INFRA_66M_UART1_PCK		45
+#define CK_INFRA_66M_UART2_PCK		46
+#define CK_INFRA_52M_UART0_CK		47
+#define CK_INFRA_52M_UART1_CK		48
+#define CK_INFRA_52M_UART2_CK		49
+#define CK_INFRA_NFI			50
+#define CK_INFRA_SPINFI			51
+#define CK_INFRA_66M_NFI_HCK		52
+#define CK_INFRA_104M_SPI0		53
+#define CK_INFRA_104M_SPI1		54
+#define CK_INFRA_104M_SPI2_BCK		55
+#define CK_INFRA_66M_SPI0_HCK		56
+#define CK_INFRA_66M_SPI1_HCK		57
+#define CK_INFRA_66M_SPI2_HCK		58
+#define CK_INFRA_66M_FLASHIF_AXI	59
+#define CK_INFRA_RTC			60
+#define CK_INFRA_26M_ADC_BCK		61
+#define CK_INFRA_RC_ADC			62
+#define CK_INFRA_MSDC400		63
+#define CK_INFRA_MSDC2_HCK		64
+#define CK_INFRA_133M_MSDC_0_HCK	65
+#define CK_INFRA_66M_MSDC_0_HCK		66
+#define CK_INFRA_133M_CPUM_BCK		67
+#define CK_INFRA_BIST2FPC		68
+#define CK_INFRA_I2C_X16W_MCK_CK_P1	69
+#define CK_INFRA_I2C_X16W_PCK_CK_P1	70
+#define CK_INFRA_133M_USB_HCK		71
+#define CK_INFRA_133M_USB_HCK_CK_P1	72
+#define CK_INFRA_66M_USB_HCK		73
+#define CK_INFRA_66M_USB_HCK_CK_P1	74
+#define CK_INFRA_USB_SYS		75
+#define CK_INFRA_USB_SYS_CK_P1		76
+#define CK_INFRA_USB_REF		77
+#define CK_INFRA_USB_CK_P1		78
+#define CK_INFRA_USB_FRMCNT		79
+#define CK_INFRA_USB_FRMCNT_CK_P1	80
+#define CK_INFRA_USB_PIPE		81
+#define CK_INFRA_USB_PIPE_CK_P1		82
+#define CK_INFRA_USB_UTMI		83
+#define CK_INFRA_USB_UTMI_CK_P1		84
+#define CK_INFRA_USB_XHCI		85
+#define CK_INFRA_USB_XHCI_CK_P1		86
+#define CK_INFRA_PCIE_GFMUX_TL_P0	87
+#define CK_INFRA_PCIE_GFMUX_TL_P1	88
+#define CK_INFRA_PCIE_GFMUX_TL_P2	89
+#define CK_INFRA_PCIE_GFMUX_TL_P3	90
+#define CK_INFRA_PCIE_PIPE_P0		91
+#define CK_INFRA_PCIE_PIPE_P1		92
+#define CK_INFRA_PCIE_PIPE_P2		93
+#define CK_INFRA_PCIE_PIPE_P3		94
+#define CK_INFRA_133M_PCIE_CK_P0	95
+#define CK_INFRA_133M_PCIE_CK_P1	96
+#define CK_INFRA_133M_PCIE_CK_P2	97
+#define CK_INFRA_133M_PCIE_CK_P3	98
+#define CK_INFRA_PCIE_PERI_26M_CK_P0	99
+#define CK_INFRA_PCIE_PERI_26M_CK_P1	100
+#define CK_INFRA_PCIE_PERI_26M_CK_P2	101
+#define CK_INFRA_PCIE_PERI_26M_CK_P3	102
+#define CLK_INFRA_AO_NR_CLK		103
+
+/* TOPCKGEN */
+
+#define CK_TOP_NETSYS_SEL		0
+#define CK_TOP_NETSYS_500M_SEL		1
+#define CK_TOP_NETSYS_2X_SEL		2
+#define CK_TOP_NETSYS_GSW_SEL		3
+#define CK_TOP_ETH_GMII_SEL		4
+#define CK_TOP_NETSYS_MCU_SEL		5
+#define CK_TOP_NETSYS_PAO_2X_SEL	6
+#define CK_TOP_EIP197_SEL		7
+#define CK_TOP_AXI_INFRA_SEL		8
+#define CK_TOP_UART_SEL			9
+#define CK_TOP_EMMC_250M_SEL		10
+#define CK_TOP_EMMC_400M_SEL		11
+#define CK_TOP_SPI_SEL			12
+#define CK_TOP_SPIM_MST_SEL		13
+#define CK_TOP_NFI1X_SEL		14
+#define CK_TOP_SPINFI_SEL		15
+#define CK_TOP_PWM_SEL			16
+#define CK_TOP_I2C_SEL			17
+#define CK_TOP_PCIE_MBIST_250M_SEL	18
+#define CK_TOP_PEXTP_TL_SEL		19
+#define CK_TOP_PEXTP_TL_P1_SEL		20
+#define CK_TOP_PEXTP_TL_P2_SEL		21
+#define CK_TOP_PEXTP_TL_P3_SEL		22
+#define CK_TOP_USB_SYS_SEL		23
+#define CK_TOP_USB_SYS_P1_SEL		24
+#define CK_TOP_USB_XHCI_SEL		25
+#define CK_TOP_USB_XHCI_P1_SEL		26
+#define CK_TOP_USB_FRMCNT_SEL		27
+#define CK_TOP_USB_FRMCNT_P1_SEL	28
+#define CK_TOP_AUD_SEL			29
+#define CK_TOP_A1SYS_SEL		30
+#define CK_TOP_AUD_L_SEL		31
+#define CK_TOP_A_TUNER_SEL		32
+#define CK_TOP_SSPXTP_SEL		33
+#define CK_TOP_USB_PHY_SEL		34
+#define CK_TOP_USXGMII_SBUS_0_SEL	35
+#define CK_TOP_USXGMII_SBUS_1_SEL	36
+#define CK_TOP_SGM_0_SEL		37
+#define CK_TOP_SGM_SBUS_0_SEL		38
+#define CK_TOP_SGM_1_SEL		39
+#define CK_TOP_SGM_SBUS_1_SEL		40
+#define CK_TOP_XFI_PHY_0_XTAL_SEL	41
+#define CK_TOP_XFI_PHY_1_XTAL_SEL	42
+#define CK_TOP_SYSAXI_SEL		43
+#define CK_TOP_SYSAPB_SEL		44
+#define CK_TOP_ETH_REFCK_50M_SEL	45
+#define CK_TOP_ETH_SYS_200M_SEL		46
+#define CK_TOP_ETH_SYS_SEL		47
+#define CK_TOP_ETH_XGMII_SEL		48
+#define CK_TOP_BUS_TOPS_SEL		49
+#define CK_TOP_NPU_TOPS_SEL		50
+#define CK_TOP_DRAMC_SEL		51
+#define CK_TOP_DRAMC_MD32_SEL		52
+#define CK_TOP_INFRA_F26M_SEL		53
+#define CK_TOP_PEXTP_P0_SEL		54
+#define CK_TOP_PEXTP_P1_SEL		55
+#define CK_TOP_PEXTP_P2_SEL		56
+#define CK_TOP_PEXTP_P3_SEL		57
+#define CK_TOP_DA_XTP_GLB_P0_SEL	58
+#define CK_TOP_DA_XTP_GLB_P1_SEL	59
+#define CK_TOP_DA_XTP_GLB_P2_SEL	60
+#define CK_TOP_DA_XTP_GLB_P3_SEL	61
+#define CK_TOP_CKM_SEL			62
+#define CK_TOP_DA_SELM_XTAL_SEL		63
+#define CK_TOP_PEXTP_SEL		64
+#define CK_TOP_TOPS_P2_26M_SEL		65
+#define CK_TOP_MCUSYS_BACKUP_625M_SEL	66
+#define CK_TOP_NETSYS_SYNC_250M_SEL	67
+#define CK_TOP_MACSEC_SEL		68
+#define CK_TOP_NETSYS_TOPS_400M_SEL	69
+#define CK_TOP_NETSYS_PPEFB_250M_SEL	70
+#define CK_TOP_NETSYS_WARP_SEL		71
+#define CK_TOP_ETH_MII_SEL		72
+#define CK_TOP_CK_NPU_SEL_CM_TOPS_SEL	73
+#define CK_TOP_CB_CKSQ_40M		74
+#define CK_TOP_CB_M_416M		75
+#define CK_TOP_CB_M_D2			76
+#define CK_TOP_M_D3_D2			77
+#define CK_TOP_CB_M_D4			78
+#define CK_TOP_CB_M_D8			79
+#define CK_TOP_M_D8_D2			80
+#define CK_TOP_CB_MM_720M		81
+#define CK_TOP_CB_MM_D2			82
+#define CK_TOP_CB_MM_D3_D5		83
+#define CK_TOP_CB_MM_D4			84
+#define CK_TOP_MM_D6_D2			85
+#define CK_TOP_CB_MM_D8			86
+#define CK_TOP_CB_APLL2_196M		87
+#define CK_TOP_CB_APLL2_D4		88
+#define CK_TOP_CB_NET1_D4		89
+#define CK_TOP_CB_NET1_D5		90
+#define CK_TOP_NET1_D5_D2		91
+#define CK_TOP_NET1_D5_D4		92
+#define CK_TOP_CB_NET1_D8		93
+#define CK_TOP_NET1_D8_D2		94
+#define CK_TOP_NET1_D8_D4		95
+#define CK_TOP_NET1_D8_D8		96
+#define CK_TOP_NET1_D8_D16		97
+#define CK_TOP_CB_NET2_800M		98
+#define CK_TOP_CB_NET2_D2		99
+#define CK_TOP_CB_NET2_D4		100
+#define CK_TOP_NET2_D4_D4		101
+#define CK_TOP_NET2_D4_D8		102
+#define CK_TOP_CB_NET2_D6		103
+#define CK_TOP_CB_NET2_D8		104
+#define CK_TOP_CB_WEDMCU_208M		105
+#define CK_TOP_CB_SGM_325M		106
+#define CK_TOP_CB_NETSYS_850M		107
+#define CK_TOP_CB_MSDC_400M		108
+#define CK_TOP_CKSQ_40M_D2		109
+#define CK_TOP_CB_RTC_32K		110
+#define CK_TOP_CB_RTC_32P7K		111
+#define CK_TOP_INFRA_F32K		112
+#define CK_TOP_CKSQ_SRC			113
+#define CK_TOP_NETSYS_2X		114
+#define CK_TOP_NETSYS_GSW		115
+#define CK_TOP_NETSYS_WED_MCU		116
+#define CK_TOP_EIP197			117
+#define CK_TOP_EMMC_250M		118
+#define CK_TOP_EMMC_400M		119
+#define CK_TOP_SPI			120
+#define CK_TOP_SPIM_MST			121
+#define CK_TOP_NFI1X			122
+#define CK_TOP_SPINFI_BCK		123
+#define CK_TOP_I2C_BCK			124
+#define CK_TOP_USB_SYS			125
+#define CK_TOP_USB_SYS_P1		126
+#define CK_TOP_USB_XHCI			127
+#define CK_TOP_USB_XHCI_P1		128
+#define CK_TOP_USB_FRMCNT		129
+#define CK_TOP_USB_FRMCNT_P1		130
+#define CK_TOP_AUD			131
+#define CK_TOP_A1SYS			132
+#define CK_TOP_AUD_L			133
+#define CK_TOP_A_TUNER			134
+#define CK_TOP_SYSAXI			135
+#define CK_TOP_INFRA_F26M		136
+#define CK_TOP_USB_REF			137
+#define CK_TOP_USB_CK_P1		138
+#define CK_TOP_AUD_I2S_M		139
+#define CLK_TOP_NR_CLK			140
+
+/* APMIXEDSYS */
+
+#define CK_APMIXED_NETSYSPLL		0
+#define CK_APMIXED_MPLL			1
+#define CK_APMIXED_MMPLL		2
+#define CK_APMIXED_APLL2		3
+#define CK_APMIXED_NET1PLL		4
+#define CK_APMIXED_NET2PLL		5
+#define CK_APMIXED_WEDMCUPLL		6
+#define CK_APMIXED_SGMPLL		7
+#define CK_APMIXED_ARM_B		8
+#define CK_APMIXED_CCIPLL2_B		9
+#define CK_APMIXED_USXGMIIPLL		10
+#define CK_APMIXED_MSDCPLL		11
+#define CLK_APMIXED_NR_CLK		12
+
+/* MCUSYS */
+
+#define CK_MCU_BUS_DIV_SEL		0
+#define CK_MCU_ARM_DIV_SEL		1
+#define CLK_MCU_NR_CLK			2
+
+/* ETHDMA */
+
+#define CK_ETHDMA_XGP1_EN		0
+#define CK_ETHDMA_XGP2_EN		1
+#define CK_ETHDMA_XGP3_EN		2
+#define CK_ETHDMA_FE_EN			3
+#define CK_ETHDMA_GP2_EN		4
+#define CK_ETHDMA_GP1_EN		5
+#define CK_ETHDMA_GP3_EN		6
+#define CK_ETHDMA_ESW_EN		7
+#define CK_ETHDMA_CRYPT0_EN		8
+#define CLK_ETHDMA_NR_CLK		9
+/* SGMIISYS_0 */
+
+#define CK_SGM0_TX_EN			0
+#define CK_SGM0_RX_EN			1
+#define CLK_SGMII0_NR_CLK		2
+
+/* SGMIISYS_1 */
+
+#define CK_SGM1_TX_EN			0
+#define CK_SGM1_RX_EN			1
+#define CLK_SGMII1_NR_CLK		2
+
+/* ETHWARP */
+
+#define CK_ETHWARP_WOCPU2_EN		0
+#define CK_ETHWARP_WOCPU1_EN		1
+#define CK_ETHWARP_WOCPU0_EN		2
+#define CLK_ETHWARP_NR_CLK		3
+
+#endif /* _DT_BINDINGS_CLK_MT7988_H */
+
diff --git a/target/linux/mediatek/files-5.4/include/dt-bindings/power/mt7988-power.h b/target/linux/mediatek/files-5.4/include/dt-bindings/power/mt7988-power.h
new file mode 100644
index 0000000..ff1100a
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/include/dt-bindings/power/mt7988-power.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ *
+ */
+
+#ifndef _DT_BINDINGS_POWER_MT7988_POWER_H
+#define _DT_BINDINGS_POWER_MT7988_POWER_H
+
+#define MT7988_POWER_DOMAIN_TOPS0			0
+#define MT7988_POWER_DOMAIN_TOPS1			1
+#define MT7988_POWER_DOMAIN_ETH2P5			2
+
+
+#endif /* _DT_BINDINGS_POWER_MT7988_POWER_H */
diff --git a/target/linux/mediatek/files-5.4/include/dt-bindings/regulator/richtek,rt5190a-regulator.h b/target/linux/mediatek/files-5.4/include/dt-bindings/regulator/richtek,rt5190a-regulator.h
new file mode 100644
index 0000000..63f99d4
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/include/dt-bindings/regulator/richtek,rt5190a-regulator.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__
+#define __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__
+
+/*
+ * BUCK/LDO mode constants which may be used in devicetree properties
+ * (eg. regulator-allowed-modes).
+ * See the manufacturer's datasheet for more information on these modes.
+ */
+
+#define RT5190A_OPMODE_AUTO	0
+#define RT5190A_OPMODE_FPWM	1
+
+#endif
diff --git a/target/linux/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch b/target/linux/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch
new file mode 100644
index 0000000..fdf953d
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch
@@ -0,0 +1,12 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index 927ebc5..03bb7b5 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -573,6 +573,7 @@ static int __init mtk_cpufreq_driver_init(void)
+ 	pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0);
+ 	if (IS_ERR(pdev)) {
+ 		pr_err("failed to register mtk-cpufreq platform device\n");
++		platform_driver_unregister(&mtk_cpufreq_platdrv);
+ 		return PTR_ERR(pdev);
+ 	}
+ 
diff --git a/target/linux/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch b/target/linux/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch
new file mode 100644
index 0000000..2fa9359
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch
@@ -0,0 +1,88 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index 03bb7b5..010a947 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -351,6 +351,12 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 		goto out_free_resources;
+ 	}
+ 
++	ret = regulator_enable(proc_reg);
++	if (ret) {
++		dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu);
++		goto out_free_resources;
++	}
++
+ 	/* Both presence and absence of sram regulator are valid cases. */
+ 	sram_reg = regulator_get_exclusive(cpu_dev, "sram");
+ 
+@@ -368,13 +374,21 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 		goto out_free_resources;
+ 	}
+ 
++	ret = clk_prepare_enable(cpu_clk);
++	if (ret)
++		goto out_free_opp_table;
++
++	ret = clk_prepare_enable(inter_clk);
++	if (ret)
++		goto out_disable_mux_clock;
++
+ 	/* Search a safe voltage for intermediate frequency. */
+ 	rate = clk_get_rate(inter_clk);
+ 	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
+ 	if (IS_ERR(opp)) {
+ 		pr_err("failed to get intermediate opp for cpu%d\n", cpu);
+ 		ret = PTR_ERR(opp);
+-		goto out_free_opp_table;
++		goto out_disable_inter_clock;
+ 	}
+ 	info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
+ 	dev_pm_opp_put(opp);
+@@ -393,10 +407,23 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 
+ 	return 0;
+ 
++out_disable_inter_clock:
++	if(!IS_ERR(inter_clk))
++		clk_disable_unprepare(inter_clk);
++
++out_disable_mux_clock:
++	if(!IS_ERR(cpu_clk))
++		clk_disable_unprepare(cpu_clk);
++
+ out_free_opp_table:
+ 	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
+ 
+ out_free_resources:
++	if (!IS_ERR(proc_reg)) {
++		if (regulator_is_enabled(proc_reg))
++			regulator_disable(proc_reg);
++	}
++
+ 	if (!IS_ERR(proc_reg))
+ 		regulator_put(proc_reg);
+ 	if (!IS_ERR(sram_reg))
+@@ -411,14 +438,20 @@ out_free_resources:
+ 
+ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
+ {
+-	if (!IS_ERR(info->proc_reg))
++	if (!IS_ERR(info->proc_reg)){
++		regulator_disable(info->proc_reg);
+ 		regulator_put(info->proc_reg);
++	}
+ 	if (!IS_ERR(info->sram_reg))
+ 		regulator_put(info->sram_reg);
+-	if (!IS_ERR(info->cpu_clk))
++	if (!IS_ERR(info->cpu_clk)){
++		clk_disable_unprepare(info->cpu_clk);
+ 		clk_put(info->cpu_clk);
+-	if (!IS_ERR(info->inter_clk))
++	}
++	if (!IS_ERR(info->inter_clk)){
++		clk_disable_unprepare(info->inter_clk);
+ 		clk_put(info->inter_clk);
++	}
+ 
+ 	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
+ }
diff --git a/target/linux/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch b/target/linux/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch
new file mode 100644
index 0000000..e673148
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch
@@ -0,0 +1,38 @@
+diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
+index 23393d5..cf3a53e 100644
+--- a/drivers/clk/mediatek/Kconfig
++++ b/drivers/clk/mediatek/Kconfig
+@@ -275,6 +275,14 @@ config COMMON_CLK_MT7981
+ 	  This driver supports MediaTek MT7981 basic clocks and clocks
+ 	  required for various periperals found on MediaTek.
+ 
++config COMMON_CLK_MT7988
++	bool "Clock driver for MediaTek MT7988"
++	depends on ARCH_MEDIATEK || COMPILE_TEST
++	select COMMON_CLK_MEDIATEK
++	---help---
++	  This driver supports MediaTek MT7988 basic clocks and clocks
++	  required for various periperals found on MediaTek.
++
+ config COMMON_CLK_MT8135
+ 	bool "Clock driver for MediaTek MT8135"
+ 	depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index ffe0850..43ca85d 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -41,6 +41,7 @@ obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
+ obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o
+ obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986.o
+ obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981.o
++obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988.o
+ obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
+ obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
+ obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o
+@@ -57,4 +58,4 @@ obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o
+ obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o
+ obj-$(CONFIG_COMMON_CLK_MT8516) += clk-mt8516.o
+ obj-$(CONFIG_COMMON_CLK_MT8516_AUDSYS) += clk-mt8516-aud.o
+-obj-y += clk-bringup.o
+\ No newline at end of file
++obj-y += clk-bringup.o
diff --git a/target/linux/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch b/target/linux/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch
new file mode 100644
index 0000000..ee87f4e
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch
@@ -0,0 +1,212 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index 010a947..291f629 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -38,6 +38,7 @@ struct mtk_cpu_dvfs_info {
+ 	struct regulator *proc_reg;
+ 	struct regulator *sram_reg;
+ 	struct clk *cpu_clk;
++	struct clk *cci_clk;
+ 	struct clk *inter_clk;
+ 	struct list_head list_head;
+ 	int intermediate_voltage;
+@@ -205,15 +206,24 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ 	struct cpufreq_frequency_table *freq_table = policy->freq_table;
+ 	struct clk *cpu_clk = policy->clk;
+ 	struct clk *armpll = clk_get_parent(cpu_clk);
++	struct clk *cci_clk = ERR_PTR(-ENODEV);
++	struct clk *ccipll;
+ 	struct mtk_cpu_dvfs_info *info = policy->driver_data;
+ 	struct device *cpu_dev = info->cpu_dev;
+ 	struct dev_pm_opp *opp;
+-	long freq_hz, old_freq_hz;
++	long freq_hz, old_freq_hz, cci_freq_hz, cci_old_freq_hz;
+ 	int vproc, old_vproc, inter_vproc, target_vproc, ret;
+ 
+ 	inter_vproc = info->intermediate_voltage;
+ 
+ 	old_freq_hz = clk_get_rate(cpu_clk);
++
++	if (!IS_ERR(info->cci_clk)) {
++		cci_clk = info->cci_clk;
++		ccipll = clk_get_parent(cci_clk);
++		cci_old_freq_hz = clk_get_rate(cci_clk);
++	}
++
+ 	old_vproc = regulator_get_voltage(info->proc_reg);
+ 	if (old_vproc < 0) {
+ 		pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
+@@ -221,6 +231,7 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ 	}
+ 
+ 	freq_hz = freq_table[index].frequency * 1000;
++	cci_freq_hz = freq_table[index].frequency * 600;
+ 
+ 	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
+ 	if (IS_ERR(opp)) {
+@@ -246,6 +257,18 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ 		}
+ 	}
+ 
++	/* Reparent the CCI clock to intermediate clock. */
++	if (!IS_ERR(cci_clk)) {
++		ret = clk_set_parent(cci_clk, info->inter_clk);
++		if (ret) {
++			pr_err("cpu%d: failed to re-parent cci clock!\n",
++			       policy->cpu);
++			mtk_cpufreq_set_voltage(info, old_vproc);
++			WARN_ON(1);
++			return ret;
++		}
++	}
++
+ 	/* Reparent the CPU clock to intermediate clock. */
+ 	ret = clk_set_parent(cpu_clk, info->inter_clk);
+ 	if (ret) {
+@@ -266,6 +289,18 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ 		return ret;
+ 	}
+ 
++	/* Set the original PLL to target rate. */
++	if (!IS_ERR(cci_clk)) {
++		ret = clk_set_rate(ccipll, cci_freq_hz);
++		if (ret) {
++			pr_err("cpu%d: failed to scale cci clock rate!\n",
++			       policy->cpu);
++			clk_set_parent(cci_clk, ccipll);
++			mtk_cpufreq_set_voltage(info, old_vproc);
++			return ret;
++		}
++	}
++
+ 	/* Set parent of CPU clock back to the original PLL. */
+ 	ret = clk_set_parent(cpu_clk, armpll);
+ 	if (ret) {
+@@ -276,6 +311,17 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ 		return ret;
+ 	}
+ 
++	/* Set parent of CCI clock back to the original PLL. */
++	if (!IS_ERR(cci_clk)) {
++		ret = clk_set_parent(cci_clk, ccipll);
++		if (ret) {
++			pr_err("cpu%d: failed to re-parent cci clock!\n",
++			       policy->cpu);
++			mtk_cpufreq_set_voltage(info, inter_vproc);
++			WARN_ON(1);
++			return ret;
++		}
++	}
+ 	/*
+ 	 * If the new voltage is lower than the intermediate voltage or the
+ 	 * original voltage, scale down to the new voltage.
+@@ -285,9 +331,20 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ 		if (ret) {
+ 			pr_err("cpu%d: failed to scale down voltage!\n",
+ 			       policy->cpu);
++			if (!IS_ERR(cci_clk))
++				clk_set_parent(cci_clk, info->inter_clk);
++
+ 			clk_set_parent(cpu_clk, info->inter_clk);
+ 			clk_set_rate(armpll, old_freq_hz);
++
++			if (!IS_ERR(cci_clk))
++				clk_set_rate(ccipll, cci_old_freq_hz);
++
+ 			clk_set_parent(cpu_clk, armpll);
++
++			if (!IS_ERR(cci_clk))
++				clk_set_parent(cci_clk, ccipll);
++
+ 			return ret;
+ 		}
+ 	}
+@@ -303,6 +360,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 	struct regulator *proc_reg = ERR_PTR(-ENODEV);
+ 	struct regulator *sram_reg = ERR_PTR(-ENODEV);
+ 	struct clk *cpu_clk = ERR_PTR(-ENODEV);
++	struct clk *cci_clk = ERR_PTR(-ENODEV);
+ 	struct clk *inter_clk = ERR_PTR(-ENODEV);
+ 	struct dev_pm_opp *opp;
+ 	unsigned long rate;
+@@ -338,6 +396,8 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 		goto out_free_resources;
+ 	}
+ 
++	cci_clk = clk_get(cpu_dev, "cci");
++
+ 	proc_reg = regulator_get_optional(cpu_dev, "proc");
+ 	if (IS_ERR(proc_reg)) {
+ 		if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
+@@ -379,16 +439,23 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 		goto out_free_opp_table;
+ 
+ 	ret = clk_prepare_enable(inter_clk);
++
+ 	if (ret)
+ 		goto out_disable_mux_clock;
+ 
++	if(!(IS_ERR(cci_clk))) {
++		ret = clk_prepare_enable(cci_clk);
++		if(ret)
++			goto out_disable_inter_clock;
++	}
++
+ 	/* Search a safe voltage for intermediate frequency. */
+ 	rate = clk_get_rate(inter_clk);
+ 	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
+ 	if (IS_ERR(opp)) {
+ 		pr_err("failed to get intermediate opp for cpu%d\n", cpu);
+ 		ret = PTR_ERR(opp);
+-		goto out_disable_inter_clock;
++		goto out_disable_cci_clock;
+ 	}
+ 	info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
+ 	dev_pm_opp_put(opp);
+@@ -397,6 +464,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 	info->proc_reg = proc_reg;
+ 	info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
+ 	info->cpu_clk = cpu_clk;
++	info->cci_clk = cci_clk;
+ 	info->inter_clk = inter_clk;
+ 
+ 	/*
+@@ -407,6 +475,10 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ 
+ 	return 0;
+ 
++out_disable_cci_clock:
++	if(!IS_ERR(cci_clk))
++		clk_disable_unprepare(cci_clk);
++
+ out_disable_inter_clock:
+ 	if(!IS_ERR(inter_clk))
+ 		clk_disable_unprepare(inter_clk);
+@@ -432,6 +504,8 @@ out_free_resources:
+ 		clk_put(cpu_clk);
+ 	if (!IS_ERR(inter_clk))
+ 		clk_put(inter_clk);
++	if (!IS_ERR(cci_clk))
++		clk_put(cci_clk);
+ 
+ 	return ret;
+ }
+@@ -452,6 +526,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);
+ 	}
++	if (!IS_ERR(info->cci_clk)){
++		clk_disable_unprepare(info->cci_clk);
++		clk_put(info->cci_clk);
++	}
+ 
+ 	dev_pm_opp_of_cpumask_remove_table(&info->cpus);
+ }
+@@ -570,6 +648,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
+ 	{ .compatible = "mediatek,mt8176", },
+ 	{ .compatible = "mediatek,mt8183", },
+ 	{ .compatible = "mediatek,mt8516", },
++	{ .compatible = "mediatek,mt7988", },
+ 
+ 	{ }
+ };
diff --git a/target/linux/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch b/target/linux/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch
new file mode 100644
index 0000000..4a9ff6f
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch
@@ -0,0 +1,28 @@
+diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
+index c3d6756..d84c45d 100644
+--- a/drivers/clk/mediatek/clk-mtk.h
++++ b/drivers/clk/mediatek/clk-mtk.h
+@@ -231,6 +231,7 @@ struct mtk_pll_data {
+ 	uint32_t pcw_reg;
+ 	int pcw_shift;
+ 	uint32_t pcw_chg_reg;
++	int pcw_chg_shift;
+ 	const struct mtk_pll_div_table *div_table;
+ 	const char *parent_name;
+ };
+diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
+index f440f2c..db318fe 100644
+--- a/drivers/clk/mediatek/clk-pll.c
++++ b/drivers/clk/mediatek/clk-pll.c
+@@ -136,7 +136,10 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
+ 			pll->data->pcw_shift);
+ 	val |= pcw << pll->data->pcw_shift;
+ 	writel(val, pll->pcw_addr);
+-	chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK;
++	if (pll->data->pcw_chg_shift)
++		chg = readl(pll->pcw_chg_addr) | BIT(pll->data->pcw_chg_shift);
++	else
++		chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK;
+ 	writel(chg, pll->pcw_chg_addr);
+ 	if (pll->tuner_addr)
+ 		writel(val + 1, pll->tuner_addr);
diff --git a/target/linux/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch b/target/linux/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch
new file mode 100644
index 0000000..7fc4f1d
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch
@@ -0,0 +1,9 @@
+diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
+index b017330..1c485e3 100644
+--- a/drivers/soc/mediatek/Makefile
++++ b/drivers/soc/mediatek/Makefile
+@@ -3,3 +3,4 @@ obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
+ obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
+ obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
++obj-$(CONFIG_MTK_SCPSYS) += mtk-pm-domains.o
diff --git a/target/linux/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch b/target/linux/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch
new file mode 100644
index 0000000..8e99118
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch
@@ -0,0 +1,47 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index b23b6d2..147a224 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -15,6 +15,7 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+ #include <linux/thermal.h>
++#include <linux/nvmem-consumer.h>
+ 
+ #define MIN_VOLT_SHIFT		(100000)
+ #define MAX_VOLT_SHIFT		(200000)
+@@ -539,6 +540,11 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
+ 	struct mtk_cpu_dvfs_info *info;
+ 	struct cpufreq_frequency_table *freq_table;
+ 	int ret;
++	int target_vproc;
++	u32 reg_val;
++	struct nvmem_cell *cell;
++	size_t len;
++	u32 *buf;
+ 
+ 	info = mtk_cpu_dvfs_info_lookup(policy->cpu);
+ 	if (!info) {
+@@ -547,6 +553,22 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
+ 		return -EINVAL;
+ 	}
+ 
++	cell = nvmem_cell_get(info->cpu_dev, "calibration-data");
++	if (!IS_ERR(cell)) {
++		buf = (u32 *)nvmem_cell_read(cell, &len);
++		nvmem_cell_put(cell);
++		if (!IS_ERR(buf)) {
++			reg_val = buf[0] & 0x1f;
++			pr_debug("%s: read vbinning value: %d\n", __func__, reg_val);
++			if (reg_val > 0) {
++				target_vproc = 850000 + reg_val * 10000;
++				dev_pm_opp_remove(info->cpu_dev, 1800000000);
++				dev_pm_opp_add(info->cpu_dev, 1800000000, target_vproc);
++			}
++			kfree(buf);
++		}
++	}
++
+ 	ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
+ 	if (ret) {
+ 		pr_err("failed to init cpufreq table for cpu%d: %d\n",
diff --git a/target/linux/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch b/target/linux/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch
new file mode 100644
index 0000000..8268e7d
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch
@@ -0,0 +1,25 @@
+diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
+index 3a5a456..6d6206e 100644
+--- a/drivers/pwm/pwm-mediatek.c
++++ b/drivers/pwm/pwm-mediatek.c
+@@ -350,6 +350,12 @@ static const struct pwm_mediatek_of_data mt7986_pwm_data = {
+ 	.reg_ver = REG_V2,
+ };
+ 
++static const struct pwm_mediatek_of_data mt7988_pwm_data = {
++	.num_pwms = 8,
++	.pwm45_fixup = false,
++	.reg_ver = REG_V2,
++};
++
+ static const struct pwm_mediatek_of_data mt8516_pwm_data = {
+ 	.num_pwms = 5,
+ 	.pwm45_fixup = false,
+@@ -364,6 +370,7 @@ static const struct of_device_id pwm_mediatek_of_match[] = {
+ 	{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
+ 	{ .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
+ 	{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
++	{ .compatible = "mediatek,mt7988-pwm", .data = &mt7988_pwm_data },
+ 	{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
+ 	{ },
+ };
diff --git a/target/linux/mediatek/patches-5.4/0950-add-pmic-config.patch b/target/linux/mediatek/patches-5.4/0950-add-pmic-config.patch
new file mode 100644
index 0000000..f5384f3
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0950-add-pmic-config.patch
@@ -0,0 +1,36 @@
+diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
+index 3ee6353..2e393a7 100644
+--- a/drivers/regulator/Kconfig
++++ b/drivers/regulator/Kconfig
+@@ -798,6 +798,16 @@ config REGULATOR_RT5033
+ 	  RT5033 PMIC. The device supports multiple regulators like
+ 	  current source, LDO and Buck.
+ 
++config REGULATOR_RT5190A
++	tristate "Richtek RT5190A PMIC"
++	depends on I2C
++       select REGMAP_I2C
++	help
++	  This add support for voltage regulator in Ritchtek RT5190A PMIC.
++	  It integrates 1 channel buck controller, 3 channels high efficiency
++	  buck converters, 1 LDO, mute AC OFF depop function, with the general
++	  I2C control interface.
++
+ config REGULATOR_S2MPA01
+ 	tristate "Samsung S2MPA01 voltage regulator"
+ 	depends on MFD_SEC_CORE
+diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
+index 2210ba5..bf75b77 100644
+--- a/drivers/regulator/Makefile
++++ b/drivers/regulator/Makefile
+@@ -100,6 +100,7 @@ obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
+ obj-$(CONFIG_REGULATOR_RK808)   += rk808-regulator.o
+ obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o
+ obj-$(CONFIG_REGULATOR_RT5033)	+= rt5033-regulator.o
++obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o
+ obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
+ obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
+ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+-- 
+2.18.0
+
diff --git a/target/linux/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch b/target/linux/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch
new file mode 100644
index 0000000..a8f1dfe
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch
@@ -0,0 +1,38 @@
+From cbd37bfc8221c1a81d235ddfb1898536a821c650 Mon Sep 17 00:00:00 2001
+From: "mingming.su" <Mingming.Su@mediatek.com>
+Date: Wed, 7 Sep 2022 15:44:46 +0800
+Subject: [PATCH] trng: Add trng support for mt7988
+
+Add trng support for mt7988.
+
+Signed-off-by: mingming.su <Mingming.Su@mediatek.com>
+---
+ drivers/char/hw_random/mtk-rng.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
+index 75fca4cef..878170c15 100644
+--- a/drivers/char/hw_random/mtk-rng.c
++++ b/drivers/char/hw_random/mtk-rng.c
+@@ -231,6 +231,10 @@ static const struct mtk_rng_of_data mt7986_rng_data = {
+ 	.rng_version = 1,
+ };
+ 
++static const struct mtk_rng_of_data mt7988_rng_data = {
++	.rng_version = 2,
++};
++
+ static const struct mtk_rng_of_data mt7623_rng_data = {
+ 	.rng_version = 1,
+ };
+@@ -238,6 +242,7 @@ static const struct mtk_rng_of_data mt7623_rng_data = {
+ static const struct of_device_id mtk_rng_match[] = {
+ 	{ .compatible = "mediatek,mt7981-rng", .data = &mt7981_rng_data },
+ 	{ .compatible = "mediatek,mt7986-rng", .data = &mt7986_rng_data },
++	{ .compatible = "mediatek,mt7988-rng", .data = &mt7988_rng_data },
+ 	{ .compatible = "mediatek,mt7623-rng", .data = &mt7623_rng_data },
+ 	{},
+ };
+-- 
+2.18.0
+
diff --git a/target/linux/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch b/target/linux/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch
new file mode 100644
index 0000000..01f01f6
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch
@@ -0,0 +1,30 @@
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index e7ec276..b6341dd 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -112,6 +112,13 @@ config PINCTRL_MT7986
+ 	default ARM64 && ARCH_MEDIATEK
+ 	select PINCTRL_MTK_MOORE
+ 
++config PINCTRL_MT7988
++        bool "Mediatek MT7988 pin control"
++        depends on OF
++        depends on ARM64 || COMPILE_TEST
++        default ARM64 && ARCH_MEDIATEK
++        select PINCTRL_MTK_MOORE
++
+ config PINCTRL_MT8173
+ 	bool "Mediatek MT8173 pin control"
+ 	depends on OF
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index e6813cf..6e28df9 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_MT7623)	+= pinctrl-mt7623.o
+ obj-$(CONFIG_PINCTRL_MT7629)	+= pinctrl-mt7629.o
+ obj-$(CONFIG_PINCTRL_MT7981)	+= pinctrl-mt7981.o
+ obj-$(CONFIG_PINCTRL_MT7986)	+= pinctrl-mt7986.o
++obj-$(CONFIG_PINCTRL_MT7988)    += pinctrl-mt7988.o
+ obj-$(CONFIG_PINCTRL_MT8173)	+= pinctrl-mt8173.o
+ obj-$(CONFIG_PINCTRL_MT8183)	+= pinctrl-mt8183.o
+ obj-$(CONFIG_PINCTRL_MT8516)	+= pinctrl-mt8516.o
diff --git a/target/linux/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch b/target/linux/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch
new file mode 100644
index 0000000..1591144
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch
@@ -0,0 +1,28 @@
+diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
+index 001a21ab..67d3da48 100644
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -348,6 +348,11 @@ config MTK_THERMAL
+ 	  Enable this option if you want to have support for thermal management
+ 	  controller present in Mediatek SoCs
+ 
++menu "Mediatek thermal drivers"
++depends on ARCH_MEDIATEK || COMPILE_TEST
++source "drivers/thermal/mediatek/Kconfig"
++endmenu
++
+ menu "Intel thermal drivers"
+ depends on X86 || X86_INTEL_QUARK || COMPILE_TEST
+ source "drivers/thermal/intel/Kconfig"
+diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
+index 74a37c7f..6be9ff19 100644
+--- a/drivers/thermal/Makefile
++++ b/drivers/thermal/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_QCOM_TSENS)	+= qcom/
+ obj-y				+= tegra/
+ obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
+ obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
++obj-y				+= mediatek/
+ obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
+ obj-$(CONFIG_ZX2967_THERMAL)	+= zx2967_thermal.o
+ obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
diff --git a/target/linux/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch b/target/linux/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
new file mode 100644
index 0000000..a102660
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
@@ -0,0 +1,24 @@
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -522,6 +522,11 @@ config MEDIATEK_GE_PHY
+ 	help
+ 	  Supports the MediaTek Gigabit Ethernet PHYs.
+ 
++config MEDIATEK_2P5GE_PHY
++	tristate "MediaTek 2.5Gb Ethernet PHYs"
++	---help---
++	  Supports MediaTek internal 2.5Gb Ethernet PHYs.
++
+ config MICREL_PHY
+ 	tristate "Micrel PHYs"
+ 	---help---
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -95,6 +95,7 @@ obj-$(CONFIG_LXT_PHY)		+= lxt.o
+ obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
+ obj-$(CONFIG_MARVELL_10G_PHY)	+= marvell10g.o
+ obj-$(CONFIG_MEDIATEK_GE_PHY)	+= mediatek-ge.o
++obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
+ obj-$(CONFIG_MESON_GXL_PHY)	+= meson-gxl.o
+ obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o
+ obj-$(CONFIG_MICREL_PHY)	+= micrel.o
diff --git a/target/linux/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch b/target/linux/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch
new file mode 100644
index 0000000..8853324
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch
@@ -0,0 +1,498 @@
+Index: linux-5.4.203/drivers/net/dsa/Makefile
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/Makefile
++++ linux-5.4.203/drivers/net/dsa/Makefile
+@@ -7,7 +7,7 @@ obj-$(CONFIG_FIXED_PHY)		+= dsa_loop_bdi
+ endif
+ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
+ obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530-dsa.o
+-mt7530-dsa-objs			:= mt7530.o mt7531_phy.o
++mt7530-dsa-objs			:= mt7530.o mt7530_nl.o mt7531_phy.o
+ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
+ obj-$(CONFIG_NET_DSA_QCA8K)	+= qca8k.o
+ obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
+Index: linux-5.4.203/drivers/net/dsa/mt7530.c
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
++++ linux-5.4.203/drivers/net/dsa/mt7530.c
+@@ -21,6 +21,7 @@
+ #include <net/dsa.h>
+
+ #include "mt7530.h"
++#include "mt7530_nl.h"
+
+ /* String, offset, and register size in bytes if different from 4 bytes */
+ static const struct mt7530_mib_desc mt7530_mib[] = {
+@@ -222,7 +223,7 @@ mt7530_mii_read(struct mt7530_priv *priv
+ 	return (hi << 16) | (lo & 0xffff);
+ }
+
+-static void
++void
+ mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
+ {
+ 	struct mii_bus *bus = priv->bus;
+@@ -255,7 +256,7 @@ _mt7530_read(struct mt7530_dummy_poll *p
+ 	return val;
+ }
+
+-static u32
++u32
+ mt7530_read(struct mt7530_priv *priv, u32 reg)
+ {
+ 	struct mt7530_dummy_poll p;
+@@ -614,7 +615,7 @@ static int mt7530_phy_write(struct dsa_s
+ 	return mdiobus_write_nested(priv->bus, port, regnum, val);
+ }
+
+-static int
++int
+ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
+ 			int regnum)
+ {
+@@ -663,7 +664,7 @@ out:
+ 	return ret;
+ }
+
+-static int
++int
+ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
+ 			 int regnum, u32 data)
+ {
+@@ -711,7 +712,7 @@ out:
+ 	return ret;
+ }
+
+-static int
++int
+ mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
+ {
+ 	struct mii_bus *bus = priv->bus;
+@@ -749,7 +750,7 @@ out:
+ 	return ret;
+ }
+
+-static int
++int
+ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
+ 			 u16 data)
+ {
+@@ -2690,6 +2691,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ {
+ 	struct mt7530_priv *priv;
+ 	struct device_node *dn;
++	int ret;
+
+ 	dn = mdiodev->dev.of_node;
+
+@@ -2765,7 +2767,13 @@ mt7530_probe(struct mdio_device *mdiodev
+ 	mutex_init(&priv->reg_mutex);
+ 	dev_set_drvdata(&mdiodev->dev, priv);
+
+-	return dsa_register_switch(priv->ds);
++	ret = dsa_register_switch(priv->ds);
++	if (ret)
++		return ret;
++
++	mt7530_nl_init(&priv);
++
++	return 0;
+ }
+
+ static void
+@@ -2786,6 +2794,8 @@ mt7530_remove(struct mdio_device *mdiode
+
+ 	dsa_unregister_switch(priv->ds);
+ 	mutex_destroy(&priv->reg_mutex);
++
++	mt7530_nl_exit();
+ }
+
+ static struct mdio_driver mt7530_mdio_driver = {
+Index: linux-5.4.203/drivers/net/dsa/mt7530.h
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
++++ linux-5.4.203/drivers/net/dsa/mt7530.h
+@@ -783,4 +783,12 @@ static inline void INIT_MT7530_DUMMY_POL
+ }
+
+ int mt7531_phy_setup(struct dsa_switch *ds);
++u32 mt7530_read(struct mt7530_priv *priv, u32 reg);
++void mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val);
++int mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, int regnum);
++int mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, int regnum, u32 data);
++int mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum);
++int mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, u16 data);
++
++
+ #endif /* __MT7530_H */
+Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.c
+===================================================================
+--- /dev/null
++++ linux-5.4.203/drivers/net/dsa/mt7530_nl.c
+@@ -0,0 +1,311 @@
++// SPDX-License-Identifier: GPL-2.0

++/*

++ * Copyright (c) 2018 MediaTek Inc.

++ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>

++ */

++

++#include <linux/types.h>

++#include <linux/kernel.h>

++#include <linux/module.h>

++#include <linux/init.h>

++#include <net/genetlink.h>

++#include <linux/of_mdio.h>

++#include <linux/phylink.h>

++#include <net/dsa.h>

++

++#include "mt7530.h"

++#include "mt7530_nl.h"

++

++struct mt7530_nl_cmd_item {

++	enum mt7530_cmd cmd;

++	bool require_dev;

++	int (*process)(struct genl_info *info);

++	u32 nr_required_attrs;

++	const enum mt7530_attr *required_attrs;

++};

++

++struct mt7530_priv *sw_priv;

++

++static DEFINE_MUTEX(mt7530_devs_lock);

++

++void mt7530_put(void)

++{

++	mutex_unlock(&mt7530_devs_lock);

++}

++

++void mt7530_lock(void)

++{

++	mutex_lock(&mt7530_devs_lock);

++}

++

++static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info);

++

++static const struct nla_policy mt7530_nl_cmd_policy[] = {

++	[MT7530_ATTR_TYPE_MESG] = { .type = NLA_STRING },

++	[MT7530_ATTR_TYPE_PHY] = { .type = NLA_S32 },

++	[MT7530_ATTR_TYPE_REG] = { .type = NLA_S32 },

++	[MT7530_ATTR_TYPE_VAL] = { .type = NLA_S32 },

++	[MT7530_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 },

++	[MT7530_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 },

++	[MT7530_ATTR_TYPE_DEVAD] = { .type = NLA_S32 },

++};

++

++static const struct genl_ops mt7530_nl_ops[] = {

++	{

++		.cmd = MT7530_CMD_REQUEST,

++		.doit = mt7530_nl_response,

++		.flags = GENL_ADMIN_PERM,

++	}, {

++		.cmd = MT7530_CMD_READ,

++		.doit = mt7530_nl_response,

++		.flags = GENL_ADMIN_PERM,

++	}, {

++		.cmd = MT7530_CMD_WRITE,

++		.doit = mt7530_nl_response,

++		.flags = GENL_ADMIN_PERM,

++	},

++};

++

++static struct genl_family mt7530_nl_family = {

++	.name =		MT7530_DSA_GENL_NAME,

++	.version =	MT7530_GENL_VERSION,

++	.maxattr =	MT7530_NR_ATTR_TYPE,

++	.ops =		mt7530_nl_ops,

++	.n_ops =	ARRAY_SIZE(mt7530_nl_ops),

++	.policy =	mt7530_nl_cmd_policy,

++};

++

++static int mt7530_nl_prepare_reply(struct genl_info *info, u8 cmd,

++				   struct sk_buff **skbp)

++{

++	struct sk_buff *msg;

++	void *reply;

++

++	if (!info)

++		return -EINVAL;

++

++	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);

++	if (!msg)

++		return -ENOMEM;

++

++	/* Construct send-back message header */

++	reply = genlmsg_put(msg, info->snd_portid, info->snd_seq,

++			    &mt7530_nl_family, 0, cmd);

++	if (!reply) {

++		nlmsg_free(msg);

++		return -EINVAL;

++	}

++

++	*skbp = msg;

++	return 0;

++}

++

++static int mt7530_nl_send_reply(struct sk_buff *skb, struct genl_info *info)

++{

++	struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));

++	void *reply = genlmsg_data(genlhdr);

++

++	/* Finalize a generic netlink message (update message header) */

++	genlmsg_end(skb, reply);

++

++	/* reply to a request */

++	return genlmsg_reply(skb, info);

++}

++

++static s32 mt7530_nl_get_s32(struct genl_info *info, enum mt7530_attr attr,

++			     s32 defval)

++{

++	struct nlattr *na;

++

++	na = info->attrs[attr];

++	if (na)

++		return nla_get_s32(na);

++

++	return defval;

++}

++

++static int mt7530_nl_get_u32(struct genl_info *info, enum mt7530_attr attr,

++			     u32 *val)

++{

++	struct nlattr *na;

++

++	na = info->attrs[attr];

++	if (na) {

++		*val = nla_get_u32(na);

++		return 0;

++	}

++

++	return -1;

++}

++

++static int mt7530_nl_reply_read(struct genl_info *info)

++{

++	struct sk_buff *rep_skb = NULL;

++	s32 phy, devad, reg;

++	int value;

++	int ret = 0;

++

++	phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);

++	devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);

++	reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);

++

++	if (reg < 0)

++		goto err;

++

++	ret = mt7530_nl_prepare_reply(info, MT7530_CMD_READ, &rep_skb);

++	if (ret < 0)

++		goto err;

++

++	if (phy >= 0) {

++		if (devad < 0)

++			value = mt7531_ind_c22_phy_read(sw_priv, phy, reg);

++		else

++			value = mt7531_ind_c45_phy_read(sw_priv, phy, devad, reg);

++	} else

++		value = mt7530_read(sw_priv, reg);

++

++	ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);

++	if (ret < 0)

++		goto err;

++

++	ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);

++	if (ret < 0)

++		goto err;

++

++	return mt7530_nl_send_reply(rep_skb, info);

++

++err:

++	if (rep_skb)

++		nlmsg_free(rep_skb);

++

++	return ret;

++}

++

++static int mt7530_nl_reply_write(struct genl_info *info)

++{

++	struct sk_buff *rep_skb = NULL;

++	s32 phy, devad, reg;

++	u32 value;

++	int ret = 0;

++

++	phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);

++	devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);

++	reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);

++

++	if (mt7530_nl_get_u32(info, MT7530_ATTR_TYPE_VAL, &value))

++		goto err;

++

++	if (reg < 0)

++		goto err;

++

++	ret = mt7530_nl_prepare_reply(info, MT7530_CMD_WRITE, &rep_skb);

++	if (ret < 0)

++		goto err;

++

++	if (phy >= 0) {

++		if (devad < 0)

++			mt7531_ind_c22_phy_write(sw_priv, phy, reg, value);

++		else

++			mt7531_ind_c45_phy_write(sw_priv, phy, devad, reg, value);

++	} else

++		mt7530_write(sw_priv, reg, value);

++

++	ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);

++	if (ret < 0)

++		goto err;

++

++	ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);

++	if (ret < 0)

++		goto err;

++

++	return mt7530_nl_send_reply(rep_skb, info);

++

++err:

++	if (rep_skb)

++		nlmsg_free(rep_skb);

++

++	return ret;

++}

++

++static const enum mt7530_attr mt7530_nl_cmd_read_attrs[] = {

++	MT7530_ATTR_TYPE_REG

++};

++

++static const enum mt7530_attr mt7530_nl_cmd_write_attrs[] = {

++	MT7530_ATTR_TYPE_REG,

++	MT7530_ATTR_TYPE_VAL

++};

++

++static const struct mt7530_nl_cmd_item mt7530_nl_cmds[] = {

++	{

++		.cmd = MT7530_CMD_READ,

++		.require_dev = true,

++		.process = mt7530_nl_reply_read,

++		.required_attrs = mt7530_nl_cmd_read_attrs,

++		.nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_read_attrs),

++	}, {

++		.cmd = MT7530_CMD_WRITE,

++		.require_dev = true,

++		.process = mt7530_nl_reply_write,

++		.required_attrs = mt7530_nl_cmd_write_attrs,

++		.nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_write_attrs),

++	}

++};

++

++static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info)

++{

++	struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);

++	const struct mt7530_nl_cmd_item *cmditem = NULL;

++	u32 sat_req_attrs = 0;

++	int i, ret;

++

++	for (i = 0; i < ARRAY_SIZE(mt7530_nl_cmds); i++) {

++		if (hdr->cmd == mt7530_nl_cmds[i].cmd) {

++			cmditem = &mt7530_nl_cmds[i];

++			break;

++		}

++	}

++

++	if (!cmditem) {

++		pr_info("mt7530-nl: unknown cmd %u\n", hdr->cmd);

++		return -EINVAL;

++	}

++

++	for (i = 0; i < cmditem->nr_required_attrs; i++) {

++		if (info->attrs[cmditem->required_attrs[i]])

++			sat_req_attrs++;

++	}

++

++	if (sat_req_attrs != cmditem->nr_required_attrs) {

++		pr_info("mt7530-nl: missing required attr(s) for cmd %u\n",

++			hdr->cmd);

++		return -EINVAL;

++	}

++

++	ret = cmditem->process(info);

++

++	mt7530_put();

++

++	return ret;

++}

++

++int mt7530_nl_init(struct mt7530_priv **priv)

++{

++	int ret;

++

++	pr_info("mt7530-nl: genl_register_family_with_ops \n");

++

++	sw_priv = *priv;

++	ret = genl_register_family(&mt7530_nl_family);

++	if (ret) {

++		return ret;

++	}

++

++	return 0;

++}

++

++void mt7530_nl_exit()

++{

++	sw_priv = NULL;

++	genl_unregister_family(&mt7530_nl_family);

++}

+Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.h
+===================================================================
+--- /dev/null
++++ linux-5.4.203/drivers/net/dsa/mt7530_nl.h
+@@ -0,0 +1,49 @@
++/* SPDX-License-Identifier: GPL-2.0-only */

++/*

++ * Copyright (c) 2018 MediaTek Inc.

++ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>

++ */

++

++#ifndef _MT753x_NL_H_

++#define _MT753x_NL_H_

++

++#define MT7530_DSA_GENL_NAME "mt753x_dsa"

++#define MT7530_GENL_VERSION		0x1

++

++enum mt7530_cmd {

++	MT7530_CMD_UNSPEC = 0,

++	MT7530_CMD_REQUEST,

++	MT7530_CMD_REPLY,

++	MT7530_CMD_READ,

++	MT7530_CMD_WRITE,

++

++	__MT7530_CMD_MAX,

++};

++

++enum mt7530_attr {

++	MT7530_ATTR_TYPE_UNSPEC = 0,

++	MT7530_ATTR_TYPE_MESG,

++	MT7530_ATTR_TYPE_PHY,

++	MT7530_ATTR_TYPE_DEVAD,

++	MT7530_ATTR_TYPE_REG,

++	MT7530_ATTR_TYPE_VAL,

++	MT7530_ATTR_TYPE_DEV_NAME,

++	MT7530_ATTR_TYPE_DEV_ID,

++

++	__MT7530_ATTR_TYPE_MAX,

++};

++

++#define MT7530_NR_ATTR_TYPE		(__MT7530_ATTR_TYPE_MAX - 1)

++

++struct mt7530_info {

++	struct mii_bus	*bus;

++	void __iomem *base;

++	int direct_access;

++};

++

++#ifdef __KERNEL__

++int  mt7530_nl_init(struct mt7530_priv **priv);

++void mt7530_nl_exit(void);

++#endif /* __KERNEL__ */

++

++#endif /* _MT7530_NL_H_ */

diff --git a/target/linux/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch b/target/linux/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch
new file mode 100644
index 0000000..7c468d8
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch
@@ -0,0 +1,360 @@
+Index: linux-5.4.203/drivers/net/dsa/mt7530.c
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
++++ linux-5.4.203/drivers/net/dsa/mt7530.c
+@@ -19,6 +19,7 @@
+ #include <linux/reset.h>
+ #include <linux/gpio/consumer.h>
+ #include <net/dsa.h>
++#include <linux/of_address.h>
+
+ #include "mt7530.h"
+ #include "mt7530_nl.h"
+@@ -170,28 +171,44 @@ core_clear(struct mt7530_priv *priv, u32
+ 	core_rmw(priv, reg, val, 0);
+ }
+
++static void
++mtk_w32(struct mt7530_priv *priv, u32 val, unsigned reg)
++{
++	__raw_writel(val, priv->base + reg);
++}
++
++static u32
++mtk_r32(struct mt7530_priv *priv, unsigned reg)
++{
++	return __raw_readl(priv->base + reg);
++}
++
+ static int
+ mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
+ {
+ 	struct mii_bus *bus = priv->bus;
+ 	u16 page, r, lo, hi;
+-	int ret;
+-
+-	page = (reg >> 6) & 0x3ff;
+-	r  = (reg >> 2) & 0xf;
+-	lo = val & 0xffff;
+-	hi = val >> 16;
+-
+-	/* MT7530 uses 31 as the pseudo port */
+-	ret = bus->write(bus, 0x1f, 0x1f, page);
+-	if (ret < 0)
+-		goto err;
++	int ret = 0;
+
+-	ret = bus->write(bus, 0x1f, r,  lo);
+-	if (ret < 0)
+-		goto err;
++	if (priv->direct_access){
++		mtk_w32(priv, val, reg);
++	} else {
++		page = (reg >> 6) & 0x3ff;
++		r  = (reg >> 2) & 0xf;
++		lo = val & 0xffff;
++		hi = val >> 16;
++
++		/* MT7530 uses 31 as the pseudo port */
++		ret = bus->write(bus, 0x1f, 0x1f, page);
++		if (ret < 0)
++			goto err;
++
++		ret = bus->write(bus, 0x1f, r,  lo);
++		if (ret < 0)
++			goto err;
+
+-	ret = bus->write(bus, 0x1f, 0x10, hi);
++		ret = bus->write(bus, 0x1f, 0x10, hi);
++	}
+ err:
+ 	if (ret < 0)
+ 		dev_err(&bus->dev,
+@@ -206,21 +223,25 @@ mt7530_mii_read(struct mt7530_priv *priv
+ 	u16 page, r, lo, hi;
+ 	int ret;
+
+-	page = (reg >> 6) & 0x3ff;
+-	r = (reg >> 2) & 0xf;
++	if (priv->direct_access){
++		return mtk_r32(priv, reg);
++	} else {
++		page = (reg >> 6) & 0x3ff;
++		r = (reg >> 2) & 0xf;
+
+-	/* MT7530 uses 31 as the pseudo port */
+-	ret = bus->write(bus, 0x1f, 0x1f, page);
+-	if (ret < 0) {
+-		dev_err(&bus->dev,
+-			"failed to read mt7530 register\n");
+-		return ret;
+-	}
++		/* MT7530 uses 31 as the pseudo port */
++		ret = bus->write(bus, 0x1f, 0x1f, page);
++		if (ret < 0) {
++			dev_err(&bus->dev,
++				"failed to read mt7530 register\n");
++			return ret;
++		}
+
+-	lo = bus->read(bus, 0x1f, r);
+-	hi = bus->read(bus, 0x1f, 0x10);
++		lo = bus->read(bus, 0x1f, r);
++		hi = bus->read(bus, 0x1f, 0x10);
+
+-	return (hi << 16) | (lo & 0xffff);
++		return (hi << 16) | (lo & 0xffff);
++	}
+ }
+
+ void
+@@ -1906,9 +1927,9 @@ mt7531_phy_supported(struct dsa_switch *
+ 		if (mt7531_is_rgmii_port(priv, port))
+ 			return phy_interface_mode_is_rgmii(state->interface);
+ 		fallthrough;
+-	case 6: /* 1st cpu port supports sgmii/8023z only */
+-		if (state->interface != PHY_INTERFACE_MODE_SGMII &&
+-		    !phy_interface_mode_is_8023z(state->interface))
++	case 6: /* 1st cpu port supports sgmii/8023z/usxgmii/10gkr */
++		if (state->interface != PHY_INTERFACE_MODE_SGMII && state->interface != PHY_INTERFACE_MODE_USXGMII &&
++		    state->interface != PHY_INTERFACE_MODE_10GKR && !phy_interface_mode_is_8023z(state->interface))
+ 			goto unsupported;
+ 		break;
+ 	default:
+@@ -2017,6 +2038,13 @@ static void mt7531_sgmii_validate(struct
+ 		phylink_set(supported, 1000baseX_Full);
+ 		phylink_set(supported, 2500baseX_Full);
+ 		phylink_set(supported, 2500baseT_Full);
++		phylink_set(supported, 10000baseKR_Full);
++		phylink_set(supported, 10000baseT_Full);
++		phylink_set(supported, 10000baseCR_Full);
++		phylink_set(supported, 10000baseSR_Full);
++		phylink_set(supported, 10000baseLR_Full);
++		phylink_set(supported, 10000baseLRM_Full);
++		phylink_set(supported, 10000baseER_Full);
+ 	}
+ }
+
+@@ -2165,6 +2193,8 @@ mt7531_mac_config(struct dsa_switch *ds,
+ 	case PHY_INTERFACE_MODE_NA:
+ 	case PHY_INTERFACE_MODE_1000BASEX:
+ 	case PHY_INTERFACE_MODE_2500BASEX:
++	case PHY_INTERFACE_MODE_USXGMII:
++	case PHY_INTERFACE_MODE_10GKR:
+ 		if (phylink_autoneg_inband(mode))
+ 			return -EINVAL;
+
+@@ -2302,8 +2332,8 @@ static void mt753x_phylink_mac_link_up(s
+ 	/* MT753x MAC works in 1G full duplex mode for all up-clocked
+ 	 * variants.
+ 	 */
+-	if (interface == PHY_INTERFACE_MODE_TRGMII ||
+-	    (phy_interface_mode_is_8023z(interface))) {
++	if (interface == PHY_INTERFACE_MODE_TRGMII || interface == PHY_INTERFACE_MODE_USXGMII ||
++	    interface == PHY_INTERFACE_MODE_10GKR || (phy_interface_mode_is_8023z(interface))) {
+ 		speed = SPEED_1000;
+ 		duplex = DUPLEX_FULL;
+ 	}
+@@ -2402,8 +2432,8 @@ mt753x_phylink_validate(struct dsa_switc
+
+ 	phylink_set_port_modes(mask);
+
+-	if (state->interface != PHY_INTERFACE_MODE_TRGMII ||
+-	    !phy_interface_mode_is_8023z(state->interface)) {
++	if (state->interface != PHY_INTERFACE_MODE_TRGMII || state->interface != PHY_INTERFACE_MODE_USXGMII ||
++	    state->interface != PHY_INTERFACE_MODE_10GKR || !phy_interface_mode_is_8023z(state->interface)) {
+ 		phylink_set(mask, 10baseT_Half);
+ 		phylink_set(mask, 10baseT_Full);
+ 		phylink_set(mask, 100baseT_Half);
+@@ -2607,6 +2637,66 @@ mt753x_phy_write(struct dsa_switch *ds,
+ 	return priv->info->phy_write(ds, port, regnum, val);
+ }
+
++static int
++mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
++{
++	return 0;
++}
++
++static int
++mt7988_setup(struct dsa_switch *ds)
++{
++	struct mt7530_priv *priv = ds->priv;
++	u32 unused_pm = 0;
++	int ret, i;
++
++	/* Reset the switch through internal reset */
++	mt7530_write(priv, MT7530_SYS_CTRL,
++		     SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST);
++
++	/* BPDU to CPU port */
++	mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
++		   BIT(MT7530_CPU_PORT));
++	mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
++		   MT753X_BPDU_CPU_ONLY);
++
++	/* Enable and reset MIB counters */
++	mt7530_mib_reset(ds);
++
++	for (i = 0; i < MT7530_NUM_PORTS; i++) {
++		/* Disable forwarding by default on all ports */
++		mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
++			   PCR_MATRIX_CLR);
++
++		mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
++
++		if (dsa_is_unused_port(ds, i))
++			unused_pm |= BIT(i);
++		else if (dsa_is_cpu_port(ds, i))
++			mt753x_cpu_port_enable(ds, i);
++		else
++			mt7530_port_disable(ds, i);
++
++		/* Enable consistent egress tag */
++		mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
++			   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
++	}
++
++	mt7531_phy_setup(ds);
++
++	/* Group and enable unused ports as a standalone dumb switch. */
++	setup_unused_ports(ds, unused_pm);
++
++	ds->configure_vlan_while_not_filtering = true;
++
++	/* Flush the FDB table */
++	ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
++	if (ret < 0)
++		return ret;
++
++	return 0;
++}
++
+ static const struct dsa_switch_ops mt7530_switch_ops = {
+ 	.get_tag_protocol	= mtk_get_tag_protocol,
+ 	.setup			= mt753x_setup,
+@@ -2676,12 +2766,28 @@ static const struct mt753x_info mt753x_t
+ 		.mac_pcs_an_restart = mt7531_sgmii_restart_an,
+ 		.mac_pcs_link_up = mt7531_sgmii_link_up_force,
+ 	},
++	[ID_MT7988] = {
++		.id = ID_MT7988,
++		.sw_setup = mt7988_setup,
++		.phy_read = mt7531_ind_phy_read,
++		.phy_write = mt7531_ind_phy_write,
++		.pad_setup = mt7988_pad_setup,
++		.cpu_port_config = mt7531_cpu_port_config,
++		.phy_mode_supported = mt7531_phy_supported,
++		.mac_port_validate = mt7531_mac_port_validate,
++		.mac_port_get_state = mt7531_phylink_mac_link_state,
++		.mac_port_config = mt7531_mac_config,
++		.mac_pcs_an_restart = mt7531_sgmii_restart_an,
++		.mac_pcs_link_up = mt7531_sgmii_link_up_force,
++	},
++
+ };
+
+ static const struct of_device_id mt7530_of_match[] = {
+ 	{ .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
+ 	{ .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
+ 	{ .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
++	{ .compatible = "mediatek,mt7988", .data = &mt753x_table[ID_MT7988], },
+ 	{ /* sentinel */ },
+ };
+ MODULE_DEVICE_TABLE(of, mt7530_of_match);
+@@ -2691,6 +2797,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ {
+ 	struct mt7530_priv *priv;
+ 	struct device_node *dn;
++	struct device_node *switch_node = NULL;
+ 	int ret;
+
+ 	dn = mdiodev->dev.of_node;
+@@ -2760,6 +2867,16 @@ mt7530_probe(struct mdio_device *mdiodev
+ 		}
+ 	}
+
++	switch_node = of_find_node_by_name(NULL, "switch0");
++	if(switch_node) {
++		priv->base = of_iomap(switch_node, 0);
++		if(priv->base == NULL){
++			dev_err(&mdiodev->dev, "of_iomap failed\n");
++			return -ENOMEM;
++		}
++		priv->direct_access = 1;
++	}
++
+ 	priv->bus = mdiodev->bus;
+ 	priv->dev = &mdiodev->dev;
+ 	priv->ds->priv = priv;
+@@ -2768,9 +2885,12 @@ mt7530_probe(struct mdio_device *mdiodev
+ 	dev_set_drvdata(&mdiodev->dev, priv);
+
+ 	ret = dsa_register_switch(priv->ds);
+-	if (ret)
+-		return ret;
+-
++	if (ret) {
++		if(priv->base)
++			iounmap(priv->base);
++
++		return ret;
++	}
+ 	mt7530_nl_init(&priv);
+
+ 	return 0;
+@@ -2795,6 +2915,9 @@ mt7530_remove(struct mdio_device *mdiode
+ 	dsa_unregister_switch(priv->ds);
+ 	mutex_destroy(&priv->reg_mutex);
+
++	if(priv->base)
++		iounmap(priv->base);
++
+ 	mt7530_nl_exit();
+ }
+
+Index: linux-5.4.203/drivers/net/dsa/mt7530.h
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
++++ linux-5.4.203/drivers/net/dsa/mt7530.h
+@@ -16,6 +16,7 @@ enum mt753x_id {
+ 	ID_MT7530 = 0,
+ 	ID_MT7621 = 1,
+ 	ID_MT7531 = 2,
++	ID_MT7988 = 3,
+ };
+
+ #define	NUM_TRGMII_CTRL			5
+@@ -51,11 +52,11 @@ enum mt753x_id {
+ #define  MT7531_MIRROR_PORT_SET(x)	(((x) & MIRROR_MASK) << 16)
+ #define  MT7531_CPU_PMAP_MASK		GENMASK(7, 0)
+
+-#define MT753X_MIRROR_REG(id)		(((id) == ID_MT7531) ? \
++#define MT753X_MIRROR_REG(id)		((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ 					 MT7531_CFC : MT7530_MFC)
+-#define MT753X_MIRROR_EN(id)		(((id) == ID_MT7531) ? \
++#define MT753X_MIRROR_EN(id)		((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ 					 MT7531_MIRROR_EN : MIRROR_EN)
+-#define MT753X_MIRROR_MASK(id)		(((id) == ID_MT7531) ? \
++#define MT753X_MIRROR_MASK(id)		((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ 					 MT7531_MIRROR_MASK : MIRROR_MASK)
+
+ /* Registers for BPDU and PAE frame control*/
+@@ -261,7 +262,7 @@ enum mt7530_vlan_port_attr {
+ 					 MT7531_FORCE_DPX | \
+ 					 MT7531_FORCE_RX_FC | \
+ 					 MT7531_FORCE_TX_FC)
+-#define  PMCR_FORCE_MODE_ID(id)		(((id) == ID_MT7531) ? \
++#define  PMCR_FORCE_MODE_ID(id)		((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ 					 MT7531_FORCE_MODE : \
+ 					 PMCR_FORCE_MODE)
+ #define  PMCR_LINK_SETTINGS_MASK	(PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
+@@ -733,6 +734,8 @@ struct mt7530_priv {
+ 	struct regulator	*core_pwr;
+ 	struct regulator	*io_pwr;
+ 	struct gpio_desc	*reset;
++	void  __iomem *base;
++	int   direct_access;
+ 	const struct mt753x_info *info;
+ 	unsigned int		id;
+ 	bool			mcm;
diff --git a/target/linux/mediatek/patches-5.4/750-add-mdio-bus-for-phy-node.patch b/target/linux/mediatek/patches-5.4/750-add-mdio-bus-for-phy-node.patch
new file mode 100644
index 0000000..5a130b1
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/750-add-mdio-bus-for-phy-node.patch
@@ -0,0 +1,165 @@
+Index: linux-5.4.203/drivers/net/dsa/mt7530.c
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
++++ linux-5.4.203/drivers/net/dsa/mt7530.c
+@@ -847,6 +847,132 @@ mt7531_ind_phy_write(struct dsa_switch *
+ 	return ret;
+ }
+
++static int mt753x_mdio_read(struct mii_bus *bus, int addr, int regnum)
++{
++	struct mt7530_priv *priv = bus->priv;
++	struct mt7530_dummy_poll p;
++	int ret;
++	u32 val;
++
++	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
++
++	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	val = MT7531_MDIO_CL22_READ | MT7531_MDIO_PHY_ADDR(addr) |
++		  MT7531_MDIO_REG_ADDR(regnum);
++
++	mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	ret = val & MT7531_MDIO_RW_DATA_MASK;
++out:
++	mutex_unlock(&priv->bus->mdio_lock);
++
++	return ret;
++}
++
++static int mt753x_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
++{
++	struct mt7530_priv *priv = bus->priv;
++	struct mt7530_dummy_poll p;
++	int ret;
++	u32 reg;
++
++	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
++
++	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
++				 !(reg & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++	reg = MT7531_MDIO_CL22_WRITE | MT7531_MDIO_PHY_ADDR(addr) |
++		  MT7531_MDIO_REG_ADDR(regnum) | val;
++
++	mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
++
++	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
++				 !(reg & MT7531_PHY_ACS_ST), 20, 100000);
++	if (ret < 0) {
++		dev_err(priv->dev, "poll timeout\n");
++		goto out;
++	}
++
++out:
++	mutex_unlock(&priv->bus->mdio_lock);
++
++	return ret;
++}
++
++static int mt753x_mdio_init(struct mt7530_priv *priv)
++{
++	struct device_node *dn;
++	struct device_node *mii_np;
++	int ret;
++
++	dn = priv->dev->of_node;
++
++	mii_np = of_get_child_by_name(dn, "mdio-bus");
++	if (!mii_np) {
++		ret = -ENODEV;
++		goto err_put_node;
++	}
++
++	if (!of_device_is_available(mii_np)) {
++		ret = -ENODEV;
++		goto err_put_node;
++	}
++
++	priv->gbus = devm_mdiobus_alloc(priv->dev);
++	if (!priv->gbus) {
++		ret = -ENOMEM;
++		goto err_put_node;
++	}
++	priv->gbus->name = "mt753x_mdio";
++	priv->gbus->read = mt753x_mdio_read;
++	priv->gbus->write = mt753x_mdio_write;
++	priv->gbus->priv = priv;
++	priv->gbus->parent = priv->dev;
++
++	if(snprintf(priv->gbus->id, MII_BUS_ID_SIZE, "%s@%s", mii_np->name, dn->name) < 0) {
++		ret = -ENOMEM;
++		goto err_put_node;
++	}
++
++	ret = of_mdiobus_register(priv->gbus, mii_np);
++	if (ret)
++		priv->gbus = NULL;
++
++err_put_node:
++	of_node_put(mii_np);
++
++	return ret;
++}
++
++static void mt753x_mdio_exit(struct mt7530_priv *priv)
++{
++	if (!priv->gbus)
++		return;
++
++	mdiobus_unregister(priv->gbus);
++}
++
+ static void
+ mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ 		   uint8_t *data)
+@@ -2892,6 +3018,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ 		return ret;
+ 	}
+ 	mt7530_nl_init(&priv);
++	mt753x_mdio_init(priv);
+
+ 	return 0;
+ }
+@@ -2919,6 +3046,7 @@ mt7530_remove(struct mdio_device *mdiode
+ 		iounmap(priv->base);
+
+ 	mt7530_nl_exit();
++	mt753x_mdio_exit(priv);
+ }
+
+ static struct mdio_driver mt7530_mdio_driver = {
+Index: linux-5.4.203/drivers/net/dsa/mt7530.h
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
++++ linux-5.4.203/drivers/net/dsa/mt7530.h
+@@ -730,6 +730,7 @@ struct mt7530_priv {
+ 	struct device		*dev;
+ 	struct dsa_switch	*ds;
+ 	struct mii_bus		*bus;
++	struct mii_bus		*gbus;
+ 	struct reset_control	*rstc;
+ 	struct regulator	*core_pwr;
+ 	struct regulator	*io_pwr;
diff --git a/target/linux/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch b/target/linux/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
new file mode 100644
index 0000000..c20e930
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
@@ -0,0 +1,142 @@
+diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c
+index 8c51131..e77092c 100644
+--- a/drivers/phy/mediatek/phy-mtk-xsphy.c
++++ b/drivers/phy/mediatek/phy-mtk-xsphy.c
+@@ -12,10 +12,12 @@
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/iopoll.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
++#include <linux/regmap.h>
+ 
+ /* u2 phy banks */
+ #define SSUSB_SIFSLV_MISC		0x000
+@@ -88,12 +90,22 @@
+ #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 xsphy_instance {
+ 	struct phy *phy;
+ 	void __iomem *port_base;
+ 	struct clk *ref_clk;	/* reference clock of anolog phy */
+ 	u32 index;
+ 	u32 type;
++	struct regmap *type_sw;
++	u32 type_sw_reg;
++	u32 type_sw_index;
+ 	/* only for HQA test */
+ 	int efuse_intr;
+ 	int efuse_tx_imp;
+@@ -365,6 +377,62 @@ static void u3_phy_props_set(struct mtk_xsphy *xsphy,
+ 	}
+ }
+ 
++/* type switch for usb3/pcie/sgmii */
++static int phy_type_syscon_get(struct xsphy_instance *instance,
++			       struct device_node *dn)
++{
++	struct of_phandle_args args;
++	int ret;
++
++	/* type switch function is optional */
++	if (!of_property_read_bool(dn, "mediatek,syscon-type"))
++		return 0;
++
++	ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
++					       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.np);
++	of_node_put(args.np);
++	dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
++		 instance->type_sw_reg, instance->type_sw_index);
++
++	return PTR_ERR_OR_ZERO(instance->type_sw);
++}
++
++static int phy_type_set(struct 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_phy_init(struct phy *phy)
+ {
+ 	struct xsphy_instance *inst = phy_get_drvdata(phy);
+@@ -385,6 +453,10 @@ static int mtk_phy_init(struct phy *phy)
+ 	case PHY_TYPE_USB3:
+ 		u3_phy_props_set(xsphy, inst);
+ 		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_unprepare(inst->ref_clk);
+@@ -463,12 +535,15 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+ 
+ 	inst->type = args->args[0];
+ 	if (!(inst->type == PHY_TYPE_USB2 ||
+-	      inst->type == PHY_TYPE_USB3)) {
++	      inst->type == PHY_TYPE_USB3 ||
++	      inst->type == PHY_TYPE_PCIE ||
++	      inst->type == PHY_TYPE_SGMII)) {
+ 		dev_err(dev, "unsupported phy type: %d\n", inst->type);
+ 		return ERR_PTR(-EINVAL);
+ 	}
+ 
+ 	phy_parse_property(xsphy, inst);
++	phy_type_set(inst);
+ 
+ 	return inst->phy;
+ }
+@@ -575,6 +650,10 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
+ 			retval = PTR_ERR(inst->ref_clk);
+ 			goto put_child;
+ 		}
++
++		retval = phy_type_syscon_get(inst, child_np);
++		if (retval)
++			goto put_child;
+ 	}
+ 
+ 	provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
diff --git a/target/linux/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch b/target/linux/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
new file mode 100644
index 0000000..e82e1bc
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
@@ -0,0 +1,57 @@
+From 5f8c12ffa661e3707790f59827a45ff4102f2886 Mon Sep 17 00:00:00 2001
+From: Zhanyong Wang <zhanyong.wang@mediatek.com>
+Date: Mon, 15 Aug 2022 14:13:50 +0800
+Subject: [PATCH] xHCI: change compliance mode de-emphasis default as gen1
+
+Port0 is using Gen2 Phy for 10GHz, and Port0 is running
+on 5GHz actually. hence to change compliance mode de-
+emphasis default as Gen1.
+
+Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
+---
+ drivers/usb/host/xhci-mtk.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
+index 2a4b73a658f9..b1201fb65fd6 100644
+--- a/drivers/usb/host/xhci-mtk.c
++++ b/drivers/usb/host/xhci-mtk.c
+@@ -24,6 +24,11 @@
+ #include "xhci-mtk.h"
+ #include "xhci-mtk-test.h"
+ 
++/* COMPLIANCE_CP5_CP7_TXDEEMPH_10G register */
++#define COMPLIANCE_CP5_CP7_TXDEEMPH_10G  0x2428
++#define CP5_CP7_TXDEEMPH_10G		 GENMASK(17, 0)
++#define CP5_CP7_TXDEEMPH_10G_VAL(val)	((val) & 0x03FFFF)
++
+ /* ip_pw_ctrl0 register */
+ #define CTRL0_IP_SW_RST	BIT(0)
+ 
+@@ -415,6 +420,7 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
+ {
+ 	struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
+ 	int ret;
++	u32 val;
+ 
+ 	if (usb_hcd_is_primary_hcd(hcd)) {
+ 		ret = xhci_mtk_ssusb_config(mtk);
+@@ -432,6 +438,15 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
+ 			return ret;
+ 	}
+ 
++	/* change COMPLIANCE_CP5_CP7_TXDEEMPH_10G  as Gen1 instead Gen2 */
++	if (hcd->rsrc_start == 0x11190000ULL) {
++		val  = readl(mtk->hcd->regs + COMPLIANCE_CP5_CP7_TXDEEMPH_10G);
++		val &= ~CP5_CP7_TXDEEMPH_10G;
++		val |= 0x00001;
++		val = CP5_CP7_TXDEEMPH_10G_VAL(val);
++		writel(val, mtk->hcd->regs + COMPLIANCE_CP5_CP7_TXDEEMPH_10G);
++	}
++
+ 	return ret;
+ }
+ 
+-- 
+2.18.0
+