[rdkb][common][bsp][Refactor and sync kernel from openwrt]

[Description]
4188a020 [kernel][mtd][backport spinand series flash from v5.7 and v6.4]
7ff8e343 [openwrt][common][network][Upgrade lldpd from 1.0.7 to 1.0.17]
f2cb506b [kernel][common][eth][Add AMDA TX/RX ring index to the dbg_regs command]
300587e3 [kernel][common][eth][Add ADMA DMAD DDONE bit check]
b0d5f063 [kernel][common][hnat][Add API for WDMA to get tx/rx port in PSE]
426fa097 [kernel][mt7988][eth][Add 10G WAN support to mt7988d base on dsa-10g-emmc DTS]
98ab710b [kernel][mt7988][dts][Add 88d option type 2 support for mt76]
d887c8b2 [kernel][mt7988][eth][Fix patch conflict issue]
0c076469 [kernel][common][eth][Add ADMAv2 TX support]
db1968be [kernel][common][eth][Update Airoha EN8811H 2.5G PHY driver to v1.2.4]
8e0fd00a [kernel][common][eth][Update Airoha EN8801SC 1G PHY driver to v1.1.8 Generic]
a5ab822f [kernel][common][eth][Add SW path PPPQ and PPPQ toggle]
dcfed304 [openwrt][common][bsp][Remove garbage file]
5b5c0b3c [kernel][common][hnat][Fix unbind issue in 2-PPE setup and improve multi-PPE handling]
159b734a [kernel][mt7988][pcie][Add WIFI HW reset flow]
f67d28ce [kernel][mt7988][dts][Add WIFI HW reset pin]
385c514b [openwrt][common][sbc][Change openssl3 version to 3.2.0]
43df8d24 [kernel][7988][hnat][Add 3PPE configuration to DTS files]
9c53fc66 [openvswitch][common][Fix spinlock recursive]
62921297 [openwrt][common][bsp][Remove garbage file]
1ed2be21 [openwrt][common][bsp][Revert "Remove garbage file"]
cc165cf8 [openwrt][mt7988][crypto][Refactor config file for IPSec WebUI]
6b2a8cbc [openwrt][common][bsp][Remove garbage file]
b005c432 [kernel][mt7988][eth][i2.5Gphy: Update firmware to 20240102 version and fix fw loading flow]
a2db05ab [kernel][common][pwm][Remove unused clock-cells in pwm dts]
683ce697 [openwrt][common][bsp][Reorganize files]
2eca8f69 [kernel][common][eth][Refactor a traffic stuck issue when changing the SGMII autoneg mode]

[Release-log]

Change-Id: I2af778a9d9182e6728c13423a729b0135a7b61eb
diff --git a/recipes-bsp/mediatek-eth-firmware/files/i2p5ge-phy-pmb.bin b/recipes-bsp/mediatek-eth-firmware/files/i2p5ge-phy-pmb.bin
index 125dbcf..e1cd1de 100644
--- a/recipes-bsp/mediatek-eth-firmware/files/i2p5ge-phy-pmb.bin
+++ b/recipes-bsp/mediatek-eth-firmware/files/i2p5ge-phy-pmb.bin
Binary files differ
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1410-mtd-spinand-gigadevice-Support-for-modify-GD-Serial-NAND-from-v6-4-9.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1410-mtd-spinand-gigadevice-Support-for-modify-GD-Serial-NAND-from-v6-4-9.patch
deleted file mode 100644
index 1365854..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1410-mtd-spinand-gigadevice-Support-for-modify-GD-Serial-NAND-from-v6-4-9.patch
+++ /dev/null
@@ -1,420 +0,0 @@
-Index: linux-5.4.246/drivers/mtd/nand/spi/gigadevice.c
-===================================================================
---- linux-5.4.246.orig/drivers/mtd/nand/spi/gigadevice.c
-+++ linux-5.4.246/drivers/mtd/nand/spi/gigadevice.c
-@@ -13,7 +13,10 @@
- #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS	(1 << 4)
- #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS	(3 << 4)
- 
--#define GD5FXGQ4UEXXG_REG_STATUS2		0xf0
-+#define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS	(1 << 4)
-+#define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS	(3 << 4)
-+
-+#define GD5FXGQXXEXXG_REG_STATUS2		0xf0
- 
- #define GD5FXGQ4UXFXXG_STATUS_ECC_MASK		(7 << 4)
- #define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS	(0 << 4)
-@@ -36,6 +39,22 @@ static SPINAND_OP_VARIANTS(read_cache_va
- 		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
- 
-+static SPINAND_OP_VARIANTS(read_cache_variants_1gq5,
-+		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
-+
-+static SPINAND_OP_VARIANTS(read_cache_variants_2gq5,
-+		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
-+		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
-+
- static SPINAND_OP_VARIANTS(write_cache_variants,
- 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
- 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
-@@ -102,7 +121,7 @@ static int gd5fxgq4xa_ecc_get_status(str
- 	return -EINVAL;
- }
- 
--static int gd5fxgq4_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
-+static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
- 				       struct mtd_oob_region *region)
- {
- 	if (section)
-@@ -114,7 +133,7 @@ static int gd5fxgq4_variant2_ooblayout_e
- 	return 0;
- }
- 
--static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
-+static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
- 					struct mtd_oob_region *region)
- {
- 	if (section)
-@@ -127,16 +146,46 @@ static int gd5fxgq4_variant2_ooblayout_f
- 	return 0;
- }
- 
--static const struct mtd_ooblayout_ops gd5fxgq4_variant2_ooblayout = {
--	.ecc = gd5fxgq4_variant2_ooblayout_ecc,
--	.free = gd5fxgq4_variant2_ooblayout_free,
-+/* Valid for Q4/Q5 and Q6 (untested) devices */
-+static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
-+	.ecc = gd5fxgqx_variant2_ooblayout_ecc,
-+	.free = gd5fxgqx_variant2_ooblayout_free,
-+};
-+
-+static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
-+					struct mtd_oob_region *oobregion)
-+{
-+	if (section)
-+		return -ERANGE;
-+
-+	oobregion->offset = 128;
-+	oobregion->length = 128;
-+
-+	return 0;
-+}
-+
-+static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section,
-+					 struct mtd_oob_region *oobregion)
-+{
-+	if (section)
-+		return -ERANGE;
-+
-+	oobregion->offset = 1;
-+	oobregion->length = 127;
-+
-+	return 0;
-+}
-+
-+static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = {
-+	.ecc = gd5fxgq4xc_ooblayout_256_ecc,
-+	.free = gd5fxgq4xc_ooblayout_256_free,
- };
- 
- static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
- 					u8 status)
- {
- 	u8 status2;
--	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4UEXXG_REG_STATUS2,
-+	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
- 						      &status2);
- 	int ret;
- 
-@@ -174,6 +223,43 @@ static int gd5fxgq4uexxg_ecc_get_status(
- 	return -EINVAL;
- }
- 
-+static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
-+					u8 status)
-+{
-+	u8 status2;
-+	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
-+						      &status2);
-+	int ret;
-+
-+	switch (status & STATUS_ECC_MASK) {
-+	case STATUS_ECC_NO_BITFLIPS:
-+		return 0;
-+
-+	case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
-+		/*
-+		 * Read status2 register to determine a more fine grained
-+		 * bit error status
-+		 */
-+		ret = spi_mem_exec_op(spinand->spimem, &op);
-+		if (ret)
-+			return ret;
-+
-+		/*
-+		 * 1 ... 4 bits are flipped (and corrected)
-+		 */
-+		/* bits sorted this way (1...0): ECCSE1, ECCSE0 */
-+		return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
-+
-+	case STATUS_ECC_UNCOR_ERROR:
-+		return -EBADMSG;
-+
-+	default:
-+		break;
-+	}
-+
-+	return -EINVAL;
-+}
-+
- static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
- 					u8 status)
- {
-@@ -195,7 +281,8 @@ static int gd5fxgq4ufxxg_ecc_get_status(
- }
- 
- static const struct spinand_info gigadevice_spinand_table[] = {
--	SPINAND_INFO("GD5F1GQ4xA", 0xF1,
-+	SPINAND_INFO("GD5F1GQ4xA",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
- 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -204,7 +291,8 @@ static const struct spinand_info gigadev
- 		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
- 				     gd5fxgq4xa_ecc_get_status)),
--	SPINAND_INFO("GD5F2GQ4xA", 0xF2,
-+	SPINAND_INFO("GD5F2GQ4xA",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
- 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -213,7 +301,8 @@ static const struct spinand_info gigadev
- 		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
- 				     gd5fxgq4xa_ecc_get_status)),
--	SPINAND_INFO("GD5F4GQ4xA", 0xF4,
-+	SPINAND_INFO("GD5F4GQ4xA",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
- 		     NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -222,59 +311,205 @@ static const struct spinand_info gigadev
- 		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
- 				     gd5fxgq4xa_ecc_get_status)),
--	SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
-+	SPINAND_INFO("GD5F4GQ4RC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
-+				     gd5fxgq4ufxxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F4GQ4UC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
-+				     gd5fxgq4ufxxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F1GQ4UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F1GQ4RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     SPINAND_HAS_QE_BIT,
--		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F2GQ4UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
- 				     gd5fxgq4uexxg_ecc_get_status)),
--	SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148,
-+	SPINAND_INFO("GD5F2GQ4RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F1GQ4UFxxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     SPINAND_HAS_QE_BIT,
--		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
- 				     gd5fxgq4ufxxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F1GQ5UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq5xexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F1GQ5RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq5xexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F2GQ5UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq5xexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F2GQ5RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq5xexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F4GQ6UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq5xexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F4GQ6RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq5xexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F1GM7UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F1GM7RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F2GM7UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F2GM7RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F4GM8UExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95),
-+		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
-+	SPINAND_INFO("GD5F4GM8RExxG",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85),
-+		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
-+				     gd5fxgq4uexxg_ecc_get_status)),
- };
- 
--static int gigadevice_spinand_detect(struct spinand_device *spinand)
--{
--	u8 *id = spinand->id.data;
--	u16 did;
--	int ret;
--
--	/*
--	 * Earlier GDF5-series devices (A,E) return [0][MID][DID]
--	 * Later (F) devices return [MID][DID1][DID2]
--	 */
--
--	if (id[0] == SPINAND_MFR_GIGADEVICE)
--		did = (id[1] << 8) + id[2];
--	else if (id[0] == 0 && id[1] == SPINAND_MFR_GIGADEVICE)
--		did = id[2];
--	else
--		return 0;
--
--	ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
--				     ARRAY_SIZE(gigadevice_spinand_table),
--				     did);
--	if (ret)
--		return ret;
--
--	return 1;
--}
--
- static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
--	.detect = gigadevice_spinand_detect,
- };
- 
- const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
- 	.id = SPINAND_MFR_GIGADEVICE,
- 	.name = "GigaDevice",
-+	.chips = gigadevice_spinand_table,
-+	.nchips = ARRAY_SIZE(gigadevice_spinand_table),
- 	.ops = &gigadevice_spinand_manuf_ops,
- };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch
deleted file mode 100644
index a8c62fa..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch
+++ /dev/null
@@ -1,647 +0,0 @@
-From 0aeb63ff705a42b9140cad179ebe7f5fc54d285c Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:09 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch]
-
----
- drivers/mtd/nand/spi/core.c       | 86 ++++++++++++++++++++++---------
- drivers/mtd/nand/spi/macronix.c   | 30 +++--------
- drivers/mtd/nand/spi/micron.c     | 26 ++--------
- drivers/mtd/nand/spi/paragon.c    | 28 +++-------
- drivers/mtd/nand/spi/toshiba.c    | 42 +++++----------
- drivers/mtd/nand/spi/winbond.c    | 34 +++---------
- include/linux/mtd/spinand.h       | 66 ++++++++++++++++--------
- 8 files changed, 155 insertions(+), 202 deletions(-)
-
-diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
-index 55e636efc..9f5f95ff7 100644
---- a/drivers/mtd/nand/spi/core.c
-+++ b/drivers/mtd/nand/spi/core.c
-@@ -16,6 +16,7 @@
- #include <linux/mtd/spinand.h>
- #include <linux/of.h>
- #include <linux/slab.h>
-+#include <linux/string.h>
- #include <linux/spi/spi.h>
- #include <linux/spi/spi-mem.h>
- 
-@@ -370,10 +371,11 @@ out:
- 	return status & STATUS_BUSY ? -ETIMEDOUT : 0;
- }
- 
--static int spinand_read_id_op(struct spinand_device *spinand, u8 *buf)
-+static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr,
-+			      u8 ndummy, u8 *buf)
- {
--	struct spi_mem_op op = SPINAND_READID_OP(0, spinand->scratchbuf,
--						 SPINAND_MAX_ID_LEN);
-+	struct spi_mem_op op = SPINAND_READID_OP(
-+		naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN);
- 	int ret;
- 
- 	ret = spi_mem_exec_op(spinand->spimem, &op);
-@@ -760,24 +762,62 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = {
- 	&winbond_spinand_manufacturer,
- };
- 
--static int spinand_manufacturer_detect(struct spinand_device *spinand)
-+static int spinand_manufacturer_match(struct spinand_device *spinand,
-+				      enum spinand_readid_method rdid_method)
- {
-+	u8 *id = spinand->id.data;
- 	unsigned int i;
- 	int ret;
- 
- 	for (i = 0; i < ARRAY_SIZE(spinand_manufacturers); i++) {
--		ret = spinand_manufacturers[i]->ops->detect(spinand);
--		if (ret > 0) {
--			spinand->manufacturer = spinand_manufacturers[i];
--			return 0;
--		} else if (ret < 0) {
--			return ret;
--		}
--	}
-+		const struct spinand_manufacturer *manufacturer =
-+			spinand_manufacturers[i];
-+
-+		if (id[0] != manufacturer->id)
-+			continue;
- 
-+		ret = spinand_match_and_init(spinand,
-+					     manufacturer->chips,
-+					     manufacturer->nchips,
-+					     rdid_method);
-+		if (ret < 0)
-+			continue;
-+
-+		spinand->manufacturer = manufacturer;
-+		return 0;
-+	}
- 	return -ENOTSUPP;
- }
- 
-+static int spinand_id_detect(struct spinand_device *spinand)
-+{
-+	u8 *id = spinand->id.data;
-+	int ret;
-+
-+	ret = spinand_read_id_op(spinand, 0, 0, id);
-+	if (ret)
-+		return ret;
-+	ret = spinand_manufacturer_match(spinand, SPINAND_READID_METHOD_OPCODE);
-+	if (!ret)
-+		return 0;
-+
-+	ret = spinand_read_id_op(spinand, 1, 0, id);
-+	if (ret)
-+		return ret;
-+	ret = spinand_manufacturer_match(spinand,
-+					 SPINAND_READID_METHOD_OPCODE_ADDR);
-+	if (!ret)
-+		return 0;
-+
-+	ret = spinand_read_id_op(spinand, 0, 1, id);
-+	if (ret)
-+		return ret;
-+	ret = spinand_manufacturer_match(spinand,
-+					 SPINAND_READID_METHOD_OPCODE_DUMMY);
-+
-+	return ret;
-+}
-+
- static int spinand_manufacturer_init(struct spinand_device *spinand)
- {
- 	if (spinand->manufacturer->ops->init)
-@@ -833,9 +873,9 @@ spinand_select_op_variant(struct spinand_device *spinand,
-  * @spinand: SPI NAND object
-  * @table: SPI NAND device description table
-  * @table_size: size of the device description table
-+ * @rdid_method: read id method to match
-  *
-- * Should be used by SPI NAND manufacturer drivers when they want to find a
-- * match between a device ID retrieved through the READ_ID command and an
-+ * Match between a device ID retrieved through the READ_ID command and an
-  * entry in the SPI NAND description table. If a match is found, the spinand
-  * object will be initialized with information provided by the matching
-  * spinand_info entry.
-@@ -844,8 +884,10 @@ spinand_select_op_variant(struct spinand_device *spinand,
-  */
- int spinand_match_and_init(struct spinand_device *spinand,
- 			   const struct spinand_info *table,
--			   unsigned int table_size, u16 devid)
-+			   unsigned int table_size,
-+			   enum spinand_readid_method rdid_method)
- {
-+	u8 *id = spinand->id.data;
- 	struct nand_device *nand = spinand_to_nand(spinand);
- 	unsigned int i;
- 
-@@ -853,13 +895,17 @@ int spinand_match_and_init(struct spinand_device *spinand,
- 		const struct spinand_info *info = &table[i];
- 		const struct spi_mem_op *op;
- 
--		if (devid != info->devid)
-+		if (rdid_method != info->devid.method)
-+			continue;
-+
-+		if (memcmp(id + 1, info->devid.id, info->devid.len))
- 			continue;
- 
- 		nand->memorg = table[i].memorg;
- 		nand->eccreq = table[i].eccreq;
- 		spinand->eccinfo = table[i].eccinfo;
- 		spinand->flags = table[i].flags;
-+		spinand->id.len = 1 + table[i].devid.len;
- 		spinand->select_target = table[i].select_target;
- 
- 		op = spinand_select_op_variant(spinand,
-@@ -896,13 +942,7 @@ static int spinand_detect(struct spinand_device *spinand)
- 	if (ret)
- 		return ret;
- 
--	ret = spinand_read_id_op(spinand, spinand->id.data);
--	if (ret)
--		return ret;
--
--	spinand->id.len = SPINAND_MAX_ID_LEN;
--
--	ret = spinand_manufacturer_detect(spinand);
-+	ret = spinand_id_detect(spinand);
- 	if (ret) {
- 		dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN,
- 			spinand->id.data);
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 21def3f8f..0f900f3aa 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -99,7 +99,8 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
- }
- 
- static const struct spinand_info macronix_spinand_table[] = {
--	SPINAND_INFO("MX35LF1GE4AB", 0x12,
-+	SPINAND_INFO("MX35LF1GE4AB",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12),
- 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(4, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -108,7 +109,8 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
--	SPINAND_INFO("MX35LF2GE4AB", 0x22,
-+	SPINAND_INFO("MX35LF2GE4AB",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
- 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
- 		     NAND_ECCREQ(4, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -118,33 +120,13 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
- };
- 
--static int macronix_spinand_detect(struct spinand_device *spinand)
--{
--	u8 *id = spinand->id.data;
--	int ret;
--
--	/*
--	 * Macronix SPI NAND read ID needs a dummy byte, so the first byte in
--	 * raw_id is garbage.
--	 */
--	if (id[1] != SPINAND_MFR_MACRONIX)
--		return 0;
--
--	ret = spinand_match_and_init(spinand, macronix_spinand_table,
--				     ARRAY_SIZE(macronix_spinand_table),
--				     id[2]);
--	if (ret)
--		return ret;
--
--	return 1;
--}
--
- static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
--	.detect = macronix_spinand_detect,
- };
- 
- const struct spinand_manufacturer macronix_spinand_manufacturer = {
- 	.id = SPINAND_MFR_MACRONIX,
- 	.name = "Macronix",
-+	.chips = macronix_spinand_table,
-+	.nchips = ARRAY_SIZE(macronix_spinand_table),
- 	.ops = &macronix_spinand_manuf_ops,
- };
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 7d7b1f7fc..f56f81325 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -91,7 +91,8 @@ static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand,
- }
- 
- static const struct spinand_info micron_spinand_table[] = {
--	SPINAND_INFO("MT29F2G01ABAGD", 0x24,
-+	SPINAND_INFO("MT29F2G01ABAGD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -102,32 +103,13 @@ static const struct spinand_info micron_spinand_table[] = {
- 				     mt29f2g01abagd_ecc_get_status)),
- };
- 
--static int micron_spinand_detect(struct spinand_device *spinand)
--{
--	u8 *id = spinand->id.data;
--	int ret;
--
--	/*
--	 * Micron SPI NAND read ID need a dummy byte,
--	 * so the first byte in raw_id is dummy.
--	 */
--	if (id[1] != SPINAND_MFR_MICRON)
--		return 0;
--
--	ret = spinand_match_and_init(spinand, micron_spinand_table,
--				     ARRAY_SIZE(micron_spinand_table), id[2]);
--	if (ret)
--		return ret;
--
--	return 1;
--}
--
- static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
--	.detect = micron_spinand_detect,
- };
- 
- const struct spinand_manufacturer micron_spinand_manufacturer = {
- 	.id = SPINAND_MFR_MICRON,
- 	.name = "Micron",
-+	.chips = micron_spinand_table,
-+	.nchips = ARRAY_SIZE(micron_spinand_table),
- 	.ops = &micron_spinand_manuf_ops,
- };
-diff --git a/drivers/mtd/nand/spi/paragon.c b/drivers/mtd/nand/spi/paragon.c
-index 52307681c..519ade513 100644
---- a/drivers/mtd/nand/spi/paragon.c
-+++ b/drivers/mtd/nand/spi/paragon.c
-@@ -97,7 +97,8 @@ static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = {
- 
- 
- static const struct spinand_info paragon_spinand_table[] = {
--	SPINAND_INFO("PN26G01A", 0xe1,
-+	SPINAND_INFO("PN26G01A",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe1),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -106,7 +107,8 @@ static const struct spinand_info paragon_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&pn26g0xa_ooblayout,
- 				     pn26g0xa_ecc_get_status)),
--	SPINAND_INFO("PN26G02A", 0xe2,
-+	SPINAND_INFO("PN26G02A",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe2),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -117,31 +119,13 @@ static const struct spinand_info paragon_spinand_table[] = {
- 				     pn26g0xa_ecc_get_status)),
- };
- 
--static int paragon_spinand_detect(struct spinand_device *spinand)
--{
--	u8 *id = spinand->id.data;
--	int ret;
--
--	/* Read ID returns [0][MID][DID] */
--
--	if (id[1] != SPINAND_MFR_PARAGON)
--		return 0;
--
--	ret = spinand_match_and_init(spinand, paragon_spinand_table,
--				     ARRAY_SIZE(paragon_spinand_table),
--				     id[2]);
--	if (ret)
--		return ret;
--
--	return 1;
--}
--
- static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = {
--	.detect = paragon_spinand_detect,
- };
- 
- const struct spinand_manufacturer paragon_spinand_manufacturer = {
- 	.id = SPINAND_MFR_PARAGON,
- 	.name = "Paragon",
-+	.chips = paragon_spinand_table,
-+	.nchips = ARRAY_SIZE(paragon_spinand_table),
- 	.ops = &paragon_spinand_manuf_ops,
- };
-diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
-index 1cb3760ff..35da3c6e9 100644
---- a/drivers/mtd/nand/spi/toshiba.c
-+++ b/drivers/mtd/nand/spi/toshiba.c
-@@ -95,7 +95,8 @@ static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
- 
- static const struct spinand_info toshiba_spinand_table[] = {
- 	/* 3.3V 1Gb */
--	SPINAND_INFO("TC58CVG0S3", 0xC2,
-+	SPINAND_INFO("TC58CVG0S3",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -105,7 +106,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
- 				     tc58cxgxsx_ecc_get_status)),
- 	/* 3.3V 2Gb */
--	SPINAND_INFO("TC58CVG1S3", 0xCB,
-+	SPINAND_INFO("TC58CVG1S3",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -115,7 +117,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
- 				     tc58cxgxsx_ecc_get_status)),
- 	/* 3.3V 4Gb */
--	SPINAND_INFO("TC58CVG2S0", 0xCD,
-+	SPINAND_INFO("TC58CVG2S0",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -125,7 +128,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
- 				     tc58cxgxsx_ecc_get_status)),
- 	/* 1.8V 1Gb */
--	SPINAND_INFO("TC58CYG0S3", 0xB2,
-+	SPINAND_INFO("TC58CYG0S3",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -135,7 +139,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
- 				     tc58cxgxsx_ecc_get_status)),
- 	/* 1.8V 2Gb */
--	SPINAND_INFO("TC58CYG1S3", 0xBB,
-+	SPINAND_INFO("TC58CYG1S3",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -145,7 +150,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
- 				     tc58cxgxsx_ecc_get_status)),
- 	/* 1.8V 4Gb */
--	SPINAND_INFO("TC58CYG2S0", 0xBD,
-+	SPINAND_INFO("TC58CYG2S0",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -156,33 +162,13 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 				     tc58cxgxsx_ecc_get_status)),
- };
- 
--static int toshiba_spinand_detect(struct spinand_device *spinand)
--{
--	u8 *id = spinand->id.data;
--	int ret;
--
--	/*
--	 * Toshiba SPI NAND read ID needs a dummy byte,
--	 * so the first byte in id is garbage.
--	 */
--	if (id[1] != SPINAND_MFR_TOSHIBA)
--		return 0;
--
--	ret = spinand_match_and_init(spinand, toshiba_spinand_table,
--				     ARRAY_SIZE(toshiba_spinand_table),
--				     id[2]);
--	if (ret)
--		return ret;
--
--	return 1;
--}
--
- static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
--	.detect = toshiba_spinand_detect,
- };
- 
- const struct spinand_manufacturer toshiba_spinand_manufacturer = {
- 	.id = SPINAND_MFR_TOSHIBA,
- 	.name = "Toshiba",
-+	.chips = toshiba_spinand_table,
-+	.nchips = ARRAY_SIZE(toshiba_spinand_table),
- 	.ops = &toshiba_spinand_manuf_ops,
- };
-diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
-index a6c17e0ca..766844283 100644
---- a/drivers/mtd/nand/spi/winbond.c
-+++ b/drivers/mtd/nand/spi/winbond.c
-@@ -75,7 +75,8 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
- }
- 
- static const struct spinand_info winbond_spinand_table[] = {
--	SPINAND_INFO("W25M02GV", 0xAB,
-+	SPINAND_INFO("W25M02GV",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
- 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
- 		     NAND_ECCREQ(1, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -84,7 +85,8 @@ static const struct spinand_info winbond_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
- 		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
--	SPINAND_INFO("W25N01GV", 0xAA,
-+	SPINAND_INFO("W25N01GV",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
- 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(1, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -94,31 +96,6 @@ static const struct spinand_info winbond_spinand_table[] = {
- 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
- };
- 
--/**
-- * winbond_spinand_detect - initialize device related part in spinand_device
-- * struct if it is a Winbond device.
-- * @spinand: SPI NAND device structure
-- */
--static int winbond_spinand_detect(struct spinand_device *spinand)
--{
--	u8 *id = spinand->id.data;
--	int ret;
--
--	/*
--	 * Winbond SPI NAND read ID need a dummy byte,
--	 * so the first byte in raw_id is dummy.
--	 */
--	if (id[1] != SPINAND_MFR_WINBOND)
--		return 0;
--
--	ret = spinand_match_and_init(spinand, winbond_spinand_table,
--				     ARRAY_SIZE(winbond_spinand_table), id[2]);
--	if (ret)
--		return ret;
--
--	return 1;
--}
--
- static int winbond_spinand_init(struct spinand_device *spinand)
- {
- 	struct nand_device *nand = spinand_to_nand(spinand);
-@@ -138,12 +115,13 @@ static int winbond_spinand_init(struct spinand_device *spinand)
- }
- 
- static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
--	.detect = winbond_spinand_detect,
- 	.init = winbond_spinand_init,
- };
- 
- const struct spinand_manufacturer winbond_spinand_manufacturer = {
- 	.id = SPINAND_MFR_WINBOND,
- 	.name = "Winbond",
-+	.chips = winbond_spinand_table,
-+	.nchips = ARRAY_SIZE(winbond_spinand_table),
- 	.ops = &winbond_spinand_manuf_ops,
- };
-diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
-index 4ea558bd3..f4c4ae871 100644
---- a/include/linux/mtd/spinand.h
-+++ b/include/linux/mtd/spinand.h
-@@ -32,9 +32,9 @@
- 		   SPI_MEM_OP_NO_DUMMY,					\
- 		   SPI_MEM_OP_NO_DATA)
- 
--#define SPINAND_READID_OP(ndummy, buf, len)				\
-+#define SPINAND_READID_OP(naddr, ndummy, buf, len)			\
- 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1),				\
--		   SPI_MEM_OP_NO_ADDR,					\
-+		   SPI_MEM_OP_ADDR(naddr, 0, 1),			\
- 		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
- 		   SPI_MEM_OP_DATA_IN(len, buf, 1))
- 
-@@ -176,37 +176,46 @@ struct spinand_device;
-  * @data: buffer containing the id bytes. Currently 4 bytes large, but can
-  *	  be extended if required
-  * @len: ID length
-- *
-- * struct_spinand_id->data contains all bytes returned after a READ_ID command,
-- * including dummy bytes if the chip does not emit ID bytes right after the
-- * READ_ID command. The responsibility to extract real ID bytes is left to
-- * struct_manufacurer_ops->detect().
-  */
- struct spinand_id {
- 	u8 data[SPINAND_MAX_ID_LEN];
- 	int len;
- };
- 
-+enum spinand_readid_method {
-+	SPINAND_READID_METHOD_OPCODE,
-+	SPINAND_READID_METHOD_OPCODE_ADDR,
-+	SPINAND_READID_METHOD_OPCODE_DUMMY,
-+};
-+
-+/**
-+ * struct spinand_devid - SPI NAND device id structure
-+ * @id: device id of current chip
-+ * @len: number of bytes in device id
-+ * @method: method to read chip id
-+ *	    There are 3 possible variants:
-+ *	    SPINAND_READID_METHOD_OPCODE: chip id is returned immediately
-+ *	    after read_id opcode.
-+ *	    SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after
-+ *	    read_id opcode + 1-byte address.
-+ *	    SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after
-+ *	    read_id opcode + 1 dummy byte.
-+ */
-+struct spinand_devid {
-+	const u8 *id;
-+	const u8 len;
-+	const enum spinand_readid_method method;
-+};
-+
- /**
-  * struct manufacurer_ops - SPI NAND manufacturer specific operations
-- * @detect: detect a SPI NAND device. Every time a SPI NAND device is probed
-- *	    the core calls the struct_manufacurer_ops->detect() hook of each
-- *	    registered manufacturer until one of them return 1. Note that
-- *	    the first thing to check in this hook is that the manufacturer ID
-- *	    in struct_spinand_device->id matches the manufacturer whose
-- *	    ->detect() hook has been called. Should return 1 if there's a
-- *	    match, 0 if the manufacturer ID does not match and a negative
-- *	    error code otherwise. When true is returned, the core assumes
-- *	    that properties of the NAND chip (spinand->base.memorg and
-- *	    spinand->base.eccreq) have been filled
-  * @init: initialize a SPI NAND device
-  * @cleanup: cleanup a SPI NAND device
-  *
-  * Each SPI NAND manufacturer driver should implement this interface so that
-- * NAND chips coming from this vendor can be detected and initialized properly.
-+ * NAND chips coming from this vendor can be initialized properly.
-  */
- struct spinand_manufacturer_ops {
--	int (*detect)(struct spinand_device *spinand);
- 	int (*init)(struct spinand_device *spinand);
- 	void (*cleanup)(struct spinand_device *spinand);
- };
-@@ -215,11 +224,16 @@ struct spinand_manufacturer_ops {
-  * struct spinand_manufacturer - SPI NAND manufacturer instance
-  * @id: manufacturer ID
-  * @name: manufacturer name
-+ * @devid_len: number of bytes in device ID
-+ * @chips: supported SPI NANDs under current manufacturer
-+ * @nchips: number of SPI NANDs available in chips array
-  * @ops: manufacturer operations
-  */
- struct spinand_manufacturer {
- 	u8 id;
- 	char *name;
-+	const struct spinand_info *chips;
-+	const size_t nchips;
- 	const struct spinand_manufacturer_ops *ops;
- };
- 
-@@ -291,7 +305,7 @@ struct spinand_ecc_info {
-  */
- struct spinand_info {
- 	const char *model;
--	u16 devid;
-+	struct spinand_devid devid;
- 	u32 flags;
- 	struct nand_memory_organization memorg;
- 	struct nand_ecc_req eccreq;
-@@ -305,6 +319,13 @@ struct spinand_info {
- 			     unsigned int target);
- };
- 
-+#define SPINAND_ID(__method, ...)					\
-+	{								\
-+		.id = (const u8[]){ __VA_ARGS__ },			\
-+		.len = sizeof((u8[]){ __VA_ARGS__ }),			\
-+		.method = __method,					\
-+	}
-+
- #define SPINAND_INFO_OP_VARIANTS(__read, __write, __update)		\
- 	{								\
- 		.read_cache = __read,					\
-@@ -451,9 +472,10 @@ static inline void spinand_set_of_node(struct spinand_device *spinand,
- 	nanddev_set_of_node(&spinand->base, np);
- }
- 
--int spinand_match_and_init(struct spinand_device *dev,
-+int spinand_match_and_init(struct spinand_device *spinand,
- 			   const struct spinand_info *table,
--			   unsigned int table_size, u16 devid);
-+			   unsigned int table_size,
-+			   enum spinand_readid_method rdid_method);
- 
- int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
- int spinand_select_target(struct spinand_device *spinand, unsigned int target);
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch
deleted file mode 100644
index d55e946..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 9c8aa0697168dac0ad3638dc075c25087d4ee19c Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:10 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch]
-
----
- drivers/mtd/nand/spi/macronix.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 0f900f3aa..6e66d8710 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -118,6 +118,16 @@ static const struct spinand_info macronix_spinand_table[] = {
- 					      &update_cache_variants),
- 		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
-+	SPINAND_INFO("MX31LF1GE4BC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
-+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0 /*SPINAND_HAS_QE_BIT*/,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch
deleted file mode 100644
index 8dcf798..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 34485df92908238e8603d2c9de486e7c41db45fb Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:10 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch]
-
----
- drivers/mtd/nand/spi/macronix.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 6e66d8710..4964fe35b 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -128,6 +128,16 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     0 /*SPINAND_HAS_QE_BIT*/,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX31UF1GE4BC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),
-+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0 /*SPINAND_HAS_QE_BIT*/,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch
deleted file mode 100644
index eaa9851..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 14f6824f11e1167bf2cbbd650cd6a7a2ad856555 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:10 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch]
-
----
- drivers/mtd/nand/spi/macronix.c | 20 ++++++++++++++++++++
- 1 file changed, 20 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 4964fe35b..16d2acafb 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -118,6 +118,26 @@ static const struct spinand_info macronix_spinand_table[] = {
- 					      &update_cache_variants),
- 		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
-+	SPINAND_INFO("MX35LF2GE4AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26),
-+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35LF4GE4AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37),
-+		     NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
- 	SPINAND_INFO("MX31LF1GE4BC",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
- 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch
deleted file mode 100644
index 41b540c..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 1de538322f8e3b2586d5b41bdcc0383ecba9ce32 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:10 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch]
-
----
- drivers/mtd/nand/spi/macronix.c | 27 +++++++++++++++++++++++++++
- 1 file changed, 27 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 16d2acafb..e0c71c654 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -138,6 +138,33 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35LF1G24AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
-+	SPINAND_INFO("MX35LF2G24AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
-+	SPINAND_INFO("MX35LF4G24AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
- 	SPINAND_INFO("MX31LF1GE4BC",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
- 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch
deleted file mode 100644
index fbcca17..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-From 3b7dc97f2ff2d354c7f624d4d04fd5dd8595c923 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:11 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch]
-
----
- drivers/mtd/nand/spi/macronix.c | 112 ++++++++++++++++++++++++++++++++
- 1 file changed, 112 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index e0c71c654..ede66b71b 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -185,6 +185,118 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     0 /*SPINAND_HAS_QE_BIT*/,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
-+
-+	SPINAND_INFO("MX35LF2G14AC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20),
-+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF4G24AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF4GE4AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF2G14AC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0),
-+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF2G24AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF2GE4AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF2GE4AC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2),
-+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF1G14AC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90),
-+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF1G24AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF1GE4AD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+	SPINAND_INFO("MX35UF1GE4AC",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
-+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
-+				     mx35lf1ge4ab_ecc_get_status)),
-+
- };
- 
- static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch
deleted file mode 100644
index bcc9df8..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From ec328d836a28d538c38f67f5467b9319d6a950a3 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:11 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch]
-
----
- drivers/mtd/nand/spi/macronix.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index ede66b71b..25319b4f8 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -125,7 +125,7 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
--		     0,
-+		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
- 	SPINAND_INFO("MX35LF4GE4AD",
-@@ -135,7 +135,7 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
--		     0,
-+		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
- 	SPINAND_INFO("MX35LF1G24AD",
-@@ -145,16 +145,16 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
--		     0,
-+		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
- 	SPINAND_INFO("MX35LF2G24AD",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
--		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
- 		     NAND_ECCREQ(8, 512),
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
--		     0,
-+		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
- 	SPINAND_INFO("MX35LF4G24AD",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
-@@ -163,7 +163,7 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
--		     0,
-+		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
- 	SPINAND_INFO("MX31LF1GE4BC",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
-@@ -172,7 +172,7 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
--		     0 /*SPINAND_HAS_QE_BIT*/,
-+		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
- 	SPINAND_INFO("MX31UF1GE4BC",
-@@ -182,7 +182,7 @@ static const struct spinand_info macronix_spinand_table[] = {
- 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
- 					      &write_cache_variants,
- 					      &update_cache_variants),
--		     0 /*SPINAND_HAS_QE_BIT*/,
-+		     SPINAND_HAS_QE_BIT,
- 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
- 				     mx35lf1ge4ab_ecc_get_status)),
- 
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch
deleted file mode 100644
index 2e888d3..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-From aebf853ada4f73280d4cf7a1799cb0ebf84f87e1 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:11 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 28 ++++++++++++++--------------
- 1 file changed, 14 insertions(+), 14 deletions(-)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index f56f81325..cc1ee6842 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -34,38 +34,38 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
- 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
- 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
- 
--static int mt29f2g01abagd_ooblayout_ecc(struct mtd_info *mtd, int section,
--					struct mtd_oob_region *region)
-+static int micron_8_ooblayout_ecc(struct mtd_info *mtd, int section,
-+				  struct mtd_oob_region *region)
- {
- 	if (section)
- 		return -ERANGE;
- 
--	region->offset = 64;
--	region->length = 64;
-+	region->offset = mtd->oobsize / 2;
-+	region->length = mtd->oobsize / 2;
- 
- 	return 0;
- }
- 
--static int mt29f2g01abagd_ooblayout_free(struct mtd_info *mtd, int section,
--					 struct mtd_oob_region *region)
-+static int micron_8_ooblayout_free(struct mtd_info *mtd, int section,
-+				   struct mtd_oob_region *region)
- {
- 	if (section)
- 		return -ERANGE;
- 
- 	/* Reserve 2 bytes for the BBM. */
- 	region->offset = 2;
--	region->length = 62;
-+	region->length = (mtd->oobsize / 2) - 2;
- 
- 	return 0;
- }
- 
--static const struct mtd_ooblayout_ops mt29f2g01abagd_ooblayout = {
--	.ecc = mt29f2g01abagd_ooblayout_ecc,
--	.free = mt29f2g01abagd_ooblayout_free,
-+static const struct mtd_ooblayout_ops micron_8_ooblayout = {
-+	.ecc = micron_8_ooblayout_ecc,
-+	.free = micron_8_ooblayout_free,
- };
- 
--static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand,
--					 u8 status)
-+static int micron_8_ecc_get_status(struct spinand_device *spinand,
-+				   u8 status)
- {
- 	switch (status & MICRON_STATUS_ECC_MASK) {
- 	case STATUS_ECC_NO_BITFLIPS:
-@@ -99,8 +99,8 @@ static const struct spinand_info micron_spinand_table[] = {
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&mt29f2g01abagd_ooblayout,
--				     mt29f2g01abagd_ecc_get_status)),
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch
deleted file mode 100644
index 3ff682b..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 59766b3af8f603e740c38d2cc03c37226c78bb11 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:11 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index cc1ee6842..4727933c8 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -91,6 +91,7 @@ static int micron_8_ecc_get_status(struct spinand_device *spinand,
- }
- 
- static const struct spinand_info micron_spinand_table[] = {
-+	/* M79A 2Gb 3.3V */
- 	SPINAND_INFO("MT29F2G01ABAGD",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch
deleted file mode 100644
index 4c5e911..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 66ea40f7c5b196eee609c5e3322aac3a7ac59e03 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:12 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 33 +++++++++++++++++++++++++++++++++
- 1 file changed, 33 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 4727933c8..26925714a 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -102,6 +102,39 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-+	/* M79A 2Gb 1.8V */
-+	SPINAND_INFO("MT29F2G01ABBGD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status)),
-+	/* M78A 1Gb 3.3V */
-+	SPINAND_INFO("MT29F1G01ABAFD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status)),
-+	/* M78A 1Gb 1.8V */
-+	SPINAND_INFO("MT29F1G01ABAFD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch
deleted file mode 100644
index ae7ac72..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From 65c3b878a33bb7edd5413860537fecdff94aaba6 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:12 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 16 ++++++++++++++++
- include/linux/mtd/spinand.h   |  1 +
- 2 files changed, 17 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 26925714a..956f7710a 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -18,6 +18,8 @@
- #define MICRON_STATUS_ECC_4TO6_BITFLIPS	(3 << 4)
- #define MICRON_STATUS_ECC_7TO8_BITFLIPS	(5 << 4)
- 
-+#define MICRON_CFG_CR			BIT(0)
-+
- static SPINAND_OP_VARIANTS(read_cache_variants,
- 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-@@ -137,7 +139,21 @@ static const struct spinand_info micron_spinand_table[] = {
- 				     micron_8_ecc_get_status)),
- };
- 
-+static int micron_spinand_init(struct spinand_device *spinand)
-+{
-+	/*
-+	 * M70A device series enable Continuous Read feature at Power-up,
-+	 * which is not supported. Disable this bit to avoid any possible
-+	 * failure.
-+	 */
-+	if (spinand->flags & SPINAND_HAS_CR_FEAT_BIT)
-+		return spinand_upd_cfg(spinand, MICRON_CFG_CR, 0);
-+
-+	return 0;
-+}
-+
- static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
-+	.init = micron_spinand_init,
- };
- 
- const struct spinand_manufacturer micron_spinand_manufacturer = {
-diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
-index f4c4ae871..1077c4572 100644
---- a/include/linux/mtd/spinand.h
-+++ b/include/linux/mtd/spinand.h
-@@ -284,6 +284,7 @@ struct spinand_ecc_info {
- };
- 
- #define SPINAND_HAS_QE_BIT		BIT(0)
-+#define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
- 
- /**
-  * struct spinand_info - Structure used to describe SPI NAND chips
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch
deleted file mode 100644
index 426d674..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 5a4cd6ba8f7ae6744ca44f78c761f26e843c0341 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:12 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 956f7710a..d6fd63008 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -137,6 +137,28 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-+	/* M70A 4Gb 3.3V */
-+	SPINAND_INFO("MT29F4G01ABAFD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_CR_FEAT_BIT,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status)),
-+	/* M70A 4Gb 1.8V */
-+	SPINAND_INFO("MT29F4G01ABBFD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_CR_FEAT_BIT,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status)),
- };
- 
- static int micron_spinand_init(struct spinand_device *spinand)
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch
deleted file mode 100644
index 2e0a356..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From ac7be09336555cf993d904bd9e42c05d1769288a Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:12 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 58 +++++++++++++++++++++++++++++++++++
- 1 file changed, 58 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index d6fd63008..5d370cfcd 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -20,6 +20,14 @@
- 
- #define MICRON_CFG_CR			BIT(0)
- 
-+/*
-+ * As per datasheet, die selection is done by the 6th bit of Die
-+ * Select Register (Address 0xD0).
-+ */
-+#define MICRON_DIE_SELECT_REG	0xD0
-+
-+#define MICRON_SELECT_DIE(x)	((x) << 6)
-+
- static SPINAND_OP_VARIANTS(read_cache_variants,
- 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-@@ -66,6 +74,20 @@ static const struct mtd_ooblayout_ops micron_8_ooblayout = {
- 	.free = micron_8_ooblayout_free,
- };
- 
-+static int micron_select_target(struct spinand_device *spinand,
-+				unsigned int target)
-+{
-+	struct spi_mem_op op = SPINAND_SET_FEATURE_OP(MICRON_DIE_SELECT_REG,
-+						      spinand->scratchbuf);
-+
-+	if (target > 1)
-+		return -EINVAL;
-+
-+	*spinand->scratchbuf = MICRON_SELECT_DIE(target);
-+
-+	return spi_mem_exec_op(spinand->spimem, &op);
-+}
-+
- static int micron_8_ecc_get_status(struct spinand_device *spinand,
- 				   u8 status)
- {
-@@ -137,6 +159,18 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-+	/* M79A 4Gb 3.3V */
-+	SPINAND_INFO("MT29F4G01ADAGD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x36),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 80, 2, 1, 2),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status),
-+		     SPINAND_SELECT_TARGET(micron_select_target)),
- 	/* M70A 4Gb 3.3V */
- 	SPINAND_INFO("MT29F4G01ABAFD",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34),
-@@ -159,6 +193,30 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_HAS_CR_FEAT_BIT,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-+	/* M70A 8Gb 3.3V */
-+	SPINAND_INFO("MT29F8G01ADAFD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x46),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_CR_FEAT_BIT,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status),
-+		     SPINAND_SELECT_TARGET(micron_select_target)),
-+	/* M70A 8Gb 1.8V */
-+	SPINAND_INFO("MT29F8G01ADBFD",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x47),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     SPINAND_HAS_CR_FEAT_BIT,
-+		     SPINAND_ECCINFO(&micron_8_ooblayout,
-+				     micron_8_ecc_get_status),
-+		     SPINAND_SELECT_TARGET(micron_select_target)),
- };
- 
- static int micron_spinand_init(struct spinand_device *spinand)
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2324-mtd-spinand-micron-Use-more-specific-names.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2324-mtd-spinand-micron-Use-more-specific-names.patch
deleted file mode 100644
index e397967..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2324-mtd-spinand-micron-Use-more-specific-names.patch
+++ /dev/null
@@ -1,157 +0,0 @@
-From 5abef195abf3faa6f8e22a2e6996316f14c4f21c Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:13 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2324-mtd-spinand-micron-Use-more-specific-names.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 60 +++++++++++++++++------------------
- 1 file changed, 30 insertions(+), 30 deletions(-)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index 5d370cfcd..afe3ba37d 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -28,7 +28,7 @@
- 
- #define MICRON_SELECT_DIE(x)	((x) << 6)
- 
--static SPINAND_OP_VARIANTS(read_cache_variants,
-+static SPINAND_OP_VARIANTS(quadio_read_cache_variants,
- 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
-@@ -36,11 +36,11 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
- 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
- 
--static SPINAND_OP_VARIANTS(write_cache_variants,
-+static SPINAND_OP_VARIANTS(x4_write_cache_variants,
- 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
- 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
- 
--static SPINAND_OP_VARIANTS(update_cache_variants,
-+static SPINAND_OP_VARIANTS(x4_update_cache_variants,
- 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
- 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
- 
-@@ -120,9 +120,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-@@ -131,9 +131,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-@@ -142,9 +142,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-@@ -153,9 +153,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-@@ -164,9 +164,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x36),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 80, 2, 1, 2),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     0,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status),
-@@ -176,9 +176,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     SPINAND_HAS_CR_FEAT_BIT,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-@@ -187,9 +187,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     SPINAND_HAS_CR_FEAT_BIT,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status)),
-@@ -198,9 +198,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x46),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     SPINAND_HAS_CR_FEAT_BIT,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status),
-@@ -210,9 +210,9 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x47),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
- 		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
-+		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
-+					      &x4_write_cache_variants,
-+					      &x4_update_cache_variants),
- 		     SPINAND_HAS_CR_FEAT_BIT,
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status),
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch
deleted file mode 100644
index b6914ce..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From 5cea72055a3bce2b8b5a1f8cb6d46165eeccd8b9 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:13 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch]
-
----
- drivers/mtd/nand/spi/micron.c | 64 +++++++++++++++++++++++++++++++++++
- 1 file changed, 64 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
-index afe3ba37d..50b7295bc 100644
---- a/drivers/mtd/nand/spi/micron.c
-+++ b/drivers/mtd/nand/spi/micron.c
-@@ -44,6 +44,19 @@ static SPINAND_OP_VARIANTS(x4_update_cache_variants,
- 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
- 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
- 
-+/* Micron  MT29F2G01AAAED Device */
-+static SPINAND_OP_VARIANTS(x4_read_cache_variants,
-+			   SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-+			   SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
-+			   SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
-+			   SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
-+
-+static SPINAND_OP_VARIANTS(x1_write_cache_variants,
-+			   SPINAND_PROG_LOAD(true, 0, NULL, 0));
-+
-+static SPINAND_OP_VARIANTS(x1_update_cache_variants,
-+			   SPINAND_PROG_LOAD(false, 0, NULL, 0));
-+
- static int micron_8_ooblayout_ecc(struct mtd_info *mtd, int section,
- 				  struct mtd_oob_region *region)
- {
-@@ -74,6 +87,47 @@ static const struct mtd_ooblayout_ops micron_8_ooblayout = {
- 	.free = micron_8_ooblayout_free,
- };
- 
-+static int micron_4_ooblayout_ecc(struct mtd_info *mtd, int section,
-+				  struct mtd_oob_region *region)
-+{
-+	struct spinand_device *spinand = mtd_to_spinand(mtd);
-+
-+	if (section >= spinand->base.memorg.pagesize /
-+			mtd->ecc_step_size)
-+		return -ERANGE;
-+
-+	region->offset = (section * 16) + 8;
-+	region->length = 8;
-+
-+	return 0;
-+}
-+
-+static int micron_4_ooblayout_free(struct mtd_info *mtd, int section,
-+				   struct mtd_oob_region *region)
-+{
-+	struct spinand_device *spinand = mtd_to_spinand(mtd);
-+
-+	if (section >= spinand->base.memorg.pagesize /
-+			mtd->ecc_step_size)
-+		return -ERANGE;
-+
-+	if (section) {
-+		region->offset = 16 * section;
-+		region->length = 8;
-+	} else {
-+		/* section 0 has two bytes reserved for the BBM */
-+		region->offset = 2;
-+		region->length = 6;
-+	}
-+
-+	return 0;
-+}
-+
-+static const struct mtd_ooblayout_ops micron_4_ooblayout = {
-+	.ecc = micron_4_ooblayout_ecc,
-+	.free = micron_4_ooblayout_free,
-+};
-+
- static int micron_select_target(struct spinand_device *spinand,
- 				unsigned int target)
- {
-@@ -217,6 +271,16 @@ static const struct spinand_info micron_spinand_table[] = {
- 		     SPINAND_ECCINFO(&micron_8_ooblayout,
- 				     micron_8_ecc_get_status),
- 		     SPINAND_SELECT_TARGET(micron_select_target)),
-+	/* M69A 2Gb 3.3V */
-+	SPINAND_INFO("MT29F2G01AAAED",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9F),
-+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 80, 2, 1, 1),
-+		     NAND_ECCREQ(4, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&x4_read_cache_variants,
-+					      &x1_write_cache_variants,
-+					      &x1_update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&micron_4_ooblayout, NULL)),
- };
- 
- static int micron_spinand_init(struct spinand_device *spinand)
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch
deleted file mode 100644
index 74bab62..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch
+++ /dev/null
@@ -1,159 +0,0 @@
-From af4301a675f4fcbaa787f1d3bd07df1c08a093c3 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:13 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch]
-
----
- drivers/mtd/nand/spi/toshiba.c | 65 ++++++++++++++++++++--------------
- 1 file changed, 38 insertions(+), 27 deletions(-)
-
-diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
-index 35da3c6e9..7ce5997dd 100644
---- a/drivers/mtd/nand/spi/toshiba.c
-+++ b/drivers/mtd/nand/spi/toshiba.c
-@@ -25,8 +25,8 @@ static SPINAND_OP_VARIANTS(write_cache_variants,
- static SPINAND_OP_VARIANTS(update_cache_variants,
- 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
- 
--static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section,
--				     struct mtd_oob_region *region)
-+static int tx58cxgxsxraix_ooblayout_ecc(struct mtd_info *mtd, int section,
-+					struct mtd_oob_region *region)
- {
- 	if (section > 0)
- 		return -ERANGE;
-@@ -37,8 +37,8 @@ static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section,
- 	return 0;
- }
- 
--static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section,
--				      struct mtd_oob_region *region)
-+static int tx58cxgxsxraix_ooblayout_free(struct mtd_info *mtd, int section,
-+					 struct mtd_oob_region *region)
- {
- 	if (section > 0)
- 		return -ERANGE;
-@@ -50,13 +50,13 @@ static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section,
- 	return 0;
- }
- 
--static const struct mtd_ooblayout_ops tc58cxgxsx_ooblayout = {
--	.ecc = tc58cxgxsx_ooblayout_ecc,
--	.free = tc58cxgxsx_ooblayout_free,
-+static const struct mtd_ooblayout_ops tx58cxgxsxraix_ooblayout = {
-+	.ecc = tx58cxgxsxraix_ooblayout_ecc,
-+	.free = tx58cxgxsxraix_ooblayout_free,
- };
- 
--static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
--				      u8 status)
-+static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
-+					 u8 status)
- {
- 	struct nand_device *nand = spinand_to_nand(spinand);
- 	u8 mbf = 0;
-@@ -95,7 +95,7 @@ static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
- 
- static const struct spinand_info toshiba_spinand_table[] = {
- 	/* 3.3V 1Gb */
--	SPINAND_INFO("TC58CVG0S3",
-+	SPINAND_INFO("TC58CVG0S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
-@@ -103,10 +103,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
--				     tc58cxgxsx_ecc_get_status)),
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
- 	/* 3.3V 2Gb */
--	SPINAND_INFO("TC58CVG1S3",
-+	SPINAND_INFO("TC58CVG1S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
-@@ -114,10 +114,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
--				     tc58cxgxsx_ecc_get_status)),
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
- 	/* 3.3V 4Gb */
--	SPINAND_INFO("TC58CVG2S0",
-+	SPINAND_INFO("TC58CVG2S0HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
-@@ -125,10 +125,21 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
--				     tc58cxgxsx_ecc_get_status)),
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 3.3V 4Gb */
-+	SPINAND_INFO("TC58CVG2S0HRAIJ",
-+			SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_variants,
-+					      &update_cache_variants),
-+		     0,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
- 	/* 1.8V 1Gb */
--	SPINAND_INFO("TC58CYG0S3",
-+	SPINAND_INFO("TC58CYG0S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
-@@ -136,10 +147,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
--				     tc58cxgxsx_ecc_get_status)),
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
- 	/* 1.8V 2Gb */
--	SPINAND_INFO("TC58CYG1S3",
-+	SPINAND_INFO("TC58CYG1S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
-@@ -147,10 +158,10 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
--				     tc58cxgxsx_ecc_get_status)),
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
- 	/* 1.8V 4Gb */
--	SPINAND_INFO("TC58CYG2S0",
-+	SPINAND_INFO("TC58CYG2S0HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
- 		     NAND_ECCREQ(8, 512),
-@@ -158,8 +169,8 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 					      &write_cache_variants,
- 					      &update_cache_variants),
- 		     0,
--		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
--				     tc58cxgxsx_ecc_get_status)),
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch
deleted file mode 100644
index 12a55cb..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch
+++ /dev/null
@@ -1,201 +0,0 @@
-From 1d16ff587875717c950c983af8eaa474d0a855ca Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:13 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch]
-
----
- drivers/mtd/nand/spi/toshiba.c | 128 ++++++++++++++++++++++++++++-----
- 1 file changed, 111 insertions(+), 17 deletions(-)
-
-diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
-index 7ce5997dd..be51a2eaf 100644
---- a/drivers/mtd/nand/spi/toshiba.c
-+++ b/drivers/mtd/nand/spi/toshiba.c
-@@ -19,6 +19,18 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
- 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
- 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
- 
-+static SPINAND_OP_VARIANTS(write_cache_x4_variants,
-+		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
-+		SPINAND_PROG_LOAD(true, 0, NULL, 0));
-+
-+static SPINAND_OP_VARIANTS(update_cache_x4_variants,
-+		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
-+		SPINAND_PROG_LOAD(false, 0, NULL, 0));
-+
-+/**
-+ * Backward compatibility for 1st generation Serial NAND devices
-+ * which don't support Quad Program Load operation.
-+ */
- static SPINAND_OP_VARIANTS(write_cache_variants,
- 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
- 
-@@ -94,7 +106,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
- }
- 
- static const struct spinand_info toshiba_spinand_table[] = {
--	/* 3.3V 1Gb */
-+	/* 3.3V 1Gb (1st generation) */
- 	SPINAND_INFO("TC58CVG0S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-@@ -105,7 +117,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
- 				     tx58cxgxsxraix_ecc_get_status)),
--	/* 3.3V 2Gb */
-+	/* 3.3V 2Gb (1st generation) */
- 	SPINAND_INFO("TC58CVG1S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-@@ -116,7 +128,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
- 				     tx58cxgxsxraix_ecc_get_status)),
--	/* 3.3V 4Gb */
-+	/* 3.3V 4Gb (1st generation) */
- 	SPINAND_INFO("TC58CVG2S0HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-@@ -127,18 +139,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
- 				     tx58cxgxsxraix_ecc_get_status)),
--	/* 3.3V 4Gb */
--	SPINAND_INFO("TC58CVG2S0HRAIJ",
--			SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
--		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
--		     NAND_ECCREQ(8, 512),
--		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
--					      &write_cache_variants,
--					      &update_cache_variants),
--		     0,
--		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
--				     tx58cxgxsxraix_ecc_get_status)),
--	/* 1.8V 1Gb */
-+	/* 1.8V 1Gb (1st generation) */
- 	SPINAND_INFO("TC58CYG0S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
- 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-@@ -149,7 +150,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
- 				     tx58cxgxsxraix_ecc_get_status)),
--	/* 1.8V 2Gb */
-+	/* 1.8V 2Gb (1st generation) */
- 	SPINAND_INFO("TC58CYG1S3HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
- 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-@@ -160,7 +161,7 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
- 				     tx58cxgxsxraix_ecc_get_status)),
--	/* 1.8V 4Gb */
-+	/* 1.8V 4Gb (1st generation) */
- 	SPINAND_INFO("TC58CYG2S0HRAIG",
- 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
- 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-@@ -171,6 +172,99 @@ static const struct spinand_info toshiba_spinand_table[] = {
- 		     0,
- 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
- 				     tx58cxgxsxraix_ecc_get_status)),
-+
-+	/*
-+	 * 2nd generation serial nand has HOLD_D which is equivalent to
-+	 * QE_BIT.
-+	 */
-+	/* 3.3V 1Gb (2nd generation) */
-+	SPINAND_INFO("TC58CVG0S3HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 3.3V 2Gb (2nd generation) */
-+	SPINAND_INFO("TC58CVG1S3HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 3.3V 4Gb (2nd generation) */
-+	SPINAND_INFO("TC58CVG2S0HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 3.3V 8Gb (2nd generation) */
-+	SPINAND_INFO("TH58CVG3S0HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
-+		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 1.8V 1Gb (2nd generation) */
-+	SPINAND_INFO("TC58CYG0S3HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2),
-+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 1.8V 2Gb (2nd generation) */
-+	SPINAND_INFO("TC58CYG1S3HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB),
-+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 1.8V 4Gb (2nd generation) */
-+	SPINAND_INFO("TC58CYG2S0HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD),
-+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
-+	/* 1.8V 8Gb (2nd generation) */
-+	SPINAND_INFO("TH58CYG3S0HRAIJ",
-+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
-+		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
-+		     NAND_ECCREQ(8, 512),
-+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-+					      &write_cache_x4_variants,
-+					      &update_cache_x4_variants),
-+		     SPINAND_HAS_QE_BIT,
-+		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
-+				     tx58cxgxsxraix_ecc_get_status)),
- };
- 
- static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
--- 
-2.34.1
-
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 b8f3dfc..69688ff 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
@@ -299,24 +299,6 @@
     file://900-v5.9-0001-dt-bindings-Add-multicolor-class-dt-bindings-documen.patch \
     file://900-v5.9-0002-leds-Add-multicolor-ID-to-the-color-ID-list.patch \
     file://900-v5.9-0003-leds-add-RGB-color-option-as-that-is-different-from-.patch \
-    file://999-1410-mtd-spinand-gigadevice-Support-for-modify-GD-Serial-NAND-from-v6-4-9.patch \
-    file://999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch \
-    file://999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch \
-    file://999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch \
-    file://999-2314-mtd-spinand-macronix-Add-support-for-MX35LFxGE4AD.patch \
-    file://999-2315-mtd-spinand-macronix-Add-support-for-MX35LFxG24AD.patch \
-    file://999-2316-mtd-spinand-macronix-Add-support-for-serial-NAND-flash.patch \
-    file://999-2317-mtd-spinand-macronix-Add-Quad-support-for-serial-NAND-flash.patch \
-    file://999-2318-mtd-spinand-micron-Generalize-the-OOB-layout-structure-and-function-names.patch \
-    file://999-2319-mtd-spinand-micron-Describe-the-SPI-NAND-device-MT29F2G01ABAGD.patch \
-    file://999-2320-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices.patch \
-    file://999-2321-mtd-spinand-micron-identify-SPI-NAND-device-with-Continuous-Read-mode.patch \
-    file://999-2322-mtd-spinand-micron-Add-M70A-series-Micron-SPI-NAND-devices.patch \
-    file://999-2323-mtd-spinand-micron-Add-new-Micron-SPI-NAND-devices-with-multiple-dies.patch \
-    file://999-2324-mtd-spinand-micron-Use-more-specific-names.patch \
-    file://999-2325-mtd-spinand-micron-Add-support-for-MT29F2G01AAAED.patch \
-    file://999-2326-mtd-spinand-toshiba-Rename-function-name-to-change-suffix-and-prefix-8Gbit.patch \
-    file://999-2327-mtd-spinand-toshiba-Support-for-new-Kioxia-Serial-NAND.patch \
     file://999-2360-v5.16-spi-add-power-control-when-set_cs.patch \
     file://999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch \
     file://999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
index 888f8f5..2c7e171 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
@@ -231,7 +231,6 @@
 	pwm: pwm@10048000 {
 		compatible = "mediatek,mt7986-pwm";
 		reg = <0 0x10048000 0 0x1000>;
-		#clock-cells = <1>;
 		#pwm-cells = <2>;
 		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&infracfg CK_INFRA_PWM>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi
index 0c3e2f4..26f093b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986b.dtsi
@@ -231,7 +231,6 @@
 	pwm: pwm@10048000 {
 		compatible = "mediatek,mt7986-pwm";
 		reg = <0 0x10048000 0 0x1000>;
-		#clock-cells = <1>;
 		#pwm-cells = <2>;
 		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&infracfg CK_INFRA_PWM>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
index 888f8f5..2c7e171 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -231,7 +231,6 @@
 	pwm: pwm@10048000 {
 		compatible = "mediatek,mt7986-pwm";
 		reg = <0 0x10048000 0 0x1000>;
-		#clock-cells = <1>;
 		#pwm-cells = <2>;
 		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&infracfg CK_INFRA_PWM>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
index 0c3e2f4..26f093b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
@@ -231,7 +231,6 @@
 	pwm: pwm@10048000 {
 		compatible = "mediatek,mt7986-pwm";
 		reg = <0 0x10048000 0 0x1000>;
-		#clock-cells = <1>;
 		#pwm-cells = <2>;
 		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&infracfg CK_INFRA_PWM>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
index 5513d04..8ebcbaf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -257,6 +258,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -330,8 +333,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -562,6 +564,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
index d060c4a..5a12bf9 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -72,6 +73,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -137,8 +140,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -348,6 +350,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
index 5790dc9..f175a27 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -63,6 +64,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -128,8 +131,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -339,6 +341,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts
index a416519..54e2cf0 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -212,6 +213,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -296,8 +299,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -481,6 +483,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
index 2029b57..a4a61d6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -97,6 +98,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -162,8 +165,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -374,5 +376,6 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
index 1d4e476..2404a40 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -253,6 +254,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -325,8 +328,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -557,6 +559,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
index 0d62ea5..2624584 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -253,6 +254,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -325,8 +328,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -557,6 +559,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
index 578a489..a22af29 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -97,6 +98,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -162,8 +165,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -366,6 +368,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
index eaf3d09..dc27135 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -198,6 +199,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -265,8 +268,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -464,5 +466,6 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
index 37b7fb6..e88bc4f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -161,6 +162,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -228,8 +231,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -315,8 +317,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -429,5 +429,6 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
index e81fff3..d6da110 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -206,6 +207,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -280,8 +283,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -373,6 +375,7 @@
 	mtketh-lan = "eth0";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
index 318cc91..daac5d7 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -189,6 +190,8 @@
 &pcie1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie1_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -262,8 +265,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -378,6 +380,7 @@
 	mtketh-lan = "eth0";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
index 4907ecd..5ea962f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
@@ -5,7 +5,7 @@
  */
 
 /dts-v1/;
-
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -199,6 +199,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -292,8 +294,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -411,6 +412,7 @@
 	mtketh-lan = "eth0";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
index 89d898a..f13573c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -76,6 +77,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -148,8 +151,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -246,8 +248,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -360,6 +360,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
index 56d1b60..858c3e0 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -67,6 +68,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -139,8 +142,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -237,8 +239,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -351,6 +351,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
index f88c0b9..a6f3257 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -200,6 +201,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -279,8 +282,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -368,8 +370,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -473,5 +473,6 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
index aec7330..f7c2338 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -101,6 +102,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -173,8 +176,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -272,8 +274,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -386,5 +386,6 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
index a1a510f..e4b03bf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -234,6 +235,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -313,8 +316,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -425,8 +427,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -539,6 +539,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
index 4cab1ae..d4f96c8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -234,6 +235,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -313,8 +316,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -425,8 +427,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -539,6 +539,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
index e743718..effcfd8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -101,6 +102,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -173,8 +176,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -264,8 +266,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -378,6 +378,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
new file mode 100644
index 0000000..508ee7b
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988D DSA 10G WAN eMMC RFB";
+	compatible = "mediatek,mt7988d-dsa-10g-wan-emmc",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    root=PARTLABEL=rootfs rootwait \
+			    rootfstype=squashfs,f2fs pci=pcie_bus_perf";
+	};
+
+	cpus {
+		/delete-node/ cpu@3;
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	wsys_adie: wsys_adie@0 {
+	// fpga cases need to manual change adie_id / sku_type for dvt only
+		compatible = "mediatek,rebb-mt7988-adie";
+		adie_id = <7976>;
+		sku_type = <3000>;
+	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	status = "disabled";
+};
+
+&pcie2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2_pins>;
+	status = "disabled";
+};
+
+&pcie3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie3_pins>;
+	status = "okay";
+};
+
+&pio {
+	mdio0_pins: mdio0-pins {
+		mux {
+			function = "mdio";
+			groups = "mdc_mdio0";
+		};
+
+		conf {
+			groups = "mdc_mdio0";
+			drive-strength = <MTK_DRIVE_10mA>;
+		};
+	};
+
+	gbe0_led0_pins: gbe0-pins {
+		mux {
+			function = "led";
+			groups = "gbe0_led0";
+		};
+	};
+
+	gbe1_led0_pins: gbe1-pins {
+		mux {
+			function = "led";
+			groups = "gbe1_led0";
+		};
+	};
+
+	gbe2_led0_pins: gbe2-pins {
+		mux {
+			function = "led";
+			groups = "gbe2_led0";
+		};
+	};
+
+	gbe3_led0_pins: gbe3-pins {
+		mux {
+			function = "led";
+			groups = "gbe3_led0";
+		};
+	};
+
+	i2p5gbe_led0_pins: 2p5gbe-pins {
+		mux {
+			function = "led";
+			groups = "2p5gbe_led0";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
+		};
+	};
+
+	pcie1_pins: pcie1-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+				 "pcie_wake_n1_0";
+		};
+	};
+
+	pcie2_pins: pcie2-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+				 "pcie_wake_n2_0";
+		};
+	};
+
+	pcie3_pins: pcie3-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+				 "pcie_wake_n3_0";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1";
+		};
+	};
+
+	mmc0_pins_default: mmc0-pins-default {
+		mux {
+			function = "flash";
+			groups = "emmc_51";
+		};
+	};
+
+	mmc0_pins_uhs: mmc0-pins-uhs {
+		mux {
+			function = "flash";
+			groups = "emmc_51";
+		};
+	};
+};
+
+&watchdog {
+	status = "disabled";
+};
+
+&eth {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio0_pins>;
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+		mac-type = "xgdm";
+		phy-mode = "10gbase-kr";
+
+		fixed-link {
+			speed = <10000>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	gmac1: mac@1 {
+		compatible = "mediatek,eth-mac";
+		reg = <1>;
+		mac-type = "xgdm";
+		phy-mode = "xgmii";
+		phy-handle = <&phy0>;
+	};
+
+	gmac2: mac@2 {
+		compatible = "mediatek,eth-mac";
+		reg = <2>;
+		mac-type = "xgdm";
+		phy-mode = "usxgmii";
+		phy-handle = <&phy1>;
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <10500000>;
+
+		phy0: ethernet-phy@0 {
+			pinctrl-names = "i2p5gbe-led";
+			pinctrl-0 = <&i2p5gbe_led0_pins>;
+			reg = <15>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			phy-mode = "xgmii";
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 3 1>;
+			reset-assert-us = <100000>;
+			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
+		};
+
+		switch@0 {
+			compatible = "mediatek,mt7988";
+			reg = <31>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					label = "lan0";
+					phy-mode = "gmii";
+					phy-handle = <&sphy0>;
+				};
+
+				port@1 {
+					reg = <1>;
+					label = "lan1";
+					phy-mode = "gmii";
+					phy-handle = <&sphy1>;
+				};
+
+				port@2 {
+					reg = <2>;
+					label = "lan2";
+					phy-mode = "gmii";
+					phy-handle = <&sphy2>;
+				};
+
+				port@3 {
+					reg = <3>;
+					label = "lan3";
+					phy-mode = "gmii";
+					phy-handle = <&sphy3>;
+				};
+
+				port@6 {
+					reg = <6>;
+					label = "cpu";
+					ethernet = <&gmac0>;
+					phy-mode = "10gbase-kr";
+
+					fixed-link {
+						speed = <10000>;
+						full-duplex;
+						pause;
+					};
+				};
+			};
+
+			mdio {
+				compatible = "mediatek,dsa-slave-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sphy0: switch_phy0@0 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <0>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe0_led0_pins>;
+					nvmem-cells = <&phy_calibration_p0>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy1: switch_phy1@1 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <1>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe1_led0_pins>;
+					nvmem-cells = <&phy_calibration_p1>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy2: switch_phy2@2 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <2>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe2_led0_pins>;
+					nvmem-cells = <&phy_calibration_p2>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy3: switch_phy3@3 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <3>;
+					pinctrl-names = "gbe-led";
+					pinctrl-0 = <&gbe3_led0_pins>;
+					nvmem-cells = <&phy_calibration_p3>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth2";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth1";
+	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc0_pins_default>;
+	pinctrl-1 = <&mmc0_pins_uhs>;
+	bus-width = <8>;
+	max-frequency = <200000000>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+	hs400-ds-delay = <0x12814>;
+	vqmmc-supply = <&reg_1p8v>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	status = "okay";
+};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
index b832d59..a3bde2e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -234,6 +235,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -313,8 +316,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -537,6 +539,7 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth1";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
index 7bcf6c0..7fdec3f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -180,6 +181,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -254,8 +257,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -342,8 +344,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -455,5 +455,6 @@
 	mtketh-lan = "lan";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
index 98e76f3..2ed715c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -194,6 +195,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -268,8 +271,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -357,8 +359,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -371,6 +371,7 @@
 	mtketh-lan = "eth0";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
index 3fbdcb0..ac3da71 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
@@ -5,7 +5,7 @@
  */
 
 /dts-v1/;
-
+#include <dt-bindings/gpio/gpio.h>
 #include "mt7988.dtsi"
 
 / {
@@ -197,6 +197,8 @@
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie0_pins>;
+	wifi-reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+	wifi-reset-msleep = <100>;
 	status = "okay";
 };
 
@@ -297,8 +299,7 @@
 	pcie0_pins: pcie0-pins {
 		mux {
 			function = "pcie";
-			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
-				 "pcie_wake_n0_0";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0";
 		};
 	};
 
@@ -388,8 +389,6 @@
 			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
-			power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
-			power-domain-names = "i2p5gbe-pd";
 			compatible = "ethernet-phy-ieee802.3-c45";
 			phy-mode = "xgmii";
 		};
@@ -410,6 +409,7 @@
 	mtketh-lan = "eth0";
 	mtketh-lan2 = "eth2";
 	mtketh-max-gmac = <3>;
+	mtketh-ppe-num = <3>;
 	status = "okay";
 };
 
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 bfe2f0d..f902989 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
@@ -420,6 +420,42 @@
 	return count;
 }
 
+static int pppq_toggle_read(struct seq_file *m, void *private)
+{
+	struct mtk_eth *eth = m->private;
+
+	pr_info("value=%d, pppq is %s now!\n",
+		eth->pppq_toggle, (eth->pppq_toggle) ? "enabled" : "disabled");
+
+	return 0;
+}
+
+static int pppq_toggle_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pppq_toggle_read, inode->i_private);
+}
+
+static ssize_t pppq_toggle_write(struct file *file, const char __user *ptr,
+				 size_t len, loff_t *off)
+{
+	struct seq_file *m = file->private_data;
+	struct mtk_eth *eth = m->private;
+	char buf[8] = {0};
+
+	if ((len > 8) || copy_from_user(buf, ptr, len))
+		return -EFAULT;
+
+	if (buf[0] == '1' && !eth->pppq_toggle) {
+		eth->pppq_toggle = 1;
+		pr_info("pppq is enabled!\n");
+	} else if (buf[0] == '0' && eth->pppq_toggle) {
+		eth->pppq_toggle = 0;
+		pr_info("pppq is disabled!\n");
+	}
+
+	return len;
+}
+
 static const struct file_operations fops_reg_w = {
 	.owner = THIS_MODULE,
 	.open = simple_open,
@@ -434,6 +470,15 @@
 	.llseek = noop_llseek,
 };
 
+static const struct file_operations fops_pppq_toggle = {
+	.owner = THIS_MODULE,
+	.open = pppq_toggle_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = pppq_toggle_write,
+	.release = single_release,
+};
+
 static const struct file_operations fops_mt7530sw_reg_w = {
 	.owner = THIS_MODULE,
 	.open = simple_open,
@@ -456,6 +501,8 @@
 		ret = -ENOMEM;
 	}
 
+	debugfs_create_file("pppq_toggle", 0444,
+			    eth_debug.root, eth, &fops_pppq_toggle);
 	debugfs_create_file("phy_regs", S_IRUGO,
 			    eth_debug.root, eth, &mtketh_debug_fops);
 	debugfs_create_file("phy_reg_w", S_IFREG | S_IWUSR,
@@ -980,6 +1027,7 @@
 int dbg_regs_read(struct seq_file *seq, void *v)
 {
 	struct mtk_eth *eth = g_eth;
+	u32 i;
 
 	seq_puts(seq, "   <<DEBUG REG DUMP>>\n");
 
@@ -1038,16 +1086,43 @@
 		   mtk_r32(eth, MTK_PRX_CRX_IDX0));
 	seq_printf(seq, "| PDMA_DRX_IDX	: %08x |\n",
 		   mtk_r32(eth, MTK_PRX_DRX_IDX0));
-	seq_printf(seq, "| QDMA_CTX_IDX	: %08x |\n",
-		   mtk_r32(eth, MTK_QTX_CTX_PTR));
-	seq_printf(seq, "| QDMA_DTX_IDX	: %08x |\n",
-		   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));
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		for (i = 1; i < eth->soc->rss_num; i++) {
+			seq_printf(seq, "| PDMA_CRX_IDX%d	: %08x |\n",
+				   i, mtk_r32(eth, MTK_PRX_CRX_IDX_CFG(i)));
+			seq_printf(seq, "| PDMA_DRX_IDX%d	: %08x |\n",
+				   i, mtk_r32(eth, MTK_PRX_DRX_IDX_CFG(i)));
+		}
+	}
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
+		for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) {
+			seq_printf(seq, "| PDMA_CRX_IDX%d	: %08x |\n",
+				   MTK_HW_LRO_RING(i),
+				   mtk_r32(eth, MTK_PRX_CRX_IDX_CFG(MTK_HW_LRO_RING(i))));
+			seq_printf(seq, "| PDMA_DRX_IDX%d	: %08x |\n",
+				   MTK_HW_LRO_RING(i),
+				   mtk_r32(eth, MTK_PRX_DRX_IDX_CFG(MTK_HW_LRO_RING(i))));
+		}
+	}
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+		seq_printf(seq, "| QDMA_CTX_IDX	: %08x |\n",
+			   mtk_r32(eth, MTK_QTX_CTX_PTR));
+		seq_printf(seq, "| QDMA_DTX_IDX	: %08x |\n",
+			   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));
+	} else {
+		seq_printf(seq, "| PDMA_CTX_IDX	: %08x |\n",
+			   mtk_r32(eth, MTK_PTX_CTX_IDX0));
+		seq_printf(seq, "| PDMA_DTX_IDX	: %08x |\n",
+			   mtk_r32(eth, MTK_PTX_DTX_IDX0));
+	}
+
 	seq_printf(seq, "| FE_PSE_FREE	: %08x |\n",
 		   mtk_r32(eth, MTK_FE_PSE_FREE));
 	seq_printf(seq, "| FE_DROP_FQ	: %08x |\n",
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 6585c10..49c123b 100644
--- 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
@@ -46,6 +46,10 @@
 	.tx_irq_mask		= 0x1a1c,
 	.tx_irq_status		= 0x1a18,
 	.pdma = {
+		.tx_ptr		= 0x0800,
+		.tx_cnt_cfg	= 0x0804,
+		.pctx_ptr	= 0x0808,
+		.pdtx_ptr	= 0x080c,
 		.rx_ptr		= 0x0900,
 		.rx_cnt_cfg	= 0x0904,
 		.pcrx_ptr	= 0x0908,
@@ -95,6 +99,10 @@
 	.tx_irq_mask		= 0x0a28,
 	.tx_irq_status		= 0x0a20,
 	.pdma = {
+		.tx_ptr		= 0x0800,
+		.tx_cnt_cfg	= 0x0804,
+		.pctx_ptr	= 0x0808,
+		.pdtx_ptr	= 0x080c,
 		.rx_ptr		= 0x0900,
 		.rx_cnt_cfg	= 0x0904,
 		.pcrx_ptr	= 0x0908,
@@ -112,6 +120,10 @@
 	.tx_irq_mask		= 0x461c,
 	.tx_irq_status		= 0x4618,
 	.pdma = {
+		.tx_ptr		= 0x4000,
+		.tx_cnt_cfg	= 0x4004,
+		.pctx_ptr	= 0x4008,
+		.pdtx_ptr	= 0x400c,
 		.rx_ptr		= 0x4100,
 		.rx_cnt_cfg	= 0x4104,
 		.pcrx_ptr	= 0x4108,
@@ -162,6 +174,10 @@
 	.tx_irq_mask		= 0x461c,
 	.tx_irq_status		= 0x4618,
 	.pdma = {
+		.tx_ptr		= 0x6800,
+		.tx_cnt_cfg	= 0x6804,
+		.pctx_ptr	= 0x6808,
+		.pdtx_ptr	= 0x680c,
 		.rx_ptr		= 0x6900,
 		.rx_cnt_cfg	= 0x6904,
 		.pcrx_ptr	= 0x6908,
@@ -601,7 +617,7 @@
 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
 					   phylink_config);
 	struct mtk_eth *eth = mac->hw;
-	u32 sid, i;
+	u32 i;
 	int val = 0, ge_mode, err = 0;
 	unsigned int mac_type = mac->type;
 
@@ -724,9 +740,6 @@
 		regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
 		spin_unlock(&eth->syscfg0_lock);
 
-		/* Save the syscfg0 value for mac_finish */
-		mac->syscfg0 = val;
-
 		mac->interface = state->interface;
 	}
 
@@ -743,9 +756,8 @@
 				   SYSCFG0_SGMII_MASK,
 				   ~(u32)SYSCFG0_SGMII_MASK);
 
-		/* Decide how GMAC and SGMIISYS be mapped */
-		sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
-		       0 : mac->id;
+		/* Save the syscfg0 value for mac_finish */
+		mac->syscfg0 = val;
 		spin_unlock(&eth->syscfg0_lock);
 	} else if (state->interface == PHY_INTERFACE_MODE_USXGMII ||
 		   state->interface == PHY_INTERFACE_MODE_10GKR ||
@@ -1012,6 +1024,88 @@
 	}
 }
 
+static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx,
+				int speed)
+{
+	const struct mtk_soc_data *soc = eth->soc;
+	u32 val;
+
+	if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA))
+		return;
+
+	val = MTK_QTX_SCH_MIN_RATE_EN |
+	      /* minimum: 10 Mbps */
+	      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
+	      FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
+	      MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
+		val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
+
+	if (IS_ENABLED(CONFIG_SOC_MT7621)) {
+		switch (speed) {
+		case SPEED_10:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 2) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_100:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3);
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_1000:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 105) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10);
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (speed) {
+		case SPEED_10:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 4) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_100:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5);
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1);
+			break;
+		case SPEED_1000:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10);
+			break;
+		case SPEED_2500:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 25) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10);
+			break;
+		case SPEED_10000:
+			val |= MTK_QTX_SCH_MAX_RATE_EN |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 100) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) |
+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10);
+			break;
+		default:
+			break;
+		}
+	}
+
+	mtk_w32(eth, (idx / MTK_QTX_PER_PAGE) & MTK_QTX_CFG_PAGE, MTK_QDMA_PAGE);
+	mtk_w32(eth, val, MTK_QTX_SCH(idx));
+}
+
 static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode,
 			    phy_interface_t interface,
 			    struct phy_device *phy)
@@ -1347,10 +1441,17 @@
 	unsigned long flags;
 	u32 val;
 
-	spin_lock_irqsave(&eth->tx_irq_lock, flags);
-	val = mtk_r32(eth, eth->soc->reg_map->tx_irq_mask);
-	mtk_w32(eth, val & ~mask, eth->soc->reg_map->tx_irq_mask);
-	spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+		spin_lock_irqsave(&eth->tx_irq_lock, flags);
+		val = mtk_r32(eth, eth->soc->reg_map->tx_irq_mask);
+		mtk_w32(eth, val & ~mask, eth->soc->reg_map->tx_irq_mask);
+		spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
+	} else {
+		spin_lock_irqsave(&eth->txrx_irq_lock, flags);
+		val = mtk_r32(eth, eth->soc->reg_map->pdma.irq_mask);
+		mtk_w32(eth, val & ~mask, eth->soc->reg_map->pdma.irq_mask);
+		spin_unlock_irqrestore(&eth->txrx_irq_lock, flags);
+	}
 }
 
 static inline void mtk_tx_irq_enable(struct mtk_eth *eth, u32 mask)
@@ -1358,32 +1459,51 @@
 	unsigned long flags;
 	u32 val;
 
-	spin_lock_irqsave(&eth->tx_irq_lock, flags);
-	val = mtk_r32(eth, eth->soc->reg_map->tx_irq_mask);
-	mtk_w32(eth, val | mask, eth->soc->reg_map->tx_irq_mask);
-	spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+		spin_lock_irqsave(&eth->tx_irq_lock, flags);
+		val = mtk_r32(eth, eth->soc->reg_map->tx_irq_mask);
+		mtk_w32(eth, val | mask, eth->soc->reg_map->tx_irq_mask);
+		spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
+	} else {
+		spin_lock_irqsave(&eth->txrx_irq_lock, flags);
+		val = mtk_r32(eth, eth->soc->reg_map->pdma.irq_mask);
+		mtk_w32(eth, val | mask, eth->soc->reg_map->pdma.irq_mask);
+		spin_unlock_irqrestore(&eth->txrx_irq_lock, flags);
+	}
 }
 
 static inline void mtk_rx_irq_disable(struct mtk_eth *eth, u32 mask)
 {
 	unsigned long flags;
 	u32 val;
+	spinlock_t *irq_lock;
 
-	spin_lock_irqsave(&eth->rx_irq_lock, flags);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+		irq_lock = &eth->rx_irq_lock;
+	else
+		irq_lock = &eth->txrx_irq_lock;
+
+	spin_lock_irqsave(irq_lock, flags);
 	val = mtk_r32(eth, eth->soc->reg_map->pdma.irq_mask);
 	mtk_w32(eth, val & ~mask, eth->soc->reg_map->pdma.irq_mask);
-	spin_unlock_irqrestore(&eth->rx_irq_lock, flags);
+	spin_unlock_irqrestore(irq_lock, flags);
 }
 
 static inline void mtk_rx_irq_enable(struct mtk_eth *eth, u32 mask)
 {
 	unsigned long flags;
 	u32 val;
+	spinlock_t *irq_lock;
 
-	spin_lock_irqsave(&eth->rx_irq_lock, flags);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+		irq_lock = &eth->rx_irq_lock;
+	else
+		irq_lock = &eth->txrx_irq_lock;
+
+	spin_lock_irqsave(irq_lock, flags);
 	val = mtk_r32(eth, eth->soc->reg_map->pdma.irq_mask);
 	mtk_w32(eth, val | mask, eth->soc->reg_map->pdma.irq_mask);
-	spin_unlock_irqrestore(&eth->rx_irq_lock, flags);
+	spin_unlock_irqrestore(irq_lock, flags);
 }
 
 static int mtk_set_mac_address(struct net_device *dev, void *p)
@@ -1591,10 +1711,7 @@
 					       &eth->phy_scratch_ring,
 					       GFP_KERNEL);
 	} else {
-		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;
+		eth->scratch_ring = eth->sram_base;
 	}
 
 	if (unlikely(!eth->scratch_ring))
@@ -1715,19 +1832,30 @@
 			 struct mtk_tx_dma *txd, dma_addr_t mapped_addr,
 			 size_t size, int idx)
 {
+	u64 addr64 = 0;
+
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
 		dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
 		dma_unmap_len_set(tx_buf, dma_len0, size);
 	} else {
+		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+			  TX_DMA_SDP1(mapped_addr) : 0;
+
 		if (idx & 1) {
 			txd->txd3 = mapped_addr;
-			txd->txd2 |= TX_DMA_PLEN1(size);
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+				txd->txd4 = TX_DMA_PLEN1(size) | addr64;
+			else
+				txd->txd2 |= TX_DMA_PLEN1(size);
 			dma_unmap_addr_set(tx_buf, dma_addr1, mapped_addr);
 			dma_unmap_len_set(tx_buf, dma_len1, size);
 		} else {
 			tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
 			txd->txd1 = mapped_addr;
-			txd->txd2 = TX_DMA_PLEN0(size);
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+				txd->txd2 = TX_DMA_PLEN0(size) | addr64;
+			else
+				txd->txd2 = TX_DMA_PLEN0(size);
 			dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
 			dma_unmap_len_set(tx_buf, dma_len0, size);
 		}
@@ -1782,9 +1910,6 @@
 	struct mtk_tx_dma_v2 *desc = txd;
 	u32 data = 0;
 
-	if (!info->qid && mac->id)
-		info->qid = MTK_QDMA_GMAC2_QID;
-
 	WRITE_ONCE(desc->txd1, info->addr);
 
 	data = TX_DMA_PLEN0(info->size);
@@ -1834,9 +1959,6 @@
 	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;
 
@@ -1883,18 +2005,50 @@
 	WRITE_ONCE(desc->txd8, 0);
 }
 
+static void mtk_tx_set_pdma_desc(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_tx_dma_v2 *desc = txd;
+	u32 data = 0;
+
+	if (info->first) {
+		data = ((mac->id == MTK_GMAC3_ID) ?
+			PSE_GDM3_PORT : (mac->id + 1)) << TX_DMA_FPORT_SHIFT_PDMA;
+		if (info->gso)
+			data |= TX_DMA_TSO_V2;
+		if (info->csum)
+			data |= TX_DMA_CHKSUM_V2;
+		if (netdev_uses_dsa(dev))
+			data |= TX_DMA_SPTAG_V3;
+		WRITE_ONCE(desc->txd5, data);
+
+		if (info->vlan) {
+			WRITE_ONCE(desc->txd6, TX_DMA_INS_VLAN_V2);
+			WRITE_ONCE(desc->txd7, info->vlan_tci);
+		}
+
+		WRITE_ONCE(desc->txd8, 0);
+	}
+}
+
 static void mtk_tx_set_dma_desc(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;
 
-	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);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+		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);
+	} else {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+			mtk_tx_set_pdma_desc(skb, dev, txd, info);
+	}
 }
 
 static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
@@ -1902,7 +2056,7 @@
 {
 	struct mtk_tx_dma_desc_info txd_info = {
 		.size = skb_headlen(skb),
-		.qid = skb->mark & MTK_QDMA_TX_MASK,
+		.qid = skb_get_queue_mapping(skb),
 		.gso = gso,
 		.csum = skb->ip_summed == CHECKSUM_PARTIAL,
 		.vlan = skb_vlan_tag_present(skb),
@@ -1910,6 +2064,7 @@
 		.first = true,
 		.last = !skb_is_nonlinear(skb),
 	};
+	struct netdev_queue *txq;
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
 	const struct mtk_soc_data *soc = eth->soc;
@@ -1917,6 +2072,7 @@
 	struct mtk_tx_dma *itxd_pdma, *txd_pdma;
 	struct mtk_tx_buf *itx_buf, *tx_buf;
 	int i, n_desc = 1;
+	int queue = skb_get_queue_mapping(skb);
 	int k = 0;
 
 	if (skb->len < 32) {
@@ -1926,6 +2082,7 @@
 		txd_info.size = skb_headlen(skb);
 	}
 
+	txq = netdev_get_tx_queue(dev, txd_info.qid);
 	itxd = ring->next_free;
 	itxd_pdma = qdma_to_pdma(ring, itxd);
 	if (itxd == ring->last_free)
@@ -1939,7 +2096,10 @@
 	if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
 		return -ENOMEM;
 
-	mtk_tx_set_dma_desc(skb, dev, itxd, &txd_info);
+	if (MTK_HAS_CAPS(soc->caps, MTK_QDMA))
+		mtk_tx_set_dma_desc(skb, dev, itxd, &txd_info);
+	else
+		mtk_tx_set_dma_desc(skb, dev, itxd_pdma, &txd_info);
 
 	itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
 	itx_buf->flags |= (mac->id == MTK_GMAC1_ID) ? MTK_TX_FLAGS_FPORT0 :
@@ -1974,7 +2134,7 @@
 
 			memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
 			txd_info.size = min(frag_size, MTK_TX_DMA_BUF_LEN);
-			txd_info.qid = skb->mark & MTK_QDMA_TX_MASK;
+			txd_info.qid = queue;
 			txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
 					!(frag_size - txd_info.size);
 			txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag,
@@ -1984,7 +2144,10 @@
 						       txd_info.addr)))
  				goto err_dma;
 
-			mtk_tx_set_dma_desc(skb, dev, txd, &txd_info);
+			if (MTK_HAS_CAPS(soc->caps, MTK_QDMA))
+				mtk_tx_set_dma_desc(skb, dev, txd, &txd_info);
+			else
+				mtk_tx_set_dma_desc(skb, dev, txd_pdma, &txd_info);
 
 			tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size);
 			if (new_desc)
@@ -2008,13 +2171,20 @@
 	itx_buf->skb = skb;
 
 	if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
-		if (k & 0x1)
-			txd_pdma->txd2 |= TX_DMA_LS0;
-		else
-			txd_pdma->txd2 |= TX_DMA_LS1;
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+			if (k & 0x1)
+				txd_pdma->txd2 |= TX_DMA_LS0;
+			else
+				txd_pdma->txd4 |= TX_DMA_LS1_V2;
+		} else {
+			if (k & 0x1)
+				txd_pdma->txd2 |= TX_DMA_LS0;
+			else
+				txd_pdma->txd2 |= TX_DMA_LS1;
+		}
 	}
 
-	netdev_sent_queue(dev, skb->len);
+	netdev_tx_sent_queue(txq, skb->len);
 	skb_tx_timestamp(skb);
 
 	ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2);
@@ -2026,13 +2196,12 @@
 	wmb();
 
 	if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
-		if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) ||
-		    !netdev_xmit_more())
+		if (netif_xmit_stopped(txq) || !netdev_xmit_more())
 			mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr);
 	} else {
 		int next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size),
 					     ring->dma_size);
-		mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
+		mtk_w32(eth, next_idx, soc->reg_map->pdma.pctx_ptr);
 	}
 
 	return 0;
@@ -2095,7 +2264,7 @@
 	for (i = 0; i < MTK_MAC_COUNT; i++) {
 		if (!eth->netdev[i])
 			continue;
-		netif_wake_queue(eth->netdev[i]);
+		netif_tx_wake_all_queues(eth->netdev[i]);
 	}
 }
 
@@ -2119,7 +2288,7 @@
 
 	tx_num = mtk_cal_txd_req(skb);
 	if (unlikely(atomic_read(&ring->free_count) <= tx_num)) {
-		netif_stop_queue(dev);
+		netif_tx_stop_all_queues(dev);
 		netif_err(eth, tx_queued, dev,
 			  "Tx Ring full when queue awake!\n");
 		spin_unlock(&eth->page_lock);
@@ -2145,7 +2314,7 @@
 		goto drop;
 
 	if (unlikely(atomic_read(&ring->free_count) <= ring->thresh))
-		netif_stop_queue(dev);
+		netif_tx_stop_all_queues(dev);
 
 	spin_unlock(&eth->page_lock);
 
@@ -2356,8 +2525,44 @@
 	return done;
 }
 
+struct mtk_poll_state {
+	struct netdev_queue *txq;
+	unsigned int total;
+	unsigned int done;
+	unsigned int bytes;
+};
+
+static void
+mtk_poll_tx_done(struct mtk_eth *eth, struct mtk_poll_state *state, u8 mac,
+		 struct sk_buff *skb)
+{
+	struct netdev_queue *txq;
+	struct net_device *dev;
+	unsigned int bytes = skb->len;
+
+	state->total++;
+
+	dev = eth->netdev[mac];
+	if (!dev)
+		return;
+
+	txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
+	if (state->txq == txq) {
+		state->done++;
+		state->bytes += bytes;
+		return;
+	}
+
+	if (state->txq)
+		netdev_tx_completed_queue(state->txq, state->done, state->bytes);
+
+	state->txq = txq;
+	state->done = 1;
+	state->bytes = bytes;
+}
+
 static void mtk_poll_tx_qdma(struct mtk_eth *eth, int budget,
-			    unsigned int *done, unsigned int *bytes)
+			     struct mtk_poll_state *state)
 {
 	const struct mtk_reg_map *reg_map = eth->soc->reg_map;
 	const struct mtk_soc_data *soc = eth->soc;
@@ -2392,8 +2597,7 @@
 			break;
 
 		if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) {
-			bytes[mac] += skb->len;
-			done[mac]++;
+			mtk_poll_tx_done(eth, state, mac, skb);
 			budget--;
 		}
 		mtk_tx_unmap(eth, tx_buf, true);
@@ -2409,8 +2613,9 @@
 }
 
 static void mtk_poll_tx_pdma(struct mtk_eth *eth, int budget,
-			    unsigned int *done, unsigned int *bytes)
+			     struct mtk_poll_state *state)
 {
+	const struct mtk_soc_data *soc = eth->soc;
 	struct mtk_tx_ring *ring = &eth->tx_ring;
 	struct mtk_tx_dma *desc;
 	struct sk_buff *skb;
@@ -2418,17 +2623,27 @@
 	u32 cpu, dma;
 
 	cpu = ring->cpu_idx;
-	dma = mtk_r32(eth, MT7628_TX_DTX_IDX0);
+	dma = mtk_r32(eth, soc->reg_map->pdma.pdtx_ptr);
 
 	while ((cpu != dma) && budget) {
+		int mac = 0;
+
+		desc = ring->dma_pdma + cpu * eth->soc->txrx.txd_size;
+		if ((desc->txd2 & TX_DMA_OWNER_CPU) == 0)
+			break;
+
 		tx_buf = &ring->buf[cpu];
+		if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
+			mac = MTK_GMAC2_ID;
+		else if (tx_buf->flags & MTK_TX_FLAGS_FPORT2)
+			mac = MTK_GMAC3_ID;
+
 		skb = tx_buf->skb;
 		if (!skb)
 			break;
 
 		if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) {
-			bytes[0] += skb->len;
-			done[0]++;
+			mtk_poll_tx_done(eth, state, mac, skb);
 			budget--;
 		}
 
@@ -2447,30 +2662,21 @@
 static int mtk_poll_tx(struct mtk_eth *eth, int budget)
 {
 	struct mtk_tx_ring *ring = &eth->tx_ring;
-	unsigned int done[MTK_MAX_DEVS];
-	unsigned int bytes[MTK_MAX_DEVS];
-	int total = 0, i;
-
-	memset(done, 0, sizeof(done));
-	memset(bytes, 0, sizeof(bytes));
+	struct mtk_poll_state state = {};
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
-		mtk_poll_tx_qdma(eth, budget, done, bytes);
+		mtk_poll_tx_qdma(eth, budget, &state);
 	else
-		mtk_poll_tx_pdma(eth, budget, done, bytes);
+		mtk_poll_tx_pdma(eth, budget, &state);
 
-	for (i = 0; i < MTK_MAC_COUNT; i++) {
-		if (!eth->netdev[i] || !done[i])
-			continue;
-		netdev_completed_queue(eth->netdev[i], done[i], bytes[i]);
-		total += done[i];
-	}
+	if (state.txq)
+		netdev_tx_completed_queue(state.txq, state.done, state.bytes);
 
 	if (mtk_queue_stopped(eth) &&
 	    (atomic_read(&ring->free_count) > ring->thresh))
 		mtk_wake_queue(eth);
 
-	return total;
+	return state.total;
 }
 
 static void mtk_handle_status_irq(struct mtk_eth *eth)
@@ -2491,14 +2697,22 @@
 	u32 status, mask;
 	int tx_done = 0;
 
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
 		mtk_handle_status_irq(eth);
-	mtk_w32(eth, MTK_TX_DONE_INT, reg_map->tx_irq_status);
+		mtk_w32(eth, MTK_TX_DONE_INT(0), reg_map->tx_irq_status);
+	} else {
+		mtk_w32(eth, MTK_TX_DONE_INT(0), reg_map->pdma.irq_status);
+	}
 	tx_done = mtk_poll_tx(eth, budget);
 
 	if (unlikely(netif_msg_intr(eth))) {
-		status = mtk_r32(eth, reg_map->tx_irq_status);
-		mask = mtk_r32(eth, reg_map->tx_irq_mask);
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+			status = mtk_r32(eth, reg_map->tx_irq_status);
+			mask = mtk_r32(eth, reg_map->tx_irq_mask);
+		} else {
+			status = mtk_r32(eth, reg_map->pdma.irq_status);
+			mask = mtk_r32(eth, reg_map->pdma.irq_mask);
+		}
 		dev_info(eth->dev,
 			 "done tx %d, intr 0x%08x/0x%x\n",
 			 tx_done, status, mask);
@@ -2507,12 +2721,15 @@
 	if (tx_done == budget)
 		return budget;
 
-	status = mtk_r32(eth, reg_map->tx_irq_status);
-	if (status & MTK_TX_DONE_INT)
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+		status = mtk_r32(eth, reg_map->tx_irq_status);
+	else
+		status = mtk_r32(eth, reg_map->pdma.irq_status);
+	if (status & MTK_TX_DONE_INT(0))
 		return budget;
 
 	if (napi_complete(napi))
-		mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+		mtk_tx_irq_enable(eth, MTK_TX_DONE_INT(0));
 
 	return tx_done;
 }
@@ -2571,7 +2788,7 @@
 		ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
 					       &ring->phys, GFP_KERNEL);
 	else {
-		ring->dma =  eth->scratch_ring + MTK_DMA_SIZE * sz;
+		ring->dma =  eth->sram_base + MTK_DMA_SIZE * sz;
 		ring->phys = eth->phy_scratch_ring +
 			     MTK_DMA_SIZE * (dma_addr_t)sz;
 	}
@@ -2609,10 +2826,17 @@
 			goto no_tx_mem;
 
 		for (i = 0; i < MTK_DMA_SIZE; i++) {
-			pdma_txd = ring->dma_pdma + i *sz;
+			pdma_txd = ring->dma_pdma + i * sz;
 
 			pdma_txd->txd2 = TX_DMA_DESP2_DEF;
 			pdma_txd->txd4 = 0;
+
+			if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+				pdma_txd->txd5 = 0;
+				pdma_txd->txd6 = 0;
+				pdma_txd->txd7 = 0;
+				pdma_txd->txd8 = 0;
+			}
 		}
 	}
 
@@ -2622,6 +2846,7 @@
 	ring->last_free = (void *)txd;
 	ring->last_free_ptr = (u32)(ring->phys + ((MTK_DMA_SIZE - 1) * sz));
 	ring->thresh = MAX_SKB_FRAGS;
+	ring->cpu_idx = 0;
 
 	/* make sure that all changes to the dma ring are flushed before we
 	 * continue
@@ -2638,10 +2863,10 @@
 		mtk_w32(eth, (QDMA_RES_THRES << 8) | QDMA_RES_THRES,
 			soc->reg_map->qdma.qtx_cfg);
 	} else {
-		mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0);
-		mtk_w32(eth, MTK_DMA_SIZE, MT7628_TX_MAX_CNT0);
-		mtk_w32(eth, 0, MT7628_TX_CTX_IDX0);
-		mtk_w32(eth, MT7628_PST_DTX_IDX0, soc->reg_map->pdma.rst_idx);
+		mtk_w32(eth, ring->phys_pdma, soc->reg_map->pdma.tx_ptr);
+		mtk_w32(eth, MTK_DMA_SIZE, soc->reg_map->pdma.tx_cnt_cfg);
+		mtk_w32(eth, ring->cpu_idx, soc->reg_map->pdma.pctx_ptr);
+		mtk_w32(eth, MTK_PST_DTX_IDX_CFG(0), soc->reg_map->pdma.rst_idx);
 	}
 
 	return 0;
@@ -3523,7 +3748,7 @@
 	struct mtk_eth *eth = _eth;
 
 	if (likely(napi_schedule_prep(&eth->tx_napi))) {
-		mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+		mtk_tx_irq_disable(eth, MTK_TX_DONE_INT(0));
 		__napi_schedule(&eth->tx_napi);
 	}
 
@@ -3539,9 +3764,17 @@
 		if (mtk_r32(eth, reg_map->pdma.irq_status) & MTK_RX_DONE_INT(0))
 			mtk_handle_irq_rx(irq, &eth->rx_napi[0]);
 	}
-	if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) {
-		if (mtk_r32(eth, reg_map->tx_irq_status) & MTK_TX_DONE_INT)
-			mtk_handle_irq_tx(irq, _eth);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+		if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT(0)) {
+			if (mtk_r32(eth, reg_map->tx_irq_status) & MTK_TX_DONE_INT(0))
+				mtk_handle_irq_tx(irq, _eth);
+		}
+	} else {
+		if (mtk_r32(eth, reg_map->pdma.irq_mask) & MTK_TX_DONE_INT(0)) {
+			if (mtk_r32(eth, reg_map->pdma.irq_status) & MTK_TX_DONE_INT(0))
+				mtk_handle_irq_tx(irq, _eth);
+		}
 	}
 
 	return IRQ_HANDLED;
@@ -3583,10 +3816,10 @@
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
 
-	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT(0));
 	mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(0));
 	mtk_handle_irq_rx(eth->irq_fe[2], &eth->rx_napi[0]);
-	mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+	mtk_tx_irq_enable(eth, MTK_TX_DONE_INT(0));
 	mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0));
 }
 #endif
@@ -3675,6 +3908,88 @@
 }
 EXPORT_SYMBOL(mtk_set_pse_drop);
 
+static int mtk_device_event(struct notifier_block *n, unsigned long event, void *ptr)
+{
+	struct mtk_mac *mac = container_of(n, struct mtk_mac, device_notifier);
+	struct mtk_eth *eth = mac->hw;
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct ethtool_link_ksettings s;
+	struct net_device *ldev;
+	struct list_head *iter;
+	struct dsa_port *dp;
+	unsigned int queue = 0;
+
+	if (!eth->pppq_toggle)
+		return NOTIFY_DONE;
+
+	if (event != NETDEV_CHANGE)
+		return NOTIFY_DONE;
+
+	switch (mac->id) {
+	case MTK_GMAC1_ID:
+		netdev_for_each_lower_dev(dev, ldev, iter) {
+			if (netdev_priv(ldev) == mac)
+				goto dsa_set_speed;
+		}
+		break;
+	case MTK_GMAC2_ID:
+		if (strcmp(netdev_name(dev), "eth1"))
+			break;
+
+		queue = MTK_QDMA_GMAC2_QID;
+		goto set_speed;
+	case MTK_GMAC3_ID:
+		if (strcmp(netdev_name(dev), "eth2"))
+			break;
+
+		queue = MTK_QDMA_GMAC3_QID;
+		goto set_speed;
+	default:
+		pr_info("%s mac id invalid", __func__);
+		break;
+	}
+
+	return NOTIFY_DONE;
+
+set_speed:
+	if (__ethtool_get_link_ksettings(dev, &s))
+		return NOTIFY_DONE;
+
+	if (s.base.speed == 0 || s.base.speed == ((__u32)-1))
+		return NOTIFY_DONE;
+
+	if (queue >= MTK_QDMA_TX_NUM)
+		return NOTIFY_DONE;
+
+	if (mac->speed > 0 && mac->speed < s.base.speed)
+		s.base.speed = 0;
+
+	mtk_set_queue_speed(eth, queue, s.base.speed);
+
+	return NOTIFY_DONE;
+
+dsa_set_speed:
+	if (!dsa_slave_dev_check(dev))
+		return NOTIFY_DONE;
+
+	if (__ethtool_get_link_ksettings(dev, &s))
+		return NOTIFY_DONE;
+
+	if (s.base.speed == 0 || s.base.speed == ((__u32)-1))
+		return NOTIFY_DONE;
+
+	dp = dsa_port_from_netdev(dev);
+	if (dp->index >= MTK_QDMA_TX_NUM)
+		return NOTIFY_DONE;
+
+	if (mac->speed > 0 && mac->speed <= s.base.speed)
+		s.base.speed = 0;
+
+	mtk_set_queue_speed(eth, dp->index, s.base.speed);
+
+	return NOTIFY_DONE;
+}
+
 static int mtk_open(struct net_device *dev)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
@@ -3710,7 +4025,7 @@
 
 		napi_enable(&eth->tx_napi);
 		napi_enable(&eth->rx_napi[0].napi);
-		mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+		mtk_tx_irq_enable(eth, MTK_TX_DONE_INT(0));
 		mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0));
 
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
@@ -3761,7 +4076,7 @@
 	}
 
 	phylink_start(mac->phylink);
-	netif_start_queue(dev);
+	netif_tx_start_all_queues(dev);
 	phy_node = of_parse_phandle(mac->of_node, "phy-handle", 0);
 	if (!phy_node && eth->sgmii->pcs[id].regmap)
 		regmap_write(eth->sgmii->pcs[id].regmap,
@@ -3829,7 +4144,7 @@
 		return 0;
 
 
-	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT(0));
 	mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(0));
 	napi_disable(&eth->tx_napi);
 	napi_disable(&eth->rx_napi[0].napi);
@@ -4024,16 +4339,26 @@
 	/* enable interrupt delay for RX/TX */
 	mtk_w32(eth, 0x8f0f8f0f, MTK_PDMA_DELAY_INT);
 	mtk_w32(eth, 0x8f0f8f0f, MTK_QDMA_DELAY_INT);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		mtk_w32(eth, 0x8f0f8f0f, MTK_PDMA_TX_DELAY_INT0);
+		mtk_w32(eth, 0x8f0f8f0f, MTK_PDMA_TX_DELAY_INT1);
+	}
 
 	mtk_tx_irq_disable(eth, ~0);
 	mtk_rx_irq_disable(eth, ~0);
 
 	/* FE int grouping */
-	mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+		mtk_w32(eth, MTK_TX_DONE_INT(0), reg_map->qdma.int_grp);
+	else
+		mtk_w32(eth, MTK_TX_DONE_INT(0), reg_map->pdma.int_grp);
 	mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->qdma.int_grp2);
-	if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT))
-		mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
-	else {
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+			mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
+		else
+			mtk_w32(eth, 0xFFFF1FF2, MTK_FE_INT_GRP);
+	} else {
 		mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->pdma.int_grp);
 		mtk_w32(eth, 0x210F2FF3, MTK_FE_INT_GRP);
 	}
@@ -4359,8 +4684,12 @@
 	int i;
 
 	for (i = 0; i < MTK_MAC_COUNT; i++) {
+		struct mtk_mac *mac;
 		if (!eth->netdev[i])
 			continue;
+		mac = netdev_priv(eth->netdev[i]);
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+			unregister_netdevice_notifier(&mac->device_notifier);
 		unregister_netdev(eth->netdev[i]);
 	}
 
@@ -4675,6 +5004,40 @@
 	return phylink_ethtool_set_eee(mac->phylink, eee);
 }
 
+static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb,
+			    struct net_device *sb_dev)
+{
+	struct mtk_mac *mac = netdev_priv(dev);
+	struct mtk_eth *eth = mac->hw;
+	unsigned int queue = 0;
+
+	if (skb->mark > 0 && skb->mark < MTK_QDMA_TX_NUM)
+		return skb->mark;
+
+	if (eth->pppq_toggle) {
+		switch (mac->id) {
+		case MTK_GMAC1_ID:
+			queue = skb_get_queue_mapping(skb);
+			break;
+		case MTK_GMAC2_ID:
+			queue = MTK_QDMA_GMAC2_QID;
+			break;
+		case MTK_GMAC3_ID:
+			queue = MTK_QDMA_GMAC3_QID;
+			break;
+		default:
+			pr_info("%s mac id invalid", __func__);
+			break;
+		}
+	} else
+		queue = mac->id ? MTK_QDMA_GMAC2_QID : 0;
+
+	if (queue >= MTK_QDMA_TX_NUM)
+		queue = 0;
+
+	return queue;
+}
+
 static const struct ethtool_ops mtk_ethtool_ops = {
 	.get_link_ksettings	= mtk_get_link_ksettings,
 	.set_link_ksettings	= mtk_set_link_ksettings,
@@ -4704,6 +5067,7 @@
 	.ndo_open		= mtk_open,
 	.ndo_stop		= mtk_stop,
 	.ndo_start_xmit		= mtk_start_xmit,
+	.ndo_select_queue       = mtk_select_queue,
 	.ndo_set_mac_address	= mtk_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= mtk_do_ioctl,
@@ -4870,6 +5234,7 @@
 	struct mtk_phylink_priv *phylink_priv;
 	struct fwnode_handle *fixed_node;
 	struct gpio_desc *desc;
+	int txqs = 1;
 
 	if (!_id) {
 		dev_err(eth->dev, "missing mac id\n");
@@ -4887,7 +5252,10 @@
 		return -EINVAL;
 	}
 
-	eth->netdev[id] = alloc_etherdev(sizeof(*mac));
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+		txqs = MTK_QDMA_TX_NUM;
+
+	eth->netdev[id] = alloc_etherdev_mqs(sizeof(*mac), txqs, 1);
 	if (!eth->netdev[id]) {
 		dev_err(eth->dev, "alloc_etherdev failed\n");
 		return -ENOMEM;
@@ -5019,6 +5387,11 @@
 	eth->netdev[id]->irq = eth->irq_fe[0];
 	eth->netdev[id]->dev.of_node = np;
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
+		mac->device_notifier.notifier_call = mtk_device_event;
+		register_netdevice_notifier(&mac->device_notifier);
+	}
+
 	return 0;
 
 free_netdev:
@@ -5074,9 +5447,11 @@
 		return PTR_ERR(eth->base);
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
-		eth->sram_base = devm_platform_ioremap_resource(pdev, 1);
+		eth->sram_base = (void __force *)devm_platform_ioremap_resource(pdev, 1);
 		if (IS_ERR(eth->sram_base))
 			return PTR_ERR(eth->sram_base);
+	} else {
+		eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET;
 	}
 
 	if(eth->soc->has_sram) {
@@ -5107,6 +5482,7 @@
 	spin_lock_init(&eth->page_lock);
 	spin_lock_init(&eth->tx_irq_lock);
 	spin_lock_init(&eth->rx_irq_lock);
+	spin_lock_init(&eth->txrx_irq_lock);
 	spin_lock_init(&eth->syscfg0_lock);
 
 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
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 a48b363..c32a0ee 100644
--- 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
@@ -203,6 +203,12 @@
 #define WDMA_BASE(x)		(0x2800 + ((x) * 0x400))
 #define PPE_BASE(x)		(0xE00 + ((x) * 0x400))
 #endif
+/* PDMA TX CPU Pointer Register */
+#define MTK_PTX_CTX_IDX0	(PDMA_BASE + 0x08)
+
+/* PDMA TX DMA Pointer Register */
+#define MTK_PTX_DTX_IDX0	(PDMA_BASE + 0x0c)
+
 /* PDMA RX Base Pointer Register */
 #define MTK_PRX_BASE_PTR0	(PDMA_BASE + 0x100)
 #define MTK_PRX_BASE_PTR_CFG(x)	(MTK_PRX_BASE_PTR0 + (x * 0x10))
@@ -298,13 +304,17 @@
 /* PDMA Reset Index Register */
 #define MTK_PDMA_RST_IDX	(PDMA_BASE + 0x208)
 #define MTK_PST_DRX_IDX0	BIT(16)
+#define MTK_PST_DTX_IDX0	BIT(0)
 #define MTK_PST_DRX_IDX_CFG(x)	(MTK_PST_DRX_IDX0 << (x))
+#define MTK_PST_DTX_IDX_CFG(x)	(MTK_PST_DTX_IDX0 << (x))
 
 /*PDMA HW RX Index Register*/
 #define MTK_ADMA_DRX_PTR	(PDMA_BASE + 0x10C)
 
 /* PDMA Delay Interrupt Register */
 #define MTK_PDMA_DELAY_INT		(PDMA_BASE + 0x20c)
+#define MTK_PDMA_TX_DELAY_INT0		(PDMA_BASE + 0x2b0)
+#define MTK_PDMA_TX_DELAY_INT1		(PDMA_BASE + 0x2b4)
 #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_PDMA_RSS_DELAY_INT		(PDMA_BASE + 0x2c0)
 #else
@@ -397,11 +407,24 @@
 #define MTK_RX_TCP_SRC_PORT_OFFSET	(16)
 
 /* QDMA TX Queue Configuration Registers */
-#define MTK_QTX_CFG(x)		(QDMA_BASE + (x * 0x10))
-#define QDMA_RES_THRES		4
+#define MTK_QTX_CFG(x)			(QDMA_BASE + (x * 0x10))
+#define MTK_QTX_CFG_HW_RESV_CNT_OFFSET	GENMASK(15, 8)
+#define MTK_QTX_CFG_SW_RESV_CNT_OFFSET	GENMASK(7, 0)
+#define QDMA_RES_THRES			4
 
 /* QDMA TX Queue Scheduler Registers */
-#define MTK_QTX_SCH(x)		(QDMA_BASE + 4 + (x * 0x10))
+#define MTK_QTX_SCH(x)			(QDMA_BASE + 4 + (x * 0x10))
+#define MTK_QTX_SCH_TX_SEL		BIT(31)
+#define MTK_QTX_SCH_TX_SEL_V2		GENMASK(31, 30)
+#define MTK_QTX_SCH_LEAKY_BUCKET_EN	BIT(30)
+#define MTK_QTX_SCH_LEAKY_BUCKET_SIZE	GENMASK(29, 28)
+#define MTK_QTX_SCH_MIN_RATE_EN		BIT(27)
+#define MTK_QTX_SCH_MIN_RATE_MAN	GENMASK(26, 20)
+#define MTK_QTX_SCH_MIN_RATE_EXP	GENMASK(19, 16)
+#define MTK_QTX_SCH_MAX_RATE_WEIGHT	GENMASK(15, 12)
+#define MTK_QTX_SCH_MAX_RATE_EN		BIT(11)
+#define MTK_QTX_SCH_MAX_RATE_MAN	GENMASK(10, 4)
+#define MTK_QTX_SCH_MAX_RATE_EXP	GENMASK(3, 0)
 
 /* QDMA RX Base Pointer Register */
 #define MTK_QRX_BASE_PTR0	(QDMA_BASE + 0x100)
@@ -419,7 +442,9 @@
 #define MTK_QRX_DRX_IDX0	(QDMA_BASE + 0x10c)
 
 /* QDMA Page Configuration Register */
-#define MTK_QDMA_PAGE	(QDMA_BASE + 0x1f0)
+#define MTK_QDMA_PAGE		(QDMA_BASE + 0x1f0)
+#define MTK_QTX_CFG_PAGE	GENMASK(3, 0)
+#define MTK_QTX_PER_PAGE	(16)
 
 /* QDMA Global Configuration Register */
 #define MTK_QDMA_GLO_CFG	(QDMA_BASE + 0x204)
@@ -475,8 +500,15 @@
 #define MTK_TX_DONE_INT2	BIT(2)
 #define MTK_TX_DONE_INT1	BIT(1)
 #define MTK_TX_DONE_INT0	BIT(0)
-#define MTK_TX_DONE_DLY         BIT(28)
-#define MTK_TX_DONE_INT         MTK_TX_DONE_DLY
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_TX_DONE_INT(ring_no)				\
+	(MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) ? BIT(28) :	\
+	 BIT(4 + (ring_no)))
+#else
+#define MTK_TX_DONE_INT(ring_no)				\
+	(MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) ? BIT(28) :	\
+	 BIT((ring_no)))
+#endif
 
 /* QDMA Interrupt grouping registers */
 #define MTK_QDMA_INT_GRP1	(QDMA_BASE + 0x220)
@@ -554,6 +586,7 @@
 #define QID_BITS_V2(x)		(((x) & 0x3f) << 16)
 
 #define MTK_QDMA_GMAC2_QID	8
+#define MTK_QDMA_GMAC3_QID	6
 
 /* QDMA V2 descriptor txd6 */
 #define TX_DMA_INS_VLAN_V2         BIT(16)
@@ -591,8 +624,14 @@
 /* QDMA descriptor txd3 */
 #define TX_DMA_OWNER_CPU	BIT(31)
 #define TX_DMA_LS0		BIT(30)
-#define TX_DMA_PLEN0(_x)	(((_x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
+#define TX_DMA_PLEN0(_x)	(((_x) & eth->soc->txrx.dma_max_len) <<	\
+				 eth->soc->txrx.dma_len_offset)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define TX_DMA_PLEN1(_x)	(((_x) & eth->soc->txrx.dma_max_len) << \
+				 eth->soc->txrx.dma_len_offset)
+#else
 #define TX_DMA_PLEN1(_x)	((_x) & eth->soc->txrx.dma_max_len)
+#endif
 #define TX_DMA_SWC		BIT(14)
 #define TX_DMA_SDP1(_x)		((((u64)(_x)) >> 32) & 0xf)
 
@@ -633,6 +672,12 @@
 #define RX_DMA_GET_SPORT(_x) 	(((_x) >> RX_DMA_SPORT_SHIFT) & RX_DMA_SPORT_MASK)
 #define RX_DMA_GET_SPORT_V2(_x) (((_x) >> RX_DMA_SPORT_SHIFT_V2) & RX_DMA_SPORT_MASK_V2)
 
+/* PDMA V2 descriptor txd4 */
+#define TX_DMA_LS1_V2	BIT(30)
+
+/* PDMA V2 descriptor txd5 */
+#define TX_DMA_FPORT_SHIFT_PDMA	16
+
 /* PDMA V2 descriptor rxd3 */
 #define RX_DMA_VTAG_V2          BIT(0)
 #define RX_DMA_L4_VALID_V2      BIT(2)
@@ -1601,6 +1646,10 @@
 	u32	tx_irq_mask;
 	u32	tx_irq_status;
 	struct {
+		u32	tx_ptr;		/* tx base pointer */
+		u32	tx_cnt_cfg;	/* tx max count configuration  */
+		u32	pctx_ptr;	/* tx cpu pointer */
+		u32	pdtx_ptr;	/* tx dma pointer */
 		u32	rx_ptr;		/* rx base pointer */
 		u32	rx_cnt_cfg;	/* rx max count configuration */
 		u32	pcrx_ptr;	/* rx cpu pointer */
@@ -1825,6 +1874,7 @@
 	spinlock_t			page_lock;
 	spinlock_t			tx_irq_lock;
 	spinlock_t			rx_irq_lock;
+	spinlock_t			txrx_irq_lock;
 	struct net_device		dummy_dev;
 	struct net_device		*netdev[MTK_MAX_DEVS];
 	struct mtk_mac			*mac[MTK_MAX_DEVS];
@@ -1833,6 +1883,7 @@
 	int				irq_pdma[MTK_PDMA_IRQ_NUM];
 	u8				hwver;
 	u32				msg_enable;
+	u32				pppq_toggle;
 	unsigned long			sysclk;
 	struct regmap			*ethsys;
 	struct regmap                   *infra;
@@ -1891,6 +1942,7 @@
 	unsigned int			syscfg0;
 	bool				tx_lpi_enabled;
 	u32				tx_lpi_timer;
+	struct notifier_block		device_notifier;
 };
 
 /* struct mtk_mux_data -	the structure that holds the private data about the
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 2ce7495..a0c22b5 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
@@ -36,6 +36,11 @@
 void (*ra_sw_nat_clear_bind_entries)(void) = NULL;
 EXPORT_SYMBOL(ra_sw_nat_clear_bind_entries);
 
+int (*hnat_get_wdma_tx_port)(int wdma_idx) = NULL;
+EXPORT_SYMBOL(hnat_get_wdma_tx_port);
+int (*hnat_get_wdma_rx_port)(int wdma_idx) = NULL;
+EXPORT_SYMBOL(hnat_get_wdma_rx_port);
+
 int (*ppe_del_entry_by_mac)(unsigned char *mac) = NULL;
 EXPORT_SYMBOL(ppe_del_entry_by_mac);
 
@@ -136,6 +141,26 @@
 	}
 }
 
+static int mtk_get_wdma_tx_port(int wdma_idx)
+{
+	if (wdma_idx == 0 || wdma_idx == 1 || wdma_idx == 2)
+		return NR_PPE0_PORT;
+
+	return -EINVAL;
+}
+
+static int mtk_get_wdma_rx_port(int wdma_idx)
+{
+	if (wdma_idx == 2)
+		return NR_WDMA2_PORT;
+	else if (wdma_idx == 1)
+		return NR_WDMA1_PORT;
+	else if (wdma_idx == 0)
+		return NR_WDMA0_PORT;
+
+	return -EINVAL;
+}
+
 void set_gmac_ppe_fwd(int id, int enable)
 {
 	void __iomem *reg;
@@ -147,9 +172,9 @@
 
 	if (enable) {
 #if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-		if (CFG_PPE_NUM == 3 && id == NR_GMAC3_PORT)
+		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)
+		else if (CFG_PPE_NUM >= 2 && 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);
@@ -162,7 +187,7 @@
 	/*disabled */
 	val = readl(reg);
 #if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-	if ((CFG_PPE_NUM == 3 &&
+	if ((CFG_PPE_NUM >= 2 &&
 	    ((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,
@@ -616,6 +641,8 @@
 		ppe_dev_register_hook = mtk_ppe_dev_register_hook;
 		ppe_dev_unregister_hook = mtk_ppe_dev_unregister_hook;
 		ra_sw_nat_clear_bind_entries = foe_clear_all_bind_entries;
+		hnat_get_wdma_tx_port = mtk_get_wdma_tx_port;
+		hnat_get_wdma_rx_port = mtk_get_wdma_rx_port;
 	}
 
 	if (hnat_register_nf_hooks())
@@ -635,6 +662,8 @@
 	ra_sw_nat_hook_tx = NULL;
 	ra_sw_nat_hook_rx = NULL;
 	ra_sw_nat_clear_bind_entries = NULL;
+	hnat_get_wdma_tx_port = NULL;
+	hnat_get_wdma_rx_port = NULL;
 	hnat_unregister_nf_hooks();
 
 	for (i = 0; i < CFG_PPE_NUM; i++) {
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 d297994..7892cf2 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
@@ -112,7 +112,7 @@
 #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_sport(skb) == NR_GMAC3_PORT) && (CFG_PPE_NUM == 3))
+	((skb_hnat_sport(skb) == NR_GMAC3_PORT) && (CFG_PPE_NUM >= 3))
 #define skb_hnat_ppe1(skb)						\
 	((skb_hnat_sport(skb) == NR_GMAC2_PORT) && (CFG_PPE_NUM >= 2))
 #define skb_hnat_ppe(skb)						\
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
index 6a0afaf..38d4c07 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h.h
@@ -46,7 +46,7 @@
 #define MII_MMD_ADDR_DATA_REG       0x0e
 #define MMD_OP_MODE_DATA            BIT(14)
 
-#define EN8811H_DRIVER_VERSION      "v1.2.2"
+#define EN8811H_DRIVER_VERSION      "v1.2.4"
 
 #define LED_ON_CTRL(i)              (0x024 + ((i)*2))
 #define LED_ON_EN                   (1 << 15)
@@ -98,6 +98,7 @@
 	unsigned int        dm_crc32;
 	unsigned int        dsp_crc32;
 	char                buf[512];
+	int                 pol;
 };
 
 struct air_base_t_led_cfg {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
index 731a37d..a73bcee 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.c
@@ -87,7 +87,7 @@
 	return ret;
 }
 
-static int __air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg)
+int __air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg)
 {
 	int ret = 0;
 	int data;
@@ -107,7 +107,7 @@
 	return data;
 }
 
-static int __air_mii_cl45_write(struct phy_device *phydev,
+int __air_mii_cl45_write(struct phy_device *phydev,
 					int devad, u16 reg, u16 write_data)
 {
 	int ret = 0;
@@ -334,6 +334,40 @@
 	}
 	return ret;
 }
+#if defined(CONFIG_OF)
+int en8811h_of_init(struct phy_device *phydev)
+{
+	struct device *dev = phydev_dev(phydev);
+	struct device_node *of_node = dev->of_node;
+	struct en8811h_priv *priv = phydev->priv;
+	u32 val = 0;
+
+	dev_info(dev, "%s: start\n", __func__);
+	if (of_find_property(of_node, "airoha,polarity", NULL)) {
+		if (of_property_read_u32(of_node, "airoha,polarity",
+					 &val) != 0) {
+			phydev_err(phydev, "airoha,polarity value is invalid.");
+			return -EINVAL;
+		}
+		if (val < AIR_POL_TX_REV_RX_NOR ||
+		    val > AIR_POL_TX_NOR_RX_REV) {
+			phydev_err(phydev,
+				   "airoha,polarity value %u out of range.",
+				   val);
+			return -EINVAL;
+		}
+		priv->pol = val;
+	} else
+		priv->pol = AIR_POL_TX_NOR_RX_NOR;
+
+	return 0;
+}
+#else
+int en8811h_of_init(struct phy_device *phydev)
+{
+	return -ESRCH;
+}
+#endif /* CONFIG_OF */
 
 static int air_resolve_an_speed(struct phy_device *phydev)
 {
@@ -588,31 +622,21 @@
 		if (unlikely(ret < 0))
 			break;
 		break;
-	case AIR_PORT_MODE_FC_DIS:
-		pr_notice("\nFlow Control Disabled\n");
-		pbus_data = air_buckpbus_reg_read(phydev, 0xe0008);
-		pbus_data &= ~(BIT(6) | BIT(7));
-		ret = air_buckpbus_reg_write(phydev, 0xe0008, pbus_data);
+	case AIR_PORT_MODE_SSC_DISABLE:
+		pr_notice("\nSSC Disabled\n");
+		pbus_data = air_buckpbus_reg_read(phydev, 0xca000);
+		pbus_data &= ~BIT(21);
+		ret = air_buckpbus_reg_write(phydev, 0xca000, pbus_data);
 		if (unlikely(ret < 0))
 			break;
-		pbus_data = air_buckpbus_reg_read(phydev, 0xe000c);
-		pbus_data &= ~(BIT(0) | BIT(1));
-		ret = air_buckpbus_reg_write(phydev, 0xe000c, pbus_data);
-		if (unlikely(ret < 0))
-			break;
 		break;
-	case AIR_PORT_MODE_FC_EN:
-		pr_notice("\nFlow Control Enabled\n");
-		pbus_data = air_buckpbus_reg_read(phydev, 0xe0008);
-		pbus_data |= (BIT(6) | BIT(7));
-		ret = air_buckpbus_reg_write(phydev, 0xe0008, pbus_data);
+	case AIR_PORT_MODE_SSC_ENABLE:
+		pr_notice("\nSSC Enabled\n");
+		pbus_data = air_buckpbus_reg_read(phydev, 0xca000);
+		pbus_data |= BIT(21);
+		ret = air_buckpbus_reg_write(phydev, 0xca000, pbus_data);
 		if (unlikely(ret < 0))
 			break;
-		pbus_data = air_buckpbus_reg_read(phydev, 0xe000c);
-		pbus_data |= (BIT(0) | BIT(1));
-		ret = air_buckpbus_reg_write(phydev, 0xe000c, pbus_data);
-		if (unlikely(ret < 0))
-			break;
 		break;
 	default:
 		pr_notice("\nWrong Port mode\n");
@@ -645,7 +669,6 @@
 	val = (air_buckpbus_reg_read(phydev, 0xca0f8) & 0x3);
 	seq_printf(seq, "| Tx, Rx Polarity      : %s(%02d)\n",
 						tx_rx_string[val], val);
-
 	seq_puts(seq, "\n");
 
 	return 0;
@@ -714,7 +737,7 @@
 	seq_printf(seq, "%010u |\n", pkt_cnt);
 	seq_puts(seq, "| RX Terminal              :");
 	pkt_cnt = air_buckpbus_reg_read(phydev, 0xC60C0);
-	seq_printf(seq, "%010u |\n\n", pkt_cnt);
+	seq_printf(seq, "%010u |\n", pkt_cnt);
 	ret = air_buckpbus_reg_write(phydev, 0xC602C, 0x4);
 	if (ret < 0)
 		return ret;
@@ -732,9 +755,29 @@
 	if (ret < 0)
 		return ret;
 	seq_puts(seq, "==========AIR PHY COUNTER==========\n");
+	if (phydev->link) {
+		ret = airphy_ss_counter_show(phydev, seq);
+		if (ret < 0)
+			return ret;
+	}
 	ret = airphy_fcm_counter_show(phydev, seq);
 	if (ret < 0)
 		return ret;
+	if (phydev->link) {
+		seq_puts(seq, "|\t<<MAC Counter>>\n");
+		seq_puts(seq, "| Tx Error from System side:");
+		pkt_cnt = air_buckpbus_reg_read(phydev, 0x131000);
+		seq_printf(seq, "%010u |\n", pkt_cnt);
+		seq_puts(seq, "| Rx Error to System side  :");
+		pkt_cnt = air_buckpbus_reg_read(phydev, 0x132000);
+		seq_printf(seq, "%010u |\n", pkt_cnt);
+		seq_puts(seq, "| Tx from System side      :");
+		pkt_cnt = air_buckpbus_reg_read(phydev, 0x131004);
+		seq_printf(seq, "%010u |\n", pkt_cnt);
+		seq_puts(seq, "| Rx to System Side        :");
+		pkt_cnt = air_buckpbus_reg_read(phydev, 0x132004);
+		seq_printf(seq, "%010u |\n", pkt_cnt);
+	}
 	if (phydev->link && phydev->speed == SPEED_2500) {
 		seq_puts(seq, "|\t<<LS Counter>>\n");
 		ret = air_buckpbus_reg_write(phydev, 0x30718, 0x10);
@@ -744,37 +787,37 @@
 		if (ret < 0)
 			return ret;
 		seq_puts(seq, "|\tBefore EF\n");
-		seq_puts(seq, "| TX to Line side_S        :");
+		seq_puts(seq, "| Tx to Line side_S        :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x3071c);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| TX to Line side_T        :");
+		seq_puts(seq, "| Tx to Line side_T        :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30720);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
+		seq_puts(seq, "| Tx_ENC                   :");
+		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30724);
+		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX from Line side_S      :");
+		seq_puts(seq, "| Rx from Line side_S      :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x3072c);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX from Line side_T      :");
+		seq_puts(seq, "| Rx from Line side_T      :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30730);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| TX_ENC                   :");
-		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30724);
-		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX_DEC                   :");
+		seq_puts(seq, "| Rx_DEC                   :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30728);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
 		seq_puts(seq, "|\tAfter EF\n");
-		seq_puts(seq, "| TX to Line side_S        :");
+		seq_puts(seq, "| Tx to Line side_S        :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30734);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| TX to Line side_T        :");
+		seq_puts(seq, "| Tx to Line side_T        :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30738);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX from Line side_S      :");
+		seq_puts(seq, "| Rx from Line side_S      :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30764);
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX from Line side_T      :");
+		seq_puts(seq, "| Rx from Line side_T      :");
 		pkt_cnt = air_buckpbus_reg_read(phydev, 0x30768);
-		seq_printf(seq, "%010u |\n", pkt_cnt);
+		seq_printf(seq, "%010u |\n\n", pkt_cnt);
 		ret = air_buckpbus_reg_write(phydev, 0x30718, 0x13);
 		if (ret < 0)
 			return ret;
@@ -787,29 +830,16 @@
 		ret = air_buckpbus_reg_write(phydev, 0x30718, 0x0);
 		if (ret < 0)
 			return ret;
-		seq_puts(seq, "|\t<<MAC Counter>>\n");
-		seq_puts(seq, "| TX Error from System side:");
-		pkt_cnt = air_buckpbus_reg_read(phydev, 0x131000);
-		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX Error to System side  :");
-		pkt_cnt = air_buckpbus_reg_read(phydev, 0x132000);
-		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| TX from System side      :");
-		pkt_cnt = air_buckpbus_reg_read(phydev, 0x131004);
-		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX to System Side        :");
-		pkt_cnt = air_buckpbus_reg_read(phydev, 0x132004);
-		seq_printf(seq, "%010u |\n", pkt_cnt);
 	}
 	if (phydev->link && ((phydev->speed != SPEED_2500))) {
 		seq_puts(seq, "|\t<<LS Counter>>\n");
 		ret = air_mii_cl22_write(mbus, addr, 0x1f, 1);
 		if (ret < 0)
 			return ret;
-		seq_puts(seq, "| RX from Line side        :");
+		seq_puts(seq, "| Rx from Line side        :");
 		pkt_cnt = air_mii_cl22_read(mbus, addr, 0x12) & 0x7fff;
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| RX Error from Line side  :");
+		seq_puts(seq, "| Rx Error from Line side  :");
 		pkt_cnt = air_mii_cl22_read(mbus, addr, 0x17) & 0xff;
 		seq_printf(seq, "%010u |\n", pkt_cnt);
 		ret = air_mii_cl22_write(mbus, addr, 0x1f, 0);
@@ -821,22 +851,17 @@
 		ret = air_mii_cl22_write(mbus, addr, 0x10, 0xBF92);
 		if (ret < 0)
 			return ret;
-		seq_puts(seq, "| TX to Line side          :");
+		seq_puts(seq, "| Tx to Line side          :");
 		pkt_cnt = (air_mii_cl22_read(mbus, addr, 0x11) & 0x7ffe) >> 1;
 		seq_printf(seq, "%010u |\n", pkt_cnt);
-		seq_puts(seq, "| TX Error to Line side    :");
+		seq_puts(seq, "| Tx Error to Line side    :");
 		pkt_cnt = air_mii_cl22_read(mbus, addr, 0x12);
 		pkt_cnt &= 0x7f;
-		seq_printf(seq, "%010u |\n", pkt_cnt);
+		seq_printf(seq, "%010u |\n\n", pkt_cnt);
 		ret = air_mii_cl22_write(mbus, addr, 0x1f, 0);
 		if (ret < 0)
 			return ret;
 	}
-	if (phydev->link) {
-		ret = airphy_ss_counter_show(phydev, seq);
-		if (ret < 0)
-			return ret;
-	}
 	return ret;
 }
 
@@ -901,6 +926,7 @@
 			"echo 2500 > /[debugfs]/port_mode\n"
 			"echo 1000 > /[debugfs]/port_mode\n"
 			"echo 100 > /[debugfs]/port_mode\n"
+			"echo ssc ena/dis > /[debugfs]/port_mode\n"
 			"echo power up/down >  /[debugfs]/port_mode\n");
 }
 
@@ -941,9 +967,11 @@
 			ret = air_set_mode(phydev, AIR_PORT_MODE_POWER_DOWN);
 		else if (!strncmp("up", param, strlen("up")))
 			ret = air_set_mode(phydev, AIR_PORT_MODE_POWER_UP);
-	} else if (!strncmp("int_sw_release", cmd, strlen("int_sw_release"))) {
-		ret = air_pbus_reg_write(phydev, 0xcf928, 0x0);
-		pr_notice("\ninternal sw reset released\n");
+	} else if (!strncmp("ssc", cmd, strlen("ssc"))) {
+		if (!strncmp("dis", param, strlen("dis")))
+			ret = air_set_mode(phydev, AIR_PORT_MODE_SSC_DISABLE);
+		else if (!strncmp("ena", param, strlen("ena")))
+			ret = air_set_mode(phydev, AIR_PORT_MODE_SSC_ENABLE);
 	} else if (!strncmp("help", cmd, strlen("help"))) {
 		airphy_port_mode_help();
 	}
@@ -1088,10 +1116,24 @@
 	int addr = phydev_addr(phydev);
 
 	seq_puts(seq, "\t<<DEBUG REG DUMP>>\n");
+	seq_printf(seq, "| RG_MII_BMCR           : 0x%08x |\n",
+		   air_mii_cl22_read(mbus, addr, MII_BMCR));
 	seq_printf(seq, "| RG_MII_BMSR           : 0x%08x |\n",
 		   air_mii_cl22_read(mbus, addr, MII_BMSR));
+	seq_printf(seq, "| RG_MII_ADVERTISE      : 0x%08x |\n",
+		   air_mii_cl22_read(mbus, addr, MII_ADVERTISE));
+	seq_printf(seq, "| RG_MII_LPA            : 0x%08x |\n",
+		   air_mii_cl22_read(mbus, addr, MII_LPA));
+	seq_printf(seq, "| RG_MII_CTRL1000       : 0x%08x |\n",
+		   air_mii_cl22_read(mbus, addr, MII_CTRL1000));
+	seq_printf(seq, "| RG_MII_STAT1000       : 0x%08x |\n",
+		   air_mii_cl22_read(mbus, addr, MII_STAT1000));
 	seq_printf(seq, "| RG_MII_REF_CLK        : 0x%08x |\n",
 		   air_mii_cl22_read(mbus, addr, 0x1d));
+	seq_printf(seq, "| RG_HW_STRAP1          : 0x%08x |\n",
+		   air_buckpbus_reg_read(phydev, 0xcf910));
+	seq_printf(seq, "| RG_HW_STRAP2          : 0x%08x |\n",
+		   air_buckpbus_reg_read(phydev, 0xcf914));
 	seq_printf(seq, "| RG_SYS_LINK_MODE      : 0x%08x |\n",
 		   air_buckpbus_reg_read(phydev, 0xe0004));
 	seq_printf(seq, "| RG_FCM_CTRL           : 0x%08x |\n",
@@ -1119,11 +1161,144 @@
 	return single_open(file, dbg_regs_show, inode->i_private);
 }
 
+
+static int airphy_temp_show(struct seq_file *seq, void *v)
+{
+	struct phy_device *phydev = seq->private;
+	int ret = 0;
+	u32 pbus_value = 0;
+
+	seq_puts(seq, "<<AIR EN8811H Temp>>\n");
+	air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1100);
+	air_mii_cl45_write(phydev, 0x1e, 0x800f, 0xe5);
+	pbus_value = air_buckpbus_reg_read(phydev, 0x3B38);
+	seq_printf(seq, "| Temperature  : %dC |\n",
+						pbus_value);
+	seq_puts(seq, "\n");
+
+	return 0;
+}
+
+static int airphy_temp_show_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, airphy_temp_show, inode->i_private);
+}
+
+
+static unsigned int air_read_lp_speed(struct phy_device *phydev)
+{
+	int val = 0, an = AUTONEG_DISABLE;
+	unsigned int ret = 0;
+	int count = 15, i, lpa, lpagb;
+	struct air_lp_speed *m;
+	struct device *dev = phydev_dev(phydev);
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	int addr = phydev_addr(phydev);
+
+	val = air_mii_cl22_read(mbus, addr, MII_BMCR) | BIT(9);
+	ret = air_mii_cl22_write(mbus, addr, MII_BMCR, val);
+	if (unlikely(ret < 0))
+		return ret;
+	msleep(1500);
+	do {
+		msleep(100);
+		ret = air_mii_cl45_read(phydev, MDIO_MMD_AN, 0x21);
+		ret &= BIT(5);
+		if (ret)
+			break;
+		count--;
+	} while (count);
+
+	count = 10;
+	do {
+		msleep(500);
+		val = air_mii_cl22_read(mbus, addr, MII_BMSR);
+		if (val < 0) {
+			dev_err(dev, "MII_BMSR reg 0x%x!\n", val);
+			return val;
+		}
+		val = air_mii_cl22_read(mbus, addr, MII_BMSR);
+		if (val < 0) {
+			dev_err(dev, "MII_BMSR reg 0x%x!\n", val);
+			return val;
+		}
+		dev_dbg(dev, "val 0x%x\n", val);
+		if (val & BMSR_LSTATUS) {
+			val = air_mii_cl22_read(mbus, addr, MII_LPA);
+			if (val < 0)
+				return val;
+			lpa = (val & (BIT(5) | BIT(6) | BIT(7) | BIT(8))) >> 5;
+			val = air_mii_cl22_read(mbus, addr, MII_STAT1000);
+			if (val < 0)
+				return val;
+			lpagb = GET_BIT(val, 11) << 4;
+			ret |= (lpagb | lpa);
+			return ret;
+		}
+	} while (count--);
+
+	return 0;
+}
+
+static int airphy_lp_speed(struct seq_file *seq, void *v)
+{
+	unsigned int ret = 0, val = 0, did1 = 0, i;
+	struct phy_device *phydev = seq->private;
+	static const struct {
+		unsigned int bit_index;
+		const char *name;
+	} mode_defs[] = {
+		{ AIR_LINK_MODE_10baseT_Half_BIT,
+		"10baseT/Half" },
+		{ AIR_LINK_MODE_10baseT_Full_BIT,
+		"10baseT/Full" },
+		{ AIR_LINK_MODE_100baseT_Half_BIT,
+		"100baseT/Half" },
+		{ AIR_LINK_MODE_100baseT_Full_BIT,
+		"100baseT/Full" },
+		{ AIR_LINK_MODE_1000baseT_Full_BIT,
+		"1000baseT/Full" },
+		{ AIR_LINK_MODE_2500baseT_Full_BIT,
+		"2500baseT/Full" }
+	};
+
+	seq_printf(seq, "%s Link Partner Ability:\n",
+			dev_name(phydev_dev(phydev)));
+	ret = air_read_lp_speed(phydev);
+	if (val < 0)
+		return val;
+	for (i = 0; i < ARRAY_SIZE(mode_defs); i++) {
+		if (ret & BIT(mode_defs[i].bit_index)) {
+			seq_printf(seq, "\t\t\t %s\n",
+						mode_defs[i].name);
+			did1++;
+		}
+	}
+	if (did1 == 0)
+		seq_puts(seq, "\t\t\t Not reported\n");
+
+	return 0;
+}
+
+static int airphy_lp_speed_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, airphy_lp_speed, inode->i_private);
+}
+
+static const struct file_operations airphy_lp_speed_fops = {
+	.owner = THIS_MODULE,
+	.open = airphy_lp_speed_open,
+	.read = seq_read,
+	.llseek = noop_llseek,
+	.release = single_release,
+};
+
 static const struct file_operations airphy_info_fops = {
 	.owner = THIS_MODULE,
 	.open = airphy_info_open,
 	.read = seq_read,
 	.llseek = noop_llseek,
+	.release = single_release,
 };
 
 static const struct file_operations airphy_counter_fops = {
@@ -1131,6 +1306,7 @@
 	.open = airphy_counter_open,
 	.read = seq_read,
 	.llseek = noop_llseek,
+	.release = single_release,
 };
 
 static const struct file_operations airphy_debugfs_buckpbus_fops = {
@@ -1166,6 +1342,7 @@
 	.open = airphy_link_status_open,
 	.read = seq_read,
 	.llseek = noop_llseek,
+	.release = single_release,
 };
 
 static const struct file_operations airphy_dbg_reg_show_fops = {
@@ -1173,8 +1350,17 @@
 	.open = airphy_dbg_regs_show_open,
 	.read = seq_read,
 	.llseek = noop_llseek,
+	.release = single_release,
 };
 
+static const struct file_operations airphy_temp_fops = {
+	.owner = THIS_MODULE,
+	.open = airphy_temp_show_open,
+	.read = seq_read,
+	.llseek = noop_llseek,
+	.release = single_release,
+};
+
 int airphy_debugfs_init(struct phy_device *phydev)
 {
 	int ret = 0;
@@ -1212,12 +1398,18 @@
 	debugfs_create_file(DEBUGFS_DBG_REG_SHOW, S_IFREG | 0444,
 					dir, phydev,
 					&airphy_dbg_reg_show_fops);
+	debugfs_create_file(DEBUGFS_TEMPERATURE, S_IFREG | 0444,
+					dir, phydev,
+					&airphy_temp_fops);
+	debugfs_create_file(DEBUGFS_LP_SPEED, S_IFREG | 0444,
+					dir, phydev,
+					&airphy_lp_speed_fops);
 
 	priv->debugfs_root = dir;
 	return ret;
 }
 
-void air_debugfs_remove(struct phy_device *phydev)
+void airphy_debugfs_remove(struct phy_device *phydev)
 {
 	struct en8811h_priv *priv = phydev->priv;
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h
index a1d97ce..9715a58 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_api.h
@@ -21,8 +21,6 @@
 #define phydev_dev(_dev) (&_dev->mdio.dev)
 #endif
 
-#define BUFFER_LENGTH 512
-
 #define DEBUGFS_COUNTER		        "counter"
 #define DEBUGFS_DRIVER_INFO	        "drvinfo"
 #define DEBUGFS_PORT_MODE           "port_mode"
@@ -31,6 +29,8 @@
 #define DEBUGFS_POLARITY            "polarity"
 #define DEBUGFS_LINK_STATUS         "link_status"
 #define DEBUGFS_DBG_REG_SHOW        "dbg_regs_show"
+#define DEBUGFS_TEMPERATURE         "temp"
+#define DEBUGFS_LP_SPEED            "lp_speed"
 
 enum air_port_mode {
 	AIR_PORT_MODE_FORCE_100,
@@ -39,10 +39,8 @@
 	AIR_PORT_MODE_AUTONEGO,
 	AIR_PORT_MODE_POWER_DOWN,
 	AIR_PORT_MODE_POWER_UP,
-	AIR_PORT_MODE_FC_UNSUPPORT,
-	AIR_PORT_MODE_FC_SUPPORT,
-	AIR_PORT_MODE_FC_DIS,
-	AIR_PORT_MODE_FC_EN,
+	AIR_PORT_MODE_SSC_DISABLE,
+	AIR_PORT_MODE_SSC_ENABLE,
 	AIR_PORT_MODE_LAST = 0xFF,
 };
 
@@ -73,6 +71,9 @@
 	unsigned int phy_register, unsigned int write_data);
 int air_mii_cl22_read(struct mii_bus *ebus,
 	int addr, unsigned int phy_register);
+int __air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg);
+int __air_mii_cl45_write(struct phy_device *phydev,
+	int devad, u16 reg, u16 write_data);
 int air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg);
 int air_mii_cl45_write(struct phy_device *phydev,
 	int devad, u16 reg, u16 write_data);
@@ -80,8 +81,9 @@
 	unsigned int pbus_address);
 int air_buckpbus_reg_write(struct phy_device *phydev,
 	unsigned int pbus_address, unsigned int pbus_data);
+int en8811h_of_init(struct phy_device *phydev);
 #ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 int airphy_debugfs_init(struct phy_device *phydev);
-void air_debugfs_remove(struct phy_device *phydev);
+void airphy_debugfs_remove(struct phy_device *phydev);
 #endif /*CONFIG_AIROHA_EN8811H_PHY_DEBUGFS*/
 #endif /* End of __EN8811H_API_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
index 353e226..50a7f49 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/air_en8811h_main.c
@@ -115,15 +115,16 @@
 	const char *firmware;
 	int ret = 0;
 	u32 pbus_value = 0;
-#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 	struct en8811h_priv *priv = phydev->priv;
-#endif
-	ret = air_buckpbus_reg_write(phydev, 0x0f0018, 0x0);
+
+	ret = air_buckpbus_reg_write(phydev,
+					0x0f0018, 0x0);
 	if (ret < 0)
 		return ret;
 	pbus_value = air_buckpbus_reg_read(phydev, 0x800000);
 	pbus_value |= BIT(11);
-	ret = air_buckpbus_reg_write(phydev, 0x800000, pbus_value);
+	ret = air_buckpbus_reg_write(phydev,
+					0x800000, pbus_value);
 	if (ret < 0)
 		return ret;
 	firmware = EN8811H_MD32_DM;
@@ -133,9 +134,7 @@
 			"failed to load firmware %s, ret: %d\n", firmware, ret);
 		return ret;
 	}
-#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 	priv->dm_crc32 = ~crc32(~0, fw->data, fw->size);
-#endif
 	dev_info(dev, "%s: crc32=0x%x\n",
 		firmware, ~crc32(~0, fw->data, fw->size));
 	/* Download DM */
@@ -154,9 +153,7 @@
 			"failed to load firmware %s, ret: %d\n", firmware, ret);
 		return ret;
 	}
-#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 	priv->dsp_crc32 = ~crc32(~0, fw->data, fw->size);
-#endif
 	dev_info(dev, "%s: crc32=0x%x\n",
 		firmware, ~crc32(~0, fw->data, fw->size));
 	/* Download PM */
@@ -333,26 +330,21 @@
 	struct mii_bus *mbus = phydev_mdio_bus(phydev);
 	int addr = phydev_addr(phydev);
 
-#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 	struct en8811h_priv *priv;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 	phydev->priv = priv;
-#endif /*CONFIG_AIROHA_EN8811H_PHY_DEBUGFS*/
 	ret = air_pbus_reg_write(phydev, 0xcf928, 0x0);
 	if (ret < 0)
-		return ret;
+		goto priv_free;
 	pid1 = air_mii_cl22_read(mbus, addr, MII_PHYSID1);
-	if (pid1 < 0)
-		return pid1;
 	pid2 = air_mii_cl22_read(mbus, addr, MII_PHYSID2);
-	if (pid2 < 0)
-		return pid2;
 	dev_info(dev, "PHY = %x - %x\n", pid1, pid2);
 	if ((pid1 != EN8811H_PHY_ID1) || (pid2 != EN8811H_PHY_ID2)) {
-		dev_err(dev, "EN8811H dose not exist !\n");
+		dev_err(dev, "EN8811H dose not exist!!\n");
+		kfree(priv);
 		return -ENODEV;
 	}
 	pbus_value = air_buckpbus_reg_read(phydev, 0xcf914);
@@ -362,15 +354,14 @@
 	ret = en8811h_load_firmware(phydev);
 	if (ret < 0) {
 		dev_err(dev, "EN8811H load firmware fail.\n");
-		return ret;
+		goto priv_free;
 	}
 #ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
 	ret = airphy_debugfs_init(phydev);
 	if (ret < 0) {
 		dev_err(dev, "air_debug_procfs_init fail. (ret=%d)\n", ret);
-		air_debugfs_remove(phydev);
-		kfree(priv);
-		return ret;
+		airphy_debugfs_remove(phydev);
+		goto priv_free;
 	}
 #endif /* CONFIG_AIROHA_EN8811H_PHY_DEBUGFS */
 	retry = MAX_RETRY;
@@ -390,29 +381,36 @@
 			"Check MD32 FW Version(0x3b3c) : %08x\n", pbus_value);
 		dev_err(dev,
 			"EN8811H initialize fail!\n");
-		return 0;
+		goto priv_free;
 	}
 	/* Mode selection*/
 	dev_info(dev, "EN8811H Mode 1 !\n");
 	ret = air_mii_cl45_write(phydev, 0x1e, 0x800c, 0x0);
 	if (ret < 0)
-		return ret;
+		goto priv_free;
 	ret = air_mii_cl45_write(phydev, 0x1e, 0x800d, 0x0);
 	if (ret < 0)
-		return ret;
+		goto priv_free;
 	ret = air_mii_cl45_write(phydev, 0x1e, 0x800e, 0x1101);
 	if (ret < 0)
-		return ret;
+		goto priv_free;
 	ret = air_mii_cl45_write(phydev, 0x1e, 0x800f, 0x0002);
 	if (ret < 0)
-		return ret;
+		goto priv_free;
 	/* Serdes polarity */
+	ret = en8811h_of_init(phydev);
+	if (ret < 0)
+		goto priv_free;
 	pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
 	pbus_value &= ~0x3;
+#if defined(CONFIG_OF)
+	pbus_value |= priv->pol;
+#else
 	pbus_value |= (EN8811H_RX_POL_NORMAL | EN8811H_TX_POL_NORMAL);
+#endif
 	ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_value);
 	if (ret < 0)
-		return ret;
+		goto priv_free;
 	pbus_value = air_buckpbus_reg_read(phydev, 0xca0f8);
 	dev_info(dev, "Tx, Rx Polarity : %08x\n", pbus_value);
 	pbus_value = air_buckpbus_reg_read(phydev, 0x3b3c);
@@ -421,25 +419,29 @@
 	ret = en8811h_led_init(phydev);
 	if (ret < 0) {
 		dev_err(dev, "en8811h_led_init fail. (ret=%d)\n", ret);
-		return ret;
+		goto priv_free;
 	}
 #endif
 	dev_info(dev, "EN8811H initialize OK! (%s)\n", EN8811H_DRIVER_VERSION);
 	return 0;
+priv_free:
+	kfree(priv);
+	return ret;
 }
 void en8811h_remove(struct phy_device *phydev)
 {
-#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
+
 	struct en8811h_priv *priv = phydev->priv;
 	struct device *dev = phydev_dev(phydev);
 
 	dev_dbg(dev, "%s: start\n", __func__);
 	if (priv) {
-		dev_info(dev, "%s: air_debugfs_remove\n", __func__);
-		air_debugfs_remove(phydev);
+		dev_info(dev, "%s: airphy_debugfs_remove\n", __func__);
+#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
+		airphy_debugfs_remove(phydev);
+#endif /*CONFIG_AIROHA_EN8811H_PHY_DEBUGFS*/
 		kfree(priv);
 	}
-#endif /*CONFIG_AIROHA_EN8811H_PHY_DEBUGFS*/
 }
 
 static struct phy_driver en8811h_driver[] = {
@@ -451,8 +453,8 @@
 	.remove         = en8811h_remove,
 #if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE)
 	.get_features   = en8811h_get_features,
-	.read_mmd       = air_mii_cl45_read,
-	.write_mmd      = air_mii_cl45_write,
+	.read_mmd       = __air_mii_cl45_read,
+	.write_mmd      = __air_mii_cl45_write,
 #endif
 } };
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.c
index f8c5ad6..2cbea72 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.c
@@ -65,6 +65,7 @@
 struct en8801s_priv {
 	bool first_init;
 	u16 count;
+	u16 pro_version;
 #if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
 	struct gpio_desc *hw_reset;
 #endif
@@ -104,6 +105,7 @@
 /************************************************************************
 *                  F U N C T I O N S
 ************************************************************************/
+static int en8801s_phase2_init(struct phy_device *phydev);
 static unsigned int airoha_cl22_read(struct mii_bus *ebus, int phy_addr,
 			unsigned int phy_register, unsigned int *read_data)
 {
@@ -472,7 +474,8 @@
 static int en8801s_phase1_init(struct phy_device *phydev)
 {
 	unsigned long pbus_data;
-	int pbusAddress = EN8801S_PBUS_DEFAULT_ID;
+	int pbus_addr = EN8801S_PBUS_DEFAULT_ADDR;
+	int phy_addr = EN8801S_PHY_DEFAULT_ADDR;
 	u16 reg_value;
 	int retry, ret = 0;
 	struct mii_bus *mbus = phydev_mdio_bus(phydev);
@@ -489,27 +492,30 @@
 
 	retry = MAX_OUI_CHECK;
 	while (1) {
-		pbus_data = airoha_pbus_read(mbus, pbusAddress,
+		pbus_data = airoha_pbus_read(mbus, pbus_addr,
 				EN8801S_RG_ETHER_PHY_OUI);      /* PHY OUI */
 		if (pbus_data == EN8801S_PBUS_OUI) {
 			dev_info(dev, "PBUS addr 0x%x: Start initialized.\n",
-					pbusAddress);
+					pbus_addr);
 			break;
 		}
-		pbusAddress = phydev_pbus_addr(phydev);
+		pbus_addr = phydev_pbus_addr(phydev);
 		if (0 == --retry) {
 			dev_err(dev, "Probe fail !\n");
 			return 0;
 		}
 	}
 
-	ret = airoha_pbus_write(mbus, pbusAddress, EN8801S_RG_BUCK_CTL, 0x03);
+	ret = airoha_pbus_write(mbus, pbus_addr, EN8801S_RG_BUCK_CTL, 0x03);
 	if (ret < 0)
 		return ret;
+	pbus_data = airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_PROD_VER);
+	priv->pro_version = pbus_data & 0xf;
+	dev_info(dev, "EN8801S Procduct Version :E%d\n", priv->pro_version);
 	mdelay(10);
-	pbus_data = (airoha_pbus_read(mbus, pbusAddress, EN8801S_RG_LTR_CTL)
+	pbus_data = (airoha_pbus_read(mbus, pbus_addr, EN8801S_RG_LTR_CTL)
 				 & 0xfffffffc) | BIT(2);
-	ret = airoha_pbus_write(mbus, pbusAddress,
+	ret = airoha_pbus_write(mbus, pbus_addr,
 				EN8801S_RG_LTR_CTL, pbus_data);
 	if (ret < 0)
 		return ret;
@@ -517,19 +523,35 @@
 	pbus_data = (pbus_data & ~BIT(2)) |
 				EN8801S_RX_POLARITY_NORMAL |
 				EN8801S_TX_POLARITY_NORMAL;
-	ret = airoha_pbus_write(mbus, pbusAddress,
+	ret = airoha_pbus_write(mbus, pbus_addr,
 				EN8801S_RG_LTR_CTL, pbus_data);
 	if (ret < 0)
 		return ret;
 	mdelay(500);
-
-	pbus_data = airoha_pbus_read(mbus, pbusAddress,
+	if (priv->pro_version == 4) {
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1900);
+		dev_dbg(dev, "Before 0x1900 0x%x\n", pbus_data);
+		ret = airoha_pbus_write(mbus, pbus_addr, 0x1900, 0x101009f);
+		if (ret < 0)
+			return ret;
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1900);
+		dev_dbg(dev, "After 0x1900 0x%x\n", pbus_data);
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x19a8);
+		dev_dbg(dev, "Before 19a8 0x%x\n", pbus_data);
+		ret = airoha_pbus_write(mbus, pbus_addr,
+				0x19a8, pbus_data & ~BIT(16));
+		if (ret < 0)
+			return ret;
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x19a8);
+		dev_dbg(dev, "After 19a8 0x%x\n", pbus_data);
+	}
+	pbus_data = airoha_pbus_read(mbus, pbus_addr,
 				EN8801S_RG_SMI_ADDR); /* SMI ADDR */
 	pbus_data = (pbus_data & 0xffff0000) |
 				(unsigned long)(phydev_pbus_addr(phydev) << 8) |
 				(unsigned long)(phydev_phy_addr(phydev));
 	dev_info(phydev_dev(phydev), "SMI_ADDR=%lx (renew)\n", pbus_data);
-	ret = airoha_pbus_write(mbus, pbusAddress,
+	ret = airoha_pbus_write(mbus, pbus_addr,
 				EN8801S_RG_SMI_ADDR, pbus_data);
 	mdelay(10);
 
@@ -566,6 +588,15 @@
 	phydev->dev_flags = PHY_STATE_INIT;
 
 	dev_info(dev, "Phase1 initialize OK ! (%s)\n", EN8801S_DRIVER_VERSION);
+	if (priv->pro_version == 4) {
+		ret = en8801s_phase2_init(phydev);
+		if (ret != 0) {
+			dev_info(dev, "en8801_phase2_init failed\n");
+			phydev->dev_flags = PHY_STATE_FAIL;
+			return 0;
+		}
+		phydev->dev_flags = PHY_STATE_PROCESS;
+	}
 
 	return 0;
 }
@@ -889,13 +920,15 @@
 		dev_dbg(dev, "phydev->link %d, count %d\n",
 					phydev->link, priv->count);
 		if ((phydev->link) || (priv->count == 5)) {
-			ret = en8801s_phase2_init(phydev);
-			if (ret != 0) {
-				dev_info(dev, "en8801_phase2_init failed\n");
-				phydev->dev_flags = PHY_STATE_FAIL;
-				return 0;
+			if (priv->pro_version != 4) {
+				ret = en8801s_phase2_init(phydev);
+				if (ret != 0) {
+					dev_info(dev, "en8801_phase2_init failed\n");
+					phydev->dev_flags = PHY_STATE_FAIL;
+					return 0;
+				}
+				phydev->dev_flags = PHY_STATE_PROCESS;
 			}
-			phydev->dev_flags = PHY_STATE_PROCESS;
 		}
 		priv->count++;
 	}
@@ -924,6 +957,7 @@
 		airoha_pbus_write(mbus, pbus_addr, 0x0600,
 				0x0c000c00);
 		if (preSpeed == SPEED_1000) {
+			dev_dbg(dev, "SPEED_1000\n");
 			ret = airoha_pbus_write(mbus, pbus_addr, 0x10,
 					0xD801);
 			if (ret < 0)
@@ -951,6 +985,7 @@
 			if (ret < 0)
 				return ret;
 		} else if (preSpeed == SPEED_100) {
+			dev_dbg(dev, "SPEED_100\n");
 			ret = airoha_pbus_write(mbus, pbus_addr, 0x10,
 					0xD401);
 			if (ret < 0)
@@ -978,6 +1013,7 @@
 			if (ret < 0)
 				return ret;
 		} else if (preSpeed == SPEED_10) {
+			dev_dbg(dev, "SPEED_10\n");
 			ret = airoha_pbus_write(mbus, pbus_addr, 0x10,
 					0xD001);
 			if (ret < 0)
@@ -1022,7 +1058,7 @@
 	struct mdio_device *mdiodev = &phydev->mdio;
 #endif
 
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
@@ -1115,7 +1151,6 @@
 			}
 		}
 	}
-
 	ret = __airoha_cl45_write(mbus, phy_addr, devad, reg, val);
 	if (ret < 0)
 		return ret;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.h
index 0a077c3..d1e268c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.h
@@ -12,12 +12,14 @@
 
 /* NAMING DECLARATIONS
  */
-#define EN8801S_DRIVER_VERSION  "1.1.7_Generic"
-#define EN8801S_PBUS_DEFAULT_ID 0x1e
+#define EN8801S_DRIVER_VERSION  "1.1.8_Generic"
+#define EN8801S_PBUS_DEFAULT_ADDR 0x1e
+#define EN8801S_PHY_DEFAULT_ADDR 0x1d
 #define EN8801S_RG_ETHER_PHY_OUI 0x19a4
 #define EN8801S_RG_SMI_ADDR      0x19a8
 #define EN8801S_RG_BUCK_CTL      0x1a20
 #define EN8801S_RG_LTR_CTL       0x0cf8
+#define EN8801S_RG_PROD_VER      0x18e0
 
 #define EN8801S_PBUS_OUI        0x17a5
 #define EN8801S_PHY_ID1         0x03a2
@@ -164,17 +166,10 @@
 /* Invalid data */
 #define INVALID_DATA            0xffffffff
 
-#define LED_SET_EVT(reg, cod, result, bit) do         \
-	{                                                 \
-		if (reg & cod) {                              \
-			result |= bit;                            \
-		}                                             \
-	} while (0)
-
 #define LED_SET_GPIO_SEL(gpio, led, val)             \
 			(val |= (led << (8 * (gpio % 4))))       \
 
-
+#define GET_BIT(val, bit) ((val & BIT(bit)) >> bit)
 /* DATA TYPE DECLARATIONS
  */
 struct AIR_BASE_T_LED_CFG_S {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
index ab87e93..31a77e0 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
@@ -88,7 +88,6 @@
 	int ret, i;
 	const struct firmware *fw;
 	struct device *dev = &phydev->mdio.dev;
-	struct device *pm_dev;
 	struct device_node *np;
 	void __iomem *pmb_addr;
 	void __iomem *md32_en_cfg_base;
@@ -97,30 +96,6 @@
 	struct pinctrl *pinctrl;
 
 	if (!phy_priv->fw_loaded) {
-		pm_dev = dev_pm_domain_attach_by_name(dev, "i2p5gbe-pd");
-		if (IS_ERR(pm_dev)) {
-			ret = PTR_ERR(pm_dev);
-			dev_err(dev, "failed to get i2p5g pm-domain: %d\n", ret);
-			return ret;
-		}
-		if (!pm_dev->pm_domain)
-			dev_info(dev, "pm_dev domain is not ready yet\n");
-
-		/* We need to add 1 to power domain counter first so that
-		 * we can correctly power off internal 2.5Gphy
-		 */
-		ret = pm_runtime_get_sync(pm_dev);
-		if (ret < 0) {
-			dev_err(&phydev->mdio.dev, "failed to power on!\n");
-			return ret;
-		}
-		pm_runtime_put_sync(pm_dev);
-		ret = pm_runtime_get_sync(pm_dev);
-		if (ret < 0) {
-			dev_err(&phydev->mdio.dev, "failed to power on!\n");
-			return ret;
-		}
-
 		np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
 		if (!np)
 			return -ENOENT;
@@ -139,16 +114,23 @@
 		}
 
 		reg = readw(md32_en_cfg_base);
-		writew(reg | DMEM_PRIORITY | PMEM_PRIORITY, md32_en_cfg_base);
+		if (reg & MD32_EN) {
+			phy_set_bits(phydev, 0, BIT(15));
+			usleep_range(10000, 11000);
+		}
+		phy_set_bits(phydev, 0, BIT(11));
+
+		/* Write magic number to safely stall MCU */
+		phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800e, 0x1100);
+		phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800f, 0x00df);
 
 		for (i = 0; i < fw->size - 1; i += 4)
 			writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
 		release_firmware(fw);
 
-		reg = readw(md32_en_cfg_base);
-		reg &= ~(DMEM_PRIORITY | PMEM_PRIORITY | MD32_EN);
-		writew(reg, md32_en_cfg_base);
+		writew(reg & ~MD32_EN, md32_en_cfg_base);
 		writew(reg | MD32_EN, md32_en_cfg_base);
+		phy_set_bits(phydev, 0, BIT(15));
 		dev_info(dev, "Firmware loading/trigger ok.\n");
 
 		phy_priv->fw_loaded = true;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c
index d2c86ac..6b50c0c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/pci/controller/pcie-mediatek-gen3.c
@@ -8,6 +8,8 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/iopoll.h>
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
@@ -15,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/msi.h>
+#include <linux/of_gpio.h>
 #include <linux/of_pci.h>
 #include <linux/pci.h>
 #include <linux/phy/phy.h>
@@ -179,6 +182,9 @@
 	int num_clks;
 	int max_link_width;
 
+	struct gpio_desc *wifi_reset;
+	u32 wifi_reset_delay_ms;
+
 	int irq;
 	int num_irqs;
 	struct mtk_pcie_irq *irqs;
@@ -379,6 +385,12 @@
 	val &= ~PCIE_INTX_ENABLE;
 	writel_relaxed(val, port->base + PCIE_INT_ENABLE_REG);
 
+	if (port->wifi_reset) {
+		gpiod_set_value_cansleep(port->wifi_reset, 0);
+		msleep(port->wifi_reset_delay_ms);
+		gpiod_set_value_cansleep(port->wifi_reset, 1);
+	}
+
 	/* Assert all reset signals */
 	val = readl_relaxed(port->base + PCIE_RST_CTRL_REG);
 	val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB;
@@ -963,6 +975,8 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct list_head *windows = &host->windows;
 	struct resource *regs, *bus;
+	enum of_gpio_flags flags;
+	enum gpiod_flags wifi_reset_init_flags;
 	int ret;
 
 	ret = pci_parse_request_of_pci_ranges(dev, windows, &bus);
@@ -1023,6 +1037,28 @@
 		return ret;
 	}
 
+	ret = of_get_named_gpio_flags(dev->of_node, "wifi-reset-gpios", 0,
+				      &flags);
+	if (ret >= 0) {
+		if (flags & OF_GPIO_ACTIVE_LOW)
+			wifi_reset_init_flags = GPIOD_OUT_HIGH;
+		else
+			wifi_reset_init_flags = GPIOD_OUT_LOW;
+		port->wifi_reset = devm_gpiod_get_optional(dev, "wifi-reset",
+							   wifi_reset_init_flags);
+		if (IS_ERR(port->wifi_reset)) {
+			ret = PTR_ERR(port->wifi_reset);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev,
+					"failed to request WIFI reset gpio\n");
+			return ret;
+		}
+		of_property_read_u32(dev->of_node, "wifi-reset-msleep",
+				     &port->wifi_reset_delay_ms);
+	} else if (ret == -EPROBE_DEFER) {
+		return ret;
+	}
+
 	return 0;
 }
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch
index 11c2c8e..dc060ea 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3000-ovs-add-multicast-to-unicast-support.patch
@@ -1,18 +1,18 @@
-From 0a78a8c88b4db2a49aad7544c085078d65dbd343 Mon Sep 17 00:00:00 2001
+From 4d7eabd37042f541f085cca6265bd22ae3f05e6e Mon Sep 17 00:00:00 2001
 From: mtk22468 <Xuzhu.Wang@mediatek.com>
 Date: Mon, 18 Sep 2023 10:50:36 +0800
-Subject: [PATCH 01/22] ovs add multicast to unicast support
+Subject: [PATCH] ovs add multicast to unicast support
 
 ---
  net/openvswitch/actions.c  |  30 ++++
- net/openvswitch/datapath.c | 289 +++++++++++++++++++++++++++++++++++++
+ net/openvswitch/datapath.c | 290 +++++++++++++++++++++++++++++++++++++
  net/openvswitch/datapath.h |  32 ++++
  net/openvswitch/vport.c    |   8 +
  net/openvswitch/vport.h    |  26 ++++
- 5 files changed, 385 insertions(+)
+ 5 files changed, 386 insertions(+)
 
 diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
-index 9e8a5c4..d5bf30d 100644
+index 9e8a5c4..e953e62 100644
 --- a/net/openvswitch/actions.c
 +++ b/net/openvswitch/actions.c
 @@ -919,6 +919,10 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
@@ -32,7 +32,7 @@
  		           (skb->len <= mru + vport->dev->hard_header_len))) {
 +			if (is_multicast_addr(skb) && !is_igmp_mld(skb)) {
 +				mdb = vport->mdb;
-+				spin_lock(&mdb->tbl_lock);
++				spin_lock_bh(&mdb->tbl_lock);
 +				list_for_each_entry(table, &mdb->list_head, mdb_node) {
 +					if ((key->eth.type == htons(ETH_P_IP) &&
 +						table->group_addr.u.ip4 == key->ipv4.addr.dst) ||
@@ -43,24 +43,24 @@
 +							if (!skb_cpy) {
 +								kfree_skb(skb);
 +								pr_err("%s(): skb copy error\n", __func__);
-+								spin_unlock(&mdb->tbl_lock);
++								spin_unlock_bh(&mdb->tbl_lock);
 +								return;
 +							}
 +							memcpy(skb_cpy->data, entry->eth_addr, ETH_ALEN);
 +							ovs_vport_send(vport, skb_cpy, ovs_key_mac_proto(key));
 +						}
-+						spin_unlock(&mdb->tbl_lock);
++						spin_unlock_bh(&mdb->tbl_lock);
 +						kfree_skb(skb);
 +						return;
 +					}
 +				}
-+				spin_unlock(&mdb->tbl_lock);
++				spin_unlock_bh(&mdb->tbl_lock);
 +			}
  			ovs_vport_send(vport, skb, ovs_key_mac_proto(key));
  		} else if (mru <= vport->dev->mtu) {
  			struct net *net = read_pnet(&dp->net);
 diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
-index 4c537e7..40b4795 100644
+index 4c537e7..e6787cc 100644
 --- a/net/openvswitch/datapath.c
 +++ b/net/openvswitch/datapath.c
 @@ -11,6 +11,9 @@
@@ -73,7 +73,7 @@
  #include <linux/jhash.h>
  #include <linux/delay.h>
  #include <linux/time.h>
-@@ -538,6 +541,270 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
+@@ -538,6 +541,271 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
  	return err;
  }
  
@@ -87,7 +87,7 @@
 +	int err;
 +
 +	mdb = input_vport->mdb;
-+	spin_lock(&mdb->tbl_lock);
++	spin_lock_bh(&mdb->tbl_lock);
 +	list_for_each_entry(table, &mdb->list_head, mdb_node) {
 +		if (!memcmp(&table->group_addr.u, &_group_addr->u, sizeof(struct ip_addr))) {
 +			list_for_each_entry(entry, &table->entry_list, entry_node) {
@@ -130,7 +130,7 @@
 +out:
 +	err = 0;
 +err:
-+	spin_unlock(&mdb->tbl_lock);
++	spin_unlock_bh(&mdb->tbl_lock);
 +	return err;
 +}
 +
@@ -144,7 +144,7 @@
 +	int err;
 +
 +	mdb = input_vport->mdb;
-+	spin_lock(&mdb->tbl_lock);
++	spin_lock_bh(&mdb->tbl_lock);
 +	list_for_each_entry_safe(table, table_tmp, &mdb->list_head, mdb_node) {
 +		if (!memcmp(&table->group_addr.u, &_group_addr->u, sizeof(struct ip_addr))) {
 +			list_for_each_entry_safe(entry, entry_tmp, &table->entry_list, entry_node) {
@@ -165,7 +165,7 @@
 +
 +out:
 +	err = 0;
-+	spin_unlock(&mdb->tbl_lock);
++	spin_unlock_bh(&mdb->tbl_lock);
 +	return err;
 +}
 +
@@ -232,7 +232,8 @@
 +				if (num_of_source == 0)
 +					ovs_multicast_leave_group(&group_addr, dl_src, input_vport);
 +
-+			grec += (8 + (num_of_source * 4) + aux_data_len);
++			grec = (struct igmpv3_grec *)((u8 *)grec + sizeof(struct igmpv3_grec)
++					+ aux_data_len * sizeof(u32));
 +		}
 +		break;
 +	case IGMP_HOST_MEMBERSHIP_QUERY:
@@ -344,7 +345,7 @@
  static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
  {
  	struct ovs_header *ovs_header = info->userhdr;
-@@ -612,6 +879,9 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
+@@ -612,6 +880,9 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
  	OVS_CB(packet)->input_vport = input_vport;
  	sf_acts = rcu_dereference(flow->sf_acts);
  
@@ -354,7 +355,7 @@
  	local_bh_disable();
  	err = ovs_execute_actions(dp, packet, sf_acts, &flow->key);
  	local_bh_enable();
-@@ -2199,6 +2469,9 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
+@@ -2199,6 +2470,9 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
  	struct datapath *dp;
  	struct vport *vport;
  	unsigned int new_headroom;
@@ -364,12 +365,12 @@
  	int err;
  
  	reply = ovs_vport_cmd_alloc_info();
-@@ -2226,6 +2499,22 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
+@@ -2226,6 +2500,22 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
  	if (netdev_get_fwd_headroom(vport->dev) == dp->max_headroom)
  		update_headroom = true;
  
 +	mdb = vport->mdb;
-+	spin_lock(&mdb->tbl_lock);
++	spin_lock_bh(&mdb->tbl_lock);
 +	list_for_each_entry_safe(table, table_tmp, &mdb->list_head, mdb_node) {
 +		list_for_each_entry_safe(entry, entry_tmp, &table->entry_list, entry_node) {
 +			list_del(&entry->entry_node);
@@ -381,7 +382,7 @@
 +			}
 +		}
 +	}
-+	spin_unlock(&mdb->tbl_lock);
++	spin_unlock_bh(&mdb->tbl_lock);
 +	kfree(mdb);
 +
  	netdev_reset_rx_headroom(vport->dev);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
index 661b93f..d51f24f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
@@ -6,7 +6,7 @@
 ---
  drivers/net/ethernet/mediatek/Makefile        |   2 +-
  drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  10 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  63 ++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  48 ++-
  drivers/net/ethernet/mediatek/mtk_ppe.c       |  48 +-
  drivers/net/ethernet/mediatek/mtk_ppe.h       |   4 +
  .../net/ethernet/mediatek/mtk_ppe_offload.c   |  28 +-
@@ -110,39 +110,6 @@
 index 101c233..7ea380e 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -400,10 +400,21 @@
- 
- /* QDMA TX Queue Configuration Registers */
- #define MTK_QTX_CFG(x)		(QDMA_BASE + (x * 0x10))
-+#define MTK_QTX_CFG_HW_RESV_CNT_OFFSET	GENMASK(15, 8)
-+#define MTK_QTX_CFG_SW_RESV_CNT_OFFSET	GENMASK(7, 0)
- #define QDMA_RES_THRES		4
- 
- /* QDMA TX Queue Scheduler Registers */
- #define MTK_QTX_SCH(x)		(QDMA_BASE + 4 + (x * 0x10))
-+#define MTK_QTX_SCH_TX_SCH_SEL		BIT(31)
-+#define MTK_QTX_SCH_TX_SCH_SEL_V2	GENMASK(31, 30)
-+#define MTK_QTX_SCH_MIN_RATE_EN		BIT(27)
-+#define MTK_QTX_SCH_MIN_RATE_MAN	GENMASK(26, 20)
-+#define MTK_QTX_SCH_MIN_RATE_EXP	GENMASK(19, 16)
-+#define MTK_QTX_SCH_MAX_RATE_WGHT	GENMASK(15, 12)
-+#define MTK_QTX_SCH_MAX_RATE_EN		BIT(11)
-+#define MTK_QTX_SCH_MAX_RATE_MAN	GENMASK(10, 4)
-+#define MTK_QTX_SCH_MAX_RATE_EXP	GENMASK(3, 0)
- 
- /* QDMA RX Base Pointer Register */
- #define MTK_QRX_BASE_PTR0	(QDMA_BASE + 0x100)
-@@ -421,7 +432,9 @@
- #define MTK_QRX_DRX_IDX0	(QDMA_BASE + 0x10c)
- 
- /* QDMA Page Configuration Register */
--#define MTK_QDMA_PAGE	(QDMA_BASE + 0x1f0)
-+#define MTK_QDMA_PAGE		(QDMA_BASE + 0x1f0)
-+#define MTK_QTX_CFG_PAGE	GENMASK(3, 0)
-+#define MTK_QTX_PER_PAGE	(16)
- 
- /* QDMA Global Configuration Register */
- #define MTK_QDMA_GLO_CFG	(QDMA_BASE + 0x204)
 @@ -458,6 +471,9 @@
  #define FC_THRES_DROP_EN	(7 << 16)
  #define FC_THRES_MIN		0x4444
@@ -428,7 +395,7 @@
 +		       FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP,  4) |
 +		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 25) |
 +		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP,  5) |
-+		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WGHT, 4);
++		       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 4);
 +
 +		writel(val, eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
 +	} else {
@@ -568,9 +535,9 @@
 +
 +		val = readl(eth->base + MTK_QTX_SCH(i % MTK_QTX_PER_PAGE));
 +		if (eth->soc->txrx.qdma_tx_sch == 4)
-+			scheduler = FIELD_GET(MTK_QTX_SCH_TX_SCH_SEL_V2, val);
++			scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, val);
 +		else
-+			scheduler = FIELD_GET(MTK_QTX_SCH_TX_SCH_SEL, val);
++			scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, val);
 +		if (id == scheduler)
 +			len += scnprintf(buf + len, buf_len - len, "%d  ", i);
 +	}
@@ -662,15 +629,15 @@
 +	qtx_cfg = readl(eth->base + MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
 +	qtx_sch = readl(eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
 +	if (eth->soc->txrx.qdma_tx_sch == 4)
-+		scheduler = FIELD_GET(MTK_QTX_SCH_TX_SCH_SEL_V2, qtx_sch);
++		scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, qtx_sch);
 +	else
-+		scheduler = FIELD_GET(MTK_QTX_SCH_TX_SCH_SEL, qtx_sch);
++		scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, qtx_sch);
 +
 +	min_rate_en  = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EN, qtx_sch);
 +	min_rate     = FIELD_GET(MTK_QTX_SCH_MIN_RATE_MAN, qtx_sch);
 +	min_rate_exp = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EXP, qtx_sch);
 +	max_rate_en  = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EN, qtx_sch);
-+	max_weight   = FIELD_GET(MTK_QTX_SCH_MAX_RATE_WGHT, qtx_sch);
++	max_weight   = FIELD_GET(MTK_QTX_SCH_MAX_RATE_WEIGHT, qtx_sch);
 +	max_rate     = FIELD_GET(MTK_QTX_SCH_MAX_RATE_MAN, qtx_sch);
 +	max_rate_exp = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EXP, qtx_sch);
 +	while (min_rate_exp--)
@@ -767,16 +734,16 @@
 +	writel(val, eth->base + MTK_QDMA_PAGE);
 +
 +	if (eth->soc->txrx.qdma_tx_sch == 4)
-+		val = FIELD_PREP(MTK_QTX_SCH_TX_SCH_SEL_V2, scheduler);
++		val = FIELD_PREP(MTK_QTX_SCH_TX_SEL_V2, scheduler);
 +	else
-+		val = FIELD_PREP(MTK_QTX_SCH_TX_SCH_SEL, scheduler);
++		val = FIELD_PREP(MTK_QTX_SCH_TX_SEL, scheduler);
 +	if (min_enable)
 +		val |= MTK_QTX_SCH_MIN_RATE_EN;
 +	val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, min_rate);
 +	val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, min_exp);
 +	if (max_enable)
 +		val |= MTK_QTX_SCH_MAX_RATE_EN;
-+	val |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WGHT, weight);
++	val |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, weight);
 +	val |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, max_rate);
 +	val |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, max_exp);
 +	writel(val, eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1401-v5.7-mtd-spinand-backport-winbond-and-base-file.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1401-v5.7-mtd-spinand-backport-winbond-and-base-file.patch
new file mode 100644
index 0000000..cd096d3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1401-v5.7-mtd-spinand-backport-winbond-and-base-file.patch
@@ -0,0 +1,369 @@
+Index: linux-5.4.260/drivers/mtd/nand/spi/core.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/core.c
++++ linux-5.4.260/drivers/mtd/nand/spi/core.c
+@@ -16,6 +16,7 @@
+ #include <linux/mtd/spinand.h>
+ #include <linux/of.h>
+ #include <linux/slab.h>
++#include <linux/string.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spi-mem.h>
+ 
+@@ -370,10 +371,11 @@ out:
+ 	return status & STATUS_BUSY ? -ETIMEDOUT : 0;
+ }
+ 
+-static int spinand_read_id_op(struct spinand_device *spinand, u8 *buf)
++static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr,
++			      u8 ndummy, u8 *buf)
+ {
+-	struct spi_mem_op op = SPINAND_READID_OP(0, spinand->scratchbuf,
+-						 SPINAND_MAX_ID_LEN);
++	struct spi_mem_op op = SPINAND_READID_OP(
++		naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN);
+ 	int ret;
+ 
+ 	ret = spi_mem_exec_op(spinand->spimem, &op);
+@@ -760,24 +762,62 @@ static const struct spinand_manufacturer
+ 	&winbond_spinand_manufacturer,
+ };
+ 
+-static int spinand_manufacturer_detect(struct spinand_device *spinand)
++static int spinand_manufacturer_match(struct spinand_device *spinand,
++				      enum spinand_readid_method rdid_method)
+ {
++	u8 *id = spinand->id.data;
+ 	unsigned int i;
+ 	int ret;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(spinand_manufacturers); i++) {
+-		ret = spinand_manufacturers[i]->ops->detect(spinand);
+-		if (ret > 0) {
+-			spinand->manufacturer = spinand_manufacturers[i];
+-			return 0;
+-		} else if (ret < 0) {
+-			return ret;
+-		}
+-	}
++		const struct spinand_manufacturer *manufacturer =
++			spinand_manufacturers[i];
++
++		if (id[0] != manufacturer->id)
++			continue;
+ 
++		ret = spinand_match_and_init(spinand,
++					     manufacturer->chips,
++					     manufacturer->nchips,
++					     rdid_method);
++		if (ret < 0)
++			continue;
++
++		spinand->manufacturer = manufacturer;
++		return 0;
++	}
+ 	return -ENOTSUPP;
+ }
+ 
++static int spinand_id_detect(struct spinand_device *spinand)
++{
++	u8 *id = spinand->id.data;
++	int ret;
++
++	ret = spinand_read_id_op(spinand, 0, 0, id);
++	if (ret)
++		return ret;
++	ret = spinand_manufacturer_match(spinand, SPINAND_READID_METHOD_OPCODE);
++	if (!ret)
++		return 0;
++
++	ret = spinand_read_id_op(spinand, 1, 0, id);
++	if (ret)
++		return ret;
++	ret = spinand_manufacturer_match(spinand,
++					 SPINAND_READID_METHOD_OPCODE_ADDR);
++	if (!ret)
++		return 0;
++
++	ret = spinand_read_id_op(spinand, 0, 1, id);
++	if (ret)
++		return ret;
++	ret = spinand_manufacturer_match(spinand,
++					 SPINAND_READID_METHOD_OPCODE_DUMMY);
++
++	return ret;
++}
++
+ static int spinand_manufacturer_init(struct spinand_device *spinand)
+ {
+ 	if (spinand->manufacturer->ops->init)
+@@ -833,9 +873,9 @@ spinand_select_op_variant(struct spinand
+  * @spinand: SPI NAND object
+  * @table: SPI NAND device description table
+  * @table_size: size of the device description table
++ * @rdid_method: read id method to match
+  *
+- * Should be used by SPI NAND manufacturer drivers when they want to find a
+- * match between a device ID retrieved through the READ_ID command and an
++ * Match between a device ID retrieved through the READ_ID command and an
+  * entry in the SPI NAND description table. If a match is found, the spinand
+  * object will be initialized with information provided by the matching
+  * spinand_info entry.
+@@ -844,8 +884,10 @@ spinand_select_op_variant(struct spinand
+  */
+ int spinand_match_and_init(struct spinand_device *spinand,
+ 			   const struct spinand_info *table,
+-			   unsigned int table_size, u16 devid)
++			   unsigned int table_size,
++			   enum spinand_readid_method rdid_method)
+ {
++	u8 *id = spinand->id.data;
+ 	struct nand_device *nand = spinand_to_nand(spinand);
+ 	unsigned int i;
+ 
+@@ -853,13 +895,17 @@ int spinand_match_and_init(struct spinan
+ 		const struct spinand_info *info = &table[i];
+ 		const struct spi_mem_op *op;
+ 
+-		if (devid != info->devid)
++		if (rdid_method != info->devid.method)
++			continue;
++
++		if (memcmp(id + 1, info->devid.id, info->devid.len))
+ 			continue;
+ 
+ 		nand->memorg = table[i].memorg;
+ 		nand->eccreq = table[i].eccreq;
+ 		spinand->eccinfo = table[i].eccinfo;
+ 		spinand->flags = table[i].flags;
++		spinand->id.len = 1 + table[i].devid.len;
+ 		spinand->select_target = table[i].select_target;
+ 
+ 		op = spinand_select_op_variant(spinand,
+@@ -896,13 +942,7 @@ static int spinand_detect(struct spinand
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = spinand_read_id_op(spinand, spinand->id.data);
+-	if (ret)
+-		return ret;
+-
+-	spinand->id.len = SPINAND_MAX_ID_LEN;
+-
+-	ret = spinand_manufacturer_detect(spinand);
++	ret = spinand_id_detect(spinand);
+ 	if (ret) {
+ 		dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN,
+ 			spinand->id.data);
+Index: linux-5.4.260/include/linux/mtd/spinand.h
+===================================================================
+--- linux-5.4.260.orig/include/linux/mtd/spinand.h
++++ linux-5.4.260/include/linux/mtd/spinand.h
+@@ -32,9 +32,9 @@
+ 		   SPI_MEM_OP_NO_DUMMY,					\
+ 		   SPI_MEM_OP_NO_DATA)
+ 
+-#define SPINAND_READID_OP(ndummy, buf, len)				\
++#define SPINAND_READID_OP(naddr, ndummy, buf, len)			\
+ 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1),				\
+-		   SPI_MEM_OP_NO_ADDR,					\
++		   SPI_MEM_OP_ADDR(naddr, 0, 1),			\
+ 		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
+ 		   SPI_MEM_OP_DATA_IN(len, buf, 1))
+ 
+@@ -176,37 +176,46 @@ struct spinand_device;
+  * @data: buffer containing the id bytes. Currently 4 bytes large, but can
+  *	  be extended if required
+  * @len: ID length
+- *
+- * struct_spinand_id->data contains all bytes returned after a READ_ID command,
+- * including dummy bytes if the chip does not emit ID bytes right after the
+- * READ_ID command. The responsibility to extract real ID bytes is left to
+- * struct_manufacurer_ops->detect().
+  */
+ struct spinand_id {
+ 	u8 data[SPINAND_MAX_ID_LEN];
+ 	int len;
+ };
+ 
++enum spinand_readid_method {
++	SPINAND_READID_METHOD_OPCODE,
++	SPINAND_READID_METHOD_OPCODE_ADDR,
++	SPINAND_READID_METHOD_OPCODE_DUMMY,
++};
++
++/**
++ * struct spinand_devid - SPI NAND device id structure
++ * @id: device id of current chip
++ * @len: number of bytes in device id
++ * @method: method to read chip id
++ *	    There are 3 possible variants:
++ *	    SPINAND_READID_METHOD_OPCODE: chip id is returned immediately
++ *	    after read_id opcode.
++ *	    SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after
++ *	    read_id opcode + 1-byte address.
++ *	    SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after
++ *	    read_id opcode + 1 dummy byte.
++ */
++struct spinand_devid {
++	const u8 *id;
++	const u8 len;
++	const enum spinand_readid_method method;
++};
++
+ /**
+  * struct manufacurer_ops - SPI NAND manufacturer specific operations
+- * @detect: detect a SPI NAND device. Every time a SPI NAND device is probed
+- *	    the core calls the struct_manufacurer_ops->detect() hook of each
+- *	    registered manufacturer until one of them return 1. Note that
+- *	    the first thing to check in this hook is that the manufacturer ID
+- *	    in struct_spinand_device->id matches the manufacturer whose
+- *	    ->detect() hook has been called. Should return 1 if there's a
+- *	    match, 0 if the manufacturer ID does not match and a negative
+- *	    error code otherwise. When true is returned, the core assumes
+- *	    that properties of the NAND chip (spinand->base.memorg and
+- *	    spinand->base.eccreq) have been filled
+  * @init: initialize a SPI NAND device
+  * @cleanup: cleanup a SPI NAND device
+  *
+  * Each SPI NAND manufacturer driver should implement this interface so that
+- * NAND chips coming from this vendor can be detected and initialized properly.
++ * NAND chips coming from this vendor can be initialized properly.
+  */
+ struct spinand_manufacturer_ops {
+-	int (*detect)(struct spinand_device *spinand);
+ 	int (*init)(struct spinand_device *spinand);
+ 	void (*cleanup)(struct spinand_device *spinand);
+ };
+@@ -215,11 +224,16 @@ struct spinand_manufacturer_ops {
+  * struct spinand_manufacturer - SPI NAND manufacturer instance
+  * @id: manufacturer ID
+  * @name: manufacturer name
++ * @devid_len: number of bytes in device ID
++ * @chips: supported SPI NANDs under current manufacturer
++ * @nchips: number of SPI NANDs available in chips array
+  * @ops: manufacturer operations
+  */
+ struct spinand_manufacturer {
+ 	u8 id;
+ 	char *name;
++	const struct spinand_info *chips;
++	const size_t nchips;
+ 	const struct spinand_manufacturer_ops *ops;
+ };
+ 
+@@ -270,6 +284,7 @@ struct spinand_ecc_info {
+ };
+ 
+ #define SPINAND_HAS_QE_BIT		BIT(0)
++#define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
+ 
+ /**
+  * struct spinand_info - Structure used to describe SPI NAND chips
+@@ -291,7 +306,7 @@ struct spinand_ecc_info {
+  */
+ struct spinand_info {
+ 	const char *model;
+-	u16 devid;
++	struct spinand_devid devid;
+ 	u32 flags;
+ 	struct nand_memory_organization memorg;
+ 	struct nand_ecc_req eccreq;
+@@ -305,6 +320,13 @@ struct spinand_info {
+ 			     unsigned int target);
+ };
+ 
++#define SPINAND_ID(__method, ...)					\
++	{								\
++		.id = (const u8[]){ __VA_ARGS__ },			\
++		.len = sizeof((u8[]){ __VA_ARGS__ }),			\
++		.method = __method,					\
++	}
++
+ #define SPINAND_INFO_OP_VARIANTS(__read, __write, __update)		\
+ 	{								\
+ 		.read_cache = __read,					\
+@@ -451,9 +473,10 @@ static inline void spinand_set_of_node(s
+ 	nanddev_set_of_node(&spinand->base, np);
+ }
+ 
+-int spinand_match_and_init(struct spinand_device *dev,
++int spinand_match_and_init(struct spinand_device *spinand,
+ 			   const struct spinand_info *table,
+-			   unsigned int table_size, u16 devid);
++			   unsigned int table_size,
++			   enum spinand_readid_method rdid_method);
+ 
+ int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
+ int spinand_select_target(struct spinand_device *spinand, unsigned int target);
+Index: linux-5.4.260/drivers/mtd/nand/spi/winbond.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/winbond.c
++++ linux-5.4.260/drivers/mtd/nand/spi/winbond.c
+@@ -75,7 +75,8 @@ static int w25m02gv_select_target(struct
+ }
+ 
+ static const struct spinand_info winbond_spinand_table[] = {
+-	SPINAND_INFO("W25M02GV", 0xAB,
++	SPINAND_INFO("W25M02GV",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
+ 		     NAND_ECCREQ(1, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -84,7 +85,8 @@ static const struct spinand_info winbond
+ 		     0,
+ 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
+ 		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
+-	SPINAND_INFO("W25N01GV", 0xAA,
++	SPINAND_INFO("W25N01GV",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ 		     NAND_ECCREQ(1, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -94,31 +96,6 @@ static const struct spinand_info winbond
+ 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+ };
+ 
+-/**
+- * winbond_spinand_detect - initialize device related part in spinand_device
+- * struct if it is a Winbond device.
+- * @spinand: SPI NAND device structure
+- */
+-static int winbond_spinand_detect(struct spinand_device *spinand)
+-{
+-	u8 *id = spinand->id.data;
+-	int ret;
+-
+-	/*
+-	 * Winbond SPI NAND read ID need a dummy byte,
+-	 * so the first byte in raw_id is dummy.
+-	 */
+-	if (id[1] != SPINAND_MFR_WINBOND)
+-		return 0;
+-
+-	ret = spinand_match_and_init(spinand, winbond_spinand_table,
+-				     ARRAY_SIZE(winbond_spinand_table), id[2]);
+-	if (ret)
+-		return ret;
+-
+-	return 1;
+-}
+-
+ static int winbond_spinand_init(struct spinand_device *spinand)
+ {
+ 	struct nand_device *nand = spinand_to_nand(spinand);
+@@ -138,12 +115,13 @@ static int winbond_spinand_init(struct s
+ }
+ 
+ static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
+-	.detect = winbond_spinand_detect,
+ 	.init = winbond_spinand_init,
+ };
+ 
+ const struct spinand_manufacturer winbond_spinand_manufacturer = {
+ 	.id = SPINAND_MFR_WINBOND,
+ 	.name = "Winbond",
++	.chips = winbond_spinand_table,
++	.nchips = ARRAY_SIZE(winbond_spinand_table),
+ 	.ops = &winbond_spinand_manuf_ops,
+ };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch
new file mode 100644
index 0000000..df4f9f9
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1402-v6.4-mtd-spinand-backport-series-flash.patch
@@ -0,0 +1,1333 @@
+Index: linux-5.4.260/drivers/mtd/nand/spi/gigadevice.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/gigadevice.c
++++ linux-5.4.260/drivers/mtd/nand/spi/gigadevice.c
+@@ -13,7 +13,10 @@
+ #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS	(1 << 4)
+ #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS	(3 << 4)
+ 
+-#define GD5FXGQ4UEXXG_REG_STATUS2		0xf0
++#define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS	(1 << 4)
++#define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS	(3 << 4)
++
++#define GD5FXGQXXEXXG_REG_STATUS2		0xf0
+ 
+ #define GD5FXGQ4UXFXXG_STATUS_ECC_MASK		(7 << 4)
+ #define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS	(0 << 4)
+@@ -36,6 +39,22 @@ static SPINAND_OP_VARIANTS(read_cache_va
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
+ 
++static SPINAND_OP_VARIANTS(read_cache_variants_1gq5,
++		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
++static SPINAND_OP_VARIANTS(read_cache_variants_2gq5,
++		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
+ static SPINAND_OP_VARIANTS(write_cache_variants,
+ 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+ 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+@@ -102,7 +121,7 @@ static int gd5fxgq4xa_ecc_get_status(str
+ 	return -EINVAL;
+ }
+ 
+-static int gd5fxgq4_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
++static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
+ 				       struct mtd_oob_region *region)
+ {
+ 	if (section)
+@@ -114,7 +133,7 @@ static int gd5fxgq4_variant2_ooblayout_e
+ 	return 0;
+ }
+ 
+-static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
++static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
+ 					struct mtd_oob_region *region)
+ {
+ 	if (section)
+@@ -127,16 +146,46 @@ static int gd5fxgq4_variant2_ooblayout_f
+ 	return 0;
+ }
+ 
+-static const struct mtd_ooblayout_ops gd5fxgq4_variant2_ooblayout = {
+-	.ecc = gd5fxgq4_variant2_ooblayout_ecc,
+-	.free = gd5fxgq4_variant2_ooblayout_free,
++/* Valid for Q4/Q5 and Q6 (untested) devices */
++static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
++	.ecc = gd5fxgqx_variant2_ooblayout_ecc,
++	.free = gd5fxgqx_variant2_ooblayout_free,
++};
++
++static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
++					struct mtd_oob_region *oobregion)
++{
++	if (section)
++		return -ERANGE;
++
++	oobregion->offset = 128;
++	oobregion->length = 128;
++
++	return 0;
++}
++
++static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section,
++					 struct mtd_oob_region *oobregion)
++{
++	if (section)
++		return -ERANGE;
++
++	oobregion->offset = 1;
++	oobregion->length = 127;
++
++	return 0;
++}
++
++static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = {
++	.ecc = gd5fxgq4xc_ooblayout_256_ecc,
++	.free = gd5fxgq4xc_ooblayout_256_free,
+ };
+ 
+ static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
+ 					u8 status)
+ {
+ 	u8 status2;
+-	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4UEXXG_REG_STATUS2,
++	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
+ 						      &status2);
+ 	int ret;
+ 
+@@ -174,6 +223,43 @@ static int gd5fxgq4uexxg_ecc_get_status(
+ 	return -EINVAL;
+ }
+ 
++static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
++					u8 status)
++{
++	u8 status2;
++	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
++						      &status2);
++	int ret;
++
++	switch (status & STATUS_ECC_MASK) {
++	case STATUS_ECC_NO_BITFLIPS:
++		return 0;
++
++	case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
++		/*
++		 * Read status2 register to determine a more fine grained
++		 * bit error status
++		 */
++		ret = spi_mem_exec_op(spinand->spimem, &op);
++		if (ret)
++			return ret;
++
++		/*
++		 * 1 ... 4 bits are flipped (and corrected)
++		 */
++		/* bits sorted this way (1...0): ECCSE1, ECCSE0 */
++		return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
++
++	case STATUS_ECC_UNCOR_ERROR:
++		return -EBADMSG;
++
++	default:
++		break;
++	}
++
++	return -EINVAL;
++}
++
+ static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
+ 					u8 status)
+ {
+@@ -195,7 +281,8 @@ static int gd5fxgq4ufxxg_ecc_get_status(
+ }
+ 
+ static const struct spinand_info gigadevice_spinand_table[] = {
+-	SPINAND_INFO("GD5F1GQ4xA", 0xF1,
++	SPINAND_INFO("GD5F1GQ4xA",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -204,7 +291,8 @@ static const struct spinand_info gigadev
+ 		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
+ 				     gd5fxgq4xa_ecc_get_status)),
+-	SPINAND_INFO("GD5F2GQ4xA", 0xF2,
++	SPINAND_INFO("GD5F2GQ4xA",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -213,7 +301,8 @@ static const struct spinand_info gigadev
+ 		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
+ 				     gd5fxgq4xa_ecc_get_status)),
+-	SPINAND_INFO("GD5F4GQ4xA", 0xF4,
++	SPINAND_INFO("GD5F4GQ4xA",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -222,59 +311,205 @@ static const struct spinand_info gigadev
+ 		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
+ 				     gd5fxgq4xa_ecc_get_status)),
+-	SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
++	SPINAND_INFO("GD5F4GQ4RC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
++				     gd5fxgq4ufxxg_ecc_get_status)),
++	SPINAND_INFO("GD5F4GQ4UC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
++				     gd5fxgq4ufxxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GQ4UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GQ4RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     SPINAND_HAS_QE_BIT,
+-		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F2GQ4UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
+ 				     gd5fxgq4uexxg_ecc_get_status)),
+-	SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148,
++	SPINAND_INFO("GD5F2GQ4RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GQ4UFxxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     SPINAND_HAS_QE_BIT,
+-		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
+ 				     gd5fxgq4ufxxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GQ5UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq5xexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GQ5RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq5xexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F2GQ5UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq5xexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F2GQ5RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq5xexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F4GQ6UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq5xexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F4GQ6RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq5xexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GM7UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GM7RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F2GM7UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F2GM7RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F4GM8UExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95),
++		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F4GM8RExxG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85),
++		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
++				     gd5fxgq4uexxg_ecc_get_status)),
+ };
+ 
+-static int gigadevice_spinand_detect(struct spinand_device *spinand)
+-{
+-	u8 *id = spinand->id.data;
+-	u16 did;
+-	int ret;
+-
+-	/*
+-	 * Earlier GDF5-series devices (A,E) return [0][MID][DID]
+-	 * Later (F) devices return [MID][DID1][DID2]
+-	 */
+-
+-	if (id[0] == SPINAND_MFR_GIGADEVICE)
+-		did = (id[1] << 8) + id[2];
+-	else if (id[0] == 0 && id[1] == SPINAND_MFR_GIGADEVICE)
+-		did = id[2];
+-	else
+-		return 0;
+-
+-	ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
+-				     ARRAY_SIZE(gigadevice_spinand_table),
+-				     did);
+-	if (ret)
+-		return ret;
+-
+-	return 1;
+-}
+-
+ static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
+-	.detect = gigadevice_spinand_detect,
+ };
+ 
+ const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
+ 	.id = SPINAND_MFR_GIGADEVICE,
+ 	.name = "GigaDevice",
++	.chips = gigadevice_spinand_table,
++	.nchips = ARRAY_SIZE(gigadevice_spinand_table),
+ 	.ops = &gigadevice_spinand_manuf_ops,
+ };
+Index: linux-5.4.260/drivers/mtd/nand/spi/macronix.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/macronix.c
++++ linux-5.4.260/drivers/mtd/nand/spi/macronix.c
+@@ -99,7 +99,8 @@ static int mx35lf1ge4ab_ecc_get_status(s
+ }
+ 
+ static const struct spinand_info macronix_spinand_table[] = {
+-	SPINAND_INFO("MX35LF1GE4AB", 0x12,
++	SPINAND_INFO("MX35LF1GE4AB",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ 		     NAND_ECCREQ(4, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -108,7 +109,8 @@ static const struct spinand_info macroni
+ 		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+ 				     mx35lf1ge4ab_ecc_get_status)),
+-	SPINAND_INFO("MX35LF2GE4AB", 0x22,
++	SPINAND_INFO("MX35LF2GE4AB",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
+ 		     NAND_ECCREQ(4, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -116,51 +118,194 @@ static const struct spinand_info macroni
+ 					      &update_cache_variants),
+ 		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
+-	SPINAND_INFO("MX35LF2GE4AD", 0x26,
++	SPINAND_INFO("MX35LF2GE4AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26),
+ 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35LF4GE4AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37),
++		     NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35LF1G24AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
+-	SPINAND_INFO("MX35LF4GE4AD", 0x37,
+-		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++	SPINAND_INFO("MX35LF2G24AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     SPINAND_HAS_QE_BIT,
+ 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
+-};
+-
+-static int macronix_spinand_detect(struct spinand_device *spinand)
+-{
+-	u8 *id = spinand->id.data;
+-	int ret;
+-
+-	/*
+-	 * Macronix SPI NAND read ID needs a dummy byte, so the first byte in
+-	 * raw_id is garbage.
+-	 */
+-	if (id[1] != SPINAND_MFR_MACRONIX)
+-		return 0;
++	SPINAND_INFO("MX35LF4G24AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
++	SPINAND_INFO("MX31LF1GE4BC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
++		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX31UF1GE4BC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),
++		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
+ 
+-	ret = spinand_match_and_init(spinand, macronix_spinand_table,
+-				     ARRAY_SIZE(macronix_spinand_table),
+-				     id[2]);
+-	if (ret)
+-		return ret;
++	SPINAND_INFO("MX35LF2G14AC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20),
++		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF4G24AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF4GE4AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF2G14AC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0),
++		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF2G24AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF2GE4AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF2GE4AC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2),
++		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF1G14AC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90),
++		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF1G24AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF1GE4AD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
++	SPINAND_INFO("MX35UF1GE4AC",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
++		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++				     mx35lf1ge4ab_ecc_get_status)),
+ 
+-	return 1;
+-}
++};
+ 
+ static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
+-	.detect = macronix_spinand_detect,
+ };
+ 
+ const struct spinand_manufacturer macronix_spinand_manufacturer = {
+ 	.id = SPINAND_MFR_MACRONIX,
+ 	.name = "Macronix",
++	.chips = macronix_spinand_table,
++	.nchips = ARRAY_SIZE(macronix_spinand_table),
+ 	.ops = &macronix_spinand_manuf_ops,
+ };
+Index: linux-5.4.260/drivers/mtd/nand/spi/micron.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/micron.c
++++ linux-5.4.260/drivers/mtd/nand/spi/micron.c
+@@ -12,13 +12,23 @@
+ 
+ #define SPINAND_MFR_MICRON		0x2c
+ 
+-#define MICRON_STATUS_ECC_MASK		GENMASK(6, 4)
++#define MICRON_STATUS_ECC_MASK		GENMASK(7, 4)
+ #define MICRON_STATUS_ECC_NO_BITFLIPS	(0 << 4)
+ #define MICRON_STATUS_ECC_1TO3_BITFLIPS	(1 << 4)
+ #define MICRON_STATUS_ECC_4TO6_BITFLIPS	(3 << 4)
+ #define MICRON_STATUS_ECC_7TO8_BITFLIPS	(5 << 4)
+ 
+-static SPINAND_OP_VARIANTS(read_cache_variants,
++#define MICRON_CFG_CR			BIT(0)
++
++/*
++ * As per datasheet, die selection is done by the 6th bit of Die
++ * Select Register (Address 0xD0).
++ */
++#define MICRON_DIE_SELECT_REG	0xD0
++
++#define MICRON_SELECT_DIE(x)	((x) << 6)
++
++static SPINAND_OP_VARIANTS(quadio_read_cache_variants,
+ 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+@@ -26,46 +36,114 @@ static SPINAND_OP_VARIANTS(read_cache_va
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+ 
+-static SPINAND_OP_VARIANTS(write_cache_variants,
++static SPINAND_OP_VARIANTS(x4_write_cache_variants,
+ 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+ 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+ 
+-static SPINAND_OP_VARIANTS(update_cache_variants,
++static SPINAND_OP_VARIANTS(x4_update_cache_variants,
+ 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+ 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
+ 
+-static int mt29f2g01abagd_ooblayout_ecc(struct mtd_info *mtd, int section,
+-					struct mtd_oob_region *region)
++/* Micron  MT29F2G01AAAED Device */
++static SPINAND_OP_VARIANTS(x4_read_cache_variants,
++			   SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++			   SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++			   SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++			   SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
++static SPINAND_OP_VARIANTS(x1_write_cache_variants,
++			   SPINAND_PROG_LOAD(true, 0, NULL, 0));
++
++static SPINAND_OP_VARIANTS(x1_update_cache_variants,
++			   SPINAND_PROG_LOAD(false, 0, NULL, 0));
++
++static int micron_8_ooblayout_ecc(struct mtd_info *mtd, int section,
++				  struct mtd_oob_region *region)
+ {
+ 	if (section)
+ 		return -ERANGE;
+ 
+-	region->offset = 64;
+-	region->length = 64;
++	region->offset = mtd->oobsize / 2;
++	region->length = mtd->oobsize / 2;
+ 
+ 	return 0;
+ }
+ 
+-static int mt29f2g01abagd_ooblayout_free(struct mtd_info *mtd, int section,
+-					 struct mtd_oob_region *region)
++static int micron_8_ooblayout_free(struct mtd_info *mtd, int section,
++				   struct mtd_oob_region *region)
+ {
+ 	if (section)
+ 		return -ERANGE;
+ 
+ 	/* Reserve 2 bytes for the BBM. */
+ 	region->offset = 2;
+-	region->length = 62;
++	region->length = (mtd->oobsize / 2) - 2;
++
++	return 0;
++}
++
++static const struct mtd_ooblayout_ops micron_8_ooblayout = {
++	.ecc = micron_8_ooblayout_ecc,
++	.free = micron_8_ooblayout_free,
++};
++
++static int micron_4_ooblayout_ecc(struct mtd_info *mtd, int section,
++				  struct mtd_oob_region *region)
++{
++	struct spinand_device *spinand = mtd_to_spinand(mtd);
++
++	if (section >= spinand->base.memorg.pagesize /
++			mtd->ecc_step_size)
++		return -ERANGE;
++
++	region->offset = (section * 16) + 8;
++	region->length = 8;
++
++	return 0;
++}
++
++static int micron_4_ooblayout_free(struct mtd_info *mtd, int section,
++				   struct mtd_oob_region *region)
++{
++	struct spinand_device *spinand = mtd_to_spinand(mtd);
++
++	if (section >= spinand->base.memorg.pagesize /
++			mtd->ecc_step_size)
++		return -ERANGE;
++
++	if (section) {
++		region->offset = 16 * section;
++		region->length = 8;
++	} else {
++		/* section 0 has two bytes reserved for the BBM */
++		region->offset = 2;
++		region->length = 6;
++	}
+ 
+ 	return 0;
+ }
+ 
+-static const struct mtd_ooblayout_ops mt29f2g01abagd_ooblayout = {
+-	.ecc = mt29f2g01abagd_ooblayout_ecc,
+-	.free = mt29f2g01abagd_ooblayout_free,
++static const struct mtd_ooblayout_ops micron_4_ooblayout = {
++	.ecc = micron_4_ooblayout_ecc,
++	.free = micron_4_ooblayout_free,
+ };
+ 
+-static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand,
+-					 u8 status)
++static int micron_select_target(struct spinand_device *spinand,
++				unsigned int target)
++{
++	struct spi_mem_op op = SPINAND_SET_FEATURE_OP(MICRON_DIE_SELECT_REG,
++						      spinand->scratchbuf);
++
++	if (target > 1)
++		return -EINVAL;
++
++	*spinand->scratchbuf = MICRON_SELECT_DIE(target);
++
++	return spi_mem_exec_op(spinand->spimem, &op);
++}
++
++static int micron_8_ecc_get_status(struct spinand_device *spinand,
++				   u8 status)
+ {
+ 	switch (status & MICRON_STATUS_ECC_MASK) {
+ 	case STATUS_ECC_NO_BITFLIPS:
+@@ -91,43 +169,141 @@ static int mt29f2g01abagd_ecc_get_status
+ }
+ 
+ static const struct spinand_info micron_spinand_table[] = {
+-	SPINAND_INFO("MT29F2G01ABAGD", 0x24,
++	/* M79A 2Gb 3.3V */
++	SPINAND_INFO("MT29F2G01ABAGD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+-		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+-					      &write_cache_variants,
+-					      &update_cache_variants),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status)),
++	/* M79A 2Gb 1.8V */
++	SPINAND_INFO("MT29F2G01ABBGD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status)),
++	/* M78A 1Gb 3.3V */
++	SPINAND_INFO("MT29F1G01ABAFD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status)),
++	/* M78A 1Gb 1.8V */
++	SPINAND_INFO("MT29F1G01ABAFD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status)),
++	/* M79A 4Gb 3.3V */
++	SPINAND_INFO("MT29F4G01ADAGD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x36),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 80, 2, 1, 2),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status),
++		     SPINAND_SELECT_TARGET(micron_select_target)),
++	/* M70A 4Gb 3.3V */
++	SPINAND_INFO("MT29F4G01ABAFD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     SPINAND_HAS_CR_FEAT_BIT,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status)),
++	/* M70A 4Gb 1.8V */
++	SPINAND_INFO("MT29F4G01ABBFD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     SPINAND_HAS_CR_FEAT_BIT,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status)),
++	/* M70A 8Gb 3.3V */
++	SPINAND_INFO("MT29F8G01ADAFD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x46),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     SPINAND_HAS_CR_FEAT_BIT,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status),
++		     SPINAND_SELECT_TARGET(micron_select_target)),
++	/* M70A 8Gb 1.8V */
++	SPINAND_INFO("MT29F8G01ADBFD",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x47),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
++					      &x4_write_cache_variants,
++					      &x4_update_cache_variants),
++		     SPINAND_HAS_CR_FEAT_BIT,
++		     SPINAND_ECCINFO(&micron_8_ooblayout,
++				     micron_8_ecc_get_status),
++		     SPINAND_SELECT_TARGET(micron_select_target)),
++	/* M69A 2Gb 3.3V */
++	SPINAND_INFO("MT29F2G01AAAED",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9F),
++		     NAND_MEMORG(1, 2048, 64, 64, 2048, 80, 2, 1, 1),
++		     NAND_ECCREQ(4, 512),
++		     SPINAND_INFO_OP_VARIANTS(&x4_read_cache_variants,
++					      &x1_write_cache_variants,
++					      &x1_update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&mt29f2g01abagd_ooblayout,
+-				     mt29f2g01abagd_ecc_get_status)),
++		     SPINAND_ECCINFO(&micron_4_ooblayout, NULL)),
+ };
+ 
+-static int micron_spinand_detect(struct spinand_device *spinand)
++static int micron_spinand_init(struct spinand_device *spinand)
+ {
+-	u8 *id = spinand->id.data;
+-	int ret;
+-
+ 	/*
+-	 * Micron SPI NAND read ID need a dummy byte,
+-	 * so the first byte in raw_id is dummy.
++	 * M70A device series enable Continuous Read feature at Power-up,
++	 * which is not supported. Disable this bit to avoid any possible
++	 * failure.
+ 	 */
+-	if (id[1] != SPINAND_MFR_MICRON)
+-		return 0;
+-
+-	ret = spinand_match_and_init(spinand, micron_spinand_table,
+-				     ARRAY_SIZE(micron_spinand_table), id[2]);
+-	if (ret)
+-		return ret;
++	if (spinand->flags & SPINAND_HAS_CR_FEAT_BIT)
++		return spinand_upd_cfg(spinand, MICRON_CFG_CR, 0);
+ 
+-	return 1;
++	return 0;
+ }
+ 
+ static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
+-	.detect = micron_spinand_detect,
++	.init = micron_spinand_init,
+ };
+ 
+ const struct spinand_manufacturer micron_spinand_manufacturer = {
+ 	.id = SPINAND_MFR_MICRON,
+ 	.name = "Micron",
++	.chips = micron_spinand_table,
++	.nchips = ARRAY_SIZE(micron_spinand_table),
+ 	.ops = &micron_spinand_manuf_ops,
+ };
+Index: linux-5.4.260/drivers/mtd/nand/spi/paragon.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/paragon.c
++++ linux-5.4.260/drivers/mtd/nand/spi/paragon.c
+@@ -97,7 +97,8 @@ static const struct mtd_ooblayout_ops pn
+ 
+ 
+ static const struct spinand_info paragon_spinand_table[] = {
+-	SPINAND_INFO("PN26G01A", 0xe1,
++	SPINAND_INFO("PN26G01A",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe1),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -106,7 +107,8 @@ static const struct spinand_info paragon
+ 		     0,
+ 		     SPINAND_ECCINFO(&pn26g0xa_ooblayout,
+ 				     pn26g0xa_ecc_get_status)),
+-	SPINAND_INFO("PN26G02A", 0xe2,
++	SPINAND_INFO("PN26G02A",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe2),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -117,31 +119,13 @@ static const struct spinand_info paragon
+ 				     pn26g0xa_ecc_get_status)),
+ };
+ 
+-static int paragon_spinand_detect(struct spinand_device *spinand)
+-{
+-	u8 *id = spinand->id.data;
+-	int ret;
+-
+-	/* Read ID returns [0][MID][DID] */
+-
+-	if (id[1] != SPINAND_MFR_PARAGON)
+-		return 0;
+-
+-	ret = spinand_match_and_init(spinand, paragon_spinand_table,
+-				     ARRAY_SIZE(paragon_spinand_table),
+-				     id[2]);
+-	if (ret)
+-		return ret;
+-
+-	return 1;
+-}
+-
+ static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = {
+-	.detect = paragon_spinand_detect,
+ };
+ 
+ const struct spinand_manufacturer paragon_spinand_manufacturer = {
+ 	.id = SPINAND_MFR_PARAGON,
+ 	.name = "Paragon",
++	.chips = paragon_spinand_table,
++	.nchips = ARRAY_SIZE(paragon_spinand_table),
+ 	.ops = &paragon_spinand_manuf_ops,
+ };
+Index: linux-5.4.260/drivers/mtd/nand/spi/toshiba.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/toshiba.c
++++ linux-5.4.260/drivers/mtd/nand/spi/toshiba.c
+@@ -10,6 +10,7 @@
+ #include <linux/kernel.h>
+ #include <linux/mtd/spinand.h>
+ 
++/* Kioxia is new name of Toshiba memory. */
+ #define SPINAND_MFR_TOSHIBA		0x98
+ #define TOSH_STATUS_ECC_HAS_BITFLIPS_T	(3 << 4)
+ 
+@@ -19,14 +20,26 @@ static SPINAND_OP_VARIANTS(read_cache_va
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+ 
++static SPINAND_OP_VARIANTS(write_cache_x4_variants,
++		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
++		SPINAND_PROG_LOAD(true, 0, NULL, 0));
++
++static SPINAND_OP_VARIANTS(update_cache_x4_variants,
++		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
++		SPINAND_PROG_LOAD(false, 0, NULL, 0));
++
++/*
++ * Backward compatibility for 1st generation Serial NAND devices
++ * which don't support Quad Program Load operation.
++ */
+ static SPINAND_OP_VARIANTS(write_cache_variants,
+ 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+ 
+ static SPINAND_OP_VARIANTS(update_cache_variants,
+ 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
+ 
+-static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section,
+-				     struct mtd_oob_region *region)
++static int tx58cxgxsxraix_ooblayout_ecc(struct mtd_info *mtd, int section,
++					struct mtd_oob_region *region)
+ {
+ 	if (section > 0)
+ 		return -ERANGE;
+@@ -37,8 +50,8 @@ static int tc58cxgxsx_ooblayout_ecc(stru
+ 	return 0;
+ }
+ 
+-static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section,
+-				      struct mtd_oob_region *region)
++static int tx58cxgxsxraix_ooblayout_free(struct mtd_info *mtd, int section,
++					 struct mtd_oob_region *region)
+ {
+ 	if (section > 0)
+ 		return -ERANGE;
+@@ -50,13 +63,13 @@ static int tc58cxgxsx_ooblayout_free(str
+ 	return 0;
+ }
+ 
+-static const struct mtd_ooblayout_ops tc58cxgxsx_ooblayout = {
+-	.ecc = tc58cxgxsx_ooblayout_ecc,
+-	.free = tc58cxgxsx_ooblayout_free,
++static const struct mtd_ooblayout_ops tx58cxgxsxraix_ooblayout = {
++	.ecc = tx58cxgxsxraix_ooblayout_ecc,
++	.free = tx58cxgxsxraix_ooblayout_free,
+ };
+ 
+-static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
+-				      u8 status)
++static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
++					 u8 status)
+ {
+ 	struct nand_device *nand = spinand_to_nand(spinand);
+ 	u8 mbf = 0;
+@@ -94,95 +107,174 @@ static int tc58cxgxsx_ecc_get_status(str
+ }
+ 
+ static const struct spinand_info toshiba_spinand_table[] = {
+-	/* 3.3V 1Gb */
+-	SPINAND_INFO("TC58CVG0S3", 0xC2,
++	/* 3.3V 1Gb (1st generation) */
++	SPINAND_INFO("TC58CVG0S3HRAIG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+-				     tc58cxgxsx_ecc_get_status)),
+-	/* 3.3V 2Gb */
+-	SPINAND_INFO("TC58CVG1S3", 0xCB,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 3.3V 2Gb (1st generation) */
++	SPINAND_INFO("TC58CVG1S3HRAIG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+-				     tc58cxgxsx_ecc_get_status)),
+-	/* 3.3V 4Gb */
+-	SPINAND_INFO("TC58CVG2S0", 0xCD,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 3.3V 4Gb (1st generation) */
++	SPINAND_INFO("TC58CVG2S0HRAIG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
+ 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+-				     tc58cxgxsx_ecc_get_status)),
+-	/* 1.8V 1Gb */
+-	SPINAND_INFO("TC58CYG0S3", 0xB2,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 1.8V 1Gb (1st generation) */
++	SPINAND_INFO("TC58CYG0S3HRAIG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+-				     tc58cxgxsx_ecc_get_status)),
+-	/* 1.8V 2Gb */
+-	SPINAND_INFO("TC58CYG1S3", 0xBB,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 1.8V 2Gb (1st generation) */
++	SPINAND_INFO("TC58CYG1S3HRAIG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
+ 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+-				     tc58cxgxsx_ecc_get_status)),
+-	/* 1.8V 4Gb */
+-	SPINAND_INFO("TC58CYG2S0", 0xBD,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 1.8V 4Gb (1st generation) */
++	SPINAND_INFO("TC58CYG2S0HRAIG",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
+ 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
+-				     tc58cxgxsx_ecc_get_status)),
+-};
+-
+-static int toshiba_spinand_detect(struct spinand_device *spinand)
+-{
+-	u8 *id = spinand->id.data;
+-	int ret;
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
+ 
+ 	/*
+-	 * Toshiba SPI NAND read ID needs a dummy byte,
+-	 * so the first byte in id is garbage.
++	 * 2nd generation serial nand has HOLD_D which is equivalent to
++	 * QE_BIT.
+ 	 */
+-	if (id[1] != SPINAND_MFR_TOSHIBA)
+-		return 0;
+-
+-	ret = spinand_match_and_init(spinand, toshiba_spinand_table,
+-				     ARRAY_SIZE(toshiba_spinand_table),
+-				     id[2]);
+-	if (ret)
+-		return ret;
+-
+-	return 1;
+-}
++	/* 3.3V 1Gb (2nd generation) */
++	SPINAND_INFO("TC58CVG0S3HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 3.3V 2Gb (2nd generation) */
++	SPINAND_INFO("TC58CVG1S3HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 3.3V 4Gb (2nd generation) */
++	SPINAND_INFO("TC58CVG2S0HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 3.3V 8Gb (2nd generation) */
++	SPINAND_INFO("TH58CVG3S0HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
++		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 1.8V 1Gb (2nd generation) */
++	SPINAND_INFO("TC58CYG0S3HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 1.8V 2Gb (2nd generation) */
++	SPINAND_INFO("TC58CYG1S3HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 1.8V 4Gb (2nd generation) */
++	SPINAND_INFO("TC58CYG2S0HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD),
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++	/* 1.8V 8Gb (2nd generation) */
++	SPINAND_INFO("TH58CYG3S0HRAIJ",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
++		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_x4_variants,
++					      &update_cache_x4_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
++				     tx58cxgxsxraix_ecc_get_status)),
++};
+ 
+ static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
+-	.detect = toshiba_spinand_detect,
+ };
+ 
+ const struct spinand_manufacturer toshiba_spinand_manufacturer = {
+ 	.id = SPINAND_MFR_TOSHIBA,
+ 	.name = "Toshiba",
++	.chips = toshiba_spinand_table,
++	.nchips = ARRAY_SIZE(toshiba_spinand_table),
+ 	.ops = &toshiba_spinand_manuf_ops,
+ };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1710-v6.2-net-phy-add-phylink-pcs-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1710-v6.2-net-phy-add-phylink-pcs-support.patch
index 8f298c3..7fbee96 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1710-v6.2-net-phy-add-phylink-pcs-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1710-v6.2-net-phy-add-phylink-pcs-support.patch
@@ -1,16 +1,15 @@
-From 45878f8001b0ad75c5497a999a43b5901c1e03a6 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:01 +0800
-Subject: [PATCH] 
- [backport-networking-drivers][999-1710-net-phy-add-phylink-pcs-support.patch]
+From 1aa4cb223c39201c1158579d291731ae3f93b322 Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Thu, 11 Jan 2024 13:30:30 +0800
+Subject: [PATCH] 999-1710-v6.2-net-phy-add-phylink-pcs-support.patch
 
 ---
- drivers/net/phy/phylink.c | 306 ++++++++++++++++++++++++++++++--------
- include/linux/phylink.h   | 195 ++++++++++++++++++++++++
- 2 files changed, 443 insertions(+), 58 deletions(-)
+ drivers/net/phy/phylink.c | 445 ++++++++++++++++++++++++++++++--------
+ include/linux/phylink.h   | 195 +++++++++++++++++
+ 2 files changed, 552 insertions(+), 88 deletions(-)
 
 diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
-index 67f34ed4c..9c76517ea 100644
+index 3c24e44..1c1ce4a 100644
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
 @@ -40,8 +40,9 @@ enum {
@@ -115,7 +114,7 @@
  static void phylink_mac_config(struct phylink *pl,
  			       const struct phylink_link_state *state)
  {
-@@ -350,37 +410,113 @@ static void phylink_mac_config(struct phylink *pl,
+@@ -350,37 +410,157 @@ static void phylink_mac_config(struct phylink *pl,
  		    __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
  		    state->pause, state->link, state->an_enabled);
  
@@ -211,10 +210,53 @@
  }
  
 -static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state *state)
++/*
++ * Reconfigure for a change of inband advertisement.
++ * If we have a separate PCS, we only need to call its pcs_config() method,
++ * and then restart AN if it indicates something changed. Otherwise, we do
++ * the full MAC reconfiguration.
++ */
++static int phylink_change_inband_advert(struct phylink *pl)
+ {
++	int ret;
+ 
++	if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
++		return 0;
++
++	if (!pl->pcs) {
++		/* Legacy method */
++		phylink_mac_config(pl, &pl->link_config);
++		phylink_mac_pcs_an_restart(pl);
++		return 0;
++	}
++
++	phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
++		    phylink_an_mode_str(pl->cur_link_an_mode),
++		    phy_modes(pl->link_config.interface),
++		    __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
++		    pl->link_config.pause);
++
++	/* Modern PCS-based method; update the advert at the PCS, and
++	 * restart negotiation if the pcs_config() helper indicates that
++	 * the programmed advertisement has changed.
++	 */
++	ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
++				       pl->link_config.interface,
++				       pl->link_config.advertising,
++				       !!(pl->link_config.pause &
++					  MLO_PAUSE_AN));
++	if (ret < 0)
++		return ret;
++
++	if (ret > 0)
++		phylink_mac_pcs_an_restart(pl);
++
++	return 0;
++}
++
 +static void phylink_mac_pcs_get_state(struct phylink *pl,
 +				      struct phylink_link_state *state)
- {
--
++{
  	linkmode_copy(state->advertising, pl->link_config.advertising);
  	linkmode_zero(state->lp_advertising);
  	state->interface = pl->link_config.interface;
@@ -244,7 +286,7 @@
  }
  
  /* The fixed state is... fixed except for the link state,
-@@ -395,6 +531,34 @@ static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_stat
+@@ -395,6 +575,34 @@ static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_stat
  		state->link = !!gpiod_get_value_cansleep(pl->link_gpio);
  }
  
@@ -279,7 +321,7 @@
  /* Flow control is resolved according to our and the link partners
   * advertisements using the following drawn from the 802.3 specs:
   *  Local device  Link partner
-@@ -445,17 +609,25 @@ static const char *phylink_pause_to_str(int pause)
+@@ -445,17 +653,25 @@ static const char *phylink_pause_to_str(int pause)
  	}
  }
  
@@ -312,7 +354,7 @@
  
  	if (ndev)
  		netif_carrier_on(ndev);
-@@ -467,14 +639,14 @@ static void phylink_mac_link_up(struct phylink *pl,
+@@ -467,14 +683,14 @@ static void phylink_mac_link_up(struct phylink *pl,
  		     phylink_pause_to_str(link_state.pause));
  }
  
@@ -330,7 +372,7 @@
  	phylink_info(pl, "Link is Down\n");
  }
  
-@@ -513,7 +685,7 @@ static void phylink_resolve(struct work_struct *w)
+@@ -513,7 +729,7 @@ static void phylink_resolve(struct work_struct *w)
  			break;
  
  		case MLO_AN_INBAND:
@@ -339,7 +381,7 @@
  
  			/* The PCS may have a latching link-fail indicator.
  			 * If the link was up, bring the link down and
-@@ -524,8 +696,8 @@ static void phylink_resolve(struct work_struct *w)
+@@ -524,8 +740,8 @@ static void phylink_resolve(struct work_struct *w)
  				if (cur_link_state)
  					retrigger = true;
  				else
@@ -349,8 +391,8 @@
 +								  &link_state);
  			}
  
- 			/* If we have a phy, the "up" state is the union of
-@@ -564,12 +736,17 @@ static void phylink_resolve(struct work_struct *w)
+ 			if (pl->phydev && !(link_state.link & pl->phy_state.link))
+@@ -573,12 +789,17 @@ static void phylink_resolve(struct work_struct *w)
  			 * then reconfigure.
  			 */
  			if (cur_link_state) {
@@ -371,7 +413,7 @@
  			phylink_mac_config(pl, &link_state);
  		}
  	}
-@@ -577,9 +754,9 @@ static void phylink_resolve(struct work_struct *w)
+@@ -586,9 +807,9 @@ static void phylink_resolve(struct work_struct *w)
  	if (link_state.link != cur_link_state) {
  		pl->old_link_state = link_state.link;
  		if (!link_state.link)
@@ -383,7 +425,7 @@
  	}
  	if (!link_state.link && retrigger) {
  		pl->mac_link_dropped = false;
-@@ -643,7 +820,7 @@ static int phylink_register_sfp(struct phylink *pl,
+@@ -652,7 +873,7 @@ static int phylink_register_sfp(struct phylink *pl,
   * @fwnode: a pointer to a &struct fwnode_handle describing the network
   *	interface
   * @iface: the desired link mode defined by &typedef phy_interface_t
@@ -392,7 +434,7 @@
   *
   * Create a new phylink instance, and parse the link parameters found in @np.
   * This will parse in-band modes, fixed-link or SFP configuration.
-@@ -656,11 +833,17 @@ static int phylink_register_sfp(struct phylink *pl,
+@@ -665,11 +886,17 @@ static int phylink_register_sfp(struct phylink *pl,
  struct phylink *phylink_create(struct phylink_config *config,
  			       struct fwnode_handle *fwnode,
  			       phy_interface_t iface,
@@ -411,7 +453,7 @@
  	pl = kzalloc(sizeof(*pl), GFP_KERNEL);
  	if (!pl)
  		return ERR_PTR(-ENOMEM);
-@@ -678,6 +861,7 @@ struct phylink *phylink_create(struct phylink_config *config,
+@@ -687,6 +914,7 @@ struct phylink *phylink_create(struct phylink_config *config,
  		return ERR_PTR(-EINVAL);
  	}
  
@@ -419,7 +461,7 @@
  	pl->phy_state.interface = iface;
  	pl->link_interface = iface;
  	if (iface == PHY_INTERFACE_MODE_MOCA)
-@@ -689,7 +873,7 @@ struct phylink *phylink_create(struct phylink_config *config,
+@@ -698,7 +926,7 @@ struct phylink *phylink_create(struct phylink_config *config,
  	pl->link_config.speed = SPEED_UNKNOWN;
  	pl->link_config.duplex = DUPLEX_UNKNOWN;
  	pl->link_config.an_enabled = true;
@@ -428,7 +470,7 @@
  	__set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
  	timer_setup(&pl->link_poll, phylink_fixed_poll, 0);
  
-@@ -1016,6 +1200,8 @@ static irqreturn_t phylink_link_handler(int irq, void *data)
+@@ -1025,6 +1253,8 @@ static irqreturn_t phylink_link_handler(int irq, void *data)
   */
  void phylink_start(struct phylink *pl)
  {
@@ -437,7 +479,7 @@
  	ASSERT_RTNL();
  
  	phylink_info(pl, "configuring for %s/%s link mode\n",
-@@ -1029,15 +1215,13 @@ void phylink_start(struct phylink *pl)
+@@ -1038,15 +1268,13 @@ void phylink_start(struct phylink *pl)
  	/* Apply the link configuration to the MAC when starting. This allows
  	 * a fixed-link to start with the correct parameters, and also
  	 * ensures that we set the appropriate advertisement for Serdes links.
@@ -457,7 +499,7 @@
  
  	clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
  	phylink_run_resolve(pl);
-@@ -1055,10 +1239,19 @@ void phylink_start(struct phylink *pl)
+@@ -1064,10 +1292,19 @@ void phylink_start(struct phylink *pl)
  				irq = 0;
  		}
  		if (irq <= 0)
@@ -480,7 +522,7 @@
  		mod_timer(&pl->link_poll, jiffies + HZ);
  	if (pl->phydev)
  		phy_start(pl->phydev);
-@@ -1202,7 +1395,7 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
+@@ -1211,7 +1448,7 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
  		if (pl->phydev)
  			break;
  
@@ -489,16 +531,45 @@
  
  		/* The MAC is reporting the link results from its own PCS
  		 * layer via in-band status. Report these as the current
-@@ -1314,7 +1507,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
- 	if (pl->cur_link_an_mode == MLO_AN_INBAND &&
- 	    !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) {
- 		phylink_mac_config(pl, &pl->link_config);
+@@ -1309,21 +1546,26 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
+ 
+ 	mutex_lock(&pl->state_mutex);
+ 	/* Configure the MAC to match the new settings */
+-	linkmode_copy(pl->link_config.advertising, our_kset.link_modes.advertising);
+-	pl->link_config.interface = config.interface;
+ 	pl->link_config.speed = our_kset.base.speed;
+ 	pl->link_config.duplex = our_kset.base.duplex;
+ 	pl->link_config.an_enabled = our_kset.base.autoneg != AUTONEG_DISABLE;
+ 
+-	/* If we have a PHY, phylib will call our link state function if the
+-	 * mode has changed, which will trigger a resolve and update the MAC
+-	 * configuration. For a fixed link, this isn't able to change any
+-	 * parameters, which just leaves inband mode.
+-	 */
+-	if (pl->cur_link_an_mode == MLO_AN_INBAND &&
+-	    !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) {
+-		phylink_mac_config(pl, &pl->link_config);
 -		phylink_mac_an_restart(pl);
-+		phylink_mac_pcs_an_restart(pl);
++	if (pl->link_config.interface != config.interface) {
++		/* The interface changed, e.g. 1000base-X <-> 2500base-X */
++		/* We need to force the link down, then change the interface */
++		if (pl->old_link_state) {
++			phylink_link_down(pl);
++			pl->old_link_state = false;
++		}
++		if (!test_bit(PHYLINK_DISABLE_STOPPED,
++			      &pl->phylink_disable_state))
++			phylink_major_config(pl, false, &config);
++		pl->link_config.interface = config.interface;
++		linkmode_copy(pl->link_config.advertising, our_kset.link_modes.advertising);
++	} else if (!linkmode_equal(pl->link_config.advertising,
++				   config.advertising)) {
++		linkmode_copy(pl->link_config.advertising, our_kset.link_modes.advertising);
++		phylink_change_inband_advert(pl);
  	}
  	mutex_unlock(&pl->state_mutex);
  
-@@ -1341,7 +1534,7 @@ int phylink_ethtool_nway_reset(struct phylink *pl)
+@@ -1350,7 +1592,7 @@ int phylink_ethtool_nway_reset(struct phylink *pl)
  
  	if (pl->phydev)
  		ret = phy_restart_aneg(pl->phydev);
@@ -507,16 +578,106 @@
  
  	return ret;
  }
-@@ -1410,7 +1603,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
+@@ -1381,9 +1623,14 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
+ 				   struct ethtool_pauseparam *pause)
+ {
+ 	struct phylink_link_state *config = &pl->link_config;
++	bool manual_changed;
++	int pause_state;
  
- 		case MLO_AN_INBAND:
- 			phylink_mac_config(pl, config);
+ 	ASSERT_RTNL();
+ 
++	if (pl->cur_link_an_mode == MLO_AN_FIXED)
++		return -EOPNOTSUPP;
++
+ 	if (!phylink_test(pl->supported, Pause) &&
+ 	    !phylink_test(pl->supported, Asym_Pause))
+ 		return -EOPNOTSUPP;
+@@ -1392,36 +1639,61 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
+ 	    pause->rx_pause != pause->tx_pause)
+ 		return -EINVAL;
+ 
+-	config->pause &= ~(MLO_PAUSE_AN | MLO_PAUSE_TXRX_MASK);
+-
++	pause_state = 0;
+ 	if (pause->autoneg)
+-		config->pause |= MLO_PAUSE_AN;
++		pause_state |= MLO_PAUSE_AN;
+ 	if (pause->rx_pause)
+-		config->pause |= MLO_PAUSE_RX;
++		pause_state |= MLO_PAUSE_RX;
+ 	if (pause->tx_pause)
+-		config->pause |= MLO_PAUSE_TX;
++		pause_state |= MLO_PAUSE_TX;
+ 
+-	/* If we have a PHY, phylib will call our link state function if the
+-	 * mode has changed, which will trigger a resolve and update the MAC
+-	 * configuration.
++	mutex_lock(&pl->state_mutex);
++	/*
++	 * See the comments for linkmode_set_pause(), wrt the deficiencies
++	 * with the current implementation.  A solution to this issue would
++	 * be:
++	 * ethtool  Local device
++	 *  rx  tx  Pause AsymDir
++	 *  0   0   0     0
++	 *  1   0   1     1
++	 *  0   1   0     1
++	 *  1   1   1     1
++	 * and then use the ethtool rx/tx enablement status to mask the
++	 * rx/tx pause resolution.
+ 	 */
+-	if (pl->phydev) {
++	linkmode_set_pause(config->advertising, pause->tx_pause,
++			   pause->rx_pause);
++
++	manual_changed = (config->pause ^ pause_state) & MLO_PAUSE_AN ||
++			 (!(pause_state & MLO_PAUSE_AN) &&
++			   (config->pause ^ pause_state) & MLO_PAUSE_TXRX_MASK);
++
++	config->pause = pause_state;
++
++	/* Update our in-band advertisement, triggering a renegotiation if
++	 * the advertisement changed.
++	 */
++	if (!pl->phydev)
++		phylink_change_inband_advert(pl);
++
++	mutex_unlock(&pl->state_mutex);
++
++	/* If we have a PHY, a change of the pause frame advertisement will
++	 * cause phylib to renegotiate (if AN is enabled) which will in turn
++	 * call our phylink_phy_change() and trigger a resolve.  Note that
++	 * we can't hold our state mutex while calling phy_set_asym_pause().
++	 */
++	if (pl->phydev)
+ 		phy_set_asym_pause(pl->phydev, pause->rx_pause,
+ 				   pause->tx_pause);
+-	} else if (!test_bit(PHYLINK_DISABLE_STOPPED,
+-			     &pl->phylink_disable_state)) {
+-		switch (pl->cur_link_an_mode) {
+-		case MLO_AN_FIXED:
+-			/* Should we allow fixed links to change against the config? */
+-			phylink_resolve_flow(pl, config);
+-			phylink_mac_config(pl, config);
+-			break;
+ 
+-		case MLO_AN_INBAND:
+-			phylink_mac_config(pl, config);
 -			phylink_mac_an_restart(pl);
-+			phylink_mac_pcs_an_restart(pl);
- 			break;
- 		}
+-			break;
+-		}
++	/* If the manual pause settings changed, make sure we trigger a
++	 * resolve to update their state; we can not guarantee that the
++	 * link will cycle.
++	 */
++	if (manual_changed) {
++		pl->mac_link_dropped = true;
++		phylink_run_resolve(pl);
  	}
-@@ -1621,10 +1814,7 @@ static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
+ 
+ 	return 0;
+@@ -1630,10 +1902,7 @@ static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
  
  	case MLO_AN_INBAND:
  		if (phy_id == 0) {
@@ -528,7 +689,7 @@
  			val = phylink_mii_emul_read(reg, &state);
  		}
  		break;
-@@ -1820,7 +2010,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
+@@ -1829,7 +2098,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
  
  	if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
  				 &pl->phylink_disable_state))
@@ -538,7 +699,7 @@
  	return ret;
  }
 diff --git a/include/linux/phylink.h b/include/linux/phylink.h
-index 8229f56a1..ba0f09d02 100644
+index 8229f56..ba0f09d 100644
 --- a/include/linux/phylink.h
 +++ b/include/linux/phylink.h
 @@ -63,17 +63,23 @@ enum phylink_op_type {
@@ -794,5 +955,5 @@
  			       phy_interface_t iface,
  			       const struct phylink_mac_ops *ops);
 -- 
-2.34.1
+2.18.0
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1715-v6.2-net-dsa-add-set-queue-mapping.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1715-v6.2-net-dsa-add-set-queue-mapping.patch
new file mode 100644
index 0000000..b976a0a
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1715-v6.2-net-dsa-add-set-queue-mapping.patch
@@ -0,0 +1,13 @@
+diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
+index c386fdc..e2bdd69 100644
+--- a/net/dsa/tag_mtk.c
++++ b/net/dsa/tag_mtk.c
+@@ -28,6 +28,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+ 	bool is_multicast_skb = is_multicast_ether_addr(dest) &&
+ 				!is_broadcast_ether_addr(dest);
+ 
++	skb_set_queue_mapping(skb, dp->index);
++
+ 	/* Build the special tag after the MAC Source Address. If VLAN header
+ 	 * is present, it's required that VLAN header and special tag is
+ 	 * being combined. Only in this way we can allow the switch can parse
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
index 42467b6..3666b6b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch
@@ -1,17 +1,7 @@
-From 2c71a01b9363f44ca077ec0e27b6a06a15617497 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:14 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch]
-
----
- drivers/mtd/nand/spi/winbond.c | 129 ++++++++++++++++++++++++++++++++-
- 1 file changed, 127 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
-index 766844283..6473b0367 100644
---- a/drivers/mtd/nand/spi/winbond.c
-+++ b/drivers/mtd/nand/spi/winbond.c
+Index: linux-5.4.260/drivers/mtd/nand/spi/winbond.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/winbond.c
++++ linux-5.4.260/drivers/mtd/nand/spi/winbond.c
 @@ -15,6 +15,23 @@
  
  #define WINBOND_CFG_BUF_READ		BIT(3)
@@ -36,7 +26,7 @@
  static SPINAND_OP_VARIANTS(read_cache_variants,
  		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
  		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
-@@ -31,6 +48,29 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
+@@ -31,6 +48,29 @@ static SPINAND_OP_VARIANTS(update_cache_
  		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
  		SPINAND_PROG_LOAD(false, 0, NULL, 0));
  
@@ -66,7 +56,7 @@
  static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
  				  struct mtd_oob_region *region)
  {
-@@ -74,9 +114,61 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
+@@ -74,9 +114,61 @@ static int w25m02gv_select_target(struct
  	return spi_mem_exec_op(spinand->spimem, &op);
  }
  
@@ -129,7 +119,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
  		     NAND_ECCREQ(1, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -85,8 +177,18 @@ static const struct spinand_info winbond_spinand_table[] = {
+@@ -85,8 +177,18 @@ static const struct spinand_info winbond
  		     0,
  		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
  		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
@@ -149,7 +139,7 @@
  		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
  		     NAND_ECCREQ(1, 512),
  		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-@@ -94,6 +196,29 @@ static const struct spinand_info winbond_spinand_table[] = {
+@@ -94,6 +196,29 @@ static const struct spinand_info winbond
  					      &update_cache_variants),
  		     0,
  		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
@@ -179,6 +169,3 @@
  };
  
  static int winbond_spinand_init(struct spinand_device *spinand)
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch
index b19492b..e21b097 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch
@@ -1,18 +1,8 @@
-From 6d8d4dc76ac31cfdecef99c72aad6a65f963d4a0 Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:14 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch]
-
----
- drivers/mtd/nand/spi/macronix.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
-index 25319b4f8..d3ae24ecc 100644
---- a/drivers/mtd/nand/spi/macronix.c
-+++ b/drivers/mtd/nand/spi/macronix.c
-@@ -86,7 +86,7 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
+Index: linux-5.4.260/drivers/mtd/nand/spi/macronix.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/macronix.c
++++ linux-5.4.260/drivers/mtd/nand/spi/macronix.c
+@@ -86,7 +86,7 @@ static int mx35lf1ge4ab_ecc_get_status(s
  		if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr))
  			return nand->eccreq.strength;
  
@@ -21,6 +11,3 @@
  			return nand->eccreq.strength;
  
  		return eccsr;
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
index cf785fe..4a36657 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch
@@ -1,18 +1,8 @@
-From ddd2951e2f35477a81fb882a976a5a1fe981883d Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:17 +0800
-Subject: [PATCH] 
- [spi-and-storage][999-2339-drivers-mtd-spinand-Add-calibration-support-for-spinand.patch]
-
----
- drivers/mtd/nand/spi/core.c | 58 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 58 insertions(+)
-
-diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
-index 9f5f95ff7..b346c7a8a 100644
---- a/drivers/mtd/nand/spi/core.c
-+++ b/drivers/mtd/nand/spi/core.c
-@@ -789,6 +789,60 @@ static int spinand_manufacturer_match(struct spinand_device *spinand,
+Index: linux-5.4.260/drivers/mtd/nand/spi/core.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/core.c
++++ linux-5.4.260/drivers/mtd/nand/spi/core.c
+@@ -789,6 +789,60 @@ static int spinand_manufacturer_match(st
  	return -ENOTSUPP;
  }
  
@@ -73,7 +63,7 @@
  static int spinand_id_detect(struct spinand_device *spinand)
  {
  	u8 *id = spinand->id.data;
-@@ -1004,6 +1058,10 @@ static int spinand_init(struct spinand_device *spinand)
+@@ -1004,6 +1058,10 @@ static int spinand_init(struct spinand_d
  	if (!spinand->scratchbuf)
  		return -ENOMEM;
  
@@ -84,6 +74,3 @@
  	ret = spinand_detect(spinand);
  	if (ret)
  		goto err_free_bufs;
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2343-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2343-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB.patch
index acf4775..084073d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2343-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2343-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB.patch
@@ -1,7 +1,7 @@
-Index: linux-5.4.246/drivers/mtd/nand/spi/gigadevice.c
+Index: linux-5.4.260/drivers/mtd/nand/spi/gigadevice.c
 ===================================================================
---- linux-5.4.246.orig/drivers/mtd/nand/spi/gigadevice.c
-+++ linux-5.4.246/drivers/mtd/nand/spi/gigadevice.c
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/gigadevice.c
++++ linux-5.4.260/drivers/mtd/nand/spi/gigadevice.c
 @@ -281,6 +281,15 @@ static int gd5fxgq4ufxxg_ecc_get_status(
  }
  
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
index dcc13b9..e5109db 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
@@ -37,6 +37,8 @@
     file://1021-ubnt-ledbar-driver.patch \
     file://999-1050-v6.4-backport-jitterrng-2.2.0.patch;apply=no \
     file://999-1051-v5.10-backport-libkcapi.patch \
+    file://999-1401-v5.7-mtd-spinand-backport-winbond-and-base-file.patch \
+    file://999-1402-v6.4-mtd-spinand-backport-series-flash.patch \
     file://999-1600-v5.18-mdiobus-add-c45.patch \
     file://999-1703-v5.18-mxl-gpy-phy-support.patch \
     file://999-1704-v6.2-net-phy-aquantia-add-AQR113C.patch \
@@ -47,6 +49,7 @@
     file://999-1712-v6.2-net-phy-add-phylink-rate-matching-support.patch;apply=no \
     file://999-1713-v5.15-net-dsa-add-dsa_port_from_netdev.patch \
     file://999-1714-v5.15-net-dsa-add-netdev_upper_dev_link.patch \
+    file://999-1715-v6.2-net-dsa-add-set-queue-mapping.patch \
     file://999-1750-v5.18-net-macsec-get-ready-to-backport-from-5-18.patch \
     file://999-1751-01-v5.18-net-macsec-move-some-definitions-in-a-dedicated-header.patch \
     file://999-1752-02-v5.18-net-macsec-introduce-the-macsec_context-structure.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
index 2d4bfaa..86d3edb 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
@@ -117,8 +117,8 @@
  		ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
  					       &ring->phys, GFP_KERNEL);
  	else {
--		ring->dma =  eth->scratch_ring + MTK_DMA_SIZE * sz;
-+		ring->dma =  eth->scratch_ring + MTK_DMA_FQ_SIZE * sz;
+-		ring->dma =  eth->sram_base + MTK_DMA_SIZE * sz;
++		ring->dma =  eth->sram_base + MTK_DMA_FQ_SIZE * sz;
  		ring->phys = eth->phy_scratch_ring +
 -			     MTK_DMA_SIZE * (dma_addr_t)sz;
 +			     MTK_DMA_FQ_SIZE * (dma_addr_t)sz;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3025-dts-88d-option-type-2-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3025-dts-88d-option-type-2-support.patch
new file mode 100644
index 0000000..9084982
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3025-dts-88d-option-type-2-support.patch
@@ -0,0 +1,38 @@
+From a344727c9d91c162839e7283aeac281f88f30e8a Mon Sep 17 00:00:00 2001
+From: Rex Lu <rex.lu@mediatek.com>
+Date: Mon, 22 Jan 2024 13:50:29 +0800
+Subject: [PATCH] dts 88d option type 2 support
+
+Signed-off-by: Rex Lu <rex.lu@mediatek.com>
+---
+ arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts | 1 +
+ arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts b/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
+index 5513d04..7619009 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
+@@ -569,6 +569,7 @@
+ 	mt7996@0,0 {
+ 		reg = <0x0000 0 0 0 0>;
+ 		device_type = "pci";
++		option_type = <2>;
+ 		mediatek,mtd-eeprom = <&factory 0x0>;
+ 	};
+ };
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
+index 4cab1ae..b98efb9 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
+@@ -546,6 +546,7 @@
+ 	mt7996@0,0 {
+ 		reg = <0x0000 0 0 0 0>;
+ 		device_type = "pci";
++		option_type = <2>;
+ 		mediatek,mtd-eeprom = <&factory 0x0>;
+ 	};
+ };
+-- 
+2.18.0
+