[rdk-b][common][bsp][Refactor and sync kernel from Openwrt]

[Description]
Refactor and sync kernel from Openwrt

[Release-log]
N/A

diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/415-v6.0-mtd-core-check-partition-before-dereference.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/415-v6.0-mtd-core-check-partition-before-dereference.patch
new file mode 100644
index 0000000..028f5ba
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/415-v6.0-mtd-core-check-partition-before-dereference.patch
@@ -0,0 +1,30 @@
+From 7ec4cdb321738d44ae5d405e7b6ac73dfbf99caa Mon Sep 17 00:00:00 2001
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Date: Mon, 25 Jul 2022 22:49:25 +0900
+Subject: [PATCH] mtd: core: check partition before dereference
+
+syzbot is reporting NULL pointer dereference at mtd_check_of_node() [1],
+for mtdram test device (CONFIG_MTD_MTDRAM) is not partition.
+
+Link: https://syzkaller.appspot.com/bug?extid=fe013f55a2814a9e8cfd [1]
+Reported-by: syzbot <syzbot+fe013f55a2814a9e8cfd@syzkaller.appspotmail.com>
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Fixes: ad9b10d1eaada169 ("mtd: core: introduce of support for dynamic partitions")
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+CC: stable@vger.kernel.org
+Signed-off-by: Richard Weinberger <richard@nod.at>
+---
+ drivers/mtd/mtdcore.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/mtd/mtdcore.c
++++ b/drivers/mtd/mtdcore.c
+@@ -602,6 +602,8 @@ static void mtd_check_of_node(struct mtd
+ 		return;
+ 
+ 	/* Check if a partitions node exist */
++	if (!mtd_is_partition(mtd))
++		return;
+ 	parent = mtd_get_master(mtd);
+ 	parent_dn = dev_of_node(&parent->dev);
+ 	if (!parent_dn)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
index d8f45e8..7dc0b8d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
@@ -169,6 +169,7 @@
     file://412-v5.19-mtd-call-of_platform_populate-for-MTD-partitions.patch \
     file://413-v6.0-mtd-next-mtd-core-introduce-of-support-for-dynamic-partitions.patch \
     file://414-v6.1-mtd-allow-getting-MTD-device-associated-with-a-speci.patch \
+    file://415-v6.0-mtd-core-check-partition-before-dereference.patch \
     file://430-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch \
     file://431-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch \
     file://432-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/480-mtd-set-rootfs-to-be-root-dev.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/480-mtd-set-rootfs-to-be-root-dev.patch
index 1189ce0..2544fa4 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/480-mtd-set-rootfs-to-be-root-dev.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/480-mtd-set-rootfs-to-be-root-dev.patch
@@ -20,7 +20,7 @@
  #include <linux/nvmem-provider.h>
  
  #include <linux/mtd/mtd.h>
-@@ -760,6 +761,15 @@ int add_mtd_device(struct mtd_info *mtd)
+@@ -762,6 +763,15 @@ int add_mtd_device(struct mtd_info *mtd)
  	   of this try_ nonsense, and no bitching about it
  	   either. :) */
  	__module_get(THIS_MODULE);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/495-mtd-core-add-get_mtd_device_by_node.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/495-mtd-core-add-get_mtd_device_by_node.patch
index a7377578..ada1415 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/495-mtd-core-add-get_mtd_device_by_node.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/495-mtd-core-add-get_mtd_device_by_node.patch
@@ -17,7 +17,7 @@
 
 --- a/drivers/mtd/mtdcore.c
 +++ b/drivers/mtd/mtdcore.c
-@@ -1142,6 +1142,44 @@ out_unlock:
+@@ -1144,6 +1144,44 @@ out_unlock:
  }
  EXPORT_SYMBOL_GPL(get_mtd_device_nm);
  
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Kconfig b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Kconfig
index 42e6b38..7bfc78b 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Kconfig
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Kconfig
@@ -20,6 +20,16 @@
 	---help---
 	  This options enable MTK Ethernet NETSYS V2 support
 
+config MEDIATEK_NETSYS_V3
+	tristate "MediaTek Ethernet NETSYS V3 support"
+	depends on ARCH_MEDIATEK && NET_MEDIATEK_SOC
+	---help---
+	  This options enable MTK Ethernet NETSYS V3 support for
+	  XGMAC and USXGMII.
+
+	  If you have a network system belong to this class, say Y.
+	  If unsure, say N.
+
 config NET_MEDIATEK_HNAT
 	tristate "MediaTek HW NAT support"
 	depends on NET_MEDIATEK_SOC && NF_CONNTRACK && IP_NF_NAT
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
index 13c5b4e..634640d 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
@@ -4,5 +4,5 @@
 #
 
 obj-$(CONFIG_NET_MEDIATEK_SOC)			+= mtk_eth.o
-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
 obj-$(CONFIG_NET_MEDIATEK_HNAT)			+= mtk_hnat/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 0d5ca16..c6f76bf 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -24,6 +24,7 @@
 #include <linux/ctype.h>
 #include <linux/debugfs.h>
 #include <linux/of_mdio.h>
+#include <linux/of_address.h>
 
 #include "mtk_eth_soc.h"
 #include "mtk_eth_dbg.h"
@@ -43,20 +44,55 @@
 typedef int (*mtk_lro_dbg_func) (int par);
 
 struct mtk_eth_debug {
-        struct dentry *root;
+	struct dentry *root;
+	void __iomem *base;
+	int direct_access;
 };
 
 struct mtk_eth *g_eth;
 
 struct mtk_eth_debug eth_debug;
 
+int mt798x_iomap(void)
+{
+	struct device_node *np = NULL;
+
+	np = of_find_node_by_name(NULL, "switch0");
+	if (np) {
+		eth_debug.base = of_iomap(np, 0);
+		if (!eth_debug.base) {
+			pr_err("of_iomap failed\n");
+			of_node_put(np);
+			return -ENOMEM;
+		}
+
+		of_node_put(np);
+		eth_debug.direct_access = 1;
+	}
+
+	return 0;
+}
+
+int mt798x_iounmap(void)
+{
+	eth_debug.direct_access = 0;
+	if (eth_debug.base)
+		iounmap(eth_debug.base);
+
+	return 0;
+}
+
 void mt7530_mdio_w32(struct mtk_eth *eth, u16 reg, u32 val)
 {
 	mutex_lock(&eth->mii_bus->mdio_lock);
 
-	_mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
-	_mtk_mdio_write(eth, 0x1f, (reg >> 2) & 0xf,  val & 0xffff);
-	_mtk_mdio_write(eth, 0x1f, 0x10, val >> 16);
+	if (eth_debug.direct_access)
+		__raw_writel(val, eth_debug.base + reg);
+	else {
+		_mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+		_mtk_mdio_write(eth, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
+		_mtk_mdio_write(eth, 0x1f, 0x10, val >> 16);
+	}
 
 	mutex_unlock(&eth->mii_bus->mdio_lock);
 }
@@ -64,9 +100,15 @@
 u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
 {
 	u16 high, low;
+	u32 ret;
 
 	mutex_lock(&eth->mii_bus->mdio_lock);
 
+	if (eth_debug.direct_access) {
+		ret = __raw_readl(eth_debug.base + reg);
+		mutex_unlock(&eth->mii_bus->mdio_lock);
+		return ret;
+	}
 	_mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
 	low = _mtk_mdio_read(eth, 0x1f, (reg >> 2) & 0xf);
 	high = _mtk_mdio_read(eth, 0x1f, 0x10);
@@ -118,6 +160,7 @@
 }
 
 static const struct file_operations mtketh_debug_fops = {
+	.owner = THIS_MODULE,
 	.open = mtketh_debug_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
@@ -209,6 +252,7 @@
 }
 
 static const struct file_operations mtketh_debug_mt7530sw_fops = {
+	.owner = THIS_MODULE,
 	.open = mtketh_debug_mt7530sw_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
@@ -417,7 +461,7 @@
 		*read_data = mt7530_mdio_r32(eth, phy_register);
 
 	else
-		*read_data = _mtk_mdio_read(eth, phy_addr, phy_register);
+		*read_data = mdiobus_read(eth->mii_bus, phy_addr, phy_register);
 }
 
 void mii_mgr_write_combine(struct mtk_eth *eth, u16 phy_addr, u16 phy_register,
@@ -427,17 +471,17 @@
 		mt7530_mdio_w32(eth, phy_register, write_data);
 
 	else
-		_mtk_mdio_write(eth, phy_addr, phy_register, write_data);
+		mdiobus_write(eth->mii_bus, phy_addr, phy_register, write_data);
 }
 
 static void mii_mgr_read_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 *data)
 {
-	*data = _mtk_mdio_read(eth, port, mdiobus_c45_addr(devad, reg));
+	*data = mdiobus_read(eth->mii_bus, port, mdiobus_c45_addr(devad, reg));
 }
 
 static void mii_mgr_write_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 data)
 {
-	_mtk_mdio_write(eth, port, mdiobus_c45_addr(devad, reg), data);
+	mdiobus_write(eth->mii_bus, port, mdiobus_c45_addr(devad, reg), data);
 }
 
 int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -519,75 +563,112 @@
 	return -EFAULT;
 }
 
+static void gdm_reg_dump_v3(struct mtk_eth *eth, u32 gdm_id, u32 mib_base)
+{
+	pr_info("| GDMA%d_RX_GBCNT  : %010u (Rx Good Bytes)	|\n",
+		gdm_id, mtk_r32(eth, mib_base));
+	pr_info("| GDMA%d_RX_GPCNT  : %010u (Rx Good Pkts)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x08));
+	pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x10));
+	pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x14));
+	pr_info("| GDMA%d_RX_SERCNT : %010u (too short)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x18));
+	pr_info("| GDMA%d_RX_LERCNT : %010u (too long)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x1C));
+	pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x20));
+	pr_info("| GDMA%d_RX_FCCNT  : %010u (flow control)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x24));
+	pr_info("| GDMA%d_RX_VDPCNT : %010u (VID drop)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x28));
+	pr_info("| GDMA%d_RX_PFCCNT : %010u (priority flow control)\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x2C));
+	pr_info("| GDMA%d_TX_GBCNT  : %010u (Tx Good Bytes)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x40));
+	pr_info("| GDMA%d_TX_GPCNT  : %010u (Tx Good Pkts)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x48));
+	pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x50));
+	pr_info("| GDMA%d_TX_COLCNT : %010u (collision count)|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x54));
+	pr_info("| GDMA%d_TX_OERCNT : %010u (overflow error)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x58));
+	pr_info("| GDMA%d_TX_FCCNT  : %010u (flow control)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x60));
+	pr_info("| GDMA%d_TX_PFCCNT : %010u (priority flow control)\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x64));
+	pr_info("|						|\n");
+}
+
+static void gdm_reg_dump_v2(struct mtk_eth *eth, u32 gdm_id, u32 mib_base)
+{
+	pr_info("| GDMA%d_RX_GBCNT  : %010u (Rx Good Bytes)	|\n",
+		gdm_id, mtk_r32(eth, mib_base));
+	pr_info("| GDMA%d_RX_GPCNT  : %010u (Rx Good Pkts)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x08));
+	pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x10));
+	pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x14));
+	pr_info("| GDMA%d_RX_SERCNT : %010u (too short)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x18));
+	pr_info("| GDMA%d_RX_LERCNT : %010u (too long)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x1C));
+	pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x20));
+	pr_info("| GDMA%d_RX_FCCNT  : %010u (flow control)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x24));
+	pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x28));
+	pr_info("| GDMA%d_TX_COLCNT : %010u (collision count)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x2C));
+	pr_info("| GDMA%d_TX_GBCNT  : %010u (Tx Good Bytes)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x30));
+	pr_info("| GDMA%d_TX_GPCNT  : %010u (Tx Good Pkts)	|\n",
+		gdm_id, mtk_r32(eth, mib_base + 0x38));
+	pr_info("|						|\n");
+}
+
+static void gdm_cnt_read(struct mtk_eth *eth)
+{
+	u32 i, mib_base;
+
+	pr_info("\n			<<CPU>>\n");
+	pr_info("			   |\n");
+	pr_info("+-----------------------------------------------+\n");
+	pr_info("|		  <<PSE>>		        |\n");
+	pr_info("+-----------------------------------------------+\n");
+	pr_info("			   |\n");
+	pr_info("+-----------------------------------------------+\n");
+	pr_info("|		  <<GDMA>>		        |\n");
+
+	for (i = 0; i < MTK_MAC_COUNT; i++) {
+		mib_base = MTK_GDM1_TX_GBCNT + MTK_STAT_OFFSET * i;
+
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+			gdm_reg_dump_v3(eth, i + 1, mib_base);
+		else
+			gdm_reg_dump_v2(eth, i + 1, mib_base);
+	}
+
+	pr_info("+-----------------------------------------------+\n");
+}
+
 int esw_cnt_read(struct seq_file *seq, void *v)
 {
 	unsigned int pkt_cnt = 0;
 	int i = 0;
 	struct mtk_eth *eth = g_eth;
-	unsigned int mib_base = MTK_GDM1_TX_GBCNT;
 
-	seq_puts(seq, "\n		  <<CPU>>\n");
-	seq_puts(seq, "		    |\n");
-	seq_puts(seq, "+-----------------------------------------------+\n");
-	seq_puts(seq, "|		  <<PSE>>		        |\n");
-	seq_puts(seq, "+-----------------------------------------------+\n");
-	seq_puts(seq, "		   |\n");
-	seq_puts(seq, "+-----------------------------------------------+\n");
-	seq_puts(seq, "|		  <<GDMA>>		        |\n");
-	seq_printf(seq, "| GDMA1_RX_GBCNT  : %010u (Rx Good Bytes)	|\n",
-		   mtk_r32(eth, mib_base));
-	seq_printf(seq, "| GDMA1_RX_GPCNT  : %010u (Rx Good Pkts)	|\n",
-		   mtk_r32(eth, mib_base+0x08));
-	seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow error)	|\n",
-		   mtk_r32(eth, mib_base+0x10));
-	seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error)	|\n",
-		   mtk_r32(eth, mib_base+0x14));
-	seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short)	|\n",
-		   mtk_r32(eth, mib_base+0x18));
-	seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long)	|\n",
-		   mtk_r32(eth, mib_base+0x1C));
-	seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (checksum error)	|\n",
-		   mtk_r32(eth, mib_base+0x20));
-	seq_printf(seq, "| GDMA1_RX_FCCNT  : %010u (flow control)	|\n",
-		   mtk_r32(eth, mib_base+0x24));
-	seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (about count)	|\n",
-		   mtk_r32(eth, mib_base+0x28));
-	seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision count)	|\n",
-		   mtk_r32(eth, mib_base+0x2C));
-	seq_printf(seq, "| GDMA1_TX_GBCNT  : %010u (Tx Good Bytes)	|\n",
-		   mtk_r32(eth, mib_base+0x30));
-	seq_printf(seq, "| GDMA1_TX_GPCNT  : %010u (Tx Good Pkts)	|\n",
-		   mtk_r32(eth, mib_base+0x38));
-	seq_puts(seq, "|						|\n");
-	seq_printf(seq, "| GDMA2_RX_GBCNT  : %010u (Rx Good Bytes)	|\n",
-		   mtk_r32(eth, mib_base+0x40));
-	seq_printf(seq, "| GDMA2_RX_GPCNT  : %010u (Rx Good Pkts)	|\n",
-		   mtk_r32(eth, mib_base+0x48));
-	seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow error)	|\n",
-		   mtk_r32(eth, mib_base+0x50));
-	seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error)	|\n",
-		   mtk_r32(eth, mib_base+0x54));
-	seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short)	|\n",
-		   mtk_r32(eth, mib_base+0x58));
-	seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long)	|\n",
-		   mtk_r32(eth, mib_base+0x5C));
-	seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (checksum error)	|\n",
-		   mtk_r32(eth, mib_base+0x60));
-	seq_printf(seq, "| GDMA2_RX_FCCNT  : %010u (flow control)	|\n",
-		   mtk_r32(eth, mib_base+0x64));
-	seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip)		|\n",
-		   mtk_r32(eth, mib_base+0x68));
-	seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision)	|\n",
-		   mtk_r32(eth, mib_base+0x6C));
-	seq_printf(seq, "| GDMA2_TX_GBCNT  : %010u (Tx Good Bytes)	|\n",
-		   mtk_r32(eth, mib_base+0x70));
-	seq_printf(seq, "| GDMA2_TX_GPCNT  : %010u (Tx Good Pkts)	|\n",
-		   mtk_r32(eth, mib_base+0x78));
-	seq_puts(seq, "+-----------------------------------------------+\n");
+	gdm_cnt_read(eth);
 
 	if (!mt7530_exist(eth))
 		return 0;
 
+	mt798x_iomap();
+
 #define DUMP_EACH_PORT(base)					\
 	do { \
 		for (i = 0; i < 7; i++) {				\
@@ -643,6 +724,8 @@
 
 	seq_puts(seq, "\n");
 
+	mt798x_iounmap();
+
 	return 0;
 }
 
@@ -680,7 +763,8 @@
 			   tx_ring->txd1, tx_ring->txd2,
 			   tx_ring->txd3, tx_ring->txd4);
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 			seq_printf(seq, " %08x %08x %08x %08x",
 				   tx_ring->txd5, tx_ring->txd6,
 				   tx_ring->txd7, tx_ring->txd8);
@@ -720,7 +804,8 @@
 			   hwtx_ring->txd1, hwtx_ring->txd2,
 			   hwtx_ring->txd3, hwtx_ring->txd4);
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 			seq_printf(seq, " %08x %08x %08x %08x",
 				   hwtx_ring->txd5, hwtx_ring->txd6,
 				   hwtx_ring->txd7, hwtx_ring->txd8);
@@ -761,7 +846,8 @@
 			   rx_ring->rxd1, rx_ring->rxd2,
 			   rx_ring->rxd3, rx_ring->rxd4);
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 			seq_printf(seq, " %08x %08x %08x %08x",
 				   rx_ring->rxd5, rx_ring->rxd6,
 				   rx_ring->rxd7, rx_ring->rxd8);
@@ -806,7 +892,8 @@
 
 	seq_printf(seq, "| FE_INT_STA	: %08x |\n",
 		   mtk_r32(eth, MTK_FE_INT_STATUS));
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 		seq_printf(seq, "| FE_INT_STA2	: %08x |\n",
 			   mtk_r32(eth, MTK_FE_INT_STATUS2));
 
@@ -817,13 +904,20 @@
 	seq_printf(seq, "| PSE_IQ_STA2	: %08x |\n",
 		   mtk_r32(eth, MTK_PSE_IQ_STA(1)));
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		seq_printf(seq, "| PSE_IQ_STA3	: %08x |\n",
 			   mtk_r32(eth, MTK_PSE_IQ_STA(2)));
 		seq_printf(seq, "| PSE_IQ_STA4	: %08x |\n",
 			   mtk_r32(eth, MTK_PSE_IQ_STA(3)));
 		seq_printf(seq, "| PSE_IQ_STA5	: %08x |\n",
 			   mtk_r32(eth, MTK_PSE_IQ_STA(4)));
+		seq_printf(seq, "| PSE_IQ_STA6	: %08x |\n",
+			   mtk_r32(eth, MTK_PSE_IQ_STA(5)));
+		seq_printf(seq, "| PSE_IQ_STA7	: %08x |\n",
+			   mtk_r32(eth, MTK_PSE_IQ_STA(6)));
+		seq_printf(seq, "| PSE_IQ_STA8	: %08x |\n",
+			   mtk_r32(eth, MTK_PSE_IQ_STA(7)));
 	}
 
 	seq_printf(seq, "| PSE_OQ_STA1	: %08x |\n",
@@ -831,13 +925,20 @@
 	seq_printf(seq, "| PSE_OQ_STA2	: %08x |\n",
 		   mtk_r32(eth, MTK_PSE_OQ_STA(1)));
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		seq_printf(seq, "| PSE_OQ_STA3	: %08x |\n",
 			   mtk_r32(eth, MTK_PSE_OQ_STA(2)));
 		seq_printf(seq, "| PSE_OQ_STA4	: %08x |\n",
 			   mtk_r32(eth, MTK_PSE_OQ_STA(3)));
 		seq_printf(seq, "| PSE_OQ_STA5	: %08x |\n",
 			   mtk_r32(eth, MTK_PSE_OQ_STA(4)));
+		seq_printf(seq, "| PSE_OQ_STA6	: %08x |\n",
+			   mtk_r32(eth, MTK_PSE_OQ_STA(5)));
+		seq_printf(seq, "| PSE_OQ_STA7	: %08x |\n",
+			   mtk_r32(eth, MTK_PSE_OQ_STA(6)));
+		seq_printf(seq, "| PSE_OQ_STA8	: %08x |\n",
+			   mtk_r32(eth, MTK_PSE_OQ_STA(7)));
 	}
 
 	seq_printf(seq, "| PDMA_CRX_IDX	: %08x |\n",
@@ -850,6 +951,10 @@
 		   mtk_r32(eth, MTK_QTX_DTX_PTR));
 	seq_printf(seq, "| QDMA_FQ_CNT	: %08x |\n",
 		   mtk_r32(eth, MTK_QDMA_FQ_CNT));
+	seq_printf(seq, "| QDMA_FWD_CNT	: %08x |\n",
+		   mtk_r32(eth, MTK_QDMA_FWD_CNT));
+	seq_printf(seq, "| QDMA_FSM	: %08x |\n",
+		   mtk_r32(eth, MTK_QDMA_FSM));
 	seq_printf(seq, "| FE_PSE_FREE	: %08x |\n",
 		   mtk_r32(eth, MTK_FE_PSE_FREE));
 	seq_printf(seq, "| FE_DROP_FQ	: %08x |\n",
@@ -862,16 +967,29 @@
 		   mtk_r32(eth, MTK_GDMA_FWD_CFG(0)));
 	seq_printf(seq, "| GDM2_IG_CTRL	: %08x |\n",
 		   mtk_r32(eth, MTK_GDMA_FWD_CFG(1)));
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		seq_printf(seq, "| GDM3_IG_CTRL	: %08x |\n",
+			   mtk_r32(eth, MTK_GDMA_FWD_CFG(2)));
+	}
 	seq_printf(seq, "| MAC_P1_MCR	: %08x |\n",
 		   mtk_r32(eth, MTK_MAC_MCR(0)));
 	seq_printf(seq, "| MAC_P2_MCR	: %08x |\n",
 		   mtk_r32(eth, MTK_MAC_MCR(1)));
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		seq_printf(seq, "| MAC_P3_MCR	: %08x |\n",
+			   mtk_r32(eth, MTK_MAC_MCR(2)));
+	}
 	seq_printf(seq, "| MAC_P1_FSM	: %08x |\n",
 		   mtk_r32(eth, MTK_MAC_FSM(0)));
 	seq_printf(seq, "| MAC_P2_FSM	: %08x |\n",
 		   mtk_r32(eth, MTK_MAC_FSM(1)));
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		seq_printf(seq, "| MAC_P3_FSM	: %08x |\n",
+			   mtk_r32(eth, MTK_MAC_FSM(2)));
+	}
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		seq_printf(seq, "| FE_CDM1_FSM	: %08x |\n",
 			   mtk_r32(eth, MTK_FE_CDM1_FSM));
 		seq_printf(seq, "| FE_CDM2_FSM	: %08x |\n",
@@ -880,6 +998,10 @@
 			   mtk_r32(eth, MTK_FE_CDM3_FSM));
 		seq_printf(seq, "| FE_CDM4_FSM	: %08x |\n",
 			   mtk_r32(eth, MTK_FE_CDM4_FSM));
+		seq_printf(seq, "| FE_CDM5_FSM	: %08x |\n",
+			   mtk_r32(eth, MTK_FE_CDM5_FSM));
+		seq_printf(seq, "| FE_CDM6_FSM	: %08x |\n",
+			   mtk_r32(eth, MTK_FE_CDM6_FSM));
 		seq_printf(seq, "| FE_GDM1_FSM	: %08x |\n",
 			   mtk_r32(eth, MTK_FE_GDM1_FSM));
 		seq_printf(seq, "| FE_GDM2_FSM	: %08x |\n",
@@ -895,7 +1017,8 @@
 	}
 
 	mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS);
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 		mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS2);
 
 	return 0;
@@ -919,7 +1042,8 @@
 	struct mtk_eth *eth = g_eth;
 	u32 idx, agg_cnt, agg_size;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		idx = ring_no - 4;
 		agg_cnt = RX_DMA_GET_AGG_CNT_V2(rxd->rxd6);
 	} else {
@@ -940,7 +1064,8 @@
 	struct mtk_eth *eth = g_eth;
 	u32 idx, flush_reason;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		idx = ring_no - 4;
 		flush_reason = RX_DMA_GET_FLUSH_RSN_V2(rxd->rxd6);
 	} else {
@@ -1187,7 +1312,8 @@
 {
 	struct mtk_eth *eth = g_eth;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 		hw_lro_stats_read_v2(seq, v);
 	else
 		hw_lro_stats_read_v1(seq, v);
@@ -1458,7 +1584,8 @@
 	seq_puts(seq, "[4] = hwlro_ring_enable_ctrl\n");
 	seq_puts(seq, "[5] = hwlro_stats_enable_ctrl\n\n");
 
-	if (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V3)) {
 		for (i = 1; i <= 8; i++)
 			hw_lro_auto_tlb_dump_v2(seq, i);
 	} else {
@@ -1494,7 +1621,7 @@
 		    ((reg_op1 >> MTK_LRO_RING_AGE_TIME_L_OFFSET) & 0x3ff);
 		seq_printf(seq,
 			   "Ring[%d]: MAX_AGG_CNT=%d, AGG_TIME=%d, AGE_TIME=%d, Threshold=%d\n",
-			   (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V2))? i+3 : i,
+			   (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V1)) ? i : i+3,
 			   agg_cnt, agg_time, age_time, reg_op4);
 	}
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index 52bd729..1932ac6 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -24,6 +24,8 @@
 #define MTK_FE_CDM2_FSM			0x224
 #define MTK_FE_CDM3_FSM			0x238
 #define MTK_FE_CDM4_FSM			0x298
+#define MTK_FE_CDM5_FSM			0x318
+#define MTK_FE_CDM6_FSM			0x328
 #define MTK_FE_GDM1_FSM			0x228
 #define MTK_FE_GDM2_FSM			0x22C
 #define MTK_FE_PSE_FREE			0x240
@@ -35,7 +37,7 @@
 #define MTK_SGMII_EFUSE			0x11D008C8
 #define MTK_WED_RTQM_GLO_CFG		0x15010B00
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_PSE_IQ_STA(x)		(0x180 + (x) * 0x4)
 #define MTK_PSE_OQ_STA(x)		(0x1A0 + (x) * 0x4)
 #else
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
index dcb3c8a..2b78ee1 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
@@ -14,11 +14,11 @@
 
 struct mtk_eth_muxc {
 	const char	*name;
-	int		cap_bit;
-	int		(*set_path)(struct mtk_eth *eth, int path);
+	u64		cap_bit;
+	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:
@@ -33,14 +33,22 @@
 		return "gmac2_sgmii";
 	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";
 	}
 }
 
-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 +79,7 @@
 	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 +102,7 @@
 	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 +133,7 @@
 	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;
@@ -167,10 +175,73 @@
 	return 0;
 }
 
-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int 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, 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) {
+			id = mtk_mac2xgmii_id(eth, mac_id);
+			if (MTK_HAS_FLAGS(eth->xgmii->flags[id],
+					  MTK_USXGMII_INT_2500)) {
+				val = mtk_r32(eth, MTK_XGMAC_STS(mac_id));
+				mtk_w32(eth,
+					val | (MTK_XGMAC_FORCE_LINK << 16),
+					MTK_XGMAC_STS(mac_id));
+			} else {
+				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;
 
 	spin_lock(&eth->syscfg0_lock);
 
@@ -186,6 +257,9 @@
 	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;
 	};
@@ -222,11 +296,19 @@
 	}, {
 		.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,
 	},
 };
 
-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;
 
@@ -255,12 +337,34 @@
 	return err;
 }
 
+int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id)
+{
+	int err;
+	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;
+
+	dev_err(eth->dev, "%s path %s in\n", __func__,
+		mtk_eth_path_name(path));
+
+	/* Setup proper MUXes along the path */
+	err = mtk_eth_mux_setup(eth, path);
+	if (err)
+		return err;
+
+	return 0;
+}
+
 int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
 {
-	int err, path;
+	int err;
+	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 */
 	err = mtk_eth_mux_setup(eth, path);
@@ -272,7 +376,8 @@
 
 int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
 {
-	int err, path = 0;
+	int err;
+	u64 path = 0;
 
 	if (mac_id == 1)
 		path = MTK_ETH_PATH_GMAC2_GEPHY;
@@ -290,7 +395,8 @@
 
 int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
 {
-	int err, path;
+	int err;
+	u64 path;
 
 	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
 				MTK_ETH_PATH_GMAC2_RGMII;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
index ebb3940..4655356 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
@@ -33,7 +33,8 @@
 
 int mtk_eth_cold_reset(struct mtk_eth *eth)
 {
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 		regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0);
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1))
@@ -41,7 +42,8 @@
 	else
 		ethsys_reset(eth,  RSTCTRL_ETH | RSTCTRL_FE | RSTCTRL_PPE0);
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 		regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0x3ffffff);
 
 	return 0;
@@ -344,12 +346,12 @@
 
 	/* Power down sgmii */
 	for (i = 0; i < MTK_MAX_DEVS; i++) {
-		if (!eth->sgmii->regmap[i])
+		if (!eth->xgmii->regmap_sgmii[i])
 			continue;
 
-		regmap_read(eth->sgmii->regmap[i], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+		regmap_read(eth->xgmii->regmap_sgmii[i], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
 		val |= SGMII_PHYA_PWD;
-		regmap_write(eth->sgmii->regmap[i], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+		regmap_write(eth->xgmii->regmap_sgmii[i], SGMSYS_QPHY_PWR_STATE_CTRL, val);
 	}
 
 	/* Force link down GMAC */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a05cd19..5806723 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -260,13 +260,35 @@
 	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_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);
+
+	/* 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));
+}
+
 static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
 			   const struct phylink_link_state *state)
 {
 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
 					   phylink_config);
 	struct mtk_eth *eth = mac->hw;
-	u32 mcr_cur, mcr_new, sid, i;
+	u32 sid, i;
 	int val, ge_mode, err=0;
 
 	/* MT76x8 has no hardware settings between for the MAC */
@@ -310,6 +332,14 @@
 					goto init_err;
 			}
 			break;
+		case PHY_INTERFACE_MODE_USXGMII:
+		case PHY_INTERFACE_MODE_10GKR:
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) {
+				err = mtk_gmac_usxgmii_path_setup(eth, mac->id);
+				if (err)
+					goto init_err;
+			}
+			break;
 		default:
 			goto err_phy;
 		}
@@ -389,10 +419,10 @@
 
 		/* Setup SGMIISYS with the determined property */
 		if (state->interface != PHY_INTERFACE_MODE_SGMII)
-			err = mtk_sgmii_setup_mode_force(eth->sgmii, sid,
+			err = mtk_sgmii_setup_mode_force(eth->xgmii, sid,
 							 state);
 		else
-			err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
+			err = mtk_sgmii_setup_mode_an(eth->xgmii, sid);
 
 		if (err) {
 			spin_unlock(&eth->syscfg0_lock);
@@ -402,6 +432,22 @@
 		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
 				   SYSCFG0_SGMII_MASK, val);
 		spin_unlock(&eth->syscfg0_lock);
+	} else if (state->interface == PHY_INTERFACE_MODE_USXGMII ||
+		   state->interface == PHY_INTERFACE_MODE_10GKR) {
+		sid = mac->id;
+
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
+		    sid != MTK_GMAC1_ID) {
+			if (phylink_autoneg_inband(mode))
+				err = mtk_usxgmii_setup_mode_force(eth->xgmii, sid,
+								   SPEED_10000);
+			else
+				err = mtk_usxgmii_setup_mode_an(eth->xgmii, sid,
+								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");
@@ -409,35 +455,25 @@
 	}
 
 	/* Setup gmac */
-	mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
-	mcr_new = mcr_cur;
-	mcr_new &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
-		     MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
-		     MAC_MCR_FORCE_RX_FC);
-	mcr_new |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
-		   MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
+	if (state->interface == PHY_INTERFACE_MODE_USXGMII ||
+	    state->interface == PHY_INTERFACE_MODE_10GKR) {
+		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 (state->speed) {
-	case SPEED_2500:
-	case SPEED_1000:
-		mcr_new |= MAC_MCR_SPEED_1000;
-		break;
-	case SPEED_100:
-		mcr_new |= MAC_MCR_SPEED_100;
-		break;
-	}
-	if (state->duplex == DUPLEX_FULL) {
-		mcr_new |= MAC_MCR_FORCE_DPX;
-		if (state->pause & MLO_PAUSE_TX)
-			mcr_new |= MAC_MCR_FORCE_TX_FC;
-		if (state->pause & MLO_PAUSE_RX)
-			mcr_new |= MAC_MCR_FORCE_RX_FC;
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+			switch (mac->id) {
+			case MTK_GMAC1_ID:
+				mtk_setup_bridge_switch(eth);
+				break;
+			case MTK_GMAC3_ID:
+				val = mtk_r32(eth, MTK_XGMAC_STS(mac->id));
+				mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK,
+					MTK_XGMAC_STS(mac->id));
+				break;
+			}
+		}
 	}
 
-	/* Only update control register when needed! */
-	if (mcr_new != mcr_cur)
-		mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
-
 	return;
 
 err_phy:
@@ -450,36 +486,90 @@
 		mac->id, phy_modes(state->interface), err);
 }
 
-static int mtk_mac_link_state(struct phylink_config *config,
-			      struct phylink_link_state *state)
+static int 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);
-	u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id));
 
-	state->link = (pmsr & MAC_MSR_LINK);
-	state->duplex = (pmsr & MAC_MSR_DPX) >> 1;
+	if (mac->type == MTK_XGDM_TYPE) {
+		u32 sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
 
-	switch (pmsr & (MAC_MSR_SPEED_1000 | MAC_MSR_SPEED_100)) {
-	case 0:
-		state->speed = SPEED_10;
-		break;
-	case MAC_MSR_SPEED_100:
-		state->speed = SPEED_100;
-		break;
-	case MAC_MSR_SPEED_1000:
-		state->speed = SPEED_1000;
-		break;
-	default:
-		state->speed = SPEED_UNKNOWN;
-		break;
-	}
+		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);
+	} else if (mac->type == MTK_GDM_TYPE) {
+		struct mtk_eth *eth = mac->hw;
+		struct mtk_xgmii *ss = eth->xgmii;
+		u32 id = mtk_mac2xgmii_id(eth, mac->id);
+		u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id));
+		u32 val;
+
+		regmap_read(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, &val);
+
+		state->link = FIELD_GET(SGMII_LINK_STATYS, val);
+
+		if (FIELD_GET(SGMII_AN_ENABLE, val)) {
+			regmap_read(ss->regmap_sgmii[id], SGMII_PCS_SPEED_ABILITY, &val);
+
+			val = val >> 16;
+
+			state->duplex = FIELD_GET(SGMII_PCS_SPEED_DUPLEX, val);
+
+			switch (FIELD_GET(SGMII_PCS_SPEED_MASK, val)) {
+			case 0:
+				state->speed = SPEED_10;
+				break;
+			case 1:
+				state->speed = SPEED_100;
+				break;
+			case 2:
+				state->speed = SPEED_1000;
+				break;
+			}
+		} else {
+			regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
+
+			state->duplex = !FIELD_GET(SGMII_DUPLEX_FULL, val);
 
-	state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX);
-	if (pmsr & MAC_MSR_RX_FC)
-		state->pause |= MLO_PAUSE_RX;
-	if (pmsr & MAC_MSR_TX_FC)
-		state->pause |= MLO_PAUSE_TX;
+			switch (FIELD_GET(SGMII_SPEED_MASK, val)) {
+			case 0:
+				state->speed = SPEED_10;
+				break;
+			case 1:
+				state->speed = SPEED_100;
+				break;
+			case 2:
+				regmap_read(ss->regmap_sgmii[id], ss->ana_rgc3, &val);
+				state->speed = (FIELD_GET(RG_PHY_SPEED_3_125G, val)) ? SPEED_2500 : SPEED_1000;
+				break;
+			}
+		}
+
+		state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX);
+		if (pmsr & MAC_MSR_RX_FC)
+			state->pause |= MLO_PAUSE_RX;
+		if (pmsr & MAC_MSR_TX_FC)
+			state->pause |= MLO_PAUSE_TX;
+	}
 
 	return 1;
 }
@@ -489,7 +579,8 @@
 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
 					   phylink_config);
 
-	mtk_sgmii_restart_an(mac->hw, mac->id);
+	if (mac->type != MTK_XGDM_TYPE)
+		mtk_sgmii_restart_an(mac->hw, mac->id);
 }
 
 static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
@@ -497,10 +588,19 @@
 {
 	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 (mac->type == MTK_GDM_TYPE) {
+		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->type == MTK_XGDM_TYPE && 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_mac_link_up(struct phylink_config *config, unsigned int mode,
@@ -509,10 +609,60 @@
 {
 	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_cur;
+
+	if (mac->type == MTK_GDM_TYPE) {
+		mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+		mcr = mcr_cur;
+		mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
+			 MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
+			 MAC_MCR_FORCE_RX_FC);
+		mcr |= MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
+		       MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
+
+		/* Configure speed */
+		switch (speed) {
+		case SPEED_2500:
+		case SPEED_1000:
+			mcr |= MAC_MCR_SPEED_1000;
+			break;
+		case SPEED_100:
+			mcr |= MAC_MCR_SPEED_100;
+			break;
+		}
 
-	mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN;
-	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+		/* Configure duplex */
+		if (duplex == DUPLEX_FULL)
+			mcr |= MAC_MCR_FORCE_DPX;
+
+		/* Configure pause modes -
+		 * phylink will avoid these for half duplex
+		 */
+		if (tx_pause)
+			mcr |= MAC_MCR_FORCE_TX_FC;
+		if (rx_pause)
+			mcr |= MAC_MCR_FORCE_RX_FC;
+
+		mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN;
+
+		/* Only update control register when needed! */
+		if (mcr != mcr_cur)
+			mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+	} else if (mac->type == MTK_XGDM_TYPE && mac->id != MTK_GMAC1_ID) {
+		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_validate(struct phylink_config *config,
@@ -532,7 +682,11 @@
 	      !mac->id && state->interface == PHY_INTERFACE_MODE_TRGMII) &&
 	    !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII) &&
 	      (state->interface == PHY_INTERFACE_MODE_SGMII ||
-	       phy_interface_mode_is_8023z(state->interface)))) {
+	       phy_interface_mode_is_8023z(state->interface))) &&
+	    !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII) &&
+	      (state->interface == PHY_INTERFACE_MODE_USXGMII)) &&
+	    !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII) &&
+	      (state->interface == PHY_INTERFACE_MODE_10GKR))) {
 		linkmode_zero(supported);
 		return;
 	}
@@ -541,12 +695,28 @@
 	phylink_set(mask, Autoneg);
 
 	switch (state->interface) {
+	case PHY_INTERFACE_MODE_USXGMII:
+	case PHY_INTERFACE_MODE_10GKR:
+		phylink_set(mask, 10000baseKR_Full);
+		phylink_set(mask, 10000baseT_Full);
+		phylink_set(mask, 10000baseCR_Full);
+		phylink_set(mask, 10000baseSR_Full);
+		phylink_set(mask, 10000baseLR_Full);
+		phylink_set(mask, 10000baseLRM_Full);
+		phylink_set(mask, 10000baseER_Full);
+		phylink_set(mask, 100baseT_Half);
+		phylink_set(mask, 100baseT_Full);
+		phylink_set(mask, 1000baseT_Half);
+		phylink_set(mask, 1000baseT_Full);
+		phylink_set(mask, 1000baseX_Full);
+		break;
 	case PHY_INTERFACE_MODE_TRGMII:
 		phylink_set(mask, 1000baseT_Full);
 		break;
 	case PHY_INTERFACE_MODE_1000BASEX:
-	case PHY_INTERFACE_MODE_2500BASEX:
 		phylink_set(mask, 1000baseX_Full);
+		/* fall through; */
+	case PHY_INTERFACE_MODE_2500BASEX:
 		phylink_set(mask, 2500baseX_Full);
 		phylink_set(mask, 2500baseT_Full);
 		/* fall through; */
@@ -574,6 +744,18 @@
 	}
 
 	if (state->interface == PHY_INTERFACE_MODE_NA) {
+
+		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) {
+			phylink_set(mask, 10000baseKR_Full);
+			phylink_set(mask, 10000baseSR_Full);
+			phylink_set(mask, 10000baseLR_Full);
+			phylink_set(mask, 10000baseLRM_Full);
+			phylink_set(mask, 10000baseER_Full);
+			phylink_set(mask, 1000baseKX_Full);
+			phylink_set(mask, 1000baseT_Full);
+			phylink_set(mask, 1000baseX_Full);
+			phylink_set(mask, 2500baseX_Full);
+		}
 		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) {
 			phylink_set(mask, 1000baseT_Full);
 			phylink_set(mask, 1000baseX_Full);
@@ -604,7 +786,7 @@
 
 static const struct phylink_mac_ops mtk_phylink_ops = {
 	.validate = mtk_validate,
-	.mac_link_state = mtk_mac_link_state,
+	.mac_link_state = mtk_mac_pcs_get_state,
 	.mac_an_restart = mtk_mac_an_restart,
 	.mac_config = mtk_mac_config,
 	.mac_link_down = mtk_mac_link_down,
@@ -737,6 +919,7 @@
 
 void mtk_stats_update_mac(struct mtk_mac *mac)
 {
+	struct mtk_eth *eth = mac->hw;
 	struct mtk_hw_stats *hw_stats = mac->hw_stats;
 	unsigned int base = MTK_GDM1_TX_GBCNT;
 	u64 stats;
@@ -757,14 +940,26 @@
 	hw_stats->rx_checksum_errors += mtk_r32(mac->hw, base + 0x20);
 	hw_stats->rx_flow_control_packets +=
 					mtk_r32(mac->hw, base + 0x24);
-	hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x28);
-	hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x2c);
-	hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x30);
-	stats =  mtk_r32(mac->hw, base + 0x34);
-	if (stats)
-		hw_stats->tx_bytes += (stats << 32);
-	hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x38);
-	u64_stats_update_end(&hw_stats->syncp);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x50);
+		hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x54);
+		hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x40);
+		stats =  mtk_r32(mac->hw, base + 0x44);
+		if (stats)
+			hw_stats->tx_bytes += (stats << 32);
+		hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x48);
+		u64_stats_update_end(&hw_stats->syncp);
+	} else {
+		hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x28);
+		hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x2c);
+		hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x30);
+		stats =  mtk_r32(mac->hw, base + 0x34);
+		if (stats)
+			hw_stats->tx_bytes += (stats << 32);
+		hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x38);
+		u64_stats_update_end(&hw_stats->syncp);
+	}
 }
 
 static void mtk_stats_update(struct mtk_eth *eth)
@@ -846,9 +1041,11 @@
 	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_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
 		rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
+		rxd->rxd7 = READ_ONCE(dma_rxd->rxd7);
 	}
 
 	return true;
@@ -869,7 +1066,10 @@
 					       &eth->phy_scratch_ring,
 					       GFP_KERNEL);
 	} else {
-		eth->scratch_ring = eth->base + MTK_ETH_SRAM_OFFSET;
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+			eth->scratch_ring = eth->sram_base;
+		else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+			eth->scratch_ring = eth->base + MTK_ETH_SRAM_OFFSET;
 	}
 
 	if (unlikely(!eth->scratch_ring))
@@ -899,7 +1099,8 @@
 		txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
 		txd->txd4 = 0;
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 			txd->txd5 = 0;
 			txd->txd6 = 0;
 			txd->txd7 = 0;
@@ -1052,7 +1253,7 @@
 	struct mtk_tx_dma_v2 *desc = txd;
 	u32 data = 0;
 
-	if(!info->qid && mac->id)
+	if (!info->qid && mac->id)
 		info->qid = MTK_QDMA_GMAC2_QID;
 
 	WRITE_ONCE(desc->txd1, info->addr);
@@ -1062,7 +1263,63 @@
 		data |= TX_DMA_LS0;
 	WRITE_ONCE(desc->txd3, data);
 
+	data = ((mac->id == MTK_GMAC3_ID) ?
+		PSE_GDM3_PORT : (mac->id + 1)) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
+	data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
+#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+	if (HNAT_SKB_CB2(skb)->magic == 0x78681415) {
+		data &= ~(0xf << TX_DMA_FPORT_SHIFT_V2);
+		data |= 0x4 << TX_DMA_FPORT_SHIFT_V2;
+	}
+
+	trace_printk("[%s] skb_shinfo(skb)->nr_frags=%x HNAT_SKB_CB2(skb)->magic=%x txd4=%x<-----\n",
+		     __func__, skb_shinfo(skb)->nr_frags, HNAT_SKB_CB2(skb)->magic, data);
+#endif
+	WRITE_ONCE(desc->txd4, data);
+
+	data = 0;
+	if (info->first) {
+		if (info->gso)
+			data |= TX_DMA_TSO_V2;
+		/* tx checksum offload */
+		if (info->csum)
+			data |= TX_DMA_CHKSUM_V2;
+	}
+	WRITE_ONCE(desc->txd5, data);
+
+	data = 0;
+	if (info->first && info->vlan)
+		data |= TX_DMA_INS_VLAN_V2 | info->vlan_tci;
+	WRITE_ONCE(desc->txd6, data);
+
+	WRITE_ONCE(desc->txd7, 0);
+	WRITE_ONCE(desc->txd8, 0);
+}
+
+static void mtk_tx_set_dma_desc_v3(struct sk_buff *skb, struct net_device *dev, void *txd,
+				struct mtk_tx_dma_desc_info *info)
+{
+	struct mtk_mac *mac = netdev_priv(dev);
+	struct mtk_eth *eth = mac->hw;
+	struct mtk_tx_dma_v2 *desc = txd;
+	u64 addr64 = 0;
+	u32 data = 0;
+
+	if (!info->qid && mac->id)
+		info->qid = MTK_QDMA_GMAC2_QID;
+
+	addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+		  TX_DMA_SDP1(info->addr) : 0;
+
+	WRITE_ONCE(desc->txd1, info->addr);
+
-	data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
+	data = TX_DMA_PLEN0(info->size);
+	if (info->last)
+		data |= TX_DMA_LS0;
+	WRITE_ONCE(desc->txd3, data | addr64);
+
+	data = ((mac->id == MTK_GMAC3_ID) ?
+		PSE_GDM3_PORT : (mac->id + 1)) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
 	data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
 #if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
 	if (HNAT_SKB_CB2(skb)->magic == 0x78681415) {
@@ -1082,6 +1339,9 @@
 		/* tx checksum offload */
 		if (info->csum)
 			data |= TX_DMA_CHKSUM_V2;
+
+		if (netdev_uses_dsa(dev))
+			data |= TX_DMA_SPTAG_V3;
 	}
 	WRITE_ONCE(desc->txd5, data);
 
@@ -1100,7 +1360,9 @@
 	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_V3))
+		mtk_tx_set_dma_desc_v3(skb, dev, txd, info);
+	else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 		mtk_tx_set_dma_desc_v2(skb, dev, txd, info);
 	else
 		mtk_tx_set_dma_desc_v1(skb, dev, txd, info);
@@ -1144,8 +1406,9 @@
 	mtk_tx_set_dma_desc(skb, dev, itxd, &txd_info);
 
 	itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
-	itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
-			  MTK_TX_FLAGS_FPORT1;
+	itx_buf->flags |= (mac->id == MTK_GMAC1_ID) ? MTK_TX_FLAGS_FPORT0 :
+			  (mac->id == MTK_GMAC2_ID) ? MTK_TX_FLAGS_FPORT1 :
+						      MTK_TX_FLAGS_FPORT2;
 	setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
 		     k++);
 
@@ -1191,8 +1454,10 @@
 				memset(tx_buf, 0, sizeof(*tx_buf));
 			tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
 			tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
-			tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
-					 MTK_TX_FLAGS_FPORT1;
+			tx_buf->flags |=
+				(mac->id == MTK_GMAC1_ID) ? MTK_TX_FLAGS_FPORT0 :
+				(mac->id == MTK_GMAC2_ID) ? MTK_TX_FLAGS_FPORT1 :
+							    MTK_TX_FLAGS_FPORT2;
 
 			setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
 				     txd_info.size, k++);
@@ -1404,6 +1669,7 @@
 	struct mtk_rx_ring *ring = rx_napi->rx_ring;
 	int idx;
 	struct sk_buff *skb;
+	u64 addr64 = 0;
 	u8 *data, *new_data;
 	struct mtk_rx_dma_v2 *rxd, trxd;
 	int done = 0;
@@ -1412,7 +1678,7 @@
 		goto rx_done;
 
 	while (done < budget) {
-		struct net_device *netdev;
+		struct net_device *netdev = NULL;
 		unsigned int pktlen;
 		dma_addr_t dma_addr;
 		int mac = 0;
@@ -1434,9 +1700,18 @@
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
 			mac = 0;
 		} else {
-			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
-				mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
-			else
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+			    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+				switch (RX_DMA_GET_SPORT_V2(trxd.rxd5)) {
+				case PSE_GDM1_PORT:
+				case PSE_GDM2_PORT:
+					mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
+					break;
+				case PSE_GDM3_PORT:
+					mac = MTK_GMAC3_ID;
+					break;
+				}
+			} else
 				mac = (trxd.rxd4 & RX_DMA_SPECIAL_TAG) ?
 				      0 : RX_DMA_GET_SPORT(trxd.rxd4) - 1;
 		}
@@ -1467,7 +1742,11 @@
 			goto release_desc;
 		}
 
-		dma_unmap_single(eth->dev, trxd.rxd1,
+		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+			  ((u64)(trxd.rxd2 & 0xf)) << 32 : 0;
+
+		dma_unmap_single(eth->dev,
+				 (u64)(trxd.rxd1 | addr64),
 				 ring->buf_size, DMA_FROM_DEVICE);
 
 		/* receive data */
@@ -1483,9 +1762,9 @@
 		skb->dev = netdev;
 		skb_put(skb, pktlen);
 
-		if ((!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
+		if ((MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) &&
 				  (trxd.rxd4 & eth->rx_dma_l4_valid)) ||
-		    (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
+		    (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) &&
 				  (trxd.rxd3 & eth->rx_dma_l4_valid)))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
@@ -1493,7 +1772,8 @@
 		skb->protocol = eth_type_trans(skb, netdev);
 
 		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
-			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+			    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 				if (trxd.rxd3 & RX_DMA_VTAG_V2)
 					__vlan_hwaccel_put_tag(skb,
 					htons(RX_DMA_VPID_V2(trxd.rxd4)),
@@ -1516,7 +1796,8 @@
 		}
 
 #if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 			*(u32 *)(skb->head) = trxd.rxd5;
 		else
 			*(u32 *)(skb->head) = trxd.rxd4;
@@ -1549,10 +1830,13 @@
 		rxd->rxd1 = (unsigned int)dma_addr;
 
 release_desc:
+		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+			  RX_DMA_SDP1(dma_addr) : 0;
+
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
 			rxd->rxd2 = RX_DMA_LSO;
 		else
-			rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size);
+			rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size) | addr64;
 
 		ring->calc_idx = idx;
 
@@ -1597,7 +1881,9 @@
 
 		tx_buf = mtk_desc_to_tx_buf(ring, desc, 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;
 
 		skb = tx_buf->skb;
 		if (!skb)
@@ -1797,7 +2083,8 @@
 		txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
 		txd->txd4 = 0;
 
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 			txd->txd5 = 0;
 			txd->txd6 = 0;
 			txd->txd7 = 0;
@@ -1890,6 +2177,7 @@
 	struct mtk_rx_ring *ring;
 	int rx_data_len, rx_dma_size;
 	int i;
+	u64 addr64 = 0;
 
 	if (rx_flag == MTK_RX_FLAGS_QDMA) {
 		if (ring_no)
@@ -1949,15 +2237,19 @@
 		rxd = ring->dma + i * eth->soc->txrx.rxd_size;
 		rxd->rxd1 = (unsigned int)dma_addr;
 
+		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+			  RX_DMA_SDP1(dma_addr) : 0;
+
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
 			rxd->rxd2 = RX_DMA_LSO;
 		else
-			rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size);
+			rxd->rxd2 = RX_DMA_PLEN0(ring->buf_size) | addr64;
 
 		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_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 			rxd->rxd5 = 0;
 			rxd->rxd6 = 0;
 			rxd->rxd7 = 0;
@@ -1994,6 +2286,7 @@
 static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_sram)
 {
 	int i;
+	u64 addr64 = 0;
 
 	if (ring->data && ring->dma) {
 		for (i = 0; i < ring->dma_size; i++) {
@@ -2006,8 +2299,12 @@
 			if (!rxd->rxd1)
 				continue;
 
+			addr64 = (MTK_HAS_CAPS(eth->soc->caps,
+					       MTK_8GB_ADDRESSING)) ?
+				  ((u64)(rxd->rxd2 & 0xf)) << 32 : 0;
+
 			dma_unmap_single(eth->dev,
-					 rxd->rxd1,
+					 (u64)(rxd->rxd1 | addr64),
 					 ring->buf_size,
 					 DMA_FROM_DEVICE);
 			skb_free_frag(ring->data[i]);
@@ -2077,7 +2374,8 @@
 	/* the minimal remaining room of SDL0 in RXD for lro aggregation */
 	lro_ctrl_dw3 |= MTK_LRO_MIN_RXD_SDL;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		val = mtk_r32(eth, MTK_PDMA_RX_CFG);
 		mtk_w32(eth, val | (MTK_PDMA_LRO_SDL << MTK_RX_CFG_SDL_OFFSET),
 			MTK_PDMA_RX_CFG);
@@ -2133,7 +2431,8 @@
 {
 	u32 reg_val;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 		idx += 1;
 
 	reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
@@ -2151,7 +2450,8 @@
 {
 	u32 reg_val;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 		idx += 1;
 
 	reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
@@ -2285,7 +2585,7 @@
 {
 	u32 val;
 
-	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
 		/* Set RSS rings to PSE modes */
 		val =  mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(1));
 		val |= MTK_RING_PSE_MODE;
@@ -2338,6 +2638,9 @@
 	/* Set GRP INT */
 	mtk_w32(eth, 0x21021030, MTK_FE_INT_GRP);
 
+	/* Enable RSS delay interrupt */
+	mtk_w32(eth, 0x8f0f8f0f, MTK_PDMA_RSS_DELAY_INT);
+
 	return 0;
 }
 
@@ -2458,7 +2761,7 @@
 		return err;
 
 	if (eth->hwlro) {
-		i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ? 4 : 1;
+		i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) ? 1 : 4;
 		for (; i < MTK_MAX_RX_RING_NUM; i++) {
 			err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_HWLRO);
 			if (err)
@@ -2514,7 +2817,7 @@
 	if (eth->hwlro) {
 		mtk_hwlro_rx_uninit(eth);
 
-		i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ? 4 : 1;
+		i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) ? 1 : 4;
 		for (; i < MTK_MAX_RX_RING_NUM; i++)
 			mtk_rx_clean(eth, &eth->rx_ring[i], 0);
 	}
@@ -2644,7 +2947,8 @@
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
 		val = mtk_r32(eth, MTK_QDMA_GLO_CFG);
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 			val &= ~MTK_RESV_BUF_MASK;
 			mtk_w32(eth,
 				val | MTK_TX_DMA_EN | MTK_RX_DMA_EN |
@@ -2673,7 +2977,7 @@
 			MTK_PDMA_GLO_CFG);
 	}
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && eth->hwlro) {
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) && eth->hwlro) {
 		val = mtk_r32(eth, MTK_PDMA_GLO_CFG);
 		mtk_w32(eth, val | MTK_RX_DMA_LRO_EN, MTK_PDMA_GLO_CFG);
 	}
@@ -2787,9 +3091,9 @@
 	phylink_start(mac->phylink);
 	netif_start_queue(dev);
 	phy_node = of_parse_phandle(mac->of_node, "phy-handle", 0);
-	if (!phy_node && eth->sgmii->regmap[mac->id]) {
-		regmap_write(eth->sgmii->regmap[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
-	}
+	if (!phy_node && eth->xgmii->regmap_sgmii[mac->id])
+		regmap_write(eth->xgmii->regmap_sgmii[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
 	return 0;
 }
 
@@ -2831,10 +3135,10 @@
 		val = _mtk_mdio_read(eth, 0, 0);
 		val |= BMCR_PDOWN;
 		_mtk_mdio_write(eth, 0, 0, val);
-	} else if (eth->sgmii->regmap[mac->id]) {
-		regmap_read(eth->sgmii->regmap[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+	} else if (eth->xgmii->regmap_sgmii[mac->id]) {
+		regmap_read(eth->xgmii->regmap_sgmii[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
 		val |= SGMII_PHYA_PWD;
-		regmap_write(eth->sgmii->regmap[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+		regmap_write(eth->xgmii->regmap_sgmii[mac->id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
 	}
 
 	//GMAC RX disable
@@ -2986,7 +3290,8 @@
 	else
 		mtk_eth_cold_reset(eth);
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
 		/* Set FE to PDMAv2 if necessary */
 		mtk_w32(eth, mtk_r32(eth, MTK_FE_GLO_MISC) | MTK_PDMA_V2, MTK_FE_GLO_MISC);
 	}
@@ -3032,7 +3337,22 @@
 		MTK_FE_INT_TSO_ILLEGAL | MTK_FE_INT_TSO_ALIGN |
 		MTK_FE_INT_RFIFO_OV | MTK_FE_INT_RFIFO_UF, MTK_FE_INT_ENABLE);
 
-	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_NO_DROP_CFG);
+
+		/* GDM and CDM Threshold */
+		mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES);
+		mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
+
+		/* 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 < MTK_STAT_OFFSET; i += 0x4)
+			mtk_r32(eth,
+				MTK_GDM1_TX_GBCNT + MTK_STAT_OFFSET * 2 + i);
+	} else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
 		/* PSE Free Queue Flow Control  */
 		mtk_w32(eth, 0x01fa01f4, PSE_FQFC_CFG2);
 
@@ -3232,9 +3552,9 @@
 	for (i = 0; i < MTK_MAC_COUNT; i++) {
 		mac = netdev_priv(eth->netdev[i]);
 		phy_node = of_parse_phandle(mac->of_node, "phy-handle", 0);
-		if (!phy_node && eth->sgmii->regmap[i]) {
+		if (!phy_node && eth->xgmii->regmap_sgmii[i]) {
 			mtk_gmac_sgmii_path_setup(eth, i);
-			regmap_write(eth->sgmii->regmap[i], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+			regmap_write(eth->xgmii->regmap_sgmii[i], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
 		}
 	}
 
@@ -3577,6 +3897,10 @@
 	mac->phylink_config.dev = &eth->netdev[id]->dev;
 	mac->phylink_config.type = PHYLINK_NETDEV;
 
+	mac->type = (phy_mode == PHY_INTERFACE_MODE_10GKR ||
+		     phy_mode == PHY_INTERFACE_MODE_USXGMII) ?
+		     MTK_XGDM_TYPE : MTK_GDM_TYPE;
+
 	phylink = phylink_create(&mac->phylink_config,
 				 of_fwnode_handle(mac->of_node),
 				 phy_mode, &mtk_phylink_ops);
@@ -3663,6 +3987,12 @@
 	if (IS_ERR(eth->base))
 		return PTR_ERR(eth->base);
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		eth->sram_base = devm_platform_ioremap_resource(pdev, 1);
+		if (IS_ERR(eth->sram_base))
+			return PTR_ERR(eth->sram_base);
+	}
+
 	if(eth->soc->has_sram) {
 		struct resource *res;
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -3683,12 +4013,25 @@
 		eth->rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA;
 		eth->ip_align = NET_IP_ALIGN;
 	} else {
-		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+		    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
 			eth->rx_dma_l4_valid = RX_DMA_L4_VALID_V2;
 		else
 			eth->rx_dma_l4_valid = RX_DMA_L4_VALID;
 	}
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) {
+		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
+		if (!err) {
+			err = dma_set_coherent_mask(&pdev->dev,
+						    DMA_BIT_MASK(36));
+			if (err) {
+				dev_err(&pdev->dev, "Wrong DMA config\n");
+				return -EINVAL;
+			}
+		}
+	}
+
 	spin_lock_init(&eth->page_lock);
 	spin_lock_init(&eth->tx_irq_lock);
 	spin_lock_init(&eth->rx_irq_lock);
@@ -3713,16 +4056,35 @@
 	}
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
-		eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii),
+		eth->xgmii = devm_kzalloc(eth->dev, sizeof(*eth->xgmii),
 					  GFP_KERNEL);
-		if (!eth->sgmii)
+		if (!eth->xgmii)
 			return -ENOMEM;
 
-		err = mtk_sgmii_init(eth->sgmii, pdev->dev.of_node,
+		eth->xgmii->eth = eth;
+		err = mtk_sgmii_init(eth->xgmii, pdev->dev.of_node,
 				     eth->soc->ana_rgc3);
 
+		if (err)
+			return err;
+	}
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) {
+		err = mtk_usxgmii_init(eth->xgmii, pdev->dev.of_node);
+		if (err)
+			return err;
+
+		err = mtk_xfi_pextp_init(eth->xgmii, pdev->dev.of_node);
 		if (err)
 			return err;
+
+		err = mtk_xfi_pll_init(eth->xgmii, pdev->dev.of_node);
+		if (err)
+			return err;
+
+		err = mtk_toprgu_init(eth, pdev->dev.of_node);
+		if (err)
+			return err;
 	}
 
 	if (eth->soc->required_pctl) {
@@ -4024,6 +4386,21 @@
 	},
 };
 
+static const struct mtk_soc_data mt7988_data = {
+	.ana_rgc3 = 0x128,
+	.caps = MT7988_CAPS,
+	.hw_features = MTK_HW_FEATURES,
+	.required_clks = MT7988_CLKS_BITMAP,
+	.required_pctl = false,
+	.has_sram = true,
+	.txrx = {
+		.txd_size = sizeof(struct mtk_tx_dma_v2),
+		.rxd_size = sizeof(struct mtk_rx_dma_v2),
+		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
+	},
+};
+
 static const struct mtk_soc_data rt5350_data = {
 	.caps = MT7628_CAPS,
 	.hw_features = MTK_HW_FEATURES_MT7628,
@@ -4046,6 +4423,7 @@
 	{ .compatible = "mediatek,mt7629-eth", .data = &mt7629_data},
 	{ .compatible = "mediatek,mt7986-eth", .data = &mt7986_data},
 	{ .compatible = "mediatek,mt7981-eth", .data = &mt7981_data},
+	{ .compatible = "mediatek,mt7988-eth", .data = &mt7988_data},
 	{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data},
 	{},
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index edaeceb..8827a36 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -20,7 +20,13 @@
 #define	MTK_MAX_RX_LENGTH	1536
 #define MTK_DMA_SIZE		2048
 #define MTK_NAPI_WEIGHT		256
+
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_MAC_COUNT		3
+#else
 #define MTK_MAC_COUNT		2
+#endif
+
 #define MTK_RX_ETH_HLEN		(VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
 #define MTK_RX_HLEN		(NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
 #define MTK_DMA_DUMMY_DESC	0xffffffff
@@ -100,23 +106,36 @@
 /* CDMP Exgress Control Register */
 #define MTK_CDMP_EG_CTRL	0x404
 
-/* GDM Exgress Control Register */
-#define MTK_GDMA_FWD_CFG(x)	(0x500 + (x * 0x1000))
+/* GDM Ingress Control Register */
+#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)
 #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
 
+/* 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))
+#define MTK_GDMA_MAC_ADRL(x)	((x == MTK_GMAC3_ID) ?		\
+				 0x548 : 0x508 + (x * 0x1000))
 
 /* Unicast Filter MAC Address Register - High */
-#define MTK_GDMA_MAC_ADRH(x)	(0x50C + (x * 0x1000))
+#define MTK_GDMA_MAC_ADRH(x)	((x == MTK_GMAC3_ID) ?		\
+				 0x54C : 0x50C + (x * 0x1000))
 
 /* Internal SRAM offset */
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_ETH_SRAM_OFFSET	0x300000
+#else
 #define MTK_ETH_SRAM_OFFSET	0x40000
+#endif
 
 /* FE global misc reg*/
 #define MTK_FE_GLO_MISC         0x124
@@ -143,7 +162,12 @@
 
 #define MTK_PDMA_V2		BIT(4)
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define PDMA_BASE               0x6800
+#define QDMA_BASE               0x4400
+#define WDMA_BASE(x)		(0x4800 + ((x) * 0x400))
+#define PPE_BASE(x)		((x == 2) ? 0x2C00 : 0x2200 + ((x) * 0x400))
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
 #define PDMA_BASE               0x6000
 #define QDMA_BASE               0x4400
 #define WDMA_BASE(x)		(0x4800 + ((x) * 0x400))
@@ -172,7 +196,7 @@
 
 /* PDMA HW LRO Control Registers */
 #define BITS(m, n)			(~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_MAX_RX_RING_NUM		(8)
 #define MTK_HW_LRO_RING_NUM		(4)
 #define IS_HW_LRO_RING(ring_no)		(((ring_no) > 3) && ((ring_no) < 8))
@@ -216,7 +240,7 @@
 #define MTK_LRO_MIN_RXD_SDL	(MTK_HW_LRO_SDL_REMAIN_ROOM << 16)
 
 /* PDMA RSS Control Registers */
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_PDMA_RSS_GLO_CFG		(PDMA_BASE + 0x800)
 #define MTK_RX_NAPI_NUM			(2)
 #define MTK_MAX_IRQ_NUM			(4)
@@ -258,6 +282,7 @@
 
 /* PDMA Delay Interrupt Register */
 #define MTK_PDMA_DELAY_INT		(PDMA_BASE + 0x20c)
+#define MTK_PDMA_RSS_DELAY_INT		(PDMA_BASE + 0x2c0)
 #define MTK_PDMA_DELAY_RX_EN		BIT(15)
 #define MTK_PDMA_DELAY_RX_PINT		4
 #define MTK_PDMA_DELAY_RX_PINT_SHIFT	8
@@ -275,7 +300,7 @@
 /* PDMA Interrupt grouping registers */
 #define MTK_PDMA_INT_GRP1	(PDMA_BASE + 0x250)
 #define MTK_PDMA_INT_GRP2	(PDMA_BASE + 0x254)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_PDMA_INT_GRP3	(PDMA_BASE + 0x258)
 #else
 #define MTK_PDMA_INT_GRP3	(PDMA_BASE + 0x22c)
@@ -284,7 +309,7 @@
 #define MTK_MAX_DELAY_INT	0x8f0f8f0f
 
 /* PDMA HW LRO IP Setting Registers */
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_LRO_RX_RING0_DIP_DW0	(PDMA_BASE + 0x414)
 #else
 #define MTK_LRO_RX_RING0_DIP_DW0	(PDMA_BASE + 0x304)
@@ -403,9 +428,10 @@
 
 /* QDMA Interrupt Status Register */
 #define MTK_QDMA_INT_STATUS	(QDMA_BASE + 0x218)
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-#define MTK_RX_DONE_INT(ring_no)		\
-	((ring_no)? BIT(16 + (ring_no)) : BIT(14))
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_RX_DONE_INT(ring_no)					\
+	(MTK_HAS_CAPS(eth->soc->caps, MTK_RSS) ? (BIT(24 + (ring_no))) :	\
+	 ((ring_no) ? BIT(16 + (ring_no)) : BIT(14)))
 #else
 #define MTK_RX_DONE_INT(ring_no)		\
 	((ring_no)? BIT(24 + (ring_no)) : BIT(30))
@@ -469,12 +495,17 @@
 #define MTK_CDM_TXFIFO_RDY	BIT(7)
 
 /* GMA1 Received Good Byte Count Register */
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_GDM1_TX_GBCNT       0x1C00
 #else
 #define MTK_GDM1_TX_GBCNT	0x2400
 #endif
+
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_STAT_OFFSET		0x80
+#else
 #define MTK_STAT_OFFSET		0x40
+#endif
 
 /* QDMA TX NUM */
 #define MTK_QDMA_TX_NUM		16
@@ -492,6 +523,7 @@
 /* QDMA V2 descriptor txd5 */
 #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
@@ -521,6 +553,7 @@
 #define TX_DMA_PLEN0(_x)	(((_x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
 #define TX_DMA_PLEN1(_x)	((_x) & eth->soc->txrx.dma_max_len)
 #define TX_DMA_SWC		BIT(14)
+#define TX_DMA_SDP1(_x)		((((u64)(_x)) >> 32) & 0xf)
 
 /* PDMA on MT7628 */
 #define TX_DMA_DONE		BIT(31)
@@ -535,6 +568,7 @@
 #define RX_DMA_GET_AGG_CNT(_x)	(((_x) >> 2) & 0xff)
 #define RX_DMA_GET_REV(_x)	(((_x) >> 10) & 0x1f)
 #define RX_DMA_VTAG		BIT(15)
+#define RX_DMA_SDP1(_x)		((((u64)(_x)) >> 32) & 0xf)
 
 /* QDMA descriptor rxd3 */
 #define RX_DMA_VID(_x)		((_x) & VLAN_VID_MASK)
@@ -561,6 +595,7 @@
 /* PDMA V2 descriptor rxd6 */
 #define RX_DMA_GET_FLUSH_RSN_V2(_x)	((_x) & 0x7)
 #define RX_DMA_GET_AGG_CNT_V2(_x)	(((_x) >> 16) & 0xff)
+#define RX_DMA_GET_TOPS_CRSN(_x)	(((_x) >> 24) & 0xff)
 
 /* PHY Indirect Access Control registers */
 #define MTK_PHY_IAC		0x10004
@@ -578,6 +613,23 @@
 #define MTK_MAC_MISC		0x1000c
 #define MTK_MUX_TO_ESW		BIT(0)
 
+/* XMAC status registers */
+#define MTK_XGMAC_STS(x)	((x == MTK_GMAC3_ID) ? 0x1001C : 0x1000C)
+#define MTK_XGMAC_FORCE_LINK	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))
 #define MAC_MCR_MAX_RX_1536	BIT(24)
@@ -595,6 +647,12 @@
 #define MAC_MCR_FORCE_LINK	BIT(0)
 #define MAC_MCR_FORCE_LINK_DOWN	(MAC_MCR_FORCE_MODE)
 
+/* 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)
+
 /* Mac status registers */
 #define MTK_MAC_MSR(x)		(0x10108 + (x * 0x100))
 #define MAC_MSR_EEE1G		BIT(7)
@@ -659,11 +717,12 @@
 #define ETHSYS_SYSCFG0		0x14
 #define SYSCFG0_GE_MASK		0x3
 #define SYSCFG0_GE_MODE(x, y)	(x << (12 + (y * 2)))
-#define SYSCFG0_SGMII_MASK     GENMASK(9, 8)
+#define SYSCFG0_SGMII_MASK     GENMASK(9, 7)
 #define SYSCFG0_SGMII_GMAC1    ((2 << 8) & SYSCFG0_SGMII_MASK)
 #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 */
@@ -701,6 +760,15 @@
 #define SGMII_PCS_FAULT		BIT(23)
 #define SGMII_AN_EXPANSION_CLR	BIT(30)
 
+/* Register to set SGMII speed */
+#define SGMII_PCS_SPEED_ABILITY	0x08
+#define SGMII_PCS_SPEED_MASK	GENMASK(11, 10)
+#define SGMII_PCS_SPEED_10	0
+#define SGMII_PCS_SPEED_100	1
+#define SGMII_PCS_SPEED_1000	2
+#define SGMII_PCS_SPEED_DUPLEX	BIT(12)
+#define SGMII_PCS_SPEED_LINK	BIT(15)
+
 /* Register to programmable link timer, the unit in 2 * 8ns */
 #define SGMSYS_PCS_LINK_TIMER	0x18
 #define SGMII_LINK_TIMER_DEFAULT	(0x186a0 & GENMASK(19, 0))
@@ -709,6 +777,7 @@
 #define SGMSYS_SGMII_MODE		0x20
 #define SGMII_IF_MODE_BIT0		BIT(0)
 #define SGMII_SPEED_DUPLEX_AN		BIT(1)
+#define SGMII_SPEED_MASK		GENMASK(3, 2)
 #define SGMII_SPEED_10			0x0
 #define SGMII_SPEED_100			BIT(2)
 #define SGMII_SPEED_1000		BIT(3)
@@ -739,12 +808,49 @@
 #define SGMII_PN_SWAP_MASK	GENMASK(1, 0)
 #define SGMII_PN_SWAP_TX_RX	(BIT(0) | BIT(1))
 
+/* 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)
 
 /* 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
@@ -846,6 +952,7 @@
 	 */
 	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
@@ -925,11 +1032,59 @@
                                  BIT(MTK_CLK_SGMII2_RX_250M) | \
                                  BIT(MTK_CLK_SGMII2_CDR_REF) | \
                                  BIT(MTK_CLK_SGMII2_CDR_FB))
+
+#define MT7988_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))
+
 enum mtk_dev_state {
 	MTK_HW_INIT,
 	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
+};
+
 /* struct mtk_tx_buf -	This struct holds the pointers to the memory pointed at
  *			by the TX descriptor	s
  * @skb:		The SKB pointer of the packet being sent
@@ -1020,6 +1175,7 @@
 	MTK_RGMII_BIT = 0,
 	MTK_TRGMII_BIT,
 	MTK_SGMII_BIT,
+	MTK_USXGMII_BIT,
 	MTK_ESW_BIT,
 	MTK_GEPHY_BIT,
 	MTK_MUX_BIT,
@@ -1030,10 +1186,13 @@
 	MTK_SHARED_INT_BIT,
 	MTK_TRGMII_MT7621_CLK_BIT,
 	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,
+	MTK_8GB_ADDRESSING_BIT,
 
 	/* MUX BITS*/
 	MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
@@ -1041,6 +1200,8 @@
 	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,
@@ -1049,13 +1210,18 @@
 	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(MTK_RGMII_BIT)
 #define MTK_TRGMII		BIT(MTK_TRGMII_BIT)
 #define MTK_SGMII		BIT(MTK_SGMII_BIT)
+#define MTK_USXGMII		BIT(MTK_USXGMII_BIT)
 #define MTK_ESW			BIT(MTK_ESW_BIT)
 #define MTK_GEPHY		BIT(MTK_GEPHY_BIT)
 #define MTK_MUX			BIT(MTK_MUX_BIT)
@@ -1066,10 +1232,13 @@
 #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_8GB_ADDRESSING	BIT(MTK_8GB_ADDRESSING_BIT)
 
 #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW		\
 	BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
@@ -1081,6 +1250,10 @@
 	BIT(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)
+#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII	\
+	BIT(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT)
+#define MTK_ETH_MUX_GMAC123_TO_USXGMII	\
+	BIT(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT)
 
 /* Supported path present on SoCs */
 #define MTK_ETH_PATH_GMAC1_RGMII	BIT(MTK_ETH_PATH_GMAC1_RGMII_BIT)
@@ -1089,7 +1262,11 @@
 #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_GMAC3_SGMII	BIT(MTK_ETH_PATH_GMAC3_SGMII_BIT)
 #define MTK_ETH_PATH_GDM1_ESW		BIT(MTK_ETH_PATH_GDM1_ESW_BIT)
+#define MTK_ETH_PATH_GMAC1_USXGMII	BIT(MTK_ETH_PATH_GMAC1_USXGMII_BIT)
+#define MTK_ETH_PATH_GMAC2_USXGMII	BIT(MTK_ETH_PATH_GMAC2_USXGMII_BIT)
+#define MTK_ETH_PATH_GMAC3_USXGMII	BIT(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)
@@ -1097,7 +1274,11 @@
 #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 */
@@ -1120,26 +1301,32 @@
 #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)
+
 #define MTK_HAS_CAPS(caps, _x)		(((caps) & (_x)) == (_x))
 
 #define MT7621_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
 		      MTK_GMAC2_RGMII | MTK_SHARED_INT | \
-		      MTK_TRGMII_MT7621_CLK | MTK_QDMA)
+		      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_GDM1_TO_GMAC1_ESW | MTK_NETSYS_V1 | \
 		      MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_QDMA)
 
 #define MT7623_CAPS  (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII | \
-		      MTK_QDMA)
+		      MTK_QDMA | MTK_NETSYS_V1)
 
-#define MT7628_CAPS  (MTK_SHARED_INT | MTK_SOC_MT7628)
+#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_GDM1_TO_GMAC1_ESW | \
 		      MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
-		      MTK_MUX_U3_GMAC2_TO_QPHY | \
+		      MTK_MUX_U3_GMAC2_TO_QPHY | MTK_NETSYS_V1 | \
 		      MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
 
 #define MT7986_CAPS   (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
@@ -1151,6 +1338,12 @@
 			MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
 			MTK_NETSYS_V2)
 
+#define MT7988_CAPS   (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC3_SGMII | \
+		       MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_QDMA | \
+		       MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | \
+		       MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
+		       MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | MTK_RSS)
+
 struct mtk_tx_dma_desc_info {
 	dma_addr_t	addr;
 	u32		size;
@@ -1180,7 +1373,7 @@
  */
 struct mtk_soc_data {
 	u32             ana_rgc3;
-	u32		caps;
+	u64		caps;
 	u32		required_clks;
 	bool		required_pctl;
 	netdev_features_t hw_features;
@@ -1193,26 +1386,37 @@
 	} txrx;
 };
 
-/* currently no SoC has more than 2 macs */
-#define MTK_MAX_DEVS			2
+/* currently no SoC has more than 3 macs */
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_MAX_DEVS		3
+#else
+#define MTK_MAX_DEVS		2
+#endif
 
 #define MTK_SGMII_PHYSPEED_AN          BIT(31)
 #define MTK_SGMII_PHYSPEED_MASK        GENMASK(2, 0)
 #define MTK_SGMII_PHYSPEED_1000        BIT(0)
 #define MTK_SGMII_PHYSPEED_2500        BIT(1)
+#define MTK_SGMII_PHYSPEED_5000	       BIT(2)
+#define MTK_SGMII_PHYSPEED_10000       BIT(3)
 #define MTK_SGMII_PN_SWAP	       BIT(16)
+#define MTK_USXGMII_INT_2500	       BIT(17)
 #define MTK_HAS_FLAGS(flags, _x)       (((flags) & (_x)) == (_x))
 
-/* struct mtk_sgmii -  This is the structure holding sgmii regmap and its
- *                     characteristics
+/* 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 modes
+ *                     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_sgmii {
-	struct regmap   *regmap[MTK_MAX_DEVS];
+struct mtk_xgmii {
+	struct mtk_eth	*eth;
+	struct regmap   *regmap_sgmii[MTK_MAX_DEVS];
+	struct regmap   *regmap_usxgmii[MTK_MAX_DEVS];
+	struct regmap   *regmap_pextp[MTK_MAX_DEVS];
+	struct regmap	*regmap_pll;
 	u32             flags[MTK_MAX_DEVS];
 	u32             ana_rgc3;
 };
@@ -1279,6 +1483,7 @@
 struct mtk_eth {
 	struct device			*dev;
 	void __iomem			*base;
+	void __iomem			*sram_base;
 	spinlock_t			page_lock;
 	spinlock_t			tx_irq_lock;
 	spinlock_t			rx_irq_lock;
@@ -1290,7 +1495,8 @@
 	unsigned long			sysclk;
 	struct regmap			*ethsys;
 	struct regmap                   *infra;
-	struct mtk_sgmii                *sgmii;
+	struct regmap                   *toprgu;
+	struct mtk_xgmii                *xgmii;
 	struct regmap			*pctl;
 	bool				hwlro;
 	refcount_t			dma_refcnt;
@@ -1331,6 +1537,7 @@
 	unsigned int			id;
 	phy_interface_t			interface;
 	unsigned int			mode;
+	unsigned int			type;
 	int				speed;
 	struct device_node		*of_node;
 	struct phylink			*phylink;
@@ -1353,17 +1560,31 @@
 u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
 u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg);
 
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
+int mtk_sgmii_init(struct mtk_xgmii *ss, struct device_node *np,
 		   u32 ana_rgc3);
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, unsigned int id);
-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, unsigned int id,
+int mtk_sgmii_setup_mode_an(struct mtk_xgmii *ss, unsigned int mac_id);
+int mtk_sgmii_setup_mode_force(struct mtk_xgmii *ss, unsigned int mac_id,
 			       const struct phylink_link_state *state);
 void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
+void mtk_sgmii_setup_phya_gen2(struct mtk_xgmii *ss, int mac_id);
 
 int mtk_gmac_sgmii_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);
 void mtk_gdm_config(struct mtk_eth *eth, u32 config);
 void ethsys_reset(struct mtk_eth *eth, u32 reset_bits);
 
+int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id);
+int mtk_usxgmii_init(struct mtk_xgmii *ss, struct device_node *r);
+int mtk_xfi_pextp_init(struct mtk_xgmii *ss, struct device_node *r);
+int mtk_xfi_pll_init(struct mtk_xgmii *ss, struct device_node *r);
+int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
+int mtk_xfi_pll_enable(struct mtk_xgmii *ss);
+int mtk_usxgmii_setup_mode_an(struct mtk_xgmii *ss, int mac_id,
+			      int max_speed);
+int mtk_usxgmii_setup_mode_force(struct mtk_xgmii *ss, int mac_id,
+				 int max_speed);
+void mtk_usxgmii_setup_phya_an_10000(struct mtk_xgmii *ss, int mac_id);
+void mtk_usxgmii_reset(struct mtk_xgmii *ss, int mac_id);
 #endif /* MTK_ETH_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
index ad4184a..2a672cb 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -139,17 +139,27 @@
 	void __iomem *reg;
 	u32 val;
 
-	reg = hnat_priv->fe_base + (id ? GDMA2_FWD_CFG : GDMA1_FWD_CFG);
+	reg = hnat_priv->fe_base +
+		((id == NR_GMAC1_PORT) ? GDMA1_FWD_CFG :
+		 (id == NR_GMAC2_PORT) ? GDMA2_FWD_CFG : GDMA3_FWD_CFG);
 
 	if (enable) {
-		cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE);
+		if (CFG_PPE_NUM == 3 && id == NR_GMAC3_PORT)
+			cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE2);
+		else if (CFG_PPE_NUM == 3 && id == NR_GMAC2_PORT)
+			cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE1);
+		else
+			cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE);
 
 		return;
 	}
 
 	/*disabled */
 	val = readl(reg);
-	if ((val & GDM_ALL_FRC_MASK) == BITS_GDM_ALL_FRC_P_PPE)
+	if ((val & GDM_ALL_FRC_MASK) == BITS_GDM_ALL_FRC_P_PPE ||
+	    (CFG_PPE_NUM == 3 &&
+	    ((val & GDM_ALL_FRC_MASK) == BITS_GDM_ALL_FRC_P_PPE1 ||
+	     (val & GDM_ALL_FRC_MASK) == BITS_GDM_ALL_FRC_P_PPE2)))
 		cr_set_field(reg, GDM_ALL_FRC_MASK,
 			     BITS_GDM_ALL_FRC_P_CPU_PDMA);
 }
@@ -297,7 +307,9 @@
 	cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, HASH_MODE, HASH_MODE_1);
 	writel(HASH_SEED_KEY, hnat_priv->ppe_base[ppe_id] + PPE_HASH_SEED);
 	cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, XMODE, 0);
-	cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, TB_ENTRY_SIZE, ENTRY_80B);
+	cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, TB_ENTRY_SIZE,
+		     (hnat_priv->data->version == MTK_HNAT_V5) ? ENTRY_128B :
+		     (hnat_priv->data->version == MTK_HNAT_V4) ? ENTRY_96B : ENTRY_80B);
 	cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, SMA, SMA_FWD_CPU_BUILD_ENTRY);
 
 	/* set ip proto */
@@ -313,7 +325,8 @@
 		    BIT_IPV4_DSL_EN | BIT_IPV6_6RD_EN |
 		    BIT_IPV6_3T_ROUTE_EN | BIT_IPV6_5T_ROUTE_EN);
 
-	if (hnat_priv->data->version == MTK_HNAT_V4)
+	if (hnat_priv->data->version == MTK_HNAT_V4 ||
+	    hnat_priv->data->version == MTK_HNAT_V5)
 		cr_set_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
 			    BIT_IPV4_MAPE_EN | BIT_IPV4_MAPT_EN);
 
@@ -360,11 +373,17 @@
 	cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, TTL0_DRP, 0);
 	cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, MCAST_TB_EN, 1);
 
-	if (hnat_priv->data->version == MTK_HNAT_V4) {
+	if (hnat_priv->data->version == MTK_HNAT_V4 ||
+	    hnat_priv->data->version == MTK_HNAT_V5) {
 		writel(0xcb777, hnat_priv->ppe_base[ppe_id] + PPE_DFT_CPORT1);
 		writel(0x7f, hnat_priv->ppe_base[ppe_id] + PPE_SBW_CTRL);
 	}
 
+	if (hnat_priv->data->version == MTK_HNAT_V5) {
+		cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_SB_FIFO_DBG,
+			     SB_MED_FULL_DRP_EN, 1);
+	}
+
 	/*enable ppe mib counter*/
 	if (hnat_priv->data->per_flow_accounting) {
 		cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MIB_CFG, MIB_EN, 1);
@@ -468,8 +487,9 @@
 		return;
 
 	/* send all traffic back to the DMA engine */
-	set_gmac_ppe_fwd(0, 0);
-	set_gmac_ppe_fwd(1, 0);
+	set_gmac_ppe_fwd(NR_GMAC1_PORT, 0);
+	set_gmac_ppe_fwd(NR_GMAC2_PORT, 0);
+	set_gmac_ppe_fwd(NR_GMAC3_PORT, 0);
 
 	dev_info(hnat_priv->dev, "hwnat stop\n");
 
@@ -500,7 +520,8 @@
 		    BIT_IPV6_6RD_EN | BIT_IPV6_3T_ROUTE_EN |
 		    BIT_IPV6_5T_ROUTE_EN | BIT_FUC_FOE | BIT_FMC_FOE);
 
-	if (hnat_priv->data->version == MTK_HNAT_V4)
+	if (hnat_priv->data->version == MTK_HNAT_V4 ||
+	    hnat_priv->data->version == MTK_HNAT_V5)
 		cr_clr_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
 			    BIT_IPV4_MAPE_EN | BIT_IPV4_MAPT_EN);
 
@@ -565,7 +586,8 @@
 	 */
 	if (hnat_priv->data->whnat) {
 		ra_sw_nat_hook_rx =
-			(hnat_priv->data->version == MTK_HNAT_V4) ?
+			(hnat_priv->data->version == MTK_HNAT_V4 ||
+			 hnat_priv->data->version == MTK_HNAT_V5) ?
 			 mtk_sw_nat_hook_rx : NULL;
 		ra_sw_nat_hook_tx = mtk_sw_nat_hook_tx;
 		ppe_dev_register_hook = mtk_ppe_dev_register_hook;
@@ -696,6 +718,13 @@
 		strncpy(hnat_priv->lan, (char *)name, IFNAMSIZ - 1);
 	dev_info(&pdev->dev, "lan = %s\n", hnat_priv->lan);
 
+	err = of_property_read_string(np, "mtketh-lan2", &name);
+	if (err < 0)
+		strncpy(hnat_priv->lan2, "eth2", IFNAMSIZ);
+	else
+		strncpy(hnat_priv->lan2, (char *)name, IFNAMSIZ - 1);
+	dev_info(&pdev->dev, "lan2 = %s\n", hnat_priv->lan2);
+
 	err = of_property_read_string(np, "mtketh-ppd", &name);
 	if (err < 0)
 		strncpy(hnat_priv->ppd, "eth0", IFNAMSIZ);
@@ -740,11 +769,14 @@
 	if (!hnat_priv->fe_base)
 		return -EADDRNOTAVAIL;
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 	hnat_priv->ppe_base[0] = hnat_priv->fe_base + 0x2200;
 
 	if (CFG_PPE_NUM > 1)
 		hnat_priv->ppe_base[1] = hnat_priv->fe_base + 0x2600;
+
+	if (CFG_PPE_NUM > 2)
+		hnat_priv->ppe_base[2] = hnat_priv->fe_base + 0x2e00;
 #else
 	hnat_priv->ppe_base[0] = hnat_priv->fe_base + 0xe00;
 #endif
@@ -885,12 +917,21 @@
 	.version = MTK_HNAT_V4,
 };
 
+static const struct mtk_hnat_data hnat_data_v5 = {
+	.num_of_sch = 4,
+	.whnat = true,
+	.per_flow_accounting = true,
+	.mcast = false,
+	.version = MTK_HNAT_V5,
+};
+
 const struct of_device_id of_hnat_match[] = {
 	{ .compatible = "mediatek,mtk-hnat", .data = &hnat_data_v3 },
 	{ .compatible = "mediatek,mtk-hnat_v1", .data = &hnat_data_v1 },
 	{ .compatible = "mediatek,mtk-hnat_v2", .data = &hnat_data_v2 },
 	{ .compatible = "mediatek,mtk-hnat_v3", .data = &hnat_data_v3 },
 	{ .compatible = "mediatek,mtk-hnat_v4", .data = &hnat_data_v4 },
+	{ .compatible = "mediatek,mtk-hnat_v5", .data = &hnat_data_v5 },
 	{},
 };
 MODULE_DEVICE_TABLE(of, of_hnat_match);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index 9a601db..b8ec87a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -94,15 +94,18 @@
 #define PPE_MIB_SER_R0 0X140
 #define PPE_MIB_SER_R1 0X144
 #define PPE_MIB_SER_R2 0X148
+#define PPE_MIB_SER_R3 0X14C
 #define PPE_MIB_CAH_CTRL 0X150
 #define PPE_MIB_CAH_TAG_SRH 0X154
 #define PPE_MIB_CAH_LINE_RW 0X158
 #define PPE_MIB_CAH_WDATA 0X15C
 #define PPE_MIB_CAH_RDATA 0X160
+#define PPE_SB_FIFO_DBG 0x170
 #define PPE_SBW_CTRL 0x174
 
 #define GDMA1_FWD_CFG 0x500
 #define GDMA2_FWD_CFG 0x1500
+#define GDMA3_FWD_CFG 0x540
 
 /* QDMA Tx queue configuration */
 #define QTX_CFG(x)			(QDMA_BASE + ((x) * 0x10))
@@ -193,10 +196,10 @@
 #define MIB_CAH_EN (0X1 << 0) /* RW */
 
 /*GDMA_FWD_CFG mask */
-#define GDM_UFRC_MASK (0x7 << 12) /* RW */
-#define GDM_BFRC_MASK (0x7 << 8) /*RW*/
-#define GDM_MFRC_MASK (0x7 << 4) /*RW*/
-#define GDM_OFRC_MASK (0x7 << 0) /*RW*/
+#define GDM_UFRC_MASK (0xF << 12) /* RW */
+#define GDM_BFRC_MASK (0xF << 8) /*RW*/
+#define GDM_MFRC_MASK (0xF << 4) /*RW*/
+#define GDM_OFRC_MASK (0xF << 0) /*RW*/
 #define GDM_ALL_FRC_MASK                                                      \
 	(GDM_UFRC_MASK | GDM_BFRC_MASK | GDM_MFRC_MASK | GDM_OFRC_MASK)
 
@@ -207,10 +210,13 @@
 #define MIB_ON_QTX_CFG (0x1 << 31) /* RW */
 #define VQTX_MIB_EN (0x1 << 28) /* RW */
 
+/* PPE Side Band FIFO Debug Mask */
+#define SB_MED_FULL_DRP_EN (0x1 << 11)
+
 /*--------------------------------------------------------------------------*/
 /* Descriptor Structure */
 /*--------------------------------------------------------------------------*/
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 struct hnat_unbind_info_blk {
 	u32 time_stamp : 8;
 	u32 sp : 4;
@@ -257,10 +263,29 @@
 	u32 dscp : 8;		/* DSCP value */
 } __packed;
 
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+struct hnat_winfo {
+	u32 wcid : 16;		/* WiFi wtable Idx */
+	u32 bssid : 8;		/* WiFi Bssidx */
+	u32 resv : 8;
+} __packed;
+
+struct hnat_winfo_pao {
+	u32 usr_info : 16;
+	u32 tid : 4;
+	u32 is_fixedrate : 1;
+	u32 is_prior : 1;
+	u32 is_sp : 1;
+	u32 hf : 1;
+	u32 amsdu : 1;
+	u32 resv : 7;
+} __packed;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
 struct hnat_winfo {
 	u32 bssid : 6;		/* WiFi Bssidx */
 	u32 wcid : 10;		/* WiFi wtable Idx */
 } __packed;
+#endif
 
 #else
 struct hnat_unbind_info_blk {
@@ -358,7 +383,7 @@
 	u16 etype;
 	u32 dmac_hi;
 	union {
-#if !defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
 		struct hnat_winfo winfo;
 #endif
 		u16 vlan2;
@@ -367,7 +392,17 @@
 	u32 smac_hi;
 	u16 pppoe_id;
 	u16 smac_lo;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+	u16 minfo;
+	u16 resv4;
+	struct hnat_winfo winfo;
+	struct hnat_winfo_pao winfo_pao;
+	u32 cdrt_id : 8;
+	u32 tops_entry : 6;
+	u32 resv5 : 2;
+	u32 tport_id : 4;
+	u32 resv6 : 12;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
 	u16 minfo;
 	struct hnat_winfo winfo;
 #endif
@@ -410,7 +445,69 @@
 	u16 etype;
 	u32 dmac_hi;
 	union {
+#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
+		struct hnat_winfo winfo;
+#endif
+		u16 vlan2;
+	};
+	u16 dmac_lo;
+	u32 smac_hi;
+	u16 pppoe_id;
+	u16 smac_lo;
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+	u16 minfo;
+	u16 resv3;
+	struct hnat_winfo winfo;
+	struct hnat_winfo_pao winfo_pao;
+	u32 cdrt_id : 8;
+	u32 tops_entry : 6;
+	u32 resv4 : 2;
+	u32 tport_id : 4;
+	u32 resv5 : 12;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
+	u16 minfo;
+	struct hnat_winfo winfo;
+#endif
+} __packed;
+
+struct hnat_ipv4_mape {
+	union {
+		struct hnat_bind_info_blk bfib1;
+		struct hnat_unbind_info_blk udib1;
+		u32 info_blk1;
+	};
+	u32 sip;
+	u32 dip;
+	u16 dport;
+	u16 sport;
+
+	u32 tunnel_sipv6_0;
+	u32 tunnel_sipv6_1;
+	u32 tunnel_sipv6_2;
+	u32 tunnel_sipv6_3;
+
+	u32 tunnel_dipv6_0;
+	u32 tunnel_dipv6_1;
+	u32 tunnel_dipv6_2;
+	u32 tunnel_dipv6_3;
+
+	u8 flow_lbl[3]; /* in order to consist with Linux kernel (should be 20bits) */
+	u8 priority;    /* in order to consist with Linux kernel (should be 8bits) */
+	u32 hop_limit : 8;
+	u32 resv2 : 18;
+	u32 act_dp : 6; /* UDF */
+
+	union {
+		struct hnat_info_blk2 iblk2;
+		struct hnat_info_blk2_whnat iblk2w;
+		u32 info_blk2;
+	};
+
+	u16 vlan1;
+	u16 etype;
+	u32 dmac_hi;
+	union {
-#if !defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
 		struct hnat_winfo winfo;
 #endif
 		u16 vlan2;
@@ -419,13 +516,27 @@
 	u32 smac_hi;
 	u16 pppoe_id;
 	u16 smac_lo;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+	u16 minfo;
+	u16 resv3;
+	u32 new_sip;
+	u32 new_dip;
+	u16 new_dport;
+	u16 new_sport;
+	struct hnat_winfo winfo;
+	struct hnat_winfo_pao winfo_pao;
+	u32 cdrt_id : 8;
+	u32 tops_entry : 6;
+	u32 resv4 : 2;
+	u32 tport_id : 4;
+	u32 resv5 : 12;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
 	u16 minfo;
 	struct hnat_winfo winfo;
 	u32 new_sip;
-        u32 new_dip;
-        u16 new_dport;
-        u16 new_sport;
+	u32 new_dip;
+	u16 new_dport;
+	u16 new_sport;
 #endif
 } __packed;
 
@@ -461,7 +572,7 @@
 	u16 etype;
 	u32 dmac_hi;
 	union {
-#if !defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
 		struct hnat_winfo winfo;
 #endif
 		u16 vlan2;
@@ -470,8 +581,18 @@
 	u32 smac_hi;
 	u16 pppoe_id;
 	u16 smac_lo;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
 	u16 minfo;
+	u16 resv5;
+	struct hnat_winfo winfo;
+	struct hnat_winfo_pao winfo_pao;
+	u32 cdrt_id : 8;
+	u32 tops_entry : 6;
+	u32 resv6 : 2;
+	u32 tport_id : 4;
+	u32 resv7 : 12;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
+	u16 minfo;
 	struct hnat_winfo winfo;
 #endif
 } __packed;
@@ -509,7 +630,7 @@
 	u16 etype;
 	u32 dmac_hi;
 	union {
-#if !defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
 		struct hnat_winfo winfo;
 #endif
 		u16 vlan2;
@@ -518,7 +639,17 @@
 	u32 smac_hi;
 	u16 pppoe_id;
 	u16 smac_lo;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+	u16 minfo;
+	u16 resv5;
+	struct hnat_winfo winfo;
+	struct hnat_winfo_pao winfo_pao;
+	u32 cdrt_id : 8;
+	u32 tops_entry : 6;
+	u32 resv6 : 2;
+	u32 tport_id : 4;
+	u32 resv7 : 12;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
 	u16 minfo;
 	struct hnat_winfo winfo;
 #endif
@@ -562,7 +693,7 @@
 	u16 etype;
 	u32 dmac_hi;
 	union {
-#if !defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
 		struct hnat_winfo winfo;
 #endif
 		u16 vlan2;
@@ -571,13 +702,31 @@
 	u32 smac_hi;
 	u16 pppoe_id;
 	u16 smac_lo;
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
 	u16 minfo;
+	u16 resv3;
+	struct hnat_winfo winfo;
+	struct hnat_winfo_pao winfo_pao;
+	u32 cdrt_id : 8;
+	u32 tops_entry : 6;
+	u32 resv4 : 2;
+	u32 tport_id : 4;
+	u32 resv5 : 12;
+	u32 resv6;
+	u32 resv7;
+	u32 resv8;
+	u32 resv9;
+	u32 resv10;
+	u32 resv11;
+	u32 resv12;
+	u32 resv13;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
+	u16 minfo;
 	struct hnat_winfo winfo;
 	u32 resv3;
-        u32 resv4;
-        u16 new_dport;
-        u16 new_sport;
+	u32 resv4;
+	u16 new_dport;
+	u16 new_sport;
 #endif
 } __packed;
 
@@ -587,6 +736,7 @@
 		struct hnat_bind_info_blk bfib1;
 		struct hnat_ipv4_hnapt ipv4_hnapt;
 		struct hnat_ipv4_dslite ipv4_dslite;
+		struct hnat_ipv4_mape ipv4_mape;
 		struct hnat_ipv6_3t_route ipv6_3t_route;
 		struct hnat_ipv6_5t_route ipv6_5t_route;
 		struct hnat_ipv6_6rd ipv6_6rd;
@@ -605,7 +755,9 @@
 #define MAX_EXT_DEVS		(0x3fU)
 #define MAX_IF_NUM		64
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MAX_PPE_NUM		3
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
 #define MAX_PPE_NUM		2
 #else
 #define MAX_PPE_NUM		1
@@ -627,10 +779,11 @@
 };
 
 enum mtk_hnat_version {
-	MTK_HNAT_V1 = 1, /* version 1: mt7621, mt7623 */
-	MTK_HNAT_V2, /* version 2: mt7622 */
-	MTK_HNAT_V3, /* version 3: mt7629 */
-	MTK_HNAT_V4, /* version 4: mt7986 */
+	MTK_HNAT_V1 = 1,	/* version 1: mt7621, mt7623 */
+	MTK_HNAT_V2,		/* version 2: mt7622 */
+	MTK_HNAT_V3,		/* version 3: mt7629 */
+	MTK_HNAT_V4,		/* version 4: mt7981, mt7986 */
+	MTK_HNAT_V5,		/* version 5: mt7988 */
 };
 
 struct mtk_hnat_data {
@@ -660,6 +813,7 @@
 	/*devices we plays for*/
 	char wan[IFNAMSIZ];
 	char lan[IFNAMSIZ];
+	char lan2[IFNAMSIZ];
 	char ppd[IFNAMSIZ];
 	u16 lvid;
 	u16 wvid;
@@ -702,7 +856,7 @@
 	IPV6_3T_ROUTE = 4,
 	IPV6_5T_ROUTE = 5,
 	IPV6_6RD = 7,
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 	IPV4_MAP_T = 8,
 	IPV4_MAP_E = 9,
 #else
@@ -719,8 +873,9 @@
 #define HASH_SEED_KEY 0x12345678
 
 /*PPE_TB_CFG value*/
+#define ENTRY_128B 0
+#define ENTRY_96B 1
 #define ENTRY_80B 1
-#define ENTRY_64B 0
 #define TABLE_1K 0
 #define TABLE_2K 1
 #define TABLE_4K 2
@@ -763,6 +918,22 @@
 	(BITS_GDM_UFRC_P_PPE | BITS_GDM_BFRC_P_PPE | BITS_GDM_MFRC_P_PPE |  \
 	 BITS_GDM_OFRC_P_PPE)
 
+#define BITS_GDM_UFRC_P_PPE1 (NR_PPE1_PORT << 12)
+#define BITS_GDM_BFRC_P_PPE1 (NR_PPE1_PORT << 8)
+#define BITS_GDM_MFRC_P_PPE1 (NR_PPE1_PORT << 4)
+#define BITS_GDM_OFRC_P_PPE1 (NR_PPE1_PORT << 0)
+#define BITS_GDM_ALL_FRC_P_PPE1					\
+	(BITS_GDM_UFRC_P_PPE1 | BITS_GDM_BFRC_P_PPE1 |		\
+	 BITS_GDM_MFRC_P_PPE1 | BITS_GDM_OFRC_P_PPE1)
+
+#define BITS_GDM_UFRC_P_PPE2 (NR_PPE2_PORT << 12)
+#define BITS_GDM_BFRC_P_PPE2 (NR_PPE2_PORT << 8)
+#define BITS_GDM_MFRC_P_PPE2 (NR_PPE2_PORT << 4)
+#define BITS_GDM_OFRC_P_PPE2 (NR_PPE2_PORT << 0)
+#define BITS_GDM_ALL_FRC_P_PPE2					\
+	(BITS_GDM_UFRC_P_PPE2 | BITS_GDM_BFRC_P_PPE2 |		\
+	 BITS_GDM_MFRC_P_PPE2 | BITS_GDM_OFRC_P_PPE2)
+
 #define BITS_GDM_UFRC_P_CPU_PDMA (NR_PDMA_PORT << 12)
 #define BITS_GDM_BFRC_P_CPU_PDMA (NR_PDMA_PORT << 8)
 #define BITS_GDM_MFRC_P_CPU_PDMA (NR_PDMA_PORT << 4)
@@ -799,7 +970,9 @@
 
 #define skb_hnat_is_hashed(skb)                                                \
 	(skb_hnat_entry(skb) != 0x3fff && skb_hnat_entry(skb) < hnat_priv->foe_etry_num)
+#define FROM_GE_LAN_GRP(skb) (FROM_GE_LAN(skb) | FROM_GE_LAN2(skb))
 #define FROM_GE_LAN(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN)
+#define FROM_GE_LAN2(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN2)
 #define FROM_GE_WAN(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_WAN)
 #define FROM_GE_PPD(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_PPD)
 #define FROM_GE_VIRTUAL(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL)
@@ -811,8 +984,10 @@
 #define FOE_MAGIC_EXT 0x3
 #define FOE_MAGIC_GE_VIRTUAL 0x4
 #define FOE_MAGIC_GE_PPD 0x5
+#define FOE_MAGIC_GE_LAN2 0x6
 #define FOE_MAGIC_WED0 0x78
 #define FOE_MAGIC_WED1 0x79
+#define FOE_MAGIC_WED2 0x7A
 #define FOE_INVALID 0xf
 #define index6b(i) (0x3fU - i)
 
@@ -826,10 +1001,11 @@
 #define NR_PDMA_PORT 0
 #define NR_GMAC1_PORT 1
 #define NR_GMAC2_PORT 2
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define NR_WHNAT_WDMA_PORT EINVAL
 #define NR_PPE0_PORT 3
 #define NR_PPE1_PORT 4
+#define NR_PPE2_PORT 0xC
 #else
 #define NR_WHNAT_WDMA_PORT 3
 #define NR_PPE0_PORT 4
@@ -838,10 +1014,15 @@
 #define NR_DISCARD 7
 #define NR_WDMA0_PORT 8
 #define NR_WDMA1_PORT 9
+#define NR_GMAC3_PORT 15
 #define LAN_DEV_NAME hnat_priv->lan
+#define LAN2_DEV_NAME hnat_priv->lan2
 #define IS_WAN(dev)                                                            \
 	(!strncmp((dev)->name, hnat_priv->wan, strlen(hnat_priv->wan)))
+#define IS_LAN_GRP(dev) (IS_LAN(dev) | IS_LAN2(dev))
 #define IS_LAN(dev) (!strncmp(dev->name, LAN_DEV_NAME, strlen(LAN_DEV_NAME)))
+#define IS_LAN2(dev) (!strncmp(dev->name, LAN2_DEV_NAME,			\
+		      strlen(LAN2_DEV_NAME)))
 #define IS_BR(dev) (!strncmp(dev->name, "br", 2))
 #define IS_WHNAT(dev)								\
 	((hnat_priv->data->whnat &&						\
@@ -923,6 +1104,7 @@
 				     struct flow_offload_hw_path *hw_path,
 				     u16 eth_proto, int mape)
 {
+	return 0;
 }
 
 static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index 73607b9..e41e859 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
@@ -402,10 +402,10 @@
 			entry->ipv4_dslite.tunnel_dipv6_1,
 			entry->ipv4_dslite.tunnel_dipv6_2,
 			entry->ipv4_dslite.tunnel_dipv6_3);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 	} else if (IS_IPV4_MAPE(entry)) {
-		nsaddr = htonl(entry->ipv4_dslite.new_sip);
-		ndaddr = htonl(entry->ipv4_dslite.new_dip);
+		nsaddr = htonl(entry->ipv4_mape.new_sip);
+		ndaddr = htonl(entry->ipv4_mape.new_dip);
 
 		pr_info("Information Block 2: %08X\n",
 			entry->ipv4_dslite.info_blk2);
@@ -414,8 +414,8 @@
 			&saddr,	entry->ipv4_dslite.sport,
 			&daddr,	entry->ipv4_dslite.dport);
 		pr_info("IPv4 MAP-E New IP/Port: %pI4:%d->%pI4:%d\n",
-			&nsaddr, entry->ipv4_dslite.new_sport,
-			&ndaddr, entry->ipv4_dslite.new_dport);
+			&nsaddr, entry->ipv4_mape.new_sport,
+			&ndaddr, entry->ipv4_mape.new_dport);
 		pr_info("EG DIPv6: %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
 			entry->ipv4_dslite.tunnel_sipv6_0,
 			entry->ipv4_dslite.tunnel_sipv6_1,
@@ -487,6 +487,12 @@
 			entry->ipv4_hnapt.bfib1.udp == 0 ?
 			"TCP" :	entry->ipv4_hnapt.bfib1.udp == 1 ?
 			"UDP" : "Unknown");
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+		pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n",
+			entry->ipv4_hnapt.tport_id,
+			entry->ipv4_hnapt.tops_entry,
+			entry->ipv4_hnapt.cdrt_id);
+#endif
 		pr_info("=========================================\n\n");
 	} else {
 		*((u32 *)h_source) = swab32(entry->ipv6_5t_route.smac_hi);
@@ -510,6 +516,12 @@
 			entry->ipv6_5t_route.bfib1.udp == 0 ?
 			"TCP" :	entry->ipv6_5t_route.bfib1.udp == 1 ?
 			"UDP" :	"Unknown");
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+		pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n",
+			entry->ipv6_5t_route.tport_id,
+			entry->ipv6_5t_route.tops_entry,
+			entry->ipv6_5t_route.cdrt_id);
+#endif
 		pr_info("=========================================\n\n");
 	}
 	return 0;
@@ -707,7 +719,7 @@
 	     u32 index, u64 *bytes, u64 *packets)
 {
 	int ret;
-	u32 val, cnt_r0, cnt_r1, cnt_r2;
+	u32 val, cnt_r0, cnt_r1, cnt_r2, cnt_r3;
 
 	if (ppe_id >= CFG_PPE_NUM)
 		return -EINVAL;
@@ -723,8 +735,15 @@
 	cnt_r0 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R0);
 	cnt_r1 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R1);
 	cnt_r2 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R2);
-	*bytes = cnt_r0 + ((u64)(cnt_r1 & 0xffff) << 32);
-	*packets = ((cnt_r1 & 0xffff0000) >> 16) + ((cnt_r2 & 0xffffff) << 16);
+
+	if (hnat_priv->data->version == MTK_HNAT_V5) {
+		cnt_r3 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R3);
+		*bytes = cnt_r0 + ((u64)cnt_r1 << 32);
+		*packets = cnt_r2 + ((u64)cnt_r3 << 32);
+	} else {
+		*bytes = cnt_r0 + ((u64)(cnt_r1 & 0xffff) << 32);
+		*packets = ((cnt_r1 & 0xffff0000) >> 16) + ((cnt_r2 & 0xffffff) << 16);
+	}
 
 	return 0;
 
@@ -946,12 +965,12 @@
 				   ntohs(entry->ipv6_5t_route.etype),
 				   entry->ipv6_5t_route.info_blk1,
 				   entry->ipv6_5t_route.info_blk2);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 		} else if (IS_IPV4_MAPE(entry)) {
 			__be32 saddr = htonl(entry->ipv4_dslite.sip);
 			__be32 daddr = htonl(entry->ipv4_dslite.dip);
-			__be32 nsaddr = htonl(entry->ipv4_dslite.new_sip);
-			__be32 ndaddr = htonl(entry->ipv4_dslite.new_dip);
+			__be32 nsaddr = htonl(entry->ipv4_mape.new_sip);
+			__be32 ndaddr = htonl(entry->ipv4_mape.new_dip);
 			u32 ipv6_tsip0 = entry->ipv4_dslite.tunnel_sipv6_0;
 			u32 ipv6_tsip1 = entry->ipv4_dslite.tunnel_sipv6_1;
 			u32 ipv6_tsip2 = entry->ipv4_dslite.tunnel_sipv6_2;
@@ -974,8 +993,8 @@
 				   es(entry), pt(entry),
 				   &saddr, entry->ipv4_dslite.sport,
 				   &daddr, entry->ipv4_dslite.dport,
-				   &nsaddr, entry->ipv4_dslite.new_sport,
-				   &ndaddr, entry->ipv4_dslite.new_dport,
+				   &nsaddr, entry->ipv4_mape.new_sport,
+				   &ndaddr, entry->ipv4_mape.new_dport,
 				   ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
 				   ipv6_tsip3, ipv6_tdip0, ipv6_tdip1,
 				   ipv6_tdip2, ipv6_tdip3, h_source, h_dest,
@@ -1231,17 +1250,17 @@
 			   entry->ipv4_dslite.tunnel_dipv6_1,
 			   entry->ipv4_dslite.tunnel_dipv6_2,
 			   entry->ipv4_dslite.tunnel_dipv6_3);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 	} else if (IS_IPV4_MAPE(entry)) {
-		nsaddr = htonl(entry->ipv4_dslite.new_sip);
-		ndaddr = htonl(entry->ipv4_dslite.new_dip);
+		nsaddr = htonl(entry->ipv4_mape.new_sip);
+		ndaddr = htonl(entry->ipv4_mape.new_dip);
 
 		seq_printf(m,
 			   "IPv4 MAP-E(%d): %pI4:%d->%pI4:%d => %pI4:%d->%pI4:%d | Tunnel=%08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
 			   index, &saddr, entry->ipv4_dslite.sport,
 			   &daddr, entry->ipv4_dslite.dport,
-			   &nsaddr, entry->ipv4_dslite.new_sport,
-			   &ndaddr, entry->ipv4_dslite.new_dport,
+			   &nsaddr, entry->ipv4_mape.new_sport,
+			   &ndaddr, entry->ipv4_mape.new_dport,
 			   entry->ipv4_dslite.tunnel_sipv6_0,
 			   entry->ipv4_dslite.tunnel_sipv6_1,
 			   entry->ipv4_dslite.tunnel_sipv6_2,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index 6b937d5..1f58eba 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -33,7 +33,7 @@
 #include "../mtk_eth_reset.h"
 
 #define do_ge2ext_fast(dev, skb)                                               \
-	((IS_LAN(dev) || IS_WAN(dev) || IS_PPD(dev)) && \
+	((IS_LAN_GRP(dev) || IS_WAN(dev) || IS_PPD(dev)) && \
 	 skb_hnat_is_hashed(skb) && \
 	 skb_hnat_reason(skb) == HIT_BIND_FORCE_TO_CPU)
 #define do_ext2ge_fast_learn(dev, skb)                                         \
@@ -189,7 +189,7 @@
 	int i, hash_index;
 	struct foe_entry *entry;
 
-	if (!IS_LAN(dev) && !IS_WAN(dev) &&
+	if (!IS_LAN_GRP(dev) && !IS_WAN(dev) &&
 	    !find_extif_from_devname(dev->name) &&
 	    !dev->netdev_ops->ndo_flow_offload_check)
 		return;
@@ -217,9 +217,11 @@
 static void gmac_ppe_fwd_enable(struct net_device *dev)
 {
 	if (IS_LAN(dev) || IS_GMAC1_MODE)
-		set_gmac_ppe_fwd(0, 1);
+		set_gmac_ppe_fwd(NR_GMAC1_PORT, 1);
 	else if (IS_WAN(dev))
-		set_gmac_ppe_fwd(1, 1);
+		set_gmac_ppe_fwd(NR_GMAC2_PORT, 1);
+	else if (IS_LAN2(dev))
+		set_gmac_ppe_fwd(NR_GMAC3_PORT, 1);
 }
 
 int nf_hnat_netdevice_event(struct notifier_block *unused, unsigned long event,
@@ -434,9 +436,11 @@
 		}
 
 		if (IS_BOND_MODE &&
-		    (((hnat_priv->data->version == MTK_HNAT_V4) &&
+		    (((hnat_priv->data->version == MTK_HNAT_V4 ||
+		       hnat_priv->data->version == MTK_HNAT_V5) &&
 				(skb_hnat_entry(skb) != 0x7fff)) ||
-		     ((hnat_priv->data->version != MTK_HNAT_V4) &&
+		     ((hnat_priv->data->version != MTK_HNAT_V4 &&
+		       hnat_priv->data->version != MTK_HNAT_V5) &&
 				(skb_hnat_entry(skb) != 0x3fff))))
 			skb_set_hash(skb, skb_hnat_entry(skb) >> 1, PKT_HASH_TYPE_L4);
 
@@ -569,6 +573,8 @@
 		return;
 	} else if (IS_LAN(state->in)) {
 		skb_hnat_iface(skb) = FOE_MAGIC_GE_LAN;
+	} else if (IS_LAN2(state->in)) {
+		skb_hnat_iface(skb) = FOE_MAGIC_GE_LAN2;
 	} else if (IS_PPD(state->in)) {
 		skb_hnat_iface(skb) = FOE_MAGIC_GE_PPD;
 	} else if (IS_EXT(state->in)) {
@@ -725,10 +731,10 @@
 
 		entry->bfib1.udp = udp;
 
-		entry->ipv4_dslite.new_sip = ntohl(iph->saddr);
-		entry->ipv4_dslite.new_dip = ntohl(iph->daddr);
-		entry->ipv4_dslite.new_sport = ntohs(pptr->src);
-		entry->ipv4_dslite.new_dport = ntohs(pptr->dst);
+		entry->ipv4_mape.new_sip = ntohl(iph->saddr);
+		entry->ipv4_mape.new_dip = ntohl(iph->daddr);
+		entry->ipv4_mape.new_sport = ntohs(pptr->src);
+		entry->ipv4_mape.new_dport = ntohs(pptr->dst);
 
 		return 0;
 	}
@@ -1115,7 +1121,8 @@
 	entry.bfib1.vlan_layer += (hw_path->flags & FLOW_OFFLOAD_PATH_VLAN) ? 1 : 0;
 	entry.bfib1.vpm = (entry.bfib1.vlan_layer) ? 1 : 0;
 	entry.bfib1.cah = 1;
-	entry.bfib1.time_stamp = (hnat_priv->data->version == MTK_HNAT_V4) ?
+	entry.bfib1.time_stamp = (hnat_priv->data->version == MTK_HNAT_V4 ||
+				  hnat_priv->data->version == MTK_HNAT_V5) ?
 		readl(hnat_priv->fe_base + 0x0010) & (0xFF) :
 		readl(hnat_priv->fe_base + 0x0010) & (0x7FFF);
 
@@ -1134,7 +1141,8 @@
 		}
 
 		entry.ipv4_hnapt.iblk2.port_ag =
-			(hnat_priv->data->version == MTK_HNAT_V4) ? 0xf : 0x3f;
+			(hnat_priv->data->version == MTK_HNAT_V4 ||
+			 hnat_priv->data->version == MTK_HNAT_V5) ? 0xf : 0x3f;
 		break;
 	case IPV4_DSLITE:
 	case IPV4_MAP_E:
@@ -1153,7 +1161,8 @@
 		}
 
 		entry.ipv6_5t_route.iblk2.port_ag =
-			(hnat_priv->data->version == MTK_HNAT_V4) ? 0xf : 0x3f;
+			(hnat_priv->data->version == MTK_HNAT_V4 ||
+			 hnat_priv->data->version == MTK_HNAT_V5) ? 0xf : 0x3f;
 		break;
 	}
 	return entry;
@@ -1190,7 +1199,7 @@
 	entry.bfib1.pkt_type = foe->udib1.pkt_type; /* Get packte type state*/
 	entry.bfib1.state = foe->udib1.state;
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 	entry.bfib1.sp = foe->udib1.sp;
 #endif
 
@@ -1214,7 +1223,7 @@
 				entry.ipv4_dslite.dport =
 					foe->ipv4_dslite.dport;
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 				if (entry.bfib1.pkt_type == IPV4_MAP_E) {
 					pptr = skb_header_pointer(skb,
 								  iph->ihl * 4,
@@ -1223,13 +1232,13 @@
 					if (unlikely(!pptr))
 						return -1;
 
-					entry.ipv4_dslite.new_sip =
+					entry.ipv4_mape.new_sip =
 							ntohl(iph->saddr);
-					entry.ipv4_dslite.new_dip =
+					entry.ipv4_mape.new_dip =
 							ntohl(iph->daddr);
-					entry.ipv4_dslite.new_sport =
+					entry.ipv4_mape.new_sport =
 							ntohs(pptr->src);
-					entry.ipv4_dslite.new_dport =
+					entry.ipv4_mape.new_dport =
 							ntohs(pptr->dst);
 				}
 #endif
@@ -1265,7 +1274,8 @@
 
 				entry.ipv4_hnapt.vlan1 = hw_path->vlan_id;
 
-				if (skb->vlan_tci && FROM_GE_WAN(skb) && IS_LAN(dev)) {
+				if (skb->vlan_tci && FROM_GE_WAN(skb) &&
+				    IS_LAN_GRP(dev)) {
 					entry.bfib1.vlan_layer += 1;
 
 					if (entry.ipv4_hnapt.vlan1)
@@ -1317,7 +1327,8 @@
 
 			entry.ipv6_5t_route.vlan1 = hw_path->vlan_id;
 
-			if (skb->vlan_tci && FROM_GE_WAN(skb) && IS_LAN(dev)) {
+			if (skb->vlan_tci && FROM_GE_WAN(skb) &&
+			    IS_LAN_GRP(dev)) {
 				entry.bfib1.vlan_layer += 1;
 
 				if (entry.ipv6_5t_route.vlan1)
@@ -1418,10 +1429,10 @@
 #if defined(CONFIG_MEDIATEK_NETSYS_V2)
 				if (mape_toggle) {
 					entry.ipv4_dslite.iblk2.dscp = foe->ipv4_dslite.iblk2.dscp;
-					entry.ipv4_dslite.new_sip = foe->ipv4_dslite.new_sip;
-					entry.ipv4_dslite.new_dip = foe->ipv4_dslite.new_dip;
-					entry.ipv4_dslite.new_sport = foe->ipv4_dslite.new_sport;
-					entry.ipv4_dslite.new_dport = foe->ipv4_dslite.new_dport;
+					entry.ipv4_mape.new_sip = foe->ipv4_mape.new_sip;
+					entry.ipv4_mape.new_dip = foe->ipv4_mape.new_dip;
+					entry.ipv4_mape.new_sport = foe->ipv4_mape.new_sport;
+					entry.ipv4_mape.new_dport = foe->ipv4_mape.new_dport;
 				}
 #endif
 			} else if (mape_toggle &&
@@ -1451,9 +1462,14 @@
 
 				if (IS_HQOS_MODE) {
 					entry.ipv4_hnapt.iblk2.qid =
-						(hnat_priv->data->version == MTK_HNAT_V4) ?
+						(hnat_priv->data->version == MTK_HNAT_V4 ||
+						 hnat_priv->data->version == MTK_HNAT_V5) ?
 						 skb->mark & 0x7f : skb->mark & 0xf;
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+					entry.ipv4_hnapt.tport_id = 1;
+#else
 					entry.ipv4_hnapt.iblk2.fqos = 1;
+#endif
 				}
 
 				entry.ipv4_hnapt.bfib1.udp =
@@ -1527,6 +1543,8 @@
 				 NR_GMAC2_PORT : NR_GMAC1_PORT;
 		else
 			gmac = NR_GMAC1_PORT;
+	} else if (IS_LAN2(dev)) {
+		gmac = NR_GMAC3_PORT;
 	} else if (IS_WAN(dev)) {
 		if (IS_DSA_WAN(dev))
 			port_id = hnat_dsa_fill_stag(dev,&entry, hw_path,
@@ -1539,7 +1557,7 @@
 		} else {
 			gmac = (IS_GMAC1_MODE) ? NR_GMAC1_PORT : NR_GMAC2_PORT;
 		}
-	} else if (IS_EXT(dev) && (FROM_GE_PPD(skb) || FROM_GE_LAN(skb) ||
+	} else if (IS_EXT(dev) && (FROM_GE_PPD(skb) || FROM_GE_LAN_GRP(skb) ||
 		   FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb) || FROM_WED(skb))) {
 		if (!hnat_priv->data->whnat && IS_GMAC1_MODE) {
 			entry.bfib1.vpm = 1;
@@ -1583,7 +1601,8 @@
 			(hnat_priv->data->version == MTK_HNAT_V1) ? 0x3f : 0;
 
 		if (qos_toggle) {
-			if (hnat_priv->data->version == MTK_HNAT_V4) {
+			if (hnat_priv->data->version == MTK_HNAT_V4 ||
+			    hnat_priv->data->version == MTK_HNAT_V5) {
 				entry.ipv4_hnapt.iblk2.qid = qid & 0x7f;
 			} else {
 				/* qid[5:0]= port_mg[1:0]+ qid[3:0] */
@@ -1592,7 +1611,7 @@
 					entry.ipv4_hnapt.iblk2.port_mg |=
 						((qid >> 4) & 0x3);
 
-				if (((IS_EXT(dev) && (FROM_GE_LAN(skb) ||
+				if (((IS_EXT(dev) && (FROM_GE_LAN_GRP(skb) ||
 				      FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) ||
 				      ((mape_toggle && mape == 1) && !FROM_EXT(skb))) &&
 				      (!whnat)) {
@@ -1606,10 +1625,14 @@
 			    (IS_PPPQ_MODE && !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
 				entry.ipv4_hnapt.iblk2.fqos = 0;
 			else
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+				entry.ipv4_hnapt.tport_id = 1;
+#else
 				entry.ipv4_hnapt.iblk2.fqos =
 					(!IS_PPPQ_MODE || (IS_PPPQ_MODE &&
 					 (IS_DSA_1G_LAN(dev) || IS_DSA_WAN(dev) ||
 					 (FROM_WED(skb) && IS_DSA_LAN(dev)))));
+#endif
 		} else {
 			entry.ipv4_hnapt.iblk2.fqos = 0;
 		}
@@ -1619,7 +1642,8 @@
 			(hnat_priv->data->version == MTK_HNAT_V1) ? 0x3f : 0;
 
 		if (qos_toggle) {
-			if (hnat_priv->data->version == MTK_HNAT_V4) {
+			if (hnat_priv->data->version == MTK_HNAT_V4 ||
+			    hnat_priv->data->version == MTK_HNAT_V5) {
 				entry.ipv6_5t_route.iblk2.qid = qid & 0x7f;
 			} else {
 				/* qid[5:0]= port_mg[1:0]+ qid[3:0] */
@@ -1628,7 +1652,7 @@
 					entry.ipv6_5t_route.iblk2.port_mg |=
 								((qid >> 4) & 0x3);
 
-				if (IS_EXT(dev) && (FROM_GE_LAN(skb) ||
+				if (IS_EXT(dev) && (FROM_GE_LAN_GRP(skb) ||
 				    FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb)) &&
 				    (!whnat)) {
 					entry.ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
@@ -1641,10 +1665,14 @@
 			    (IS_PPPQ_MODE && !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
 				entry.ipv6_5t_route.iblk2.fqos = 0;
 			else
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+				entry.ipv6_5t_route.tport_id = 1;
+#else
 				entry.ipv6_5t_route.iblk2.fqos =
 					(!IS_PPPQ_MODE || (IS_PPPQ_MODE &&
 					 (IS_DSA_1G_LAN(dev) || IS_DSA_WAN(dev) ||
 					 (FROM_WED(skb) && IS_DSA_LAN(dev)))));
+#endif
 		} else {
 			entry.ipv6_5t_route.iblk2.fqos = 0;
 		}
@@ -1758,11 +1786,26 @@
 		entry->ipv4_hnapt.iblk2.fqos = 0;
 		if ((hnat_priv->data->version == MTK_HNAT_V2 &&
 		     gmac_no == NR_WHNAT_WDMA_PORT) ||
-		    (hnat_priv->data->version == MTK_HNAT_V4 &&
+		    ((hnat_priv->data->version == MTK_HNAT_V4 ||
+		      hnat_priv->data->version == MTK_HNAT_V5) &&
 		     (gmac_no == NR_WDMA0_PORT || gmac_no == NR_WDMA1_PORT))) {
 			entry->ipv4_hnapt.winfo.bssid = skb_hnat_bss_id(skb);
 			entry->ipv4_hnapt.winfo.wcid = skb_hnat_wc_id(skb);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+			entry->ipv4_hnapt.tport_id = (IS_HQOS_MODE) ? 1 : 0;
+			entry->ipv4_hnapt.iblk2.rxid = skb_hnat_rx_id(skb);
+			entry->ipv4_hnapt.iblk2.winfoi = 1;
+			entry->ipv4_hnapt.winfo_pao.usr_info =
+				skb_hnat_usr_info(skb);
+			entry->ipv4_hnapt.winfo_pao.tid = skb_hnat_tid(skb);
+			entry->ipv4_hnapt.winfo_pao.is_fixedrate =
+				skb_hnat_is_fixedrate(skb);
+			entry->ipv4_hnapt.winfo_pao.is_prior =
+				skb_hnat_is_prior(skb);
+			entry->ipv4_hnapt.winfo_pao.is_sp = skb_hnat_is_sp(skb);
+			entry->ipv4_hnapt.winfo_pao.hf = skb_hnat_hf(skb);
+			entry->ipv4_hnapt.winfo_pao.amsdu = skb_hnat_amsdu(skb);
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
 			entry->ipv4_hnapt.iblk2.rxid = skb_hnat_rx_id(skb);
 			entry->ipv4_hnapt.iblk2.winfoi = 1;
 #else
@@ -1775,14 +1818,14 @@
 				bfib1_tx.vpm = 1;
 				bfib1_tx.vlan_layer = 1;
 
-				if (FROM_GE_LAN(skb))
+				if (FROM_GE_LAN_GRP(skb))
 					entry->ipv4_hnapt.vlan1 = 1;
 				else if (FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))
 					entry->ipv4_hnapt.vlan1 = 2;
 			}
 
 			if (IS_HQOS_MODE &&
-			    (FROM_GE_LAN(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
+			    (FROM_GE_LAN_GRP(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
 				bfib1_tx.vpm = 0;
 				bfib1_tx.vlan_layer = 1;
 				entry->ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
@@ -1795,13 +1838,32 @@
 		entry->ipv6_5t_route.iblk2.fqos = 0;
 		if ((hnat_priv->data->version == MTK_HNAT_V2 &&
 		     gmac_no == NR_WHNAT_WDMA_PORT) ||
-		    (hnat_priv->data->version == MTK_HNAT_V4 &&
+		    ((hnat_priv->data->version == MTK_HNAT_V4 ||
+		      hnat_priv->data->version == MTK_HNAT_V5) &&
 		     (gmac_no == NR_WDMA0_PORT || gmac_no == NR_WDMA1_PORT))) {
 			entry->ipv6_5t_route.winfo.bssid = skb_hnat_bss_id(skb);
 			entry->ipv6_5t_route.winfo.wcid = skb_hnat_wc_id(skb);
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+			entry->ipv6_5t_route.tport_id = (IS_HQOS_MODE) ? 1 : 0;
 			entry->ipv6_5t_route.iblk2.rxid = skb_hnat_rx_id(skb);
 			entry->ipv6_5t_route.iblk2.winfoi = 1;
+			entry->ipv6_5t_route.winfo_pao.usr_info =
+				skb_hnat_usr_info(skb);
+			entry->ipv6_5t_route.winfo_pao.tid =
+				skb_hnat_tid(skb);
+			entry->ipv6_5t_route.winfo_pao.is_fixedrate =
+				skb_hnat_is_fixedrate(skb);
+			entry->ipv6_5t_route.winfo_pao.is_prior =
+				skb_hnat_is_prior(skb);
+			entry->ipv6_5t_route.winfo_pao.is_sp =
+				skb_hnat_is_sp(skb);
+			entry->ipv6_5t_route.winfo_pao.hf =
+				skb_hnat_hf(skb);
+			entry->ipv6_5t_route.winfo_pao.amsdu =
+				skb_hnat_amsdu(skb);
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
+			entry->ipv6_5t_route.iblk2.rxid = skb_hnat_rx_id(skb);
+			entry->ipv6_5t_route.iblk2.winfoi = 1;
 #else
 			entry->ipv6_5t_route.winfo.rxid = skb_hnat_rx_id(skb);
 			entry->ipv6_5t_route.iblk2w.winfoi = 1;
@@ -1812,14 +1874,14 @@
 				bfib1_tx.vpm = 1;
 				bfib1_tx.vlan_layer = 1;
 
-				if (FROM_GE_LAN(skb))
+				if (FROM_GE_LAN_GRP(skb))
 					entry->ipv6_5t_route.vlan1 = 1;
 				else if (FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))
 					entry->ipv6_5t_route.vlan1 = 2;
 			}
 
 			if (IS_HQOS_MODE &&
-			    (FROM_GE_LAN(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
+			    (FROM_GE_LAN_GRP(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
 				bfib1_tx.vpm = 0;
 				bfib1_tx.vlan_layer = 1;
 				entry->ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
@@ -2021,7 +2083,7 @@
 		out = (IS_GMAC1_MODE) ? hw_path.virt_dev : hw_path.dev;
 	}
 
-	if (!IS_LAN(out) && !IS_WAN(out) && !IS_EXT(out))
+	if (!IS_LAN_GRP(out) && !IS_WAN(out) && !IS_EXT(out))
 		return 0;
 
 	trace_printk("[%s] case hit, %x-->%s, reason=%x\n", __func__,
@@ -2067,7 +2129,7 @@
 	case HIT_BIND_MULTICAST_TO_CPU:
 	case HIT_BIND_MULTICAST_TO_GMAC_CPU:
 		/*do not forward to gdma again,if ppe already done it*/
-		if (IS_LAN(out) || IS_WAN(out))
+		if (IS_LAN_GRP(out) || IS_WAN(out))
 			return -1;
 		break;
 	}
@@ -2119,13 +2181,13 @@
 				entry->bfib1.udp = udp;
 
 				/* Map-E LAN->WAN record inner IPv4 header info. */
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 				entry->bfib1.pkt_type = IPV4_MAP_E;
 				entry->ipv4_dslite.iblk2.dscp = iph->tos;
-				entry->ipv4_dslite.new_sip = ntohl(iph->saddr);
-				entry->ipv4_dslite.new_dip = ntohl(iph->daddr);
-				entry->ipv4_dslite.new_sport = ntohs(pptr->src);
-				entry->ipv4_dslite.new_dport = ntohs(pptr->dst);
+				entry->ipv4_mape.new_sip = ntohl(iph->saddr);
+				entry->ipv4_mape.new_dip = ntohl(iph->daddr);
+				entry->ipv4_mape.new_sport = ntohs(pptr->src);
+				entry->ipv4_mape.new_dport = ntohs(pptr->dst);
 #else
 				entry->ipv4_hnapt.iblk2.dscp = iph->tos;
 				entry->ipv4_hnapt.new_sip = ntohl(iph->saddr);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
index 96bbe06..23a95fd 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
@@ -23,7 +23,7 @@
 	__u32 magic;
 };
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
 struct hnat_desc {
 	u32 entry : 15;
 	u32 filled : 3;
@@ -35,6 +35,30 @@
 	u32 iface : 8;
 	u32 wdmaid : 2;
 	u32 rxid : 2;
+	u32 wcid : 16;
+	u32 bssid : 8;
+	u32 usr_info : 16;
+	u32 tid : 4;
+	u32 is_fixedrate : 1;
+	u32 is_prior : 1;
+	u32 is_sp : 1;
+	u32 hf : 1;
+	u32 amsdu : 1;
+	u32 resv3 : 19;
+	u32 magic_tag_protect : 16;
+} __packed;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
+struct hnat_desc {
+	u32 entry : 15;
+	u32 filled : 3;
+	u32 crsn : 5;
+	u32 resv1 : 3;
+	u32 sport : 4;
+	u32 resv2 : 1;
+	u32 alg : 1;
+	u32 iface : 8;
+	u32 wdmaid : 2;
+	u32 rxid : 2;
 	u32 wcid : 10;
 	u32 bssid : 6;
 	u32 resv5 : 20;
@@ -62,7 +86,7 @@
 
 #define HNAT_MAGIC_TAG 0x6789
 #define HNAT_INFO_FILLED 0x7
-#define WIFI_INFO_LEN 3
+#define WIFI_INFO_LEN 6
 #define FOE_INFO_LEN (10 + WIFI_INFO_LEN)
 #define IS_SPACE_AVAILABLE_HEAD(skb)                                           \
 	((((skb_headroom(skb) >= FOE_INFO_LEN) ? 1 : 0)))
@@ -80,8 +104,22 @@
 #define skb_hnat_rx_id(skb) (((struct hnat_desc *)((skb)->head))->rxid)
 #define skb_hnat_wc_id(skb) (((struct hnat_desc *)((skb)->head))->wcid)
 #define skb_hnat_bss_id(skb) (((struct hnat_desc *)((skb)->head))->bssid)
-#define skb_hnat_ppe(skb)				\
-	((skb_hnat_iface(skb) == FOE_MAGIC_WED1 && CFG_PPE_NUM > 1) ? 1 : 0)
+#define skb_hnat_usr_info(skb) (((struct hnat_desc *)((skb)->head))->usr_info)
+#define skb_hnat_tid(skb) (((struct hnat_desc *)((skb)->head))->tid)
+#define skb_hnat_is_fixedrate(skb)				\
+	(((struct hnat_desc *)((skb)->head))->is_fixedrate)
+#define skb_hnat_is_prior(skb) (((struct hnat_desc *)((skb)->head))->is_prior)
+#define skb_hnat_is_sp(skb) (((struct hnat_desc *)((skb)->head))->is_sp)
+#define skb_hnat_hf(skb) (((struct hnat_desc *)((skb)->head))->hf)
+#define skb_hnat_amsdu(skb) (((struct hnat_desc *)((skb)->head))->amsdu)
+#define skb_hnat_ppe2(skb)						\
+	((skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN2 ||			\
+	 skb_hnat_iface(skb) == FOE_MAGIC_WED2) && CFG_PPE_NUM == 3)
+#define skb_hnat_ppe1(skb)						\
+	((skb_hnat_iface(skb) == FOE_MAGIC_GE_WAN && CFG_PPE_NUM == 3) ||	\
+	 (skb_hnat_iface(skb) == FOE_MAGIC_WED1 && CFG_PPE_NUM > 1))
+#define skb_hnat_ppe(skb)						\
+	(skb_hnat_ppe2(skb) ? 2 : (skb_hnat_ppe1(skb) ? 1 : 0))
 #define do_ext2ge_fast_try(dev, skb)						\
 	((skb_hnat_iface(skb) == FOE_MAGIC_EXT) && !is_from_extge(skb))
 #define set_from_extge(skb) (HNAT_SKB_CB2(skb)->magic = 0x78786688)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 2661645..d200b16 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -13,7 +13,7 @@
 
 #include "mtk_eth_soc.h"
 
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+int mtk_sgmii_init(struct mtk_xgmii *ss, struct device_node *r, u32 ana_rgc3)
 {
 	struct device_node *np;
 	int i;
@@ -25,9 +25,9 @@
 		if (!np)
 			break;
 
-		ss->regmap[i] = syscon_node_to_regmap(np);
-		if (IS_ERR(ss->regmap[i]))
-			return PTR_ERR(ss->regmap[i]);
+		ss->regmap_sgmii[i] = syscon_node_to_regmap(np);
+		if (IS_ERR(ss->regmap_sgmii[i]))
+			return PTR_ERR(ss->regmap_sgmii[i]);
 
 		ss->flags[i] &= ~(MTK_SGMII_PN_SWAP);
 		if (of_property_read_bool(np, "pn_swap"))
@@ -37,78 +37,213 @@
 	return 0;
 }
 
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, unsigned int id)
+void mtk_sgmii_setup_phya_gen1(struct mtk_xgmii *ss, int mac_id)
 {
+	u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+	if (id < 0 || id >= MTK_MAX_DEVS ||
+	    !ss->regmap_sgmii[id] || !ss->regmap_pextp[id])
+		return;
+
+	regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00D9071C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020207);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E05050F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00200032);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014BA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+	regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+	regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000EAF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080E0D);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030B09);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0606);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x00FA32FA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F21);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00011110);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x40704000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3064, GENMASK(31, 0), 0x0000C000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0xA8000000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x000000AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x20200F00);
+	regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00050000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000007);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+	udelay(150);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+	udelay(15);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C101);
+	udelay(100);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+	udelay(400);
+}
+
+void mtk_sgmii_setup_phya_gen2(struct mtk_xgmii *ss, int mac_id)
+{
+	u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+	if (id < 0 || id >= MTK_MAX_DEVS ||
+	    !ss->regmap_sgmii[id] || !ss->regmap_pextp[id])
+		return;
+
+	regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00D9071C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020707);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E050F0F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00140032);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+	regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+	regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000AAF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080D0D);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030909);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0C06);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x009C329C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F21);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00011110);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x40704000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0xA8000000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x000000AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x22000F00);
+	regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00050000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000005);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+	udelay(150);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+	udelay(15);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0201C101);
+	udelay(100);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+	udelay(400);
+}
+
+int mtk_sgmii_setup_mode_an(struct mtk_xgmii *ss, unsigned int mac_id)
+{
+	struct mtk_eth *eth = ss->eth;
 	unsigned int val;
+	u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
 
-	if (!ss->regmap[id])
+	if (!ss->regmap_sgmii[id])
 		return -EINVAL;
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+		mtk_xfi_pll_enable(ss);
+
 	/* Assert PHYA power down state */
-	regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
 
 	/* Reset SGMII PCS state */
-	regmap_write(ss->regmap[id], SGMII_RESERVED_0, SGMII_SW_RESET);
+	regmap_write(ss->regmap_sgmii[id], SGMII_RESERVED_0, SGMII_SW_RESET);
 
-	regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+	regmap_read(ss->regmap_sgmii[id], ss->ana_rgc3, &val);
 	val &= ~RG_PHY_SPEED_3_125G;
-	regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+	regmap_write(ss->regmap_sgmii[id], ss->ana_rgc3, val);
 
 	/* Setup the link timer and QPHY power up inside SGMIISYS */
-	regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_PCS_LINK_TIMER,
 		     SGMII_LINK_TIMER_DEFAULT);
 
-	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+	regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
 	val |= SGMII_REMOTE_FAULT_DIS;
-	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, val);
 
 	/* SGMII AN mode setting */
-	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+	regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
 	val &= ~SGMII_IF_MODE_MASK;
 	val |= SGMII_SPEED_DUPLEX_AN;
-	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, val);
 
-	regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+	/* Enable SGMII AN */
+	regmap_read(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, &val);
 	val |= SGMII_AN_ENABLE;
-	regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, val);
 
 	if(MTK_HAS_FLAGS(ss->flags[id],MTK_SGMII_PN_SWAP))
-		regmap_update_bits(ss->regmap[id], SGMSYS_QPHY_WRAP_CTRL,
+		regmap_update_bits(ss->regmap_sgmii[id], SGMSYS_QPHY_WRAP_CTRL,
 				   SGMII_PN_SWAP_MASK, SGMII_PN_SWAP_TX_RX);
 
 	/* Release PHYA power down state */
-	regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+		mtk_sgmii_setup_phya_gen1(ss, mac_id);
 
 	return 0;
 }
 
-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, unsigned int id,
+int mtk_sgmii_setup_mode_force(struct mtk_xgmii *ss, unsigned int mac_id,
 			       const struct phylink_link_state *state)
 {
+	struct mtk_eth *eth = ss->eth;
 	unsigned int val;
+	u32 id = mtk_mac2xgmii_id(eth, mac_id);
 
-	if (!ss->regmap[id])
+	if (!ss->regmap_sgmii[id])
 		return -EINVAL;
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+		mtk_xfi_pll_enable(ss);
+
 	/* Assert PHYA power down state */
-	regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD);
 
 	/* Reset SGMII PCS state */
-	regmap_write(ss->regmap[id], SGMII_RESERVED_0, SGMII_SW_RESET);
+	regmap_write(ss->regmap_sgmii[id], SGMII_RESERVED_0, SGMII_SW_RESET);
 
-	regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+	regmap_read(ss->regmap_sgmii[id], ss->ana_rgc3, &val);
 	val &= ~RG_PHY_SPEED_MASK;
 	if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
 		val |= RG_PHY_SPEED_3_125G;
-	regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+	regmap_write(ss->regmap_sgmii[id], ss->ana_rgc3, val);
 
 	/* Disable SGMII AN */
-	regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+	regmap_read(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, &val);
 	val &= ~SGMII_AN_ENABLE;
-	regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_PCS_CONTROL_1, val);
 
 	/* SGMII force mode setting */
-	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+	regmap_read(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, &val);
 	val &= ~SGMII_IF_MODE_MASK;
 	val &= ~SGMII_REMOTE_FAULT_DIS;
 
@@ -121,6 +256,7 @@
 		break;
 	case SPEED_2500:
 	case SPEED_1000:
+	default:
 		val |= SGMII_SPEED_1000;
 		break;
 	};
@@ -131,31 +267,34 @@
 	if (state->duplex != DUPLEX_FULL)
 		val |= SGMII_DUPLEX_FULL;
 
-	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_SGMII_MODE, val);
 
 	if(MTK_HAS_FLAGS(ss->flags[id],MTK_SGMII_PN_SWAP))
-		regmap_update_bits(ss->regmap[id], SGMSYS_QPHY_WRAP_CTRL,
+		regmap_update_bits(ss->regmap_sgmii[id], SGMSYS_QPHY_WRAP_CTRL,
 				   SGMII_PN_SWAP_MASK, SGMII_PN_SWAP_TX_RX);
 
 	/* Release PHYA power down state */
-	regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+	regmap_write(ss->regmap_sgmii[id], SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+		mtk_sgmii_setup_phya_gen2(ss, mac_id);
 
 	return 0;
 }
 
 void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
 {
-	struct mtk_sgmii *ss = eth->sgmii;
-	unsigned int val, sid;
+	struct mtk_xgmii *ss = eth->xgmii;
+	unsigned int val, sid = mtk_mac2xgmii_id(eth, mac_id);
 
 	/* Decide how GMAC and SGMIISYS be mapped */
 	sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
-	       0 : mac_id;
+	       0 : sid;
 
-	if (!ss->regmap[sid])
+	if (!ss->regmap_sgmii[sid])
 		return;
 
-	regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
+	regmap_read(ss->regmap_sgmii[sid], SGMSYS_PCS_CONTROL_1, &val);
 	val |= SGMII_AN_RESTART;
-	regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
+	regmap_write(ss->regmap_sgmii[sid], SGMSYS_PCS_CONTROL_1, val);
 }
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
new file mode 100644
index 0000000..aaefa80
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
@@ -0,0 +1,350 @@
+/* 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_xgmii *ss, struct device_node *r)
+{
+	struct device_node *np;
+	int i;
+
+	for (i = 0; i < MTK_MAX_DEVS; i++) {
+		np = of_parse_phandle(r, "mediatek,usxgmiisys", i);
+		if (!np)
+			break;
+
+		ss->regmap_usxgmii[i] = syscon_node_to_regmap(np);
+		if (IS_ERR(ss->regmap_usxgmii[i]))
+			return PTR_ERR(ss->regmap_usxgmii[i]);
+
+		ss->flags[i] &= ~(MTK_USXGMII_INT_2500);
+		if (of_property_read_bool(np, "internal_2500"))
+			ss->flags[i] |= MTK_USXGMII_INT_2500;
+	}
+
+	return 0;
+}
+
+int mtk_xfi_pextp_init(struct mtk_xgmii *ss, struct device_node *r)
+{
+	struct device_node *np;
+	int i;
+
+	for (i = 0; i < MTK_MAX_DEVS; i++) {
+		np = of_parse_phandle(r, "mediatek,xfi_pextp", i);
+		if (!np)
+			break;
+
+		ss->regmap_pextp[i] = syscon_node_to_regmap(np);
+		if (IS_ERR(ss->regmap_pextp[i]))
+			return PTR_ERR(ss->regmap_pextp[i]);
+	}
+
+	return 0;
+}
+
+int mtk_xfi_pll_init(struct mtk_xgmii *ss, struct device_node *r)
+{
+	struct device_node *np;
+
+	np = of_parse_phandle(r, "mediatek,xfi_pll", 0);
+	if (!np)
+		return -1;
+
+	ss->regmap_pll = syscon_node_to_regmap(np);
+	if (IS_ERR(ss->regmap_pll))
+		return PTR_ERR(ss->regmap_pll);
+
+	return 0;
+}
+
+int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r)
+{
+	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_xgmii *ss)
+{
+	u32 val = 0;
+
+	if (!ss->regmap_pll)
+		return -EINVAL;
+
+	/* Add software workaround for USXGMII PLL TCL issue */
+	regmap_write(ss->regmap_pll, XFI_PLL_ANA_GLB8, RG_XFI_PLL_ANA_SWWA);
+
+	regmap_read(ss->regmap_pll, XFI_PLL_DIG_GLB8, &val);
+	val |= RG_XFI_PLL_EN;
+	regmap_write(ss->regmap_pll, XFI_PLL_DIG_GLB8, val);
+
+	return 0;
+}
+
+int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id)
+{
+	u32 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:
+			pr_info("[%s] Warning: get illegal mac_id=%d !=!!!\n",
+				__func__, mac_id);
+		}
+	}
+
+	return xgmii_id;
+}
+
+void mtk_usxgmii_setup_phya_an_10000(struct mtk_xgmii *ss, int mac_id)
+{
+	u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+	if (id < 0 || id >= MTK_MAX_DEVS ||
+	    !ss->regmap_usxgmii[id] || !ss->regmap_pextp[id])
+		return;
+
+	regmap_update_bits(ss->regmap_usxgmii[id], 0x810, GENMASK(31, 0), 0x000FFE6D);
+	regmap_update_bits(ss->regmap_usxgmii[id], 0x818, GENMASK(31, 0), 0x07B1EC7B);
+	regmap_update_bits(ss->regmap_usxgmii[id], 0x80C, GENMASK(31, 0), 0x30000000);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_usxgmii[id], 0x80C, GENMASK(31, 0), 0x10000000);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_usxgmii[id], 0x80C, GENMASK(31, 0), 0x00000000);
+
+	regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00C9071C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020707);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E050F0F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00140032);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+	regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+	regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000AAF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080D0D);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030909);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0C06);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x01423342);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F20);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00022220);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5064, GENMASK(31, 0), 0x0F020A01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50B4, GENMASK(31, 0), 0x06100600);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x40704000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0xA8000000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x000000AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x00000F00);
+	regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00040000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000001);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+	udelay(150);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+	udelay(15);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C101);
+	udelay(100);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F00);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+	udelay(400);
+}
+
+void mtk_usxgmii_setup_phya_force(struct mtk_xgmii *ss, int mac_id, int max_speed)
+{
+	unsigned int val;
+	u32 id = mtk_mac2xgmii_id(ss->eth, mac_id);
+
+	if (id < 0 || id >= MTK_MAX_DEVS ||
+	    !ss->regmap_usxgmii[id] || !ss->regmap_pextp[id])
+		return;
+
+	/* Decide USXGMII speed */
+	switch (max_speed) {
+	case SPEED_5000:
+		val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_5G) |
+		      FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_5G);
+		break;
+	case SPEED_10000:
+	default:
+		val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_10G) |
+		      FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_10G);
+		break;
+	};
+	regmap_write(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+	/* Disable USXGMII AN mode */
+	regmap_read(ss->regmap_usxgmii[id], RG_PCS_AN_CTRL0, &val);
+	val &= ~RG_AN_ENABLE;
+	regmap_write(ss->regmap_usxgmii[id], RG_PCS_AN_CTRL0, val);
+
+	/* Gated USXGMII */
+	regmap_read(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
+	val |= RG_MAC_CK_GATED;
+	regmap_write(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+	ndelay(1020);
+
+	/* USXGMII force mode setting */
+	regmap_read(ss->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(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+	/* Un-gated USXGMII */
+	regmap_read(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val);
+	val &= ~RG_MAC_CK_GATED;
+	regmap_write(ss->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val);
+
+	ndelay(1020);
+
+	regmap_update_bits(ss->regmap_pextp[id], 0x9024, GENMASK(31, 0), 0x00C9071C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2020, GENMASK(31, 0), 0xAA8585AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2030, GENMASK(31, 0), 0x0C020707);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2034, GENMASK(31, 0), 0x0E050F0F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x2040, GENMASK(31, 0), 0x00140032);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50F0, GENMASK(31, 0), 0x00C014AA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E0, GENMASK(31, 0), 0x3777C12B);
+	regmap_update_bits(ss->regmap_pextp[id], 0x506C, GENMASK(31, 0), 0x005F9CFF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5070, GENMASK(31, 0), 0x9D9DFAFA);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5074, GENMASK(31, 0), 0x27273F3F);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5078, GENMASK(31, 0), 0xA7883C68);
+	regmap_update_bits(ss->regmap_pextp[id], 0x507C, GENMASK(31, 0), 0x11661166);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5080, GENMASK(31, 0), 0x0E000AAF);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5084, GENMASK(31, 0), 0x08080D0D);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5088, GENMASK(31, 0), 0x02030909);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E4, GENMASK(31, 0), 0x0C0C0000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50E8, GENMASK(31, 0), 0x04040000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50EC, GENMASK(31, 0), 0x0F0F0C06);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50A8, GENMASK(31, 0), 0x506E8C8C);
+	regmap_update_bits(ss->regmap_pextp[id], 0x6004, GENMASK(31, 0), 0x18190000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F8, GENMASK(31, 0), 0x01423342);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F20);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0030, GENMASK(31, 0), 0x00050C00);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x02002800);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3028, GENMASK(31, 0), 0x00008A01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x302C, GENMASK(31, 0), 0x0000A884);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3024, GENMASK(31, 0), 0x00083002);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3010, GENMASK(31, 0), 0x00022220);
+	regmap_update_bits(ss->regmap_pextp[id], 0x5064, GENMASK(31, 0), 0x0F020A01);
+	regmap_update_bits(ss->regmap_pextp[id], 0x50B4, GENMASK(31, 0), 0x06100600);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3048, GENMASK(31, 0), 0x49664100);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3050, GENMASK(31, 0), 0x00000000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3054, GENMASK(31, 0), 0x00000000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x306C, GENMASK(31, 0), 0x00000F00);
+	regmap_update_bits(ss->regmap_pextp[id], 0xA060, GENMASK(31, 0), 0x00040000);
+	regmap_update_bits(ss->regmap_pextp[id], 0x90D0, GENMASK(31, 0), 0x00000001);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200E800);
+	udelay(150);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0200C101);
+	udelay(15);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C111);
+	ndelay(1020);
+	regmap_update_bits(ss->regmap_pextp[id], 0x0070, GENMASK(31, 0), 0x0202C101);
+	udelay(100);
+	regmap_update_bits(ss->regmap_pextp[id], 0x30B0, GENMASK(31, 0), 0x00000030);
+	regmap_update_bits(ss->regmap_pextp[id], 0x00F4, GENMASK(31, 0), 0x80201F00);
+	regmap_update_bits(ss->regmap_pextp[id], 0x3040, GENMASK(31, 0), 0x30000000);
+	udelay(400);
+}
+
+void mtk_usxgmii_reset(struct mtk_xgmii *ss, int mac_id)
+{
+	struct mtk_eth *eth = ss->eth;
+	u32 id = mtk_mac2xgmii_id(eth, mac_id);
+
+	if (id < 0 || id >= MTK_MAX_DEVS || !eth->toprgu)
+		return;
+
+	switch (mac_id) {
+	case MTK_GMAC2_ID:
+		regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x0000A004);
+		regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F0A004);
+		regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x00000000);
+		regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F00000);
+		regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x00F00000);
+		break;
+	case MTK_GMAC3_ID:
+		regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x00005002);
+		regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F05002);
+		regmap_update_bits(eth->toprgu, 0xFC, GENMASK(31, 0), 0x00000000);
+		regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x88F00000);
+		regmap_update_bits(eth->toprgu, 0x18, GENMASK(31, 0), 0x00F00000);
+		break;
+	}
+
+	udelay(100);
+}
+
+int mtk_usxgmii_setup_mode_an(struct mtk_xgmii *ss, int mac_id, int max_speed)
+{
+	if (mac_id < 0 || mac_id >= MTK_MAX_DEVS)
+		return -EINVAL;
+
+	if ((max_speed != SPEED_10000) && (max_speed != SPEED_5000))
+		return -EINVAL;
+
+	mtk_xfi_pll_enable(ss);
+	mtk_usxgmii_reset(ss, mac_id);
+	mtk_usxgmii_setup_phya_an_10000(ss, mac_id);
+
+	return 0;
+}
+
+int mtk_usxgmii_setup_mode_force(struct mtk_xgmii *ss, int mac_id, int max_speed)
+{
+	if (mac_id < 0 || mac_id >= MTK_MAX_DEVS)
+		return -EINVAL;
+
+	if ((max_speed != SPEED_10000) && (max_speed != SPEED_5000))
+		return -EINVAL;
+
+	mtk_xfi_pll_enable(ss);
+	mtk_usxgmii_reset(ss, mac_id);
+	mtk_usxgmii_setup_phya_force(ss, mac_id, max_speed);
+
+	return 0;
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
index 0dc5129..062abae 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
@@ -105,6 +105,8 @@
 #define   MTK_PHY_RG_REXT_TRIM_MASK	GENMASK(13, 8)
 #define   MTK_PHY_RG_ZCAL_CTRL_MASK	GENMASK(5, 0)
 
+#define MTK_PHY_RG_TX_FILTER		(0xfe)
+
 #define MTK_PHY_RG_DEV1E_REG172		(0x172)
 #define   MTK_PHY_CR_TX_AMP_OFFSET_A_MASK	GENMASK(13, 8)
 #define   MTK_PHY_CR_TX_AMP_OFFSET_B_MASK	GENMASK(6, 0)
@@ -882,6 +884,8 @@
 	for(i=0; i<MTK_PHY_TX_MLT3_END; i++) {
 		phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
 	}
+
+	phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
 }
 
 static int mt798x_phy_calibration(struct phy_device *phydev)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/include/net/ra_nat.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/include/net/ra_nat.h
index 83412a4..5f3bead 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/include/net/ra_nat.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/include/net/ra_nat.h
@@ -103,6 +103,7 @@
 
 #define MAX_IF_NUM 64
 
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
 struct dmad_rx_descinfo4 {
 	uint32_t foe_entry_num:15;
 	uint32_t rsv0:3;
@@ -114,6 +115,33 @@
 	uint32_t IF:8;
 	uint32_t WDMAID:2;
 	uint32_t RXID:2;
+	uint32_t WCID:16;
+	uint32_t BSSID:8;
+	uint32_t USR_INFO:16;
+	uint32_t TID:4;
+	uint32_t IS_FIXEDRATE:1;
+	uint32_t IS_PRIOR:1;
+	uint32_t IS_SP:1;
+	uint32_t HF:1;
+	uint32_t AMSDU:1;
+	uint16_t minfo:1;
+	uint16_t ntype:3;
+	uint16_t chid:8;
+	uint16_t rsv2:7;
+	u16 MAGIC_TAG_PROTECT;
+} __packed;
+#else
+struct dmad_rx_descinfo4 {
+	uint32_t foe_entry_num:15;
+	uint32_t rsv0:3;
+	uint32_t CRSN:5;
+	uint32_t rsv1:3;
+	uint32_t SPORT:4;
+	uint32_t ppe:1;
+	uint32_t ALG:1;
+	uint32_t IF:8;
+	uint32_t WDMAID:2;
+	uint32_t RXID:2;
 	uint32_t WCID:10;
 	uint32_t BSSID:6;
 	uint32_t rsv3:4;
@@ -123,6 +151,7 @@
 	uint16_t rsv4:4;
 	u16 MAGIC_TAG_PROTECT;
 } __packed;
+#endif
 
 struct pdma_rx_desc_info4 {
 	u16 MAGIC_TAG_PROTECT;
@@ -221,12 +250,12 @@
 
 
 
-#define FOE_INFO_LEN		    12
 #define WIFI_INFO_LEN		    6
+#define FOE_INFO_LEN		    (10 + WIFI_INFO_LEN)
 
 
 #if defined(CONFIG_RA_HW_NAT_PPTP_L2TP)
-#define FOE_INFO_LEN		    (6 + 4 + WIFI_INFO_LEN)
+#define FOE_INFO_LEN		    (10 + 4 + WIFI_INFO_LEN)
 #define FOE_MAGIC_FASTPATH	    0x77
 #define FOE_MAGIC_L2TPPATH	    0x78
 #endif
@@ -237,6 +266,7 @@
 #define FOE_MAGIC_PPE		    0x76
 #define FOE_MAGIC_WED0		    0x78
 #define FOE_MAGIC_WED1		    0x79
+#define FOE_MAGIC_WED2		    0x7A
 #define FOE_MAGIC_MED		    0x80
 #define FOE_MAGIC_EDMA0		    0x81
 #define FOE_MAGIC_EDMA1		    0x82
@@ -265,6 +295,16 @@
 #define FOE_RX_ID(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->RXID)
 #define FOE_WC_ID(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->WCID)
 #define FOE_BSS_ID(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->BSSID)
+#define FOE_USR_INFO(skb)	\
+	(((struct dmad_rx_descinfo4 *)((skb)->head))->USR_INFO)
+#define FOE_TID(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->TID)
+#define FOE_IS_FIXEDRATE(skb)	\
+	(((struct dmad_rx_descinfo4 *)((skb)->head))->IS_FIXEDRATE)
+#define FOE_IS_PRIOR(skb)	\
+	(((struct dmad_rx_descinfo4 *)((skb)->head))->IS_PRIOR)
+#define FOE_IS_SP(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->IS_SP)
+#define FOE_HF(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->HF)
+#define FOE_AMSDU(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->AMSDU)
 #define FOE_PPE(skb)	(((struct dmad_rx_descinfo4 *)((skb)->head))->ppe)
 
 /***********************HEAD FORMAT*************************************/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
index e2cb03b..0d93e46 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
@@ -66,8 +66,8 @@
  #
  
  obj-$(CONFIG_NET_MEDIATEK_SOC)			+= mtk_eth.o
--mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
-+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o	\
+-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
++mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o	\
 +	     mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
  obj-$(CONFIG_NET_MEDIATEK_HNAT)			+= mtk_hnat/
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -256,7 +256,7 @@
 +int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
 +		     void *type_data);
 +
- #endif /* MTK_ETH_H */
+ int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id);
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
 new file mode 100644
 index 000000000..66298e223
@@ -4941,7 +4941,7 @@
 index 000000000..d94c6fb92
 --- /dev/null
 +++ b/net/netfilter/nf_flow_table_offload.c
-@@ -0,0 +1,1191 @@
+@@ -0,0 +1,1195 @@
 +#include <linux/kernel.h>
 +#include <linux/init.h>
 +#include <linux/module.h>
@@ -6011,6 +6011,8 @@
 +	struct flow_block_cb *block_cb, *next;
 +	int err = 0;
 +
++	down_read(&flowtable->flow_block_lock);
++
 +	switch (cmd) {
 +	case FLOW_BLOCK_BIND:
 +		list_splice(&bo->cb_list, &flowtable->flow_block.cb_list);
@@ -6026,6 +6028,8 @@
 +		err = -EOPNOTSUPP;
 +	}
 +
++	up_read(&flowtable->flow_block_lock);
++
 +	return err;
 +}
 +
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
index 166ab26..b09682f 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
@@ -248,7 +248,7 @@
  		int mac = 0;
  
  		if (eth->hwlro)
-@@ -1427,18 +1431,18 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -1427,22 +1431,22 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  			netdev->stats.rx_dropped++;
  			goto release_desc;
  		}
@@ -265,8 +265,12 @@
  			goto release_desc;
  		}
  
--		dma_unmap_single(eth->dev, trxd.rxd1,
-+		dma_unmap_single(eth->dma_dev, trxd.rxd1,
+ 		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+ 			  ((u64)(trxd.rxd2 & 0xf)) << 32 : 0;
+ 
+-		dma_unmap_single(eth->dev,
++		dma_unmap_single(eth->dma_dev,
+ 				 (u64)(trxd.rxd1 | addr64),
  				 ring->buf_size, DMA_FROM_DEVICE);
  
  		/* receive data */
@@ -346,14 +350,13 @@
  			return -ENOMEM;
 
  		rxd = ring->dma + i * eth->soc->txrx.rxd_size;
-@@ -1968,8 +1983,8 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_s
- 			rxd = ring->dma + i * eth->soc->txrx.rxd_size;
- 			if (!rxd->rxd1)
- 				continue;
-
+@@ -1968,7 +1983,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_s
+ 					       MTK_8GB_ADDRESSING)) ?
+ 				  ((u64)(rxd->rxd2 & 0xf)) << 32 : 0;
+ 
 -			dma_unmap_single(eth->dev,
 +			dma_unmap_single(eth->dma_dev,
- 					 rxd->rxd1,
+ 					 (u64)(rxd->rxd1 | addr64),
  					 ring->buf_size,
  					 DMA_FROM_DEVICE);
 @@ -1982,7 +1997,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, int in_s
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9995-flow-offload-add-mkhnat-dual-ppe-new-v2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9995-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
index df74a7d..8277899 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9995-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9995-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
@@ -177,7 +177,7 @@
  
 +int mtk_ppe_debugfs_init(struct mtk_eth *eth);
 +
- #endif /* MTK_ETH_H */
+ int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id);
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
 index d46e91178..3d6ff30ba 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-flow-offload-add-mtkhnat-qdma-qos.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-flow-offload-add-mtkhnat-qdma-qos.patch
index 989cb6c..66cb14e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-flow-offload-add-mtkhnat-qdma-qos.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-flow-offload-add-mtkhnat-qdma-qos.patch
@@ -5,7 +5,7 @@
 @@ -5,7 +5,7 @@
  
  obj-$(CONFIG_NET_MEDIATEK_SOC)			+= mtk_eth.o
- mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o	\
+ mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o	\
 -	     mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
 +	     mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o  mtk_qdma_debugfs.o
  mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o
@@ -176,7 +176,7 @@
  
 +int mtk_qdma_debugfs_init(struct mtk_eth *eth);
 +
- #endif /* MTK_ETH_H */
+ int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id);
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
 index a49275f..1767823 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
diff --git a/recipes-kernel/linux/linux-mediatek_5.4.bb b/recipes-kernel/linux/linux-mediatek_5.4.bb
index 37ea0a1..f8f5f06 100644
--- a/recipes-kernel/linux/linux-mediatek_5.4.bb
+++ b/recipes-kernel/linux/linux-mediatek_5.4.bb
@@ -7,8 +7,8 @@
 
 KBRANCH ?= "linux-5.4.y"
 
-LINUX_VERSION ?= "5.4.213"
-SRCREV_machine ?= "7e17397001a93541ffefdef553a3d541f9c1c8f8"
+LINUX_VERSION ?= "5.4.215"
+SRCREV_machine ?= "6215647d9699cb8f1bf7333ec849242c4a9cf9a6"
 KMETA = "kernel-meta"
 SRCREV_meta ?= "feeb59687bc0f054af837a5061f8d413ec7c93e9"