[openwrt/openwrt] generic: add support for MediaTek NETSYS v3

LEDE Commits lede-commits at lists.infradead.org
Thu May 25 01:40:24 PDT 2023


dangole pushed a commit to openwrt/openwrt.git, branch openwrt-23.05:
https://git.openwrt.org/5970f5d02764fa414660f773e8e7556c69577195

commit 5970f5d02764fa414660f773e8e7556c69577195
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Sun Apr 30 17:16:12 2023 +0100

    generic: add support for MediaTek NETSYS v3
    
    In order to support Ethernet on the MT7988 SoC add support for NETSYS v3
    as well as new paths and USXGMII SerDes to the mtk_eth_soc driver.
    
    Signed-off-by: Daniel Golle <daniel at makrotopia.org>
    (cherry picked from commit 6983a215d9d1966f95bc5b1c0045c200948b2079)
---
 ...t-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch |  223 +++
 ...t-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch |  181 +++
 ...t-mtk_eth_soc-rely-on-num_devs-and-remove.patch |  153 ++
 ...t-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch |  292 ++++
 ...t-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch |  197 +++
 ...et-mtk_eth_soc-add-support-for-MT7988-SoC.patch |  495 ++++++
 ...t-mtk_eth_soc-add-paths-and-SerDes-modes-.patch | 1671 ++++++++++++++++++++
 target/linux/mediatek/filogic/config-5.15          |    1 +
 target/linux/mediatek/mt7622/config-5.15           |    1 +
 ...t-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch |    8 +-
 ...-net-ethernet-mediatek-support-net-labels.patch |    4 +-
 11 files changed, 3220 insertions(+), 6 deletions(-)

diff --git a/target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch b/target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch
new file mode 100644
index 0000000000..621a7b0fcf
--- /dev/null
+++ b/target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch
@@ -0,0 +1,223 @@
+From 663fa1b7e0cb2c929008482014a70c6625caad75 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo at kernel.org>
+Date: Tue, 7 Mar 2023 15:55:13 +0000
+Subject: [PATCH 1/7] net: ethernet: mtk_eth_soc: add MTK_NETSYS_V1 capability
+ bit
+
+Introduce MTK_NETSYS_V1 bit in the device capabilities for
+MT7621/MT7622/MT7623/MT7628/MT7629 SoCs.
+Use !MTK_NETSYS_V1 instead of MTK_NETSYS_V2 in the driver codebase.
+This is a preliminary patch to introduce support for MT7988 SoC.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 +++++++-------
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 45 ++++++++++++---------
+ 2 files changed, 41 insertions(+), 34 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -597,7 +597,7 @@ static void mtk_set_queue_speed(struct m
+ 	      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
+ 	      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
+ 	      MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
+-	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+ 		val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
+ 
+ 	if (IS_ENABLED(CONFIG_SOC_MT7621)) {
+@@ -974,7 +974,7 @@ static bool mtk_rx_get_desc(struct mtk_e
+ 	rxd->rxd1 = READ_ONCE(dma_rxd->rxd1);
+ 	rxd->rxd3 = READ_ONCE(dma_rxd->rxd3);
+ 	rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
+-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
+ 		rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
+ 		rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
+ 	}
+@@ -1032,7 +1032,7 @@ static int mtk_init_fq_dma(struct mtk_et
+ 
+ 		txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
+ 		txd->txd4 = 0;
+-		if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) {
++		if (!MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V1)) {
+ 			txd->txd5 = 0;
+ 			txd->txd6 = 0;
+ 			txd->txd7 = 0;
+@@ -1221,7 +1221,7 @@ static void mtk_tx_set_dma_desc(struct n
+ 	struct mtk_mac *mac = netdev_priv(dev);
+ 	struct mtk_eth *eth = mac->hw;
+ 
+-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+ 		mtk_tx_set_dma_desc_v2(dev, txd, info);
+ 	else
+ 		mtk_tx_set_dma_desc_v1(dev, txd, info);
+@@ -1902,7 +1902,7 @@ static int mtk_poll_rx(struct napi_struc
+ 			break;
+ 
+ 		/* find out which mac the packet come from. values start at 1 */
+-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+ 			mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
+ 		else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
+ 			 !(trxd.rxd4 & RX_DMA_SPECIAL_TAG))
+@@ -1998,7 +1998,7 @@ static int mtk_poll_rx(struct napi_struc
+ 		skb->dev = netdev;
+ 		bytes += skb->len;
+ 
+-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
+ 			reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5);
+ 			hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY;
+ 			if (hash != MTK_RXD5_FOE_ENTRY)
+@@ -2023,7 +2023,7 @@ static int mtk_poll_rx(struct napi_struc
+ 		/* When using VLAN untagging in combination with DSA, the
+ 		 * hardware treats the MTK special tag as a VLAN and untags it.
+ 		 */
+-		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
++		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) &&
+ 		    (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) {
+ 			unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0);
+ 
+@@ -2328,7 +2328,7 @@ static int mtk_tx_alloc(struct mtk_eth *
+ 		txd->txd2 = next_ptr;
+ 		txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
+ 		txd->txd4 = 0;
+-		if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) {
++		if (!MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V1)) {
+ 			txd->txd5 = 0;
+ 			txd->txd6 = 0;
+ 			txd->txd7 = 0;
+@@ -2381,7 +2381,7 @@ static int mtk_tx_alloc(struct mtk_eth *
+ 			      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
+ 			      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
+ 			      MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
+-			if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+ 				val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
+ 			mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
+ 			ofs += MTK_QTX_OFFSET;
+@@ -2515,7 +2515,7 @@ static int mtk_rx_alloc(struct mtk_eth *
+ 
+ 		rxd->rxd3 = 0;
+ 		rxd->rxd4 = 0;
+-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
+ 			rxd->rxd5 = 0;
+ 			rxd->rxd6 = 0;
+ 			rxd->rxd7 = 0;
+@@ -3063,7 +3063,7 @@ static int mtk_start_dma(struct mtk_eth
+ 		       MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO |
+ 		       MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE;
+ 
+-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+ 			val |= MTK_MUTLI_CNT | MTK_RESV_BUF |
+ 			       MTK_WCOMP_EN | MTK_DMAD_WR_WDONE |
+ 			       MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN;
+@@ -3475,7 +3475,7 @@ static void mtk_hw_reset(struct mtk_eth
+ {
+ 	u32 val;
+ 
+-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
+ 		regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0);
+ 		val = RSTCTRL_PPE0_V2;
+ 	} else {
+@@ -3487,7 +3487,7 @@ static void mtk_hw_reset(struct mtk_eth
+ 
+ 	ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val);
+ 
+-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+ 		regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN,
+ 			     0x3ffffff);
+ }
+@@ -3683,7 +3683,7 @@ static int mtk_hw_init(struct mtk_eth *e
+ 	else
+ 		mtk_hw_reset(eth);
+ 
+-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
+ 		/* Set FE to PDMAv2 if necessary */
+ 		val = mtk_r32(eth, MTK_FE_GLO_MISC);
+ 		mtk_w32(eth,  val | BIT(4), MTK_FE_GLO_MISC);
+@@ -3720,7 +3720,7 @@ static int mtk_hw_init(struct mtk_eth *e
+ 	 */
+ 	val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+ 	mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+-	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
+ 		val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
+ 		mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -816,6 +816,7 @@ enum mkt_eth_capabilities {
+ 	MTK_SHARED_INT_BIT,
+ 	MTK_TRGMII_MT7621_CLK_BIT,
+ 	MTK_QDMA_BIT,
++	MTK_NETSYS_V1_BIT,
+ 	MTK_NETSYS_V2_BIT,
+ 	MTK_SOC_MT7628_BIT,
+ 	MTK_RSTCTRL_PPE1_BIT,
+@@ -851,6 +852,7 @@ enum mkt_eth_capabilities {
+ #define MTK_SHARED_INT		BIT(MTK_SHARED_INT_BIT)
+ #define MTK_TRGMII_MT7621_CLK	BIT(MTK_TRGMII_MT7621_CLK_BIT)
+ #define MTK_QDMA		BIT(MTK_QDMA_BIT)
++#define MTK_NETSYS_V1		BIT(MTK_NETSYS_V1_BIT)
+ #define MTK_NETSYS_V2		BIT(MTK_NETSYS_V2_BIT)
+ #define MTK_SOC_MT7628		BIT(MTK_SOC_MT7628_BIT)
+ #define MTK_RSTCTRL_PPE1	BIT(MTK_RSTCTRL_PPE1_BIT)
+@@ -913,25 +915,30 @@ enum mkt_eth_capabilities {
+ 
+ #define MTK_HAS_CAPS(caps, _x)		(((caps) & (_x) & ~(MTK_CAP_MASK)) == (_x))
+ 
+-#define MT7621_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
+-		      MTK_GMAC2_RGMII | MTK_SHARED_INT | \
+-		      MTK_TRGMII_MT7621_CLK | MTK_QDMA)
+-
+-#define MT7622_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | MTK_GMAC2_RGMII | \
+-		      MTK_GMAC2_SGMII | MTK_GDM1_ESW | \
+-		      MTK_MUX_GDM1_TO_GMAC1_ESW | \
+-		      MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_QDMA)
+-
+-#define MT7623_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII | \
+-		      MTK_QDMA)
+-
+-#define MT7628_CAPS  (MTK_SHARED_INT | MTK_SOC_MT7628)
+-
+-#define MT7629_CAPS  (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
+-		      MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \
+-		      MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
+-		      MTK_MUX_U3_GMAC2_TO_QPHY | \
+-		      MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
++#define MT7621_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII |	\
++		      MTK_GMAC2_RGMII | MTK_SHARED_INT |	\
++		      MTK_TRGMII_MT7621_CLK | MTK_QDMA |	\
++		      MTK_NETSYS_V1)
++
++#define MT7622_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII |	\
++		      MTK_GMAC2_RGMII | MTK_GMAC2_SGMII |	\
++		      MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW |\
++		      MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII |	\
++		      MTK_QDMA | MTK_NETSYS_V1)
++
++#define MT7623_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII |	\
++		      MTK_GMAC2_RGMII | MTK_QDMA |		\
++		      MTK_NETSYS_V1)
++
++#define MT7628_CAPS  (MTK_SHARED_INT | MTK_SOC_MT7628 |		\
++		      MTK_NETSYS_V1)
++
++#define MT7629_CAPS  (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII |	\
++		      MTK_GMAC2_GEPHY | MTK_GDM1_ESW |		\
++		      MTK_MUX_GMAC2_GMAC0_TO_GEPHY | MTK_QDMA |	\
++		      MTK_MUX_U3_GMAC2_TO_QPHY | MTK_NETSYS_V1 |\
++		      MTK_MUX_GDM1_TO_GMAC1_ESW |		\
++		      MTK_MUX_GMAC12_TO_GEPHY_SGMII)
+ 
+ #define MT7981_CAPS  (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
+ 		      MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
diff --git a/target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch b/target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch
new file mode 100644
index 0000000000..a8debc41bf
--- /dev/null
+++ b/target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch
@@ -0,0 +1,181 @@
+From 5af2b2dc4d6ba0ff7696e79f18e5b2bf862194eb Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo at kernel.org>
+Date: Tue, 7 Mar 2023 15:55:24 +0000
+Subject: [PATCH 2/7] net: ethernet: mtk_eth_soc: move MAX_DEVS in mtk_soc_data
+
+This is a preliminary patch to add MT7988 SoC support since it runs 3
+macs instead of 2.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 +++++++++++++++++++--
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 +++----
+ 2 files changed, 36 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -3989,7 +3989,10 @@ static void mtk_sgmii_destroy(struct mtk
+ {
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAX_DEVS; i++)
++	if (!eth->sgmii_pcs)
++		return;
++
++	for (i = 0; i < eth->soc->num_devs; i++)
+ 		mtk_pcs_lynxi_destroy(eth->sgmii_pcs[i]);
+ }
+ 
+@@ -4432,7 +4435,12 @@ static int mtk_sgmii_init(struct mtk_eth
+ 	u32 flags;
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAX_DEVS; i++) {
++	eth->sgmii_pcs = devm_kzalloc(eth->dev,
++				      sizeof(*eth->sgmii_pcs) *
++				      eth->soc->num_devs,
++				      GFP_KERNEL);
++
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		np = of_parse_phandle(eth->dev->of_node, "mediatek,sgmiisys", i);
+ 		if (!np)
+ 			break;
+@@ -4477,6 +4485,18 @@ static int mtk_probe(struct platform_dev
+ 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
+ 		eth->ip_align = NET_IP_ALIGN;
+ 
++	eth->netdev = devm_kzalloc(eth->dev,
++				   sizeof(*eth->netdev) * eth->soc->num_devs,
++				   GFP_KERNEL);
++	if (!eth->netdev)
++		return -ENOMEM;
++
++	eth->mac = devm_kzalloc(eth->dev,
++				sizeof(*eth->mac) * eth->soc->num_devs,
++				GFP_KERNEL);
++	if (!eth->mac)
++		return -ENOMEM;
++
+ 	spin_lock_init(&eth->page_lock);
+ 	spin_lock_init(&eth->tx_irq_lock);
+ 	spin_lock_init(&eth->rx_irq_lock);
+@@ -4662,7 +4682,7 @@ static int mtk_probe(struct platform_dev
+ 			goto err_free_dev;
+ 	}
+ 
+-	for (i = 0; i < MTK_MAX_DEVS; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!eth->netdev[i])
+ 			continue;
+ 
+@@ -4739,6 +4759,7 @@ static const struct mtk_soc_data mt2701_
+ 	.hw_features = MTK_HW_FEATURES,
+ 	.required_clks = MT7623_CLKS_BITMAP,
+ 	.required_pctl = true,
++	.num_devs = 2,
+ 	.txrx = {
+ 		.txd_size = sizeof(struct mtk_tx_dma),
+ 		.rxd_size = sizeof(struct mtk_rx_dma),
+@@ -4757,6 +4778,7 @@ static const struct mtk_soc_data mt7621_
+ 	.required_pctl = false,
+ 	.offload_version = 1,
+ 	.hash_offset = 2,
++	.num_devs = 2,
+ 	.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
+ 	.txrx = {
+ 		.txd_size = sizeof(struct mtk_tx_dma),
+@@ -4778,6 +4800,7 @@ static const struct mtk_soc_data mt7622_
+ 	.offload_version = 2,
+ 	.hash_offset = 2,
+ 	.has_accounting = true,
++	.num_devs = 2,
+ 	.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
+ 	.txrx = {
+ 		.txd_size = sizeof(struct mtk_tx_dma),
+@@ -4797,6 +4820,7 @@ static const struct mtk_soc_data mt7623_
+ 	.required_pctl = true,
+ 	.offload_version = 1,
+ 	.hash_offset = 2,
++	.num_devs = 2,
+ 	.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
+ 	.txrx = {
+ 		.txd_size = sizeof(struct mtk_tx_dma),
+@@ -4816,6 +4840,7 @@ static const struct mtk_soc_data mt7629_
+ 	.required_clks = MT7629_CLKS_BITMAP,
+ 	.required_pctl = false,
+ 	.has_accounting = true,
++	.num_devs = 2,
+ 	.txrx = {
+ 		.txd_size = sizeof(struct mtk_tx_dma),
+ 		.rxd_size = sizeof(struct mtk_rx_dma),
+@@ -4837,6 +4862,7 @@ static const struct mtk_soc_data mt7981_
+ 	.hash_offset = 4,
+ 	.foe_entry_size = sizeof(struct mtk_foe_entry),
+ 	.has_accounting = true,
++	.num_devs = 2,
+ 	.txrx = {
+ 		.txd_size = sizeof(struct mtk_tx_dma_v2),
+ 		.rxd_size = sizeof(struct mtk_rx_dma_v2),
+@@ -4856,6 +4882,7 @@ static const struct mtk_soc_data mt7986_
+ 	.required_pctl = false,
+ 	.offload_version = 2,
+ 	.hash_offset = 4,
++	.num_devs = 2,
+ 	.foe_entry_size = sizeof(struct mtk_foe_entry),
+ 	.has_accounting = true,
+ 	.txrx = {
+@@ -4874,6 +4901,7 @@ static const struct mtk_soc_data rt5350_
+ 	.hw_features = MTK_HW_FEATURES_MT7628,
+ 	.required_clks = MT7628_CLKS_BITMAP,
+ 	.required_pctl = false,
++	.num_devs = 2,
+ 	.txrx = {
+ 		.txd_size = sizeof(struct mtk_tx_dma),
+ 		.rxd_size = sizeof(struct mtk_rx_dma),
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1018,6 +1018,7 @@ struct mtk_reg_map {
+  * @required_pctl		A bool value to show whether the SoC requires
+  *				the extra setup for those pins used by GMAC.
+  * @hash_offset			Flow table hash offset.
++ * @num_devs			SoC number of macs.
+  * @foe_entry_size		Foe table entry size.
+  * @has_accounting		Bool indicating support for accounting of
+  *				offloaded flows.
+@@ -1036,6 +1037,7 @@ struct mtk_soc_data {
+ 	bool		required_pctl;
+ 	u8		offload_version;
+ 	u8		hash_offset;
++	u8		num_devs;
+ 	u16		foe_entry_size;
+ 	netdev_features_t hw_features;
+ 	bool		has_accounting;
+@@ -1051,9 +1053,6 @@ struct mtk_soc_data {
+ 
+ #define MTK_DMA_MONITOR_TIMEOUT		msecs_to_jiffies(1000)
+ 
+-/* currently no SoC has more than 2 macs */
+-#define MTK_MAX_DEVS			2
+-
+ /* struct mtk_eth -	This is the main datasructure for holding the state
+  *			of the driver
+  * @dev:		The device pointer
+@@ -1108,14 +1107,14 @@ struct mtk_eth {
+ 	spinlock_t			tx_irq_lock;
+ 	spinlock_t			rx_irq_lock;
+ 	struct net_device		dummy_dev;
+-	struct net_device		*netdev[MTK_MAX_DEVS];
+-	struct mtk_mac			*mac[MTK_MAX_DEVS];
++	struct net_device		**netdev;
++	struct mtk_mac			**mac;
+ 	int				irq[3];
+ 	u32				msg_enable;
+ 	unsigned long			sysclk;
+ 	struct regmap			*ethsys;
+ 	struct regmap			*infra;
+-	struct phylink_pcs		*sgmii_pcs[MTK_MAX_DEVS];
++	struct phylink_pcs		**sgmii_pcs;
+ 	struct regmap			*pctl;
+ 	bool				hwlro;
+ 	refcount_t			dma_refcnt;
diff --git a/target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch b/target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch
new file mode 100644
index 0000000000..d6b36bf636
--- /dev/null
+++ b/target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch
@@ -0,0 +1,153 @@
+From 4e35e80750b33727e606be9e7ce447bde2e0deb7 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo at kernel.org>
+Date: Tue, 7 Mar 2023 15:55:35 +0000
+Subject: [PATCH 3/7] net: ethernet: mtk_eth_soc: rely on num_devs and remove
+ MTK_MAC_COUNT
+
+Get rid of MTK_MAC_COUNT since it is a duplicated of eth->soc->num_devs.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 ++++++++++-----------
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h |  1 -
+ 2 files changed, 15 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -900,7 +900,7 @@ static void mtk_stats_update(struct mtk_
+ {
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!eth->mac[i] || !eth->mac[i]->hw_stats)
+ 			continue;
+ 		if (spin_trylock(&eth->mac[i]->hw_stats->stats_lock)) {
+@@ -1403,7 +1403,7 @@ static int mtk_queue_stopped(struct mtk_
+ {
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!eth->netdev[i])
+ 			continue;
+ 		if (netif_queue_stopped(eth->netdev[i]))
+@@ -1417,7 +1417,7 @@ static void mtk_wake_queue(struct mtk_et
+ {
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!eth->netdev[i])
+ 			continue;
+ 		netif_tx_wake_all_queues(eth->netdev[i]);
+@@ -1908,7 +1908,7 @@ static int mtk_poll_rx(struct napi_struc
+ 			 !(trxd.rxd4 & RX_DMA_SPECIAL_TAG))
+ 			mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1;
+ 
+-		if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
++		if (unlikely(mac < 0 || mac >= eth->soc->num_devs ||
+ 			     !eth->netdev[mac]))
+ 			goto release_desc;
+ 
+@@ -2937,7 +2937,7 @@ static void mtk_dma_free(struct mtk_eth
+ 	const struct mtk_soc_data *soc = eth->soc;
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++)
++	for (i = 0; i < soc->num_devs; i++)
+ 		if (eth->netdev[i])
+ 			netdev_reset_queue(eth->netdev[i]);
+ 	if (eth->scratch_ring) {
+@@ -3091,7 +3091,7 @@ static void mtk_gdm_config(struct mtk_et
+ 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
+ 		return;
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i));
+ 
+ 		/* default setup the forward port to send frame to PDMA */
+@@ -3704,7 +3704,7 @@ static int mtk_hw_init(struct mtk_eth *e
+ 	 * up with the more appropriate value when mtk_mac_config call is being
+ 	 * invoked.
+ 	 */
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		struct net_device *dev = eth->netdev[i];
+ 
+ 		mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i));
+@@ -3909,7 +3909,7 @@ static void mtk_pending_work(struct work
+ 	mtk_prepare_for_reset(eth);
+ 
+ 	/* stop all devices to make sure that dma is properly shut down */
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!eth->netdev[i] || !netif_running(eth->netdev[i]))
+ 			continue;
+ 
+@@ -3925,7 +3925,7 @@ static void mtk_pending_work(struct work
+ 	mtk_hw_init(eth, true);
+ 
+ 	/* restart DMA and enable IRQs */
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!test_bit(i, &restart))
+ 			continue;
+ 
+@@ -3953,7 +3953,7 @@ static int mtk_free_dev(struct mtk_eth *
+ {
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!eth->netdev[i])
+ 			continue;
+ 		free_netdev(eth->netdev[i]);
+@@ -3972,7 +3972,7 @@ static int mtk_unreg_dev(struct mtk_eth
+ {
+ 	int i;
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		struct mtk_mac *mac;
+ 		if (!eth->netdev[i])
+ 			continue;
+@@ -4277,7 +4277,7 @@ static int mtk_add_mac(struct mtk_eth *e
+ 	}
+ 
+ 	id = be32_to_cpup(_id);
+-	if (id >= MTK_MAC_COUNT) {
++	if (id >= eth->soc->num_devs) {
+ 		dev_err(eth->dev, "%d is not a valid mac id\n", id);
+ 		return -EINVAL;
+ 	}
+@@ -4407,7 +4407,7 @@ void mtk_eth_set_dma_device(struct mtk_e
+ 
+ 	rtnl_lock();
+ 
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		dev = eth->netdev[i];
+ 
+ 		if (!dev || !(dev->flags & IFF_UP))
+@@ -4734,7 +4734,7 @@ static int mtk_remove(struct platform_de
+ 	int i;
+ 
+ 	/* stop all devices to make sure that dma is properly shut down */
+-	for (i = 0; i < MTK_MAC_COUNT; i++) {
++	for (i = 0; i < eth->soc->num_devs; i++) {
+ 		if (!eth->netdev[i])
+ 			continue;
+ 		mtk_stop(eth->netdev[i]);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -33,7 +33,6 @@
+ #define MTK_TX_DMA_BUF_LEN_V2	0xffff
+ #define MTK_QDMA_RING_SIZE	2048
+ #define MTK_DMA_SIZE		512
+-#define MTK_MAC_COUNT		2
+ #define MTK_RX_ETH_HLEN		(VLAN_ETH_HLEN + ETH_FCS_LEN)
+ #define MTK_RX_HLEN		(NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
+ #define MTK_DMA_DUMMY_DESC	0xffffffff
diff --git a/target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch b/target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch
new file mode 100644
index 0000000000..80d729db17
--- /dev/null
+++ b/target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch
@@ -0,0 +1,292 @@
+From ab817f559d505329d8a413c7d29250f6d87d77a0 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo at kernel.org>
+Date: Tue, 7 Mar 2023 15:55:47 +0000
+Subject: [PATCH 4/7] net: ethernet: mtk_eth_soc: add MTK_NETSYS_V3 capability
+ bit
+
+Introduce MTK_NETSYS_V3 bit in the device capabilities.
+This is a preliminary patch to introduce support for MT7988 SoC.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 115 ++++++++++++++++----
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h |  44 +++++++-
+ 2 files changed, 134 insertions(+), 25 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -880,17 +880,32 @@ void mtk_stats_update_mac(struct mtk_mac
+ 			mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x20 + offs);
+ 		hw_stats->rx_flow_control_packets +=
+ 			mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x24 + offs);
+-		hw_stats->tx_skip +=
+-			mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs);
+-		hw_stats->tx_collisions +=
+-			mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs);
+-		hw_stats->tx_bytes +=
+-			mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs);
+-		stats =  mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs);
+-		if (stats)
+-			hw_stats->tx_bytes += (stats << 32);
+-		hw_stats->tx_packets +=
+-			mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs);
++
++		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++			hw_stats->tx_skip +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x50 + offs);
++			hw_stats->tx_collisions +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x54 + offs);
++			hw_stats->tx_bytes +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x40 + offs);
++			stats =  mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x44 + offs);
++			if (stats)
++				hw_stats->tx_bytes += (stats << 32);
++			hw_stats->tx_packets +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x48 + offs);
++		} else {
++			hw_stats->tx_skip +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs);
++			hw_stats->tx_collisions +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs);
++			hw_stats->tx_bytes +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs);
++			stats =  mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs);
++			if (stats)
++				hw_stats->tx_bytes += (stats << 32);
++			hw_stats->tx_packets +=
++				mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs);
++		}
+ 	}
+ 
+ 	u64_stats_update_end(&hw_stats->syncp);
+@@ -1192,7 +1207,10 @@ static void mtk_tx_set_dma_desc_v2(struc
+ 		data |= TX_DMA_LS0;
+ 	WRITE_ONCE(desc->txd3, data);
+ 
+-	data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
++	if (mac->id == MTK_GMAC3_ID)
++		data = PSE_GDM3_PORT;
++	else
++		data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
+ 	data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
+ 	WRITE_ONCE(desc->txd4, data);
+ 
+@@ -1203,6 +1221,9 @@ static void mtk_tx_set_dma_desc_v2(struc
+ 		/* tx checksum offload */
+ 		if (info->csum)
+ 			data |= TX_DMA_CHKSUM_V2;
++		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
++		    netdev_uses_dsa(dev))
++			data |= TX_DMA_SPTAG_V3;
+ 	}
+ 	WRITE_ONCE(desc->txd5, data);
+ 
+@@ -1268,8 +1289,13 @@ static int mtk_tx_map(struct sk_buff *sk
+ 	mtk_tx_set_dma_desc(dev, itxd, &txd_info);
+ 
+ 	itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
+-	itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
+-			  MTK_TX_FLAGS_FPORT1;
++	if (mac->id == MTK_GMAC1_ID)
++		itx_buf->flags |= MTK_TX_FLAGS_FPORT0;
++	else if (mac->id == MTK_GMAC2_ID)
++		itx_buf->flags |= MTK_TX_FLAGS_FPORT1;
++	else
++		itx_buf->flags |= MTK_TX_FLAGS_FPORT2;
++
+ 	setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
+ 		     k++);
+ 
+@@ -1317,8 +1343,13 @@ static int mtk_tx_map(struct sk_buff *sk
+ 				memset(tx_buf, 0, sizeof(*tx_buf));
+ 			tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
+ 			tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
+-			tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
+-					 MTK_TX_FLAGS_FPORT1;
++
++			if (mac->id == MTK_GMAC1_ID)
++				tx_buf->flags |= MTK_TX_FLAGS_FPORT0;
++			else if (mac->id == MTK_GMAC2_ID)
++				tx_buf->flags |= MTK_TX_FLAGS_FPORT1;
++			else
++				tx_buf->flags |= MTK_TX_FLAGS_FPORT2;
+ 
+ 			setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
+ 				     txd_info.size, k++);
+@@ -1902,11 +1933,24 @@ static int mtk_poll_rx(struct napi_struc
+ 			break;
+ 
+ 		/* find out which mac the packet come from. values start at 1 */
+-		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+-			mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
+-		else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
+-			 !(trxd.rxd4 & RX_DMA_SPECIAL_TAG))
++		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
++			u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5);
++
++			switch (val) {
++			case PSE_GDM1_PORT:
++			case PSE_GDM2_PORT:
++				mac = val - 1;
++				break;
++			case PSE_GDM3_PORT:
++				mac = MTK_GMAC3_ID;
++				break;
++			default:
++				break;
++			}
++		} else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
++			 !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) {
+ 			mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1;
++		}
+ 
+ 		if (unlikely(mac < 0 || mac >= eth->soc->num_devs ||
+ 			     !eth->netdev[mac]))
+@@ -2135,7 +2179,9 @@ static int mtk_poll_tx_qdma(struct mtk_e
+ 		tx_buf = mtk_desc_to_tx_buf(ring, desc,
+ 					    eth->soc->txrx.txd_size);
+ 		if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
+-			mac = 1;
++			mac = MTK_GMAC2_ID;
++		else if (tx_buf->flags & MTK_TX_FLAGS_FPORT2)
++			mac = MTK_GMAC3_ID;
+ 
+ 		if (!tx_buf->data)
+ 			break;
+@@ -3742,7 +3788,26 @@ static int mtk_hw_init(struct mtk_eth *e
+ 	mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4);
+ 	mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
+ 
+-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++		/* PSE should not drop port1, port8 and port9 packets */
++		mtk_w32(eth, 0x00000302, PSE_DROP_CFG);
++
++		/* GDM and CDM Threshold */
++		mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES);
++		mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
++
++		/* Disable GDM1 RX CRC stripping */
++		val = mtk_r32(eth, MTK_GDMA_FWD_CFG(0));
++		val &= ~MTK_GDMA_STRP_CRC;
++		mtk_w32(eth, val, MTK_GDMA_FWD_CFG(0));
++
++		/* PSE GDM3 MIB counter has incorrect hw default values,
++		 * so the driver ought to read clear the values beforehand
++		 * in case ethtool retrieve wrong mib values.
++		 */
++		for (i = 0; i < 0x80; i += 0x4)
++			mtk_r32(eth, reg_map->gdm1_cnt + 0x100 + i);
++	} else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ 		/* PSE should not drop port8 and port9 packets from WDMA Tx */
+ 		mtk_w32(eth, 0x00000300, PSE_DROP_CFG);
+ 
+@@ -4314,7 +4379,11 @@ static int mtk_add_mac(struct mtk_eth *e
+ 	}
+ 	spin_lock_init(&mac->hw_stats->stats_lock);
+ 	u64_stats_init(&mac->hw_stats->syncp);
+-	mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET;
++
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
++		mac->hw_stats->reg_offset = id * 0x80;
++	else
++		mac->hw_stats->reg_offset = id * 0x40;
+ 
+ 	/* phylink create */
+ 	err = of_get_phy_mode(np, &phy_mode);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -121,6 +121,7 @@
+ #define MTK_GDMA_ICS_EN		BIT(22)
+ #define MTK_GDMA_TCS_EN		BIT(21)
+ #define MTK_GDMA_UCS_EN		BIT(20)
++#define MTK_GDMA_STRP_CRC	BIT(16)
+ #define MTK_GDMA_TO_PDMA	0x0
+ #define MTK_GDMA_DROP_ALL       0x7777
+ 
+@@ -286,8 +287,6 @@
+ /* QDMA Interrupt grouping registers */
+ #define MTK_RLS_DONE_INT	BIT(0)
+ 
+-#define MTK_STAT_OFFSET		0x40
+-
+ /* QDMA TX NUM */
+ #define QID_BITS_V2(x)		(((x) & 0x3f) << 16)
+ #define MTK_QDMA_GMAC2_QID	8
+@@ -300,6 +299,8 @@
+ #define TX_DMA_CHKSUM_V2	(0x7 << 28)
+ #define TX_DMA_TSO_V2		BIT(31)
+ 
++#define TX_DMA_SPTAG_V3         BIT(27)
++
+ /* QDMA V2 descriptor txd4 */
+ #define TX_DMA_FPORT_SHIFT_V2	8
+ #define TX_DMA_FPORT_MASK_V2	0xf
+@@ -636,6 +637,7 @@ enum mtk_tx_flags {
+ 	 */
+ 	MTK_TX_FLAGS_FPORT0	= 0x04,
+ 	MTK_TX_FLAGS_FPORT1	= 0x08,
++	MTK_TX_FLAGS_FPORT2	= 0x10,
+ };
+ 
+ /* This enum allows us to identify how the clock is defined on the array of the
+@@ -721,6 +723,42 @@ enum mtk_dev_state {
+ 	MTK_RESETTING
+ };
+ 
++/* PSE Port Definition */
++enum mtk_pse_port {
++	PSE_ADMA_PORT = 0,
++	PSE_GDM1_PORT,
++	PSE_GDM2_PORT,
++	PSE_PPE0_PORT,
++	PSE_PPE1_PORT,
++	PSE_QDMA_TX_PORT,
++	PSE_QDMA_RX_PORT,
++	PSE_DROP_PORT,
++	PSE_WDMA0_PORT,
++	PSE_WDMA1_PORT,
++	PSE_TDMA_PORT,
++	PSE_NONE_PORT,
++	PSE_PPE2_PORT,
++	PSE_WDMA2_PORT,
++	PSE_EIP197_PORT,
++	PSE_GDM3_PORT,
++	PSE_PORT_MAX
++};
++
++/* GMAC Identifier */
++enum mtk_gmac_id {
++	MTK_GMAC1_ID = 0,
++	MTK_GMAC2_ID,
++	MTK_GMAC3_ID,
++	MTK_GMAC_ID_MAX
++};
++
++/* GDM Type */
++enum mtk_gdm_type {
++	MTK_GDM_TYPE = 0,
++	MTK_XGDM_TYPE,
++	MTK_GDM_TYPE_MAX
++};
++
+ enum mtk_tx_buf_type {
+ 	MTK_TYPE_SKB,
+ 	MTK_TYPE_XDP_TX,
+@@ -817,6 +855,7 @@ enum mkt_eth_capabilities {
+ 	MTK_QDMA_BIT,
+ 	MTK_NETSYS_V1_BIT,
+ 	MTK_NETSYS_V2_BIT,
++	MTK_NETSYS_V3_BIT,
+ 	MTK_SOC_MT7628_BIT,
+ 	MTK_RSTCTRL_PPE1_BIT,
+ 	MTK_U3_COPHY_V2_BIT,
+@@ -853,6 +892,7 @@ enum mkt_eth_capabilities {
+ #define MTK_QDMA		BIT(MTK_QDMA_BIT)
+ #define MTK_NETSYS_V1		BIT(MTK_NETSYS_V1_BIT)
+ #define MTK_NETSYS_V2		BIT(MTK_NETSYS_V2_BIT)
++#define MTK_NETSYS_V3		BIT(MTK_NETSYS_V3_BIT)
+ #define MTK_SOC_MT7628		BIT(MTK_SOC_MT7628_BIT)
+ #define MTK_RSTCTRL_PPE1	BIT(MTK_RSTCTRL_PPE1_BIT)
+ #define MTK_U3_COPHY_V2		BIT(MTK_U3_COPHY_V2_BIT)
diff --git a/target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch b/target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch
new file mode 100644
index 0000000000..bd26cca305
--- /dev/null
+++ b/target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch
@@ -0,0 +1,197 @@
+From 45b575fd9e6a455090820248bf1b98b1f2c7b6c8 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo at kernel.org>
+Date: Tue, 7 Mar 2023 15:56:00 +0000
+Subject: [PATCH 5/7] net: ethernet: mtk_eth_soc: convert caps in mtk_soc_data
+ struct to u64
+
+This is a preliminary patch to introduce support for MT7988 SoC.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_path.c | 22 +++----
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h  | 62 ++++++++++----------
+ 2 files changed, 42 insertions(+), 42 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c
+@@ -15,10 +15,10 @@
+ struct mtk_eth_muxc {
+ 	const char	*name;
+ 	int		cap_bit;
+-	int		(*set_path)(struct mtk_eth *eth, int path);
++	int		(*set_path)(struct mtk_eth *eth, u64 path);
+ };
+ 
+-static const char *mtk_eth_path_name(int path)
++static const char *mtk_eth_path_name(u64 path)
+ {
+ 	switch (path) {
+ 	case MTK_ETH_PATH_GMAC1_RGMII:
+@@ -40,7 +40,7 @@ static const char *mtk_eth_path_name(int
+ 	}
+ }
+ 
+-static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
++static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
+ {
+ 	bool updated = true;
+ 	u32 val, mask, set;
+@@ -71,7 +71,7 @@ static int set_mux_gdm1_to_gmac1_esw(str
+ 	return 0;
+ }
+ 
+-static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
++static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
+ {
+ 	unsigned int val = 0;
+ 	bool updated = true;
+@@ -94,7 +94,7 @@ static int set_mux_gmac2_gmac0_to_gephy(
+ 	return 0;
+ }
+ 
+-static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
++static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
+ {
+ 	unsigned int val = 0, mask = 0, reg = 0;
+ 	bool updated = true;
+@@ -125,7 +125,7 @@ static int set_mux_u3_gmac2_to_qphy(stru
+ 	return 0;
+ }
+ 
+-static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
++static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
+ {
+ 	unsigned int val = 0;
+ 	bool updated = true;
+@@ -163,7 +163,7 @@ static int set_mux_gmac1_gmac2_to_sgmii_
+ 	return 0;
+ }
+ 
+-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
++static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
+ {
+ 	unsigned int val = 0;
+ 	bool updated = true;
+@@ -218,7 +218,7 @@ static const struct mtk_eth_muxc mtk_eth
+ 	},
+ };
+ 
+-static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
++static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
+ {
+ 	int i, err = 0;
+ 
+@@ -249,7 +249,7 @@ out:
+ 
+ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
+ {
+-	int path;
++	u64 path;
+ 
+ 	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
+ 				MTK_ETH_PATH_GMAC2_SGMII;
+@@ -260,7 +260,7 @@ int mtk_gmac_sgmii_path_setup(struct mtk
+ 
+ int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
+ {
+-	int path = 0;
++	u64 path = 0;
+ 
+ 	if (mac_id == 1)
+ 		path = MTK_ETH_PATH_GMAC2_GEPHY;
+@@ -274,7 +274,7 @@ int mtk_gmac_gephy_path_setup(struct mtk
+ 
+ int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
+ {
+-	int path;
++	u64 path;
+ 
+ 	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
+ 				MTK_ETH_PATH_GMAC2_RGMII;
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -878,44 +878,44 @@ enum mkt_eth_capabilities {
+ };
+ 
+ /* Supported hardware group on SoCs */
+-#define MTK_RGMII		BIT(MTK_RGMII_BIT)
+-#define MTK_TRGMII		BIT(MTK_TRGMII_BIT)
+-#define MTK_SGMII		BIT(MTK_SGMII_BIT)
+-#define MTK_ESW			BIT(MTK_ESW_BIT)
+-#define MTK_GEPHY		BIT(MTK_GEPHY_BIT)
+-#define MTK_MUX			BIT(MTK_MUX_BIT)
+-#define MTK_INFRA		BIT(MTK_INFRA_BIT)
+-#define MTK_SHARED_SGMII	BIT(MTK_SHARED_SGMII_BIT)
+-#define MTK_HWLRO		BIT(MTK_HWLRO_BIT)
+-#define MTK_SHARED_INT		BIT(MTK_SHARED_INT_BIT)
+-#define MTK_TRGMII_MT7621_CLK	BIT(MTK_TRGMII_MT7621_CLK_BIT)
+-#define MTK_QDMA		BIT(MTK_QDMA_BIT)
+-#define MTK_NETSYS_V1		BIT(MTK_NETSYS_V1_BIT)
+-#define MTK_NETSYS_V2		BIT(MTK_NETSYS_V2_BIT)
+-#define MTK_NETSYS_V3		BIT(MTK_NETSYS_V3_BIT)
+-#define MTK_SOC_MT7628		BIT(MTK_SOC_MT7628_BIT)
+-#define MTK_RSTCTRL_PPE1	BIT(MTK_RSTCTRL_PPE1_BIT)
+-#define MTK_U3_COPHY_V2		BIT(MTK_U3_COPHY_V2_BIT)
++#define MTK_RGMII		BIT_ULL(MTK_RGMII_BIT)
++#define MTK_TRGMII		BIT_ULL(MTK_TRGMII_BIT)
++#define MTK_SGMII		BIT_ULL(MTK_SGMII_BIT)
++#define MTK_ESW			BIT_ULL(MTK_ESW_BIT)
++#define MTK_GEPHY		BIT_ULL(MTK_GEPHY_BIT)
++#define MTK_MUX			BIT_ULL(MTK_MUX_BIT)
++#define MTK_INFRA		BIT_ULL(MTK_INFRA_BIT)
++#define MTK_SHARED_SGMII	BIT_ULL(MTK_SHARED_SGMII_BIT)
++#define MTK_HWLRO		BIT_ULL(MTK_HWLRO_BIT)
++#define MTK_SHARED_INT		BIT_ULL(MTK_SHARED_INT_BIT)
++#define MTK_TRGMII_MT7621_CLK	BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT)
++#define MTK_QDMA		BIT_ULL(MTK_QDMA_BIT)
++#define MTK_NETSYS_V1		BIT_ULL(MTK_NETSYS_V1_BIT)
++#define MTK_NETSYS_V2		BIT_ULL(MTK_NETSYS_V2_BIT)
++#define MTK_NETSYS_V3		BIT_ULL(MTK_NETSYS_V3_BIT)
++#define MTK_SOC_MT7628		BIT_ULL(MTK_SOC_MT7628_BIT)
++#define MTK_RSTCTRL_PPE1	BIT_ULL(MTK_RSTCTRL_PPE1_BIT)
++#define MTK_U3_COPHY_V2		BIT_ULL(MTK_U3_COPHY_V2_BIT)
+ 
+ #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW		\
+-	BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
++	BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
+ #define MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY	\
+-	BIT(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
++	BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
+ #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY		\
+-	BIT(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
++	BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
+ #define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII	\
+-	BIT(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
++	BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
+ #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII	\
+-	BIT(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
++	BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
+ 
+ /* Supported path present on SoCs */
+-#define MTK_ETH_PATH_GMAC1_RGMII	BIT(MTK_ETH_PATH_GMAC1_RGMII_BIT)
+-#define MTK_ETH_PATH_GMAC1_TRGMII	BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
+-#define MTK_ETH_PATH_GMAC1_SGMII	BIT(MTK_ETH_PATH_GMAC1_SGMII_BIT)
+-#define MTK_ETH_PATH_GMAC2_RGMII	BIT(MTK_ETH_PATH_GMAC2_RGMII_BIT)
+-#define MTK_ETH_PATH_GMAC2_SGMII	BIT(MTK_ETH_PATH_GMAC2_SGMII_BIT)
+-#define MTK_ETH_PATH_GMAC2_GEPHY	BIT(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
+-#define MTK_ETH_PATH_GDM1_ESW		BIT(MTK_ETH_PATH_GDM1_ESW_BIT)
++#define MTK_ETH_PATH_GMAC1_RGMII	BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT)
++#define MTK_ETH_PATH_GMAC1_TRGMII	BIT_ULL(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
++#define MTK_ETH_PATH_GMAC1_SGMII	BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT)
++#define MTK_ETH_PATH_GMAC2_RGMII	BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
++#define MTK_ETH_PATH_GMAC2_SGMII	BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
++#define MTK_ETH_PATH_GMAC2_GEPHY	BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
++#define MTK_ETH_PATH_GDM1_ESW		BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT)
+ 
+ #define MTK_GMAC1_RGMII		(MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
+ #define MTK_GMAC1_TRGMII	(MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
+@@ -1071,7 +1071,7 @@ struct mtk_reg_map {
+ struct mtk_soc_data {
+ 	const struct mtk_reg_map *reg_map;
+ 	u32             ana_rgc3;
+-	u32		caps;
++	u64		caps;
+ 	u32		required_clks;
+ 	bool		required_pctl;
+ 	u8		offload_version;
diff --git a/target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch b/target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch
new file mode 100644
index 0000000000..504d2ea226
--- /dev/null
+++ b/target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch
@@ -0,0 +1,495 @@
+From 661bacf4363ca68939c15e20056b5f72fbd034e7 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo at kernel.org>
+Date: Sat, 25 Feb 2023 00:08:24 +0100
+Subject: [PATCH 6/7] net: ethernet: mtk_eth_soc: add support for MT7988 SoC
+
+Introduce support for ethernet chip available in MT7988 SoC to
+mtk_eth_soc driver.
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 153 ++++++++++++++--
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 193 ++++++++++++++------
+ 2 files changed, 279 insertions(+), 67 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -152,6 +152,54 @@ static const struct mtk_reg_map mt7986_r
+ 	.pse_oq_sta		= 0x01a0,
+ };
+ 
++static const struct mtk_reg_map mt7988_reg_map = {
++	.tx_irq_mask		= 0x461c,
++	.tx_irq_status		= 0x4618,
++	.pdma = {
++		.rx_ptr		= 0x6900,
++		.rx_cnt_cfg	= 0x6904,
++		.pcrx_ptr	= 0x6908,
++		.glo_cfg	= 0x6a04,
++		.rst_idx	= 0x6a08,
++		.delay_irq	= 0x6a0c,
++		.irq_status	= 0x6a20,
++		.irq_mask	= 0x6a28,
++		.adma_rx_dbg0	= 0x6a38,
++		.int_grp	= 0x6a50,
++	},
++	.qdma = {
++		.qtx_cfg	= 0x4400,
++		.qtx_sch	= 0x4404,
++		.rx_ptr		= 0x4500,
++		.rx_cnt_cfg	= 0x4504,
++		.qcrx_ptr	= 0x4508,
++		.glo_cfg	= 0x4604,
++		.rst_idx	= 0x4608,
++		.delay_irq	= 0x460c,
++		.fc_th		= 0x4610,
++		.int_grp	= 0x4620,
++		.hred		= 0x4644,
++		.ctx_ptr	= 0x4700,
++		.dtx_ptr	= 0x4704,
++		.crx_ptr	= 0x4710,
++		.drx_ptr	= 0x4714,
++		.fq_head	= 0x4720,
++		.fq_tail	= 0x4724,
++		.fq_count	= 0x4728,
++		.fq_blen	= 0x472c,
++		.tx_sch_rate	= 0x4798,
++	},
++	.gdm1_cnt		= 0x1c00,
++	.gdma_to_ppe0		= 0x3333,
++	.ppe_base		= 0x2200,
++	.wdma_base = {
++		[0]		= 0x4800,
++		[1]		= 0x4c00,
++	},
++	.pse_iq_sta		= 0x0180,
++	.pse_oq_sta		= 0x01a0,
++};
++
+ /* strings used by ethtool */
+ static const struct mtk_ethtool_stats {
+ 	char str[ETH_GSTRING_LEN];
+@@ -179,10 +227,54 @@ static const struct mtk_ethtool_stats {
+ };
+ 
+ static const char * const mtk_clks_source_name[] = {
+-	"ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2", "fe", "trgpll",
+-	"sgmii_tx250m", "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb",
+-	"sgmii2_tx250m", "sgmii2_rx250m", "sgmii2_cdr_ref", "sgmii2_cdr_fb",
+-	"sgmii_ck", "eth2pll", "wocpu0", "wocpu1", "netsys0", "netsys1"
++	"ethif",
++	"sgmiitop",
++	"esw",
++	"gp0",
++	"gp1",
++	"gp2",
++	"gp3",
++	"xgp1",
++	"xgp2",
++	"xgp3",
++	"crypto",
++	"fe",
++	"trgpll",
++	"sgmii_tx250m",
++	"sgmii_rx250m",
++	"sgmii_cdr_ref",
++	"sgmii_cdr_fb",
++	"sgmii2_tx250m",
++	"sgmii2_rx250m",
++	"sgmii2_cdr_ref",
++	"sgmii2_cdr_fb",
++	"sgmii_ck",
++	"eth2pll",
++	"wocpu0",
++	"wocpu1",
++	"netsys0",
++	"netsys1",
++	"ethwarp_wocpu2",
++	"ethwarp_wocpu1",
++	"ethwarp_wocpu0",
++	"top_usxgmii0_sel",
++	"top_usxgmii1_sel",
++	"top_sgm0_sel",
++	"top_sgm1_sel",
++	"top_xfi_phy0_xtal_sel",
++	"top_xfi_phy1_xtal_sel",
++	"top_eth_gmii_sel",
++	"top_eth_refck_50m_sel",
++	"top_eth_sys_200m_sel",
++	"top_eth_sys_sel",
++	"top_eth_xgmii_sel",
++	"top_eth_mii_sel",
++	"top_netsys_sel",
++	"top_netsys_500m_sel",
++	"top_netsys_pao_2x_sel",
++	"top_netsys_sync_250m_sel",
++	"top_netsys_ppefb_250m_sel",
++	"top_netsys_warp_sel",
+ };
+ 
+ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
+@@ -1207,10 +1299,19 @@ static void mtk_tx_set_dma_desc_v2(struc
+ 		data |= TX_DMA_LS0;
+ 	WRITE_ONCE(desc->txd3, data);
+ 
+-	if (mac->id == MTK_GMAC3_ID)
+-		data = PSE_GDM3_PORT;
+-	else
+-		data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
++	 /* set forward port */
++	switch (mac->id) {
++	case MTK_GMAC1_ID:
++		data = PSE_GDM1_PORT << TX_DMA_FPORT_SHIFT_V2;
++		break;
++	case MTK_GMAC2_ID:
++		data = PSE_GDM2_PORT << TX_DMA_FPORT_SHIFT_V2;
++		break;
++	case MTK_GMAC3_ID:
++		data = PSE_GDM3_PORT << TX_DMA_FPORT_SHIFT_V2;
++		break;
++	}
++
+ 	data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
+ 	WRITE_ONCE(desc->txd4, data);
+ 
+@@ -4964,6 +5065,25 @@ static const struct mtk_soc_data mt7986_
+ 	},
+ };
+ 
++static const struct mtk_soc_data mt7988_data = {
++	.reg_map = &mt7988_reg_map,
++	.ana_rgc3 = 0x128,
++	.caps = MT7988_CAPS,
++	.hw_features = MTK_HW_FEATURES,
++	.required_clks = MT7988_CLKS_BITMAP,
++	.required_pctl = false,
++	.num_devs = 3,
++	.txrx = {
++		.txd_size = sizeof(struct mtk_tx_dma_v2),
++		.rxd_size = sizeof(struct mtk_rx_dma_v2),
++		.rx_irq_done_mask = MTK_RX_DONE_INT_V2,
++		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
++		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
++		.dma_len_offset = 8,
++	},
++};
++
++
+ static const struct mtk_soc_data rt5350_data = {
+ 	.reg_map = &mt7628_reg_map,
+ 	.caps = MT7628_CAPS,
+@@ -4982,14 +5102,15 @@ static const struct mtk_soc_data rt5350_
+ };
+ 
+ const struct of_device_id of_mtk_match[] = {
+-	{ .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
+-	{ .compatible = "mediatek,mt7621-eth", .data = &mt7621_data},
+-	{ .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
+-	{ .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
+-	{ .compatible = "mediatek,mt7629-eth", .data = &mt7629_data},
+-	{ .compatible = "mediatek,mt7981-eth", .data = &mt7981_data},
+-	{ .compatible = "mediatek,mt7986-eth", .data = &mt7986_data},
+-	{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data},
++	{ .compatible = "mediatek,mt2701-eth", .data = &mt2701_data },
++	{ .compatible = "mediatek,mt7621-eth", .data = &mt7621_data },
++	{ .compatible = "mediatek,mt7622-eth", .data = &mt7622_data },
++	{ .compatible = "mediatek,mt7623-eth", .data = &mt7623_data },
++	{ .compatible = "mediatek,mt7629-eth", .data = &mt7629_data },
++	{ .compatible = "mediatek,mt7981-eth", .data = &mt7981_data },
++	{ .compatible = "mediatek,mt7986-eth", .data = &mt7986_data },
++	{ .compatible = "mediatek,mt7988-eth", .data = &mt7988_data },
++	{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data },
+ 	{},
+ };
+ MODULE_DEVICE_TABLE(of, of_mtk_match);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -116,7 +116,8 @@
+ #define MTK_CDMP_EG_CTRL	0x404
+ 
+ /* GDM Exgress Control Register */
+-#define MTK_GDMA_FWD_CFG(x)	(0x500 + (x * 0x1000))
++#define MTK_GDMA_FWD_CFG(x)	((x == MTK_GMAC3_ID) ?		\
++				 0x540 : 0x500 + (x * 0x1000))
+ #define MTK_GDMA_SPECIAL_TAG	BIT(24)
+ #define MTK_GDMA_ICS_EN		BIT(22)
+ #define MTK_GDMA_TCS_EN		BIT(21)
+@@ -650,6 +651,11 @@ enum mtk_clks_map {
+ 	MTK_CLK_GP0,
+ 	MTK_CLK_GP1,
+ 	MTK_CLK_GP2,
++	MTK_CLK_GP3,
++	MTK_CLK_XGP1,
++	MTK_CLK_XGP2,
++	MTK_CLK_XGP3,
++	MTK_CLK_CRYPTO,
+ 	MTK_CLK_FE,
+ 	MTK_CLK_TRGPLL,
+ 	MTK_CLK_SGMII_TX_250M,
+@@ -666,57 +672,108 @@ enum mtk_clks_map {
+ 	MTK_CLK_WOCPU1,
+ 	MTK_CLK_NETSYS0,
+ 	MTK_CLK_NETSYS1,
++	MTK_CLK_ETHWARP_WOCPU2,
++	MTK_CLK_ETHWARP_WOCPU1,
++	MTK_CLK_ETHWARP_WOCPU0,
++	MTK_CLK_TOP_USXGMII_SBUS_0_SEL,
++	MTK_CLK_TOP_USXGMII_SBUS_1_SEL,
++	MTK_CLK_TOP_SGM_0_SEL,
++	MTK_CLK_TOP_SGM_1_SEL,
++	MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL,
++	MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL,
++	MTK_CLK_TOP_ETH_GMII_SEL,
++	MTK_CLK_TOP_ETH_REFCK_50M_SEL,
++	MTK_CLK_TOP_ETH_SYS_200M_SEL,
++	MTK_CLK_TOP_ETH_SYS_SEL,
++	MTK_CLK_TOP_ETH_XGMII_SEL,
++	MTK_CLK_TOP_ETH_MII_SEL,
++	MTK_CLK_TOP_NETSYS_SEL,
++	MTK_CLK_TOP_NETSYS_500M_SEL,
++	MTK_CLK_TOP_NETSYS_PAO_2X_SEL,
++	MTK_CLK_TOP_NETSYS_SYNC_250M_SEL,
++	MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL,
++	MTK_CLK_TOP_NETSYS_WARP_SEL,
+ 	MTK_CLK_MAX
+ };
+ 
+-#define MT7623_CLKS_BITMAP	(BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) |  \
+-				 BIT(MTK_CLK_GP1) | BIT(MTK_CLK_GP2) | \
+-				 BIT(MTK_CLK_TRGPLL))
+-#define MT7622_CLKS_BITMAP	(BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) |  \
+-				 BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \
+-				 BIT(MTK_CLK_GP2) | \
+-				 BIT(MTK_CLK_SGMII_TX_250M) | \
+-				 BIT(MTK_CLK_SGMII_RX_250M) | \
+-				 BIT(MTK_CLK_SGMII_CDR_REF) | \
+-				 BIT(MTK_CLK_SGMII_CDR_FB) | \
+-				 BIT(MTK_CLK_SGMII_CK) | \
+-				 BIT(MTK_CLK_ETH2PLL))
++#define MT7623_CLKS_BITMAP	(BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) |  \
++				 BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \
++				 BIT_ULL(MTK_CLK_TRGPLL))
++#define MT7622_CLKS_BITMAP	(BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) |  \
++				 BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \
++				 BIT_ULL(MTK_CLK_GP2) | \
++				 BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
++				 BIT_ULL(MTK_CLK_SGMII_CK) | \
++				 BIT_ULL(MTK_CLK_ETH2PLL))
+ #define MT7621_CLKS_BITMAP	(0)
+ #define MT7628_CLKS_BITMAP	(0)
+-#define MT7629_CLKS_BITMAP	(BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) |  \
+-				 BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \
+-				 BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \
+-				 BIT(MTK_CLK_SGMII_TX_250M) | \
+-				 BIT(MTK_CLK_SGMII_RX_250M) | \
+-				 BIT(MTK_CLK_SGMII_CDR_REF) | \
+-				 BIT(MTK_CLK_SGMII_CDR_FB) | \
+-				 BIT(MTK_CLK_SGMII2_TX_250M) | \
+-				 BIT(MTK_CLK_SGMII2_RX_250M) | \
+-				 BIT(MTK_CLK_SGMII2_CDR_REF) | \
+-				 BIT(MTK_CLK_SGMII2_CDR_FB) | \
+-				 BIT(MTK_CLK_SGMII_CK) | \
+-				 BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP))
+-#define MT7981_CLKS_BITMAP	(BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \
+-				 BIT(MTK_CLK_WOCPU0) | \
+-				 BIT(MTK_CLK_SGMII_TX_250M) | \
+-				 BIT(MTK_CLK_SGMII_RX_250M) | \
+-				 BIT(MTK_CLK_SGMII_CDR_REF) | \
+-				 BIT(MTK_CLK_SGMII_CDR_FB) | \
+-				 BIT(MTK_CLK_SGMII2_TX_250M) | \
+-				 BIT(MTK_CLK_SGMII2_RX_250M) | \
+-				 BIT(MTK_CLK_SGMII2_CDR_REF) | \
+-				 BIT(MTK_CLK_SGMII2_CDR_FB) | \
+-				 BIT(MTK_CLK_SGMII_CK))
+-#define MT7986_CLKS_BITMAP	(BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \
+-				 BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \
+-				 BIT(MTK_CLK_SGMII_TX_250M) | \
+-				 BIT(MTK_CLK_SGMII_RX_250M) | \
+-				 BIT(MTK_CLK_SGMII_CDR_REF) | \
+-				 BIT(MTK_CLK_SGMII_CDR_FB) | \
+-				 BIT(MTK_CLK_SGMII2_TX_250M) | \
+-				 BIT(MTK_CLK_SGMII2_RX_250M) | \
+-				 BIT(MTK_CLK_SGMII2_CDR_REF) | \
+-				 BIT(MTK_CLK_SGMII2_CDR_FB))
++#define MT7629_CLKS_BITMAP	(BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) |  \
++				 BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \
++				 BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_FE) | \
++				 BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
++				 BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \
++				 BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \
++				 BIT_ULL(MTK_CLK_SGMII_CK) | \
++				 BIT_ULL(MTK_CLK_ETH2PLL) | BIT_ULL(MTK_CLK_SGMIITOP))
++#define MT7981_CLKS_BITMAP	(BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_GP1) | \
++				 BIT_ULL(MTK_CLK_WOCPU0) | \
++				 BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
++				 BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \
++				 BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \
++				 BIT_ULL(MTK_CLK_SGMII_CK))
++#define MT7986_CLKS_BITMAP	(BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_GP1) | \
++				 BIT_ULL(MTK_CLK_WOCPU1) | BIT_ULL(MTK_CLK_WOCPU0) | \
++				 BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
++				 BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
++				 BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \
++				 BIT_ULL(MTK_CLK_SGMII2_CDR_FB))
++#define MT7988_CLKS_BITMAP	(BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_ESW) | \
++				 BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \
++				 BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \
++				 BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \
++				 BIT_ULL(MTK_CLK_CRYPTO) | \
++				 BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
++				 BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
++				 BIT_ULL(MTK_CLK_ETHWARP_WOCPU2) | \
++				 BIT_ULL(MTK_CLK_ETHWARP_WOCPU1) | \
++				 BIT_ULL(MTK_CLK_ETHWARP_WOCPU0) | \
++				 BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_0_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_1_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_SGM_0_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_SGM_1_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_ETH_SYS_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_ETH_XGMII_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_ETH_MII_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_NETSYS_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_NETSYS_500M_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_NETSYS_PAO_2X_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_NETSYS_SYNC_250M_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL) | \
++				 BIT_ULL(MTK_CLK_TOP_NETSYS_WARP_SEL))
+ 
+ enum mtk_dev_state {
+ 	MTK_HW_INIT,
+@@ -844,6 +901,7 @@ enum mkt_eth_capabilities {
+ 	MTK_RGMII_BIT = 0,
+ 	MTK_TRGMII_BIT,
+ 	MTK_SGMII_BIT,
++	MTK_USXGMII_BIT,
+ 	MTK_ESW_BIT,
+ 	MTK_GEPHY_BIT,
+ 	MTK_MUX_BIT,
+@@ -866,6 +924,8 @@ enum mkt_eth_capabilities {
+ 	MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
+ 	MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT,
+ 	MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT,
++	MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT,
++	MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT,
+ 
+ 	/* PATH BITS */
+ 	MTK_ETH_PATH_GMAC1_RGMII_BIT,
+@@ -874,13 +934,18 @@ enum mkt_eth_capabilities {
+ 	MTK_ETH_PATH_GMAC2_RGMII_BIT,
+ 	MTK_ETH_PATH_GMAC2_SGMII_BIT,
+ 	MTK_ETH_PATH_GMAC2_GEPHY_BIT,
++	MTK_ETH_PATH_GMAC3_SGMII_BIT,
+ 	MTK_ETH_PATH_GDM1_ESW_BIT,
++	MTK_ETH_PATH_GMAC1_USXGMII_BIT,
++	MTK_ETH_PATH_GMAC2_USXGMII_BIT,
++	MTK_ETH_PATH_GMAC3_USXGMII_BIT,
+ };
+ 
+ /* Supported hardware group on SoCs */
+ #define MTK_RGMII		BIT_ULL(MTK_RGMII_BIT)
+ #define MTK_TRGMII		BIT_ULL(MTK_TRGMII_BIT)
+ #define MTK_SGMII		BIT_ULL(MTK_SGMII_BIT)
++#define MTK_USXGMII		BIT_ULL(MTK_USXGMII_BIT)
+ #define MTK_ESW			BIT_ULL(MTK_ESW_BIT)
+ #define MTK_GEPHY		BIT_ULL(MTK_GEPHY_BIT)
+ #define MTK_MUX			BIT_ULL(MTK_MUX_BIT)
+@@ -907,6 +972,10 @@ enum mkt_eth_capabilities {
+ 	BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
+ #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII	\
+ 	BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
++#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII	\
++	BIT_ULL(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT)
++#define MTK_ETH_MUX_GMAC123_TO_USXGMII	\
++	BIT_ULL(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT)
+ 
+ /* Supported path present on SoCs */
+ #define MTK_ETH_PATH_GMAC1_RGMII	BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT)
+@@ -915,7 +984,11 @@ enum mkt_eth_capabilities {
+ #define MTK_ETH_PATH_GMAC2_RGMII	BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
+ #define MTK_ETH_PATH_GMAC2_SGMII	BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
+ #define MTK_ETH_PATH_GMAC2_GEPHY	BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
++#define MTK_ETH_PATH_GMAC3_SGMII	BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT)
+ #define MTK_ETH_PATH_GDM1_ESW		BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT)
++#define MTK_ETH_PATH_GMAC1_USXGMII	BIT_ULL(MTK_ETH_PATH_GMAC1_USXGMII_BIT)
++#define MTK_ETH_PATH_GMAC2_USXGMII	BIT_ULL(MTK_ETH_PATH_GMAC2_USXGMII_BIT)
++#define MTK_ETH_PATH_GMAC3_USXGMII	BIT_ULL(MTK_ETH_PATH_GMAC3_USXGMII_BIT)
+ 
+ #define MTK_GMAC1_RGMII		(MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
+ #define MTK_GMAC1_TRGMII	(MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
+@@ -923,7 +996,11 @@ enum mkt_eth_capabilities {
+ #define MTK_GMAC2_RGMII		(MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
+ #define MTK_GMAC2_SGMII		(MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
+ #define MTK_GMAC2_GEPHY		(MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
++#define MTK_GMAC3_SGMII		(MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII)
+ #define MTK_GDM1_ESW		(MTK_ETH_PATH_GDM1_ESW | MTK_ESW)
++#define MTK_GMAC1_USXGMII	(MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII)
++#define MTK_GMAC2_USXGMII	(MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII)
++#define MTK_GMAC3_USXGMII	(MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII)
+ 
+ /* MUXes present on SoCs */
+ /* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
+@@ -946,6 +1023,12 @@ enum mkt_eth_capabilities {
+ #define MTK_MUX_GMAC12_TO_GEPHY_SGMII   \
+ 	(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX)
+ 
++#define MTK_MUX_GMAC123_TO_GEPHY_SGMII   \
++	(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII | MTK_MUX)
++
++#define MTK_MUX_GMAC123_TO_USXGMII   \
++	(MTK_ETH_MUX_GMAC123_TO_USXGMII | MTK_MUX | MTK_INFRA)
++
+ #ifdef CONFIG_SOC_MT7621
+ #define MTK_CAP_MASK MTK_NETSYS_V2
+ #else
+@@ -984,9 +1067,17 @@ enum mkt_eth_capabilities {
+ 		      MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
+ 		      MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1)
+ 
+-#define MT7986_CAPS  (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
+-		      MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
+-		      MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1)
++#define MT7986_CAPS  (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII |	\
++		      MTK_MUX_GMAC12_TO_GEPHY_SGMII |		\
++		      MTK_QDMA | MTK_NETSYS_V2 |		\
++		      MTK_RSTCTRL_PPE1)
++
++#define MT7988_CAPS   (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII |	\
++		       MTK_GMAC3_SGMII | MTK_QDMA |		\
++		       MTK_MUX_GMAC123_TO_GEPHY_SGMII |		\
++		       MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 |	\
++		       MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII |	\
++		       MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII)
+ 
+ struct mtk_tx_dma_desc_info {
+ 	dma_addr_t	addr;
+@@ -1072,7 +1163,7 @@ struct mtk_soc_data {
+ 	const struct mtk_reg_map *reg_map;
+ 	u32             ana_rgc3;
+ 	u64		caps;
+-	u32		required_clks;
++	u64		required_clks;
+ 	bool		required_pctl;
+ 	u8		offload_version;
+ 	u8		hash_offset;
diff --git a/target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch
new file mode 100644
index 0000000000..68170b6614
--- /dev/null
+++ b/target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch
@@ -0,0 +1,1671 @@
+From 20ac14fedba025b6b336a821ea60660afe2d46cd Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel at makrotopia.org>
+Date: Wed, 1 Mar 2023 11:56:04 +0000
+Subject: [PATCH 7/7] net: ethernet: mtk_eth_soc: add paths and SerDes modes
+ for MT7988
+
+MT7988 comes with a built-in 2.5G PHY as well as USXGMII or 10Base-KR
+compatible SerDes lanes for external PHYs.
+Add support for configuring the MAC and SerDes parts for the new paths.
+
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/net/ethernet/mediatek/Makefile       |   2 +-
+ drivers/net/ethernet/mediatek/mtk_eth_path.c | 154 ++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c  | 291 +++++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h  | 162 ++++-
+ drivers/net/ethernet/mediatek/mtk_usxgmii.c  | 659 +++++++++++++++++++
+ 5 files changed, 1236 insertions(+), 32 deletions(-)
+ create mode 100644 drivers/net/ethernet/mediatek/mtk_usxgmii.c
+
+--- a/drivers/net/ethernet/mediatek/Makefile
++++ b/drivers/net/ethernet/mediatek/Makefile
+@@ -5,6 +5,7 @@
+ 
+ obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
+ mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_USXGMII) += mtk_usxgmii.o
+ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o
+ ifdef CONFIG_DEBUG_FS
+ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
+--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c
+@@ -31,10 +31,20 @@ static const char *mtk_eth_path_name(u64
+ 		return "gmac2_rgmii";
+ 	case MTK_ETH_PATH_GMAC2_SGMII:
+ 		return "gmac2_sgmii";
++	case MTK_ETH_PATH_GMAC2_2P5GPHY:
++		return "gmac2_2p5gphy";
+ 	case MTK_ETH_PATH_GMAC2_GEPHY:
+ 		return "gmac2_gephy";
++	case MTK_ETH_PATH_GMAC3_SGMII:
++		return "gmac3_sgmii";
+ 	case MTK_ETH_PATH_GDM1_ESW:
+ 		return "gdm1_esw";
++	case MTK_ETH_PATH_GMAC1_USXGMII:
++		return "gmac1_usxgmii";
++	case MTK_ETH_PATH_GMAC2_USXGMII:
++		return "gmac2_usxgmii";
++	case MTK_ETH_PATH_GMAC3_USXGMII:
++		return "gmac3_usxgmii";
+ 	default:
+ 		return "unknown path";
+ 	}
+@@ -42,8 +52,8 @@ static const char *mtk_eth_path_name(u64
+ 
+ static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
+ {
++	u32 val, mask, set, reg;
+ 	bool updated = true;
+-	u32 val, mask, set;
+ 
+ 	switch (path) {
+ 	case MTK_ETH_PATH_GMAC1_SGMII:
+@@ -59,10 +69,15 @@ static int set_mux_gdm1_to_gmac1_esw(str
+ 		break;
+ 	}
+ 
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
++		reg = MTK_MAC_MISC_V3;
++	else
++		reg = MTK_MAC_MISC;
++
+ 	if (updated) {
+-		val = mtk_r32(eth, MTK_MAC_MISC);
++		val = mtk_r32(eth, reg);
+ 		val = (val & mask) | set;
+-		mtk_w32(eth, val, MTK_MAC_MISC);
++		mtk_w32(eth, val, reg);
+ 	}
+ 
+ 	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
+@@ -125,6 +140,31 @@ static int set_mux_u3_gmac2_to_qphy(stru
+ 	return 0;
+ }
+ 
++static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
++{
++	unsigned int val = 0;
++	bool updated = true;
++	int mac_id = 0;
++
++	regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
++
++	switch (path) {
++	case MTK_ETH_PATH_GMAC2_2P5GPHY:
++		val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
++		mac_id = MTK_GMAC2_ID;
++		break;
++	default:
++		updated = false;
++		break;
++	};
++
++	if (updated)
++		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
++				   SYSCFG0_SGMII_MASK, val);
++
++	return 0;
++}
++
+ static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
+ {
+ 	unsigned int val = 0;
+@@ -163,7 +203,61 @@ static int set_mux_gmac1_gmac2_to_sgmii_
+ 	return 0;
+ }
+ 
+-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
++static int set_mux_gmac123_to_usxgmii(struct mtk_eth *eth, u64 path)
++{
++	unsigned int val = 0;
++	bool updated = true;
++	int mac_id = 0;
++
++	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
++		mtk_eth_path_name(path), __func__, updated);
++
++	/* Disable SYSCFG1 SGMII */
++	regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
++
++	switch (path) {
++	case MTK_ETH_PATH_GMAC1_USXGMII:
++		val &= ~(u32)SYSCFG0_SGMII_GMAC1_V2;
++		mac_id = MTK_GMAC1_ID;
++		break;
++	case MTK_ETH_PATH_GMAC2_USXGMII:
++		val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
++		mac_id = MTK_GMAC2_ID;
++		break;
++	case MTK_ETH_PATH_GMAC3_USXGMII:
++		val &= ~(u32)SYSCFG0_SGMII_GMAC3_V2;
++		mac_id = MTK_GMAC3_ID;
++		break;
++	default:
++		updated = false;
++	};
++
++	if (updated) {
++		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
++				   SYSCFG0_SGMII_MASK, val);
++
++		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
++		    mac_id == MTK_GMAC2_ID) {
++			regmap_update_bits(eth->infra,
++					   TOP_MISC_NETSYS_PCS_MUX,
++					   NETSYS_PCS_MUX_MASK,
++					   MUX_G2_USXGMII_SEL);
++		}
++	}
++
++	/* Enable XGDM Path */
++	val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac_id));
++	val |= MTK_GDMA_XGDM_SEL;
++	mtk_w32(eth, val, MTK_GDMA_EG_CTRL(mac_id));
++
++	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
++		mtk_eth_path_name(path), __func__, updated);
++
++
++	return 0;
++}
++
++static int set_mux_gmac123_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
+ {
+ 	unsigned int val = 0;
+ 	bool updated = true;
+@@ -180,6 +274,9 @@ static int set_mux_gmac12_to_gephy_sgmii
+ 	case MTK_ETH_PATH_GMAC2_SGMII:
+ 		val |= SYSCFG0_SGMII_GMAC2_V2;
+ 		break;
++	case MTK_ETH_PATH_GMAC3_SGMII:
++		val |= SYSCFG0_SGMII_GMAC3_V2;
++		break;
+ 	default:
+ 		updated = false;
+ 	}
+@@ -208,13 +305,25 @@ static const struct mtk_eth_muxc mtk_eth
+ 		.cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
+ 		.set_path = set_mux_u3_gmac2_to_qphy,
+ 	}, {
++		.name = "mux_gmac2_to_2p5gphy",
++		.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
++		.set_path = set_mux_gmac2_to_2p5gphy,
++	}, {
+ 		.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
+ 		.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
+ 		.set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
+ 	}, {
+ 		.name = "mux_gmac12_to_gephy_sgmii",
+ 		.cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
+-		.set_path = set_mux_gmac12_to_gephy_sgmii,
++		.set_path = set_mux_gmac123_to_gephy_sgmii,
++	}, {
++		.name = "mux_gmac123_to_gephy_sgmii",
++		.cap_bit = MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII,
++		.set_path = set_mux_gmac123_to_gephy_sgmii,
++	}, {
++		.name = "mux_gmac123_to_usxgmii",
++		.cap_bit = MTK_ETH_MUX_GMAC123_TO_USXGMII,
++		.set_path = set_mux_gmac123_to_usxgmii,
+ 	},
+ };
+ 
+@@ -243,16 +352,46 @@ static int mtk_eth_mux_setup(struct mtk_
+ 		}
+ 	}
+ 
++	dev_dbg(eth->dev, "leaving mux_setup %s\n",
++		mtk_eth_path_name(path));
++
+ out:
+ 	return err;
+ }
+ 
++int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id)
++{
++	u64 path;
++
++	path = (mac_id == MTK_GMAC1_ID) ?  MTK_ETH_PATH_GMAC1_USXGMII :
++	       (mac_id == MTK_GMAC2_ID) ?  MTK_ETH_PATH_GMAC2_USXGMII :
++					   MTK_ETH_PATH_GMAC3_USXGMII;
++
++	/* Setup proper MUXes along the path */
++	return mtk_eth_mux_setup(eth, path);
++}
++
+ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
+ {
+ 	u64 path;
+ 
+-	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
+-				MTK_ETH_PATH_GMAC2_SGMII;
++	path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII :
++	       (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_SGMII :
++					  MTK_ETH_PATH_GMAC3_SGMII;
++
++	/* Setup proper MUXes along the path */
++	return mtk_eth_mux_setup(eth, path);
++}
++
++int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id)
++{
++	u64 path = 0;
++
++	if (mac_id == MTK_GMAC2_ID)
++		path = MTK_ETH_PATH_GMAC2_2P5GPHY;
++
++	if (!path)
++		return -EINVAL;
+ 
+ 	/* Setup proper MUXes along the path */
+ 	return mtk_eth_mux_setup(eth, path);
+@@ -282,4 +421,3 @@ int mtk_gmac_rgmii_path_setup(struct mtk
+ 	/* Setup proper MUXes along the path */
+ 	return mtk_eth_mux_setup(eth, path);
+ }
+-
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -437,6 +437,23 @@ static void mtk_gmac0_rgmii_adjust(struc
+ 	mtk_w32(eth, val, TRGMII_TCK_CTRL);
+ }
+ 
++static void mtk_setup_bridge_switch(struct mtk_eth *eth)
++{
++	int val;
++
++	/* Force Port1 XGMAC Link Up */
++	val = mtk_r32(eth, MTK_XGMAC_STS(MTK_GMAC1_ID));
++	mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID),
++		MTK_XGMAC_STS(MTK_GMAC1_ID));
++
++	/* Adjust GSW bridge IPG to 11*/
++	val = mtk_r32(eth, MTK_GSW_CFG);
++	val &= ~(GSWTX_IPG_MASK | GSWRX_IPG_MASK);
++	val |= (GSW_IPG_11 << GSWTX_IPG_SHIFT) |
++	       (GSW_IPG_11 << GSWRX_IPG_SHIFT);
++	mtk_w32(eth, val, MTK_GSW_CFG);
++}
++
+ static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
+ 					      phy_interface_t interface)
+ {
+@@ -462,7 +479,7 @@ static void mtk_mac_config(struct phylin
+ 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ 					   phylink_config);
+ 	struct mtk_eth *eth = mac->hw;
+-	int val, ge_mode, err = 0;
++	int val, ge_mode, force_link, err = 0;
+ 	u32 i;
+ 
+ 	/* MT76x8 has no hardware settings between for the MAC */
+@@ -506,6 +523,23 @@ static void mtk_mac_config(struct phylin
+ 					goto init_err;
+ 			}
+ 			break;
++		case PHY_INTERFACE_MODE_USXGMII:
++		case PHY_INTERFACE_MODE_10GKR:
++		case PHY_INTERFACE_MODE_5GBASER:
++			if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) {
++				err = mtk_gmac_usxgmii_path_setup(eth, mac->id);
++				if (err)
++					goto init_err;
++			}
++			break;
++		case PHY_INTERFACE_MODE_INTERNAL:
++			if (mac->id == MTK_GMAC2_ID &&
++			    MTK_HAS_CAPS(eth->soc->caps, MTK_2P5GPHY)) {
++				err = mtk_gmac_2p5gphy_path_setup(eth, mac->id);
++				if (err)
++					goto init_err;
++			}
++			break;
+ 		default:
+ 			goto err_phy;
+ 		}
+@@ -584,14 +618,92 @@ static void mtk_mac_config(struct phylin
+ 				   SYSCFG0_SGMII_MASK,
+ 				   ~(u32)SYSCFG0_SGMII_MASK);
+ 
++		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++			mtk_xfi_pll_enable(eth);
++			mtk_sgmii_reset(eth, mac->id);
++			if (phylink_autoneg_inband(mode))
++				mtk_sgmii_setup_phya_gen1(eth, mac->id);
++			else
++				mtk_sgmii_setup_phya_gen2(eth, mac->id);
++		}
+ 		/* Save the syscfg0 value for mac_finish */
+ 		mac->syscfg0 = val;
++	} else if (state->interface == PHY_INTERFACE_MODE_USXGMII ||
++		   state->interface == PHY_INTERFACE_MODE_10GKR ||
++		   state->interface == PHY_INTERFACE_MODE_5GBASER) {
++
++		if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++			err = -EINVAL;
++			goto init_err;
++		}
++		if (phylink_autoneg_inband(mode))
++			err = mtk_usxgmii_setup_mode_force(eth, mac->id,
++							   state);
++		else
++			err = mtk_usxgmii_setup_mode_an(eth, mac->id,
++							SPEED_10000);
++
++		if (err)
++			goto init_err;
+ 	} else if (phylink_autoneg_inband(mode)) {
+ 		dev_err(eth->dev,
+ 			"In-band mode not supported in non SGMII mode!\n");
+ 		return;
+ 	}
+ 
++	/* Setup gmac */
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
++	    (mtk_interface_mode_is_xgmii(state->interface) ||
++	     mac->interface == PHY_INTERFACE_MODE_INTERNAL)) {
++		mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id));
++		mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id));
++
++		switch (mac->id) {
++		case MTK_GMAC1_ID:
++			mtk_setup_bridge_switch(eth);
++			break;
++		case MTK_GMAC2_ID:
++			force_link = (mac->interface ==
++				      PHY_INTERFACE_MODE_INTERNAL) ?
++				      MTK_XGMAC_FORCE_LINK(mac->id) : 0;
++			val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
++			mtk_w32(eth, val | force_link,
++				MTK_XGMAC_STS(mac->id));
++			break;
++		case MTK_GMAC3_ID:
++			val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
++			mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK(mac->id),
++				MTK_XGMAC_STS(mac->id));
++			break;
++		}
++	} else {
++		val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac->id));
++		mtk_w32(eth, val & ~MTK_GDMA_XGDM_SEL,
++			MTK_GDMA_EG_CTRL(mac->id));
++
++		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++			switch (mac->id) {
++			case MTK_GMAC2_ID:
++			case MTK_GMAC3_ID:
++				val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
++				mtk_w32(eth,
++					val & ~MTK_XGMAC_FORCE_LINK(mac->id),
++					MTK_XGMAC_STS(mac->id));
++				break;
++			}
++		}
++
++/*
++		if (mac->type != mac_type) {
++			if (atomic_read(&reset_pending) == 0) {
++				atomic_inc(&force);
++				schedule_work(&eth->pending_work);
++				atomic_inc(&reset_pending);
++			} else
++				atomic_dec(&reset_pending);
++		}
++*/
++	}
+ 	return;
+ 
+ err_phy:
+@@ -632,11 +744,37 @@ static int mtk_mac_finish(struct phylink
+ 	return 0;
+ }
+ 
+-static void mtk_mac_pcs_get_state(struct phylink_config *config,
++static void mtk_xgdm_pcs_get_state(struct mtk_mac *mac,
++				  struct phylink_link_state *state)
++{
++	u32 sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
++
++	if (mac->id == MTK_GMAC2_ID)
++		sts = sts >> 16;
++
++	state->duplex = 1;
++
++	switch (FIELD_GET(MTK_USXGMII_PCS_MODE, sts)) {
++	case 0:
++		state->speed = SPEED_10000;
++		break;
++	case 1:
++		state->speed = SPEED_5000;
++		break;
++	case 2:
++		state->speed = SPEED_2500;
++		break;
++	case 3:
++		state->speed = SPEED_1000;
++		break;
++	}
++
++	state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, sts);
++}
++
++static void mtk_gdm_pcs_get_state(struct mtk_mac *mac,
+ 				  struct phylink_link_state *state)
+ {
+-	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+-					   phylink_config);
+ 	u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id));
+ 
+ 	state->link = (pmsr & MAC_MSR_LINK);
+@@ -664,15 +802,35 @@ static void mtk_mac_pcs_get_state(struct
+ 		state->pause |= MLO_PAUSE_TX;
+ }
+ 
++static void mtk_mac_pcs_get_state(struct phylink_config *config,
++				  struct phylink_link_state *state)
++{
++	struct mtk_mac *mac = container_of(config, struct mtk_mac,
++					   phylink_config);
++
++	if (mtk_interface_mode_is_xgmii(state->interface))
++		mtk_xgdm_pcs_get_state(mac, state);
++	else
++		mtk_gdm_pcs_get_state(mac, state);
++}
++
+ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
+ 			      phy_interface_t interface)
+ {
+ 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ 					   phylink_config);
+-	u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
++	u32 mcr;
+ 
+-	mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN);
+-	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
++	if (!mtk_interface_mode_is_xgmii(interface)) {
++		mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
++		mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN);
++		mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
++	} else if (mac->id != MTK_GMAC1_ID) {
++		mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
++		mcr &= 0xfffffff0;
++		mcr |= XMAC_MCR_TRX_DISABLE;
++		mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
++	}
+ }
+ 
+ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
+@@ -744,13 +902,11 @@ static void mtk_set_queue_speed(struct m
+ 	mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
+ }
+ 
+-static void mtk_mac_link_up(struct phylink_config *config,
+-			    struct phy_device *phy,
+-			    unsigned int mode, phy_interface_t interface,
+-			    int speed, int duplex, bool tx_pause, bool rx_pause)
++static void mtk_gdm_mac_link_up(struct mtk_mac *mac,
++				struct phy_device *phy,
++				unsigned int mode, phy_interface_t interface,
++				int speed, int duplex, bool tx_pause, bool rx_pause)
+ {
+-	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+-					   phylink_config);
+ 	u32 mcr;
+ 
+ 	mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+@@ -784,6 +940,47 @@ static void mtk_mac_link_up(struct phyli
+ 	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ }
+ 
++static void mtk_xgdm_mac_link_up(struct mtk_mac *mac,
++				 struct phy_device *phy,
++				 unsigned int mode, phy_interface_t interface,
++				 int speed, int duplex, bool tx_pause, bool rx_pause)
++{
++	u32 mcr;
++
++	if (mac->id == MTK_GMAC1_ID)
++		return;
++
++	mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
++
++	mcr &= ~(XMAC_MCR_FORCE_TX_FC |	XMAC_MCR_FORCE_RX_FC);
++	/* Configure pause modes -
++	 * phylink will avoid these for half duplex
++	 */
++	if (tx_pause)
++		mcr |= XMAC_MCR_FORCE_TX_FC;
++	if (rx_pause)
++		mcr |= XMAC_MCR_FORCE_RX_FC;
++
++	mcr &= ~(XMAC_MCR_TRX_DISABLE);
++	mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
++}
++
++static void mtk_mac_link_up(struct phylink_config *config,
++			    struct phy_device *phy,
++			    unsigned int mode, phy_interface_t interface,
++			    int speed, int duplex, bool tx_pause, bool rx_pause)
++{
++	struct mtk_mac *mac = container_of(config, struct mtk_mac,
++					   phylink_config);
++
++	if (mtk_interface_mode_is_xgmii(interface))
++		mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex,
++				     tx_pause, rx_pause);
++	else
++		mtk_gdm_mac_link_up(mac, phy, mode, interface, speed, duplex,
++				    tx_pause, rx_pause);
++}
++
+ static const struct phylink_mac_ops mtk_phylink_ops = {
+ 	.validate = phylink_generic_validate,
+ 	.mac_select_pcs = mtk_mac_select_pcs,
+@@ -836,10 +1033,21 @@ static int mtk_mdio_init(struct mtk_eth
+ 	}
+ 	divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63);
+ 
++	/* Configure MDC Turbo Mode */
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++		val = mtk_r32(eth, MTK_MAC_MISC_V3);
++		val |= MISC_MDC_TURBO;
++		mtk_w32(eth, val, MTK_MAC_MISC_V3);
++	} else {
++		val = mtk_r32(eth, MTK_PPSC);
++		val |= PPSC_MDC_TURBO;
++		mtk_w32(eth, val, MTK_PPSC);
++	}
++
+ 	/* Configure MDC Divider */
+ 	val = mtk_r32(eth, MTK_PPSC);
+ 	val &= ~PPSC_MDC_CFG;
+-	val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO;
++	val |= FIELD_PREP(PPSC_MDC_CFG, divider);
+ 	mtk_w32(eth, val, MTK_PPSC);
+ 
+ 	dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider);
+@@ -4433,8 +4641,8 @@ static int mtk_add_mac(struct mtk_eth *e
+ 	const __be32 *_id = of_get_property(np, "reg", NULL);
+ 	phy_interface_t phy_mode;
+ 	struct phylink *phylink;
+-	struct mtk_mac *mac;
+ 	int id, err;
++	struct mtk_mac *mac;
+ 	int txqs = 1;
+ 
+ 	if (!_id) {
+@@ -4525,6 +4733,32 @@ static int mtk_add_mac(struct mtk_eth *e
+ 			  mac->phylink_config.supported_interfaces);
+ 	}
+ 
++	if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) {
++		if (id == MTK_GMAC1_ID) {
++			mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE |
++							       MAC_SYM_PAUSE |
++							       MAC_10000FD;
++			phy_interface_zero(
++				mac->phylink_config.supported_interfaces);
++			__set_bit(PHY_INTERFACE_MODE_INTERNAL,
++				  mac->phylink_config.supported_interfaces);
++		} else {
++			mac->phylink_config.mac_capabilities |= MAC_5000FD | MAC_10000FD;
++			__set_bit(PHY_INTERFACE_MODE_5GBASER,
++				  mac->phylink_config.supported_interfaces);
++			__set_bit(PHY_INTERFACE_MODE_10GKR,
++				  mac->phylink_config.supported_interfaces);
++			__set_bit(PHY_INTERFACE_MODE_USXGMII,
++				  mac->phylink_config.supported_interfaces);
++		}
++	}
++
++	if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY)) {
++		if (id == MTK_GMAC2_ID)
++			__set_bit(PHY_INTERFACE_MODE_INTERNAL,
++				  mac->phylink_config.supported_interfaces);
++	}
++
+ 	phylink = phylink_create(&mac->phylink_config,
+ 				 of_fwnode_handle(mac->of_node),
+ 				 phy_mode, &mtk_phylink_ops);
+@@ -4714,6 +4948,33 @@ static int mtk_probe(struct platform_dev
+ 			return err;
+ 	}
+ 
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) {
++		eth->xgmii = devm_kzalloc(eth->dev, sizeof(*eth->xgmii), GFP_KERNEL);
++		err = mtk_usxgmii_init(eth);
++		if (err) {
++			dev_err(&pdev->dev, "usxgmii init failed\n");
++			return err;
++		}
++
++		err = mtk_xfi_pextp_init(eth);
++		if (err) {
++			dev_err(&pdev->dev, "pextp init failed\n");
++			return err;
++		}
++
++		err = mtk_xfi_pll_init(eth);
++		if (err) {
++			dev_err(&pdev->dev, "xfi pll init failed\n");
++			return err;
++		}
++
++		err = mtk_toprgu_init(eth);
++		if (err) {
++			dev_err(&pdev->dev, "toprgu init failed\n");
++			return err;
++		}
++	}
++
+ 	if (eth->soc->required_pctl) {
+ 		eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ 							    "mediatek,pctl");
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -126,6 +126,11 @@
+ #define MTK_GDMA_TO_PDMA	0x0
+ #define MTK_GDMA_DROP_ALL       0x7777
+ 
++/* GDM Egress Control Register */
++#define MTK_GDMA_EG_CTRL(x)	((x == MTK_GMAC3_ID) ?		\
++				 0x544 : 0x504 + (x * 0x1000))
++#define MTK_GDMA_XGDM_SEL	BIT(31)
++
+ /* Unicast Filter MAC Address Register - Low */
+ #define MTK_GDMA_MAC_ADRL(x)	(0x508 + (x * 0x1000))
+ 
+@@ -386,7 +391,26 @@
+ #define PHY_IAC_TIMEOUT		HZ
+ 
+ #define MTK_MAC_MISC		0x1000c
++#define MTK_MAC_MISC_V3		0x10010
+ #define MTK_MUX_TO_ESW		BIT(0)
++#define MISC_MDC_TURBO		BIT(4)
++
++/* XMAC status registers */
++#define MTK_XGMAC_STS(x)	((x == MTK_GMAC3_ID) ? 0x1001C : 0x1000C)
++#define MTK_XGMAC_FORCE_LINK(x)	((x == MTK_GMAC2_ID) ? BIT(31) : BIT(15))
++#define MTK_USXGMII_PCS_LINK	BIT(8)
++#define MTK_XGMAC_RX_FC		BIT(5)
++#define MTK_XGMAC_TX_FC		BIT(4)
++#define MTK_USXGMII_PCS_MODE	GENMASK(3, 1)
++#define MTK_XGMAC_LINK_STS	BIT(0)
++
++/* GSW bridge registers */
++#define MTK_GSW_CFG		(0x10080)
++#define GSWTX_IPG_MASK		GENMASK(19, 16)
++#define GSWTX_IPG_SHIFT		16
++#define GSWRX_IPG_MASK		GENMASK(3, 0)
++#define GSWRX_IPG_SHIFT		0
++#define GSW_IPG_11		11
+ 
+ /* Mac control registers */
+ #define MTK_MAC_MCR(x)		(0x10100 + (x * 0x100))
+@@ -411,6 +435,17 @@
+ #define MAC_MCR_FORCE_LINK	BIT(0)
+ #define MAC_MCR_FORCE_LINK_DOWN	(MAC_MCR_FORCE_MODE)
+ 
++/* Mac EEE control registers */
++#define MTK_MAC_EEE(x)		(0x10104 + (x * 0x100))
++#define MAC_EEE_WAKEUP_TIME_1000	GENMASK(31, 24)
++#define MAC_EEE_WAKEUP_TIME_100	GENMASK(23, 16)
++#define MAC_EEE_LPI_TXIDLE_THD	GENMASK(15, 8)
++#define MAC_EEE_RESV0		GENMASK(7, 4)
++#define MAC_EEE_CKG_TXILDE	BIT(3)
++#define MAC_EEE_CKG_RXLPI	BIT(2)
++#define MAC_EEE_TX_DOWN_REQ	BIT(1)
++#define MAC_EEE_LPI_MODE	BIT(0)
++
+ /* Mac status registers */
+ #define MTK_MAC_MSR(x)		(0x10108 + (x * 0x100))
+ #define MAC_MSR_EEE1G		BIT(7)
+@@ -455,6 +490,12 @@
+ #define INTF_MODE_RGMII_1000    (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED)
+ #define INTF_MODE_RGMII_10_100  0
+ 
++/* XFI Mac control registers */
++#define MTK_XMAC_MCR(x)		(0x12000 + ((x - 1) * 0x1000))
++#define XMAC_MCR_TRX_DISABLE	0xf
++#define XMAC_MCR_FORCE_TX_FC	BIT(5)
++#define XMAC_MCR_FORCE_RX_FC	BIT(4)
++
+ /* GPIO port control registers for GMAC 2*/
+ #define GPIO_OD33_CTRL8		0x4c0
+ #define GPIO_BIAS_CTRL		0xed0
+@@ -480,6 +521,7 @@
+ #define SYSCFG0_SGMII_GMAC2    ((3 << 8) & SYSCFG0_SGMII_MASK)
+ #define SYSCFG0_SGMII_GMAC1_V2 BIT(9)
+ #define SYSCFG0_SGMII_GMAC2_V2 BIT(8)
++#define SYSCFG0_SGMII_GMAC3_V2 BIT(7)
+ 
+ 
+ /* ethernet subsystem clock register */
+@@ -506,16 +548,69 @@
+ #define ETHSYS_DMA_AG_MAP_QDMA	BIT(1)
+ #define ETHSYS_DMA_AG_MAP_PPE	BIT(2)
+ 
++/* USXGMII subsystem config registers */
++/* Register to control speed */
++#define RG_PHY_TOP_SPEED_CTRL1	0x80C
++#define RG_USXGMII_RATE_UPDATE_MODE	BIT(31)
++#define RG_MAC_CK_GATED		BIT(29)
++#define RG_IF_FORCE_EN		BIT(28)
++#define RG_RATE_ADAPT_MODE	GENMASK(10, 8)
++#define RG_RATE_ADAPT_MODE_X1	0
++#define RG_RATE_ADAPT_MODE_X2	1
++#define RG_RATE_ADAPT_MODE_X4	2
++#define RG_RATE_ADAPT_MODE_X10	3
++#define RG_RATE_ADAPT_MODE_X100	4
++#define RG_RATE_ADAPT_MODE_X5	5
++#define RG_RATE_ADAPT_MODE_X50	6
++#define RG_XFI_RX_MODE		GENMASK(6, 4)
++#define RG_XFI_RX_MODE_10G	0
++#define RG_XFI_RX_MODE_5G	1
++#define RG_XFI_TX_MODE		GENMASK(2, 0)
++#define RG_XFI_TX_MODE_10G	0
++#define RG_XFI_TX_MODE_5G	1
++
++/* Register to control PCS AN */
++#define RG_PCS_AN_CTRL0		0x810
++#define RG_AN_ENABLE		BIT(0)
++
++/* Register to control USXGMII XFI PLL digital */
++#define XFI_PLL_DIG_GLB8	0x08
++#define RG_XFI_PLL_EN		BIT(31)
++
++/* Register to control USXGMII XFI PLL analog */
++#define XFI_PLL_ANA_GLB8	0x108
++#define RG_XFI_PLL_ANA_SWWA	0x02283248
++
+ /* Infrasys subsystem config registers */
+ #define INFRA_MISC2            0x70c
+ #define CO_QPHY_SEL            BIT(0)
+ #define GEPHY_MAC_SEL          BIT(1)
+ 
++/* Toprgu subsystem config registers */
++#define TOPRGU_SWSYSRST		0x18
++#define SWSYSRST_UNLOCK_KEY	GENMASK(31, 24)
++#define SWSYSRST_XFI_PLL_GRST	BIT(16)
++#define SWSYSRST_XFI_PEXPT1_GRST	BIT(15)
++#define SWSYSRST_XFI_PEXPT0_GRST	BIT(14)
++#define SWSYSRST_SGMII1_GRST	BIT(2)
++#define SWSYSRST_SGMII0_GRST	BIT(1)
++#define TOPRGU_SWSYSRST_EN		0xFC
++
+ /* Top misc registers */
++#define TOP_MISC_NETSYS_PCS_MUX	0x84
++#define NETSYS_PCS_MUX_MASK	GENMASK(1, 0)
++#define	MUX_G2_USXGMII_SEL	BIT(1)
++#define MUX_HSGMII1_G1_SEL	BIT(0)
++
+ #define USB_PHY_SWITCH_REG	0x218
+ #define QPHY_SEL_MASK		GENMASK(1, 0)
+ #define SGMII_QPHY_SEL		0x2
+ 
++/* MDIO control */
++#define MII_MMD_ACC_CTL_REG	0x0d
++#define MII_MMD_ADDR_DATA_REG	0x0e
++#define MMD_OP_MODE_DATA	BIT(14)
++
+ /* MT7628/88 specific stuff */
+ #define MT7628_PDMA_OFFSET	0x0800
+ #define MT7628_SDM_OFFSET	0x0c00
+@@ -809,13 +904,6 @@ enum mtk_gmac_id {
+ 	MTK_GMAC_ID_MAX
+ };
+ 
+-/* GDM Type */
+-enum mtk_gdm_type {
+-	MTK_GDM_TYPE = 0,
+-	MTK_XGDM_TYPE,
+-	MTK_GDM_TYPE_MAX
+-};
+-
+ enum mtk_tx_buf_type {
+ 	MTK_TYPE_SKB,
+ 	MTK_TYPE_XDP_TX,
+@@ -902,6 +990,7 @@ enum mkt_eth_capabilities {
+ 	MTK_TRGMII_BIT,
+ 	MTK_SGMII_BIT,
+ 	MTK_USXGMII_BIT,
++	MTK_2P5GPHY_BIT,
+ 	MTK_ESW_BIT,
+ 	MTK_GEPHY_BIT,
+ 	MTK_MUX_BIT,
+@@ -922,6 +1011,7 @@ enum mkt_eth_capabilities {
+ 	MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
+ 	MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT,
+ 	MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
++	MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT,
+ 	MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT,
+ 	MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT,
+ 	MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT,
+@@ -933,6 +1023,7 @@ enum mkt_eth_capabilities {
+ 	MTK_ETH_PATH_GMAC1_SGMII_BIT,
+ 	MTK_ETH_PATH_GMAC2_RGMII_BIT,
+ 	MTK_ETH_PATH_GMAC2_SGMII_BIT,
++	MTK_ETH_PATH_GMAC2_2P5GPHY_BIT,
+ 	MTK_ETH_PATH_GMAC2_GEPHY_BIT,
+ 	MTK_ETH_PATH_GMAC3_SGMII_BIT,
+ 	MTK_ETH_PATH_GDM1_ESW_BIT,
+@@ -946,6 +1037,7 @@ enum mkt_eth_capabilities {
+ #define MTK_TRGMII		BIT_ULL(MTK_TRGMII_BIT)
+ #define MTK_SGMII		BIT_ULL(MTK_SGMII_BIT)
+ #define MTK_USXGMII		BIT_ULL(MTK_USXGMII_BIT)
++#define MTK_2P5GPHY		BIT_ULL(MTK_2P5GPHY_BIT)
+ #define MTK_ESW			BIT_ULL(MTK_ESW_BIT)
+ #define MTK_GEPHY		BIT_ULL(MTK_GEPHY_BIT)
+ #define MTK_MUX			BIT_ULL(MTK_MUX_BIT)
+@@ -968,6 +1060,8 @@ enum mkt_eth_capabilities {
+ 	BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
+ #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY		\
+ 	BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
++#define MTK_ETH_MUX_GMAC2_TO_2P5GPHY		\
++	BIT_ULL(MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT)
+ #define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII	\
+ 	BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
+ #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII	\
+@@ -983,6 +1077,7 @@ enum mkt_eth_capabilities {
+ #define MTK_ETH_PATH_GMAC1_SGMII	BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT)
+ #define MTK_ETH_PATH_GMAC2_RGMII	BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
+ #define MTK_ETH_PATH_GMAC2_SGMII	BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
++#define MTK_ETH_PATH_GMAC2_2P5GPHY	BIT_ULL(MTK_ETH_PATH_GMAC2_2P5GPHY_BIT)
+ #define MTK_ETH_PATH_GMAC2_GEPHY	BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
+ #define MTK_ETH_PATH_GMAC3_SGMII	BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT)
+ #define MTK_ETH_PATH_GDM1_ESW		BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT)
+@@ -996,6 +1091,7 @@ enum mkt_eth_capabilities {
+ #define MTK_GMAC2_RGMII		(MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
+ #define MTK_GMAC2_SGMII		(MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
+ #define MTK_GMAC2_GEPHY		(MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
++#define MTK_GMAC2_2P5GPHY	(MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY)
+ #define MTK_GMAC3_SGMII		(MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII)
+ #define MTK_GDM1_ESW		(MTK_ETH_PATH_GDM1_ESW | MTK_ESW)
+ #define MTK_GMAC1_USXGMII	(MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII)
+@@ -1019,6 +1115,10 @@ enum mkt_eth_capabilities {
+ 	(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \
+ 	MTK_SHARED_SGMII)
+ 
++/* 2: GMAC2 -> XGMII */
++#define MTK_MUX_GMAC2_TO_2P5GPHY      \
++	(MTK_ETH_MUX_GMAC2_TO_2P5GPHY | MTK_MUX | MTK_INFRA)
++
+ /* 0: GMACx -> GEPHY, 1: GMACx -> SGMII where x is 1 or 2 */
+ #define MTK_MUX_GMAC12_TO_GEPHY_SGMII   \
+ 	(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX)
+@@ -1077,7 +1177,8 @@ enum mkt_eth_capabilities {
+ 		       MTK_MUX_GMAC123_TO_GEPHY_SGMII |		\
+ 		       MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 |	\
+ 		       MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII |	\
+-		       MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII)
++		       MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | \
++		       MTK_GMAC2_2P5GPHY | MTK_MUX_GMAC2_TO_2P5GPHY)
+ 
+ struct mtk_tx_dma_desc_info {
+ 	dma_addr_t	addr;
+@@ -1183,6 +1284,19 @@ struct mtk_soc_data {
+ 
+ #define MTK_DMA_MONITOR_TIMEOUT		msecs_to_jiffies(1000)
+ 
++/* struct mtk_xgmii -  This is the structure holding sgmii/usxgmii regmap and
++ *		       its characteristics
++ * @regmap:            The register map pointing at the range used to setup
++ *                     SGMII/USXGMII modes
++ * @flags:             The enum refers to which mode the sgmii wants to run on
++ * @ana_rgc3:          The offset refers to register ANA_RGC3 related to regmap
++ */
++struct mtk_xgmii {
++	struct regmap	**regmap_usxgmii;
++	struct regmap	**regmap_pextp;
++	struct regmap	*regmap_pll;
++};
++
+ /* struct mtk_eth -	This is the main datasructure for holding the state
+  *			of the driver
+  * @dev:		The device pointer
+@@ -1244,7 +1358,9 @@ struct mtk_eth {
+ 	unsigned long			sysclk;
+ 	struct regmap			*ethsys;
+ 	struct regmap			*infra;
++	struct regmap			*toprgu;
+ 	struct phylink_pcs		**sgmii_pcs;
++	struct mtk_xgmii		*xgmii;
+ 	struct regmap			*pctl;
+ 	bool				hwlro;
+ 	refcount_t			dma_refcnt;
+@@ -1400,6 +1516,19 @@ static inline u32 mtk_get_ib2_multicast_
+ 	return MTK_FOE_IB2_MULTICAST;
+ }
+ 
++static inline bool mtk_interface_mode_is_xgmii(phy_interface_t interface)
++{
++	switch (interface) {
++	case PHY_INTERFACE_MODE_USXGMII:
++	case PHY_INTERFACE_MODE_10GKR:
++	case PHY_INTERFACE_MODE_5GBASER:
++		return true;
++		break;
++	default:
++		return false;
++	}
++}
++
+ /* read the hardware status register */
+ void mtk_stats_update_mac(struct mtk_mac *mac);
+ 
+@@ -1407,8 +1536,10 @@ void mtk_w32(struct mtk_eth *eth, u32 va
+ u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
+ 
+ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
++int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id);
+ int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
+ int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id);
++int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id);
+ 
+ int mtk_eth_offload_init(struct mtk_eth *eth);
+ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+@@ -1418,5 +1549,36 @@ int mtk_flow_offload_cmd(struct mtk_eth
+ void mtk_flow_offload_cleanup(struct mtk_eth *eth, struct list_head *list);
+ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+ 
++#ifdef CONFIG_NET_MEDIATEK_SOC_USXGMII
++int mtk_usxgmii_init(struct mtk_eth *eth);
++int mtk_xfi_pextp_init(struct mtk_eth *eth);
++int mtk_xfi_pll_init(struct mtk_eth *eth);
++int mtk_toprgu_init(struct mtk_eth *eth);
++int mtk_xfi_pll_enable(struct mtk_eth *eth);
++int mtk_usxgmii_setup_mode_an(struct mtk_eth *eth, int mac_id,
++			      int max_speed);
++int mtk_usxgmii_setup_mode_force(struct mtk_eth *eth, int mac_id,
++				 const struct phylink_link_state *state);
++void mtk_usxgmii_setup_phya_an_10000(struct mtk_eth *eth, int mac_id);
++void mtk_usxgmii_reset(struct mtk_eth *eth, int mac_id);
++void mtk_sgmii_setup_phya_gen1(struct mtk_eth *eth, int mac_id);
++void mtk_sgmii_setup_phya_gen2(struct mtk_eth *eth, int mac_id);
++void mtk_sgmii_reset(struct mtk_eth *eth, int mac_id);
++#else
++static inline int mtk_usxgmii_init(struct mtk_eth *eth) { return 0; };
++static inline int mtk_xfi_pextp_init(struct mtk_eth *eth) { return 0; };
++static inline int mtk_xfi_pll_init(struct mtk_eth *eth) { return 0; };
++static inline int mtk_toprgu_init(struct mtk_eth *eth) { return 0; };
++static inline int mtk_xfi_pll_enable(struct mtk_eth *eth) { return 0; };
++static inline int mtk_usxgmii_setup_mode_an(struct mtk_eth *eth, int mac_id,
++			      int max_speed) { return 0; };
++static inline int mtk_usxgmii_setup_mode_force(struct mtk_eth *eth, int mac_id,
++				 const struct phylink_link_state *state) { return 0; };
++static inline void mtk_usxgmii_setup_phya_an_10000(struct mtk_eth *eth, int mac_id) { };
++static inline void mtk_usxgmii_reset(struct mtk_eth *eth, int mac_id) { };
++static inline void mtk_sgmii_setup_phya_gen1(struct mtk_eth *eth, int mac_id) { };
++static inline void mtk_sgmii_setup_phya_gen2(struct mtk_eth *eth, int mac_id) { };
++static inline void mtk_sgmii_reset(struct mtk_eth *eth, int mac_id) { };
++#endif
+ 
+ #endif /* MTK_ETH_H */
+--- /dev/null
++++ b/drivers/net/ethernet/mediatek/mtk_usxgmii.c
+@@ -0,0 +1,646 @@
++/* SPDX-License-Identifier: GPL-2.0
++ *
++ * Copyright (c) 2022 MediaTek Inc.
++ * Author: Henry Yen <henry.yen at mediatek.com>
++ */
++
++#include <linux/mfd/syscon.h>
++#include <linux/of.h>
++#include <linux/regmap.h>
++#include "mtk_eth_soc.h"
++
++int mtk_usxgmii_init(struct mtk_eth *eth)
++{
++	struct device_node *r = eth->dev->of_node;
++	struct mtk_xgmii *xs = eth->xgmii;
++	struct device *dev = eth->dev;
++	struct device_node *np;
++	int i;
++
++	xs->regmap_usxgmii = devm_kzalloc(dev, sizeof(*xs->regmap_usxgmii) *
++					  eth->soc->num_devs, GFP_KERNEL);
++	if (!xs->regmap_usxgmii)
++		return -ENOMEM;
++
++	for (i = 0; i < eth->soc->num_devs; i++) {
++		np = of_parse_phandle(r, "mediatek,usxgmiisys", i);
++		if (!np)
++			break;
++
++		xs->regmap_usxgmii[i] = syscon_node_to_regmap(np);
++		if (IS_ERR(xs->regmap_usxgmii[i]))
++			return PTR_ERR(xs->regmap_usxgmii[i]);
++	}
++
++	return 0;
++}
++
++int mtk_xfi_pextp_init(struct mtk_eth *eth)
++{
++	struct device *dev = eth->dev;
++	struct device_node *r = dev->of_node;
++	struct mtk_xgmii *xs = eth->xgmii;
++	struct device_node *np;
++	int i;
++
++	xs->regmap_pextp = devm_kzalloc(dev, sizeof(*xs->regmap_pextp) *
++				        eth->soc->num_devs, GFP_KERNEL);
++	if (!xs->regmap_pextp)
++		return -ENOMEM;
++
++	for (i = 0; i < eth->soc->num_devs; i++) {
++		np = of_parse_phandle(r, "mediatek,xfi_pextp", i);
++		if (!np)
++			break;
++
++		xs->regmap_pextp[i] = syscon_node_to_regmap(np);
++		if (IS_ERR(xs->regmap_pextp[i]))
++			return PTR_ERR(xs->regmap_pextp[i]);
++	}
++
++	return 0;
++}
++
++int mtk_xfi_pll_init(struct mtk_eth *eth)
++{
++	struct device_node *r = eth->dev->of_node;
++	struct mtk_xgmii *xs = eth->xgmii;
++	struct device_node *np;
++
++	np = of_parse_phandle(r, "mediatek,xfi_pll", 0);
++	if (!np)
++		return -1;
++
++	xs->regmap_pll = syscon_node_to_regmap(np);
++	if (IS_ERR(xs->regmap_pll))
++		return PTR_ERR(xs->regmap_pll);
++
++	return 0;
++}
++
++int mtk_toprgu_init(struct mtk_eth *eth)
++{
++	struct device_node *r = eth->dev->of_node;
++	struct device_node *np;
++
++	np = of_parse_phandle(r, "mediatek,toprgu", 0);
++	if (!np)
++		return -1;
++
++	eth->toprgu = syscon_node_to_regmap(np);
++	if (IS_ERR(eth->toprgu))
++		return PTR_ERR(eth->toprgu);
++
++	return 0;
++}
++
++int mtk_xfi_pll_enable(struct mtk_eth *eth)
++{
++	struct mtk_xgmii *xs = eth->xgmii;
++	u32 val = 0;
++
++	if (!xs->regmap_pll)
++		return -EINVAL;
++
++	/* Add software workaround for USXGMII PLL TCL issue */
++	regmap_write(xs->regmap_pll, XFI_PLL_ANA_GLB8, RG_XFI_PLL_ANA_SWWA);
++
++	regmap_read(xs->regmap_pll, XFI_PLL_DIG_GLB8, &val);
++	val |= RG_XFI_PLL_EN;
++	regmap_write(xs->regmap_pll, XFI_PLL_DIG_GLB8, val);
++
++	return 0;
++}
++
++static int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id)
++{
++	int xgmii_id = mac_id;
++
++	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++		switch (mac_id) {
++		case MTK_GMAC1_ID:
++		case MTK_GMAC2_ID:
++			xgmii_id = 1;
++			break;
++		case MTK_GMAC3_ID:
++			xgmii_id = 0;
++			break;
++		default:
++			xgmii_id = -1;
++		}
++	}
++
++	return xgmii_id;
++}
++
++void mtk_usxgmii_setup_phya_an_10000(struct mtk_eth *eth, int mac_id)
++{
++	struct mtk_xgmii *xs = eth->xgmii;
++	u32 id = mtk_mac2xgmii_id(eth, mac_id);
++
++	if (id >= eth->soc->num_devs ||
++	    !xs->regmap_usxgmii[id] || !xs->regmap_pextp[id])
++		return;
++
++	regmap_write(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, 0x000FFE6D);
++	regmap_write(xs->regmap_usxgmii[id], 0x818, 0x07B1EC7B);
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, 0x30000000);
++	ndelay(1020);
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, 0x10000000);
++	ndelay(1020);
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, 0x00000000);
++
++	regmap_write(xs->regmap_pextp[id], 0x9024, 0x00C9071C);
++	regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA);
++	regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707);
++	regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F);
++	regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032);
++	regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014AA);
++	regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B);
++	regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF);
++	regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA);
++	regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F);
++	regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68);
++	regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166);
++	regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000AAF);
++	regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080D0D);
++	regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030909);
++	regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000);
++	regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000);
++	regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06);
++	regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C);
++	regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000);
++	regmap_write(xs->regmap_pextp[id], 0x00F8, 0x01423342);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F20);
++	regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020);
++	regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01);
++	regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884);
++	regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002);
++	regmap_write(xs->regmap_pextp[id], 0x3010, 0x00022220);
++	regmap_write(xs->regmap_pextp[id], 0x5064, 0x0F020A01);
++	regmap_write(xs->regmap_pextp[id], 0x50B4, 0x06100600);
++	regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000);
++	regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000);
++	regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA);
++	regmap_write(xs->regmap_pextp[id], 0x306C, 0x00000F00);
++	regmap_write(xs->regmap_pextp[id], 0xA060, 0x00040000);
++	regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000001);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800);
++	udelay(150);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101);
++	udelay(15);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C101);
++	udelay(100);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F00);
++	regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000);
++	udelay(400);
++}
++
++void mtk_usxgmii_setup_phya_force_5000(struct mtk_eth *eth, int mac_id)
++{
++	unsigned int val;
++	struct mtk_xgmii *xs = eth->xgmii;
++	u32 id = mtk_mac2xgmii_id(eth, mac_id);
++
++	if (id >= eth->soc->num_devs ||
++	    !xs->regmap_usxgmii[id] || !xs->regmap_pextp[id])
++		return;
++
++	/* Setup USXGMII speed */
++	val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_5G) |
++	      FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_5G);
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	/* Disable USXGMII AN mode */
++	regmap_read(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, &val);
++	val &= ~RG_AN_ENABLE;
++	regmap_write(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, val);
++
++	/* Gated USXGMII */
++	regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
++	val |= RG_MAC_CK_GATED;
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	ndelay(1020);
++
++	/* USXGMII force mode setting */
++	regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
++	val |= RG_USXGMII_RATE_UPDATE_MODE;
++	val |= RG_IF_FORCE_EN;
++	val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1);
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	/* Un-gated USXGMII */
++	regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
++	val &= ~RG_MAC_CK_GATED;
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	ndelay(1020);
++
++	regmap_write(xs->regmap_pextp[id], 0x9024, 0x00D9071C);
++	regmap_write(xs->regmap_pextp[id], 0x2020, 0xAAA5A5AA);
++	regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707);
++	regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F);
++	regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032);
++	regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C018AA);
++	regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777812B);
++	regmap_write(xs->regmap_pextp[id], 0x506C, 0x005C9CFF);
++	regmap_write(xs->regmap_pextp[id], 0x5070, 0x9DFAFAFA);
++	regmap_write(xs->regmap_pextp[id], 0x5074, 0x273F3F3F);
++	regmap_write(xs->regmap_pextp[id], 0x5078, 0xA8883868);
++	regmap_write(xs->regmap_pextp[id], 0x507C, 0x14661466);
++	regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E001ABF);
++	regmap_write(xs->regmap_pextp[id], 0x5084, 0x080B0D0D);
++	regmap_write(xs->regmap_pextp[id], 0x5088, 0x02050909);
++	regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C000000);
++	regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04000000);
++	regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06);
++	regmap_write(xs->regmap_pextp[id], 0x50A8, 0x50808C8C);
++	regmap_write(xs->regmap_pextp[id], 0x6004, 0x18000000);
++	regmap_write(xs->regmap_pextp[id], 0x00F8, 0x00A132A1);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F20);
++	regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020);
++	regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01);
++	regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884);
++	regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002);
++	regmap_write(xs->regmap_pextp[id], 0x3010, 0x00022220);
++	regmap_write(xs->regmap_pextp[id], 0x5064, 0x0F020A01);
++	regmap_write(xs->regmap_pextp[id], 0x50B4, 0x06100600);
++	regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000);
++	regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000);
++	regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA);
++	regmap_write(xs->regmap_pextp[id], 0x306C, 0x00000F00);
++	regmap_write(xs->regmap_pextp[id], 0xA060, 0x00040000);
++	regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000003);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800);
++	udelay(150);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101);
++	udelay(15);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C101);
++	udelay(100);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F00);
++	regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000);
++	udelay(400);
++}
++
++void mtk_usxgmii_setup_phya_force_10000(struct mtk_eth *eth, int mac_id)
++{
++	struct mtk_xgmii *xs = eth->xgmii;
++	unsigned int val;
++	u32 id = mtk_mac2xgmii_id(eth, mac_id);
++
++	if (id >= eth->soc->num_devs ||
++	    !xs->regmap_usxgmii[id] || !xs->regmap_pextp[id])
++		return;
++
++	/* Setup USXGMII speed */
++	val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_10G) |
++	      FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_10G);
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	/* Disable USXGMII AN mode */
++	regmap_read(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, &val);
++	val &= ~RG_AN_ENABLE;
++	regmap_write(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, val);
++
++	/* Gated USXGMII */
++	regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
++	val |= RG_MAC_CK_GATED;
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	ndelay(1020);
++
++	/* USXGMII force mode setting */
++	regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
++	val |= RG_USXGMII_RATE_UPDATE_MODE;
++	val |= RG_IF_FORCE_EN;
++	val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1);
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	/* Un-gated USXGMII */
++	regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
++	val &= ~RG_MAC_CK_GATED;
++	regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
++
++	ndelay(1020);
++
++	regmap_write(xs->regmap_pextp[id], 0x9024, 0x00C9071C);
++	regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA);
++	regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707);
++	regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F);
++	regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032);
++	regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014AA);
++	regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B);
++	regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF);
++	regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA);
++	regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F);
++	regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68);
++	regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166);
++	regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000AAF);
++	regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080D0D);
++	regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030909);
++	regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000);
++	regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000);
++	regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06);
++	regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C);
++	regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000);
++	regmap_write(xs->regmap_pextp[id], 0x00F8, 0x01423342);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F20);
++	regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020);
++	regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01);
++	regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884);
++	regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002);
++	regmap_write(xs->regmap_pextp[id], 0x3010, 0x00022220);
++	regmap_write(xs->regmap_pextp[id], 0x5064, 0x0F020A01);
++	regmap_write(xs->regmap_pextp[id], 0x50B4, 0x06100600);
++	regmap_write(xs->regmap_pextp[id], 0x3048, 0x49664100);
++	regmap_write(xs->regmap_pextp[id], 0x3050, 0x00000000);
++	regmap_write(xs->regmap_pextp[id], 0x3054, 0x00000000);
++	regmap_write(xs->regmap_pextp[id], 0x306C, 0x00000F00);
++	regmap_write(xs->regmap_pextp[id], 0xA060, 0x00040000);
++	regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000001);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800);
++	udelay(150);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101);
++	udelay(15);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C101);
++	udelay(100);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F00);
++	regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000);
++	udelay(400);
++}
++
++void mtk_usxgmii_reset(struct mtk_eth *eth, int mac_id)
++{
++	u32 id = mtk_mac2xgmii_id(eth, mac_id);
++
++	if (id >= eth->soc->num_devs || !eth->toprgu)
++		return;
++
++	switch (mac_id) {
++	case MTK_GMAC2_ID:
++		regmap_write(eth->toprgu, 0xFC, 0x0000A004);
++		regmap_write(eth->toprgu, 0x18, 0x88F0A004);
++		regmap_write(eth->toprgu, 0xFC, 0x00000000);
++		regmap_write(eth->toprgu, 0x18, 0x88F00000);
++		regmap_write(eth->toprgu, 0x18, 0x00F00000);
++		break;
++	case MTK_GMAC3_ID:
++		regmap_write(eth->toprgu, 0xFC, 0x00005002);
++		regmap_write(eth->toprgu, 0x18, 0x88F05002);
++		regmap_write(eth->toprgu, 0xFC, 0x00000000);
++		regmap_write(eth->toprgu, 0x18, 0x88F00000);
++		regmap_write(eth->toprgu, 0x18, 0x00F00000);
++		break;
++	}
++
++	mdelay(10);
++}
++
++int mtk_usxgmii_setup_mode_an(struct mtk_eth *eth, int mac_id, int max_speed)
++{
++	if (mac_id < 0 || mac_id >= eth->soc->num_devs)
++		return -EINVAL;
++
++	if ((max_speed != SPEED_10000) && (max_speed != SPEED_5000))
++		return -EINVAL;
++
++	mtk_xfi_pll_enable(eth);
++	mtk_usxgmii_reset(eth, mac_id);
++	mtk_usxgmii_setup_phya_an_10000(eth, mac_id);
++
++	return 0;
++}
++
++int mtk_usxgmii_setup_mode_force(struct mtk_eth *eth, int mac_id,
++				 const struct phylink_link_state *state)
++{
++	if (mac_id < 0 || mac_id >= eth->soc->num_devs)
++		return -EINVAL;
++
++	mtk_xfi_pll_enable(eth);
++	mtk_usxgmii_reset(eth, mac_id);
++	if (state->interface == PHY_INTERFACE_MODE_5GBASER)
++		mtk_usxgmii_setup_phya_force_5000(eth, mac_id);
++	else
++		mtk_usxgmii_setup_phya_force_10000(eth, mac_id);
++
++	return 0;
++}
++
++void mtk_sgmii_setup_phya_gen1(struct mtk_eth *eth, int mac_id)
++{
++	u32 id = mtk_mac2xgmii_id(eth, mac_id);
++	struct mtk_xgmii *xs = eth->xgmii;
++
++	if (id >= eth->soc->num_devs || !xs->regmap_pextp[id])
++		return;
++
++	regmap_write(xs->regmap_pextp[id], 0x9024, 0x00D9071C);
++	regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA);
++	regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020207);
++	regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E05050F);
++	regmap_write(xs->regmap_pextp[id], 0x2040, 0x00200032);
++	regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014BA);
++	regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B);
++	regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF);
++	regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA);
++	regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F);
++	regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68);
++	regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166);
++	regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000EAF);
++	regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080E0D);
++	regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030B09);
++	regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000);
++	regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000);
++	regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0606);
++	regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C);
++	regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000);
++	regmap_write(xs->regmap_pextp[id], 0x00F8, 0x00FA32FA);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F21);
++	regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020);
++	regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01);
++	regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884);
++	regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002);
++	regmap_write(xs->regmap_pextp[id], 0x3010, 0x00011110);
++	regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000);
++	regmap_write(xs->regmap_pextp[id], 0x3064, 0x0000C000);
++	regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000);
++	regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA);
++	regmap_write(xs->regmap_pextp[id], 0x306C, 0x20200F00);
++	regmap_write(xs->regmap_pextp[id], 0xA060, 0x00050000);
++	regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000007);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800);
++	udelay(150);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101);
++	udelay(15);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C101);
++	udelay(100);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F01);
++	regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000);
++	udelay(400);
++}
++
++void mtk_sgmii_setup_phya_gen2(struct mtk_eth *eth, int mac_id)
++{
++	struct mtk_xgmii *xs = eth->xgmii;
++	u32 id = mtk_mac2xgmii_id(eth, mac_id);
++
++	if (id >= eth->soc->num_devs || !xs->regmap_pextp[id])
++		return;
++
++	regmap_write(xs->regmap_pextp[id], 0x9024, 0x00D9071C);
++	regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA);
++	regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707);
++	regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F);
++	regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032);
++	regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014AA);
++	regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B);
++	regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF);
++	regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA);
++	regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F);
++	regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68);
++	regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166);
++	regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000AAF);
++	regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080D0D);
++	regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030909);
++	regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000);
++	regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000);
++	regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06);
++	regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C);
++	regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000);
++	regmap_write(xs->regmap_pextp[id], 0x00F8, 0x009C329C);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F21);
++	regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020);
++	regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01);
++	regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884);
++	regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002);
++	regmap_write(xs->regmap_pextp[id], 0x3010, 0x00011110);
++	regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000);
++	regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000);
++	regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA);
++	regmap_write(xs->regmap_pextp[id], 0x306C, 0x22000F00);
++	regmap_write(xs->regmap_pextp[id], 0xA060, 0x00050000);
++	regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000005);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800);
++	udelay(150);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101);
++	udelay(15);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C111);
++	ndelay(1020);
++	regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C101);
++	udelay(100);
++	regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030);
++	regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F01);
++	regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000);
++	udelay(400);
++}
++
++void mtk_sgmii_reset(struct mtk_eth *eth, int mac_id)
++{
++	u32 id = mtk_mac2xgmii_id(eth, mac_id);
++	u32 val = 0;
++
++	if (id >= eth->soc->num_devs || !eth->toprgu)
++		return;
++
++	switch (mac_id) {
++	case MTK_GMAC2_ID:
++		/* Enable software reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
++		val |= SWSYSRST_XFI_PEXPT1_GRST |
++		       SWSYSRST_SGMII1_GRST;
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
++
++		/* Assert SGMII reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
++		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
++		       SWSYSRST_XFI_PEXPT1_GRST |
++		       SWSYSRST_SGMII1_GRST;
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
++
++		udelay(100);
++
++		/* De-assert SGMII reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
++		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
++		val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
++			 SWSYSRST_SGMII1_GRST);
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
++
++		/* Disable software reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
++		val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
++			 SWSYSRST_SGMII1_GRST);
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
++		break;
++	case MTK_GMAC3_ID:
++		/* Enable Software reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
++		val |= SWSYSRST_XFI_PEXPT0_GRST |
++		       SWSYSRST_SGMII0_GRST;
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
++
++		/* Assert SGMII reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
++		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
++		       SWSYSRST_XFI_PEXPT0_GRST |
++		       SWSYSRST_SGMII0_GRST;
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
++
++		udelay(100);
++
++		/* De-assert SGMII reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
++		val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
++		val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
++			 SWSYSRST_SGMII0_GRST);
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
++
++		/* Disable software reset */
++		regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
++		val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
++			 SWSYSRST_SGMII0_GRST);
++		regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
++		break;
++	}
++
++	mdelay(1);
++}
+--- a/drivers/net/ethernet/mediatek/Kconfig
++++ b/drivers/net/ethernet/mediatek/Kconfig
+@@ -11,6 +11,14 @@ config NET_MEDIATEK_SOC_WED
+ 	depends on ARCH_MEDIATEK || COMPILE_TEST
+ 	def_bool NET_MEDIATEK_SOC != n
+ 
++config NET_MEDIATEK_SOC_USXGMII
++	bool "Support USXGMII SerDes on MT7988"
++	depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
++	def_bool NET_MEDIATEK_SOC != n
++	help
++	  Include support for 10G USXGMII SerDes unit which can
++	  be found on MT7988.
++
+ config NET_MEDIATEK_SOC
+ 	tristate "MediaTek SoC Gigabit Ethernet support"
+ 	depends on NET_DSA || !NET_DSA
diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15
index 5170dfdf98..7268b69389 100644
--- a/target/linux/mediatek/filogic/config-5.15
+++ b/target/linux/mediatek/filogic/config-5.15
@@ -253,6 +253,7 @@ CONFIG_NET_DSA_MT7530=y
 CONFIG_NET_DSA_TAG_MTK=y
 CONFIG_NET_FLOW_LIMIT=y
 CONFIG_NET_MEDIATEK_SOC=y
+CONFIG_NET_MEDIATEK_SOC_USXGMII=y
 CONFIG_NET_MEDIATEK_SOC_WED=y
 CONFIG_NET_SELFTESTS=y
 CONFIG_NET_SWITCHDEV=y
diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15
index be51e02f4d..88ca94472c 100644
--- a/target/linux/mediatek/mt7622/config-5.15
+++ b/target/linux/mediatek/mt7622/config-5.15
@@ -275,6 +275,7 @@ CONFIG_NET_DSA_MT7530=y
 CONFIG_NET_DSA_TAG_MTK=y
 CONFIG_NET_FLOW_LIMIT=y
 CONFIG_NET_MEDIATEK_SOC=y
+# CONFIG_NET_MEDIATEK_SOC_USXGMII is not set
 CONFIG_NET_MEDIATEK_SOC_WED=y
 CONFIG_NET_SELFTESTS=y
 CONFIG_NET_SWITCHDEV=y
diff --git a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch
index 4187557b78..04ca80c213 100644
--- a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch
+++ b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch
@@ -20,7 +20,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
 
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -231,13 +231,35 @@ static int _mtk_mdio_write(struct mtk_et
+@@ -323,13 +323,35 @@ static int _mtk_mdio_write(struct mtk_et
  	if (ret < 0)
  		return ret;
  
@@ -63,7 +63,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  
  	ret = mtk_mdio_busy_wait(eth);
  	if (ret < 0)
-@@ -254,12 +276,33 @@ static int _mtk_mdio_read(struct mtk_eth
+@@ -346,12 +368,33 @@ static int _mtk_mdio_read(struct mtk_eth
  	if (ret < 0)
  		return ret;
  
@@ -103,7 +103,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  
  	ret = mtk_mdio_busy_wait(eth);
  	if (ret < 0)
-@@ -729,6 +772,7 @@ static int mtk_mdio_init(struct mtk_eth
+@@ -1018,6 +1061,7 @@ static int mtk_mdio_init(struct mtk_eth
  	eth->mii_bus->name = "mdio";
  	eth->mii_bus->read = mtk_mdio_read;
  	eth->mii_bus->write = mtk_mdio_write;
@@ -113,7 +113,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -376,9 +376,12 @@
+@@ -382,9 +382,12 @@
  #define PHY_IAC_ADDR_MASK	GENMASK(24, 20)
  #define PHY_IAC_ADDR(x)		FIELD_PREP(PHY_IAC_ADDR_MASK, (x))
  #define PHY_IAC_CMD_MASK	GENMASK(19, 18)
diff --git a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch
index 285e24429a..a613803ee6 100644
--- a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch
+++ b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch
@@ -14,7 +14,7 @@ Signed-off-by: René van Dorst <opensource at vdorst.com>
 
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -4261,6 +4261,7 @@ static const struct net_device_ops mtk_n
+@@ -4638,6 +4638,7 @@ static const struct net_device_ops mtk_n
  
  static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
  {
@@ -22,7 +22,7 @@ Signed-off-by: René van Dorst <opensource at vdorst.com>
  	const __be32 *_id = of_get_property(np, "reg", NULL);
  	phy_interface_t phy_mode;
  	struct phylink *phylink;
-@@ -4389,6 +4390,9 @@ static int mtk_add_mac(struct mtk_eth *e
+@@ -4796,6 +4797,9 @@ static int mtk_add_mac(struct mtk_eth *e
  		register_netdevice_notifier(&mac->device_notifier);
  	}
  




More information about the lede-commits mailing list