aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux
diff options
context:
space:
mode:
authorDaniel Golle <daniel@makrotopia.org>2023-04-30 17:16:12 +0100
committerDaniel Golle <daniel@makrotopia.org>2023-05-24 19:26:52 +0100
commit5970f5d02764fa414660f773e8e7556c69577195 (patch)
treeabe9aff69ff9a09360b3d857cbc33ad18c313136 /target/linux
parentd5dc84f44eafc2d9c2d2621c43821d8d43cef9b1 (diff)
downloadupstream-5970f5d02764fa414660f773e8e7556c69577195.tar.gz
upstream-5970f5d02764fa414660f773e8e7556c69577195.tar.bz2
upstream-5970f5d02764fa414660f773e8e7556c69577195.zip
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@makrotopia.org> (cherry picked from commit 6983a215d9d1966f95bc5b1c0045c200948b2079)
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch223
-rw-r--r--target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch181
-rw-r--r--target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch153
-rw-r--r--target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch292
-rw-r--r--target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch197
-rw-r--r--target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch495
-rw-r--r--target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch1671
-rw-r--r--target/linux/mediatek/filogic/config-5.151
-rw-r--r--target/linux/mediatek/mt7622/config-5.151
-rw-r--r--target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch8
-rw-r--r--target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch4
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@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@kernel.org>
+Signed-off-by: Daniel Golle <daniel@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@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@kernel.org>
+Signed-off-by: Daniel Golle <daniel@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@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@kernel.org>
+Signed-off-by: Daniel Golle <daniel@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@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@kernel.org>
+Signed-off-by: Daniel Golle <daniel@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@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@kernel.org>
+Signed-off-by: Daniel Golle <daniel@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@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@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@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@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@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@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@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@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@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@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);
}