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

[Description]
c244aa7e [kernel][mt7988][eth][Change LRO DMA size for reducing memory usage]
09f4883d [MAC80211][hnat][Fix patch fail issue for the mt7622]
f9ed7707 [MAC80211][hnat][Update per-flow accounting function for the mt7988]
cf5c9c95 [kernel][mt7988][eth][Fix HW path traffic stuck issue on the 4GB/8GB RFB]
e9e3fef3 [MAC80211][hnat][Fix PPE hanging issue during the reboot test]
0e022a6c [kernel][common][i2c][update kernel config to prevent build stop]
6e1f1f58 [kernel][mt7988][i2c][synchronize i2c1 nodes in the DTs]
38d9ec10 [kernel][common][i2c][add zts8032 sensor support]
f42e0a1b [openwrt][common][watchgog][fix watchdog interrupt ID]
d2247030 [kernel][mt7988][eth][Make the LRO and RSS coexistence]
e7de2468 [[kernel][mt7988][hnat][Fix the bind PPE when WAN/LAN2 -> LAN  in 3 PPEs conditions]
e90611df [openwrt][common][crypto][Upgrade Strongswan to v5.9.11]

[Release-log]

Change-Id: I3d47c47154e7718ed96003d3e669a31eedcdbd70
diff --git a/recipes-devtools/smp/files/smp-mt76.sh b/recipes-devtools/smp/files/smp-mt76.sh
index f383cf6..5b8710a 100644
--- a/recipes-devtools/smp/files/smp-mt76.sh
+++ b/recipes-devtools/smp/files/smp-mt76.sh
@@ -268,10 +268,34 @@
 	wifi1_irq=
 	wifi2_irq=
 	wifi3_irq=
+
 	#AX3000
-	if [[ "$WIFI_RADIO1" -eq "1" ]]; then
-		wifi1_irq=245
+	if [[ "$WED_ENABLE" -eq "1" ]]; then
+		dbg2 "WED_ENABLE ON irq/iptable setting"
+		#TCP Binding
+		iptables -D FORWARD -p tcp -m conntrack --ctstate	\
+				RELATED,ESTABLISHED -j FLOWOFFLOAD --hw
+		iptables -I FORWARD -p tcp -m conntrack --ctstate	\
+				RELATED,ESTABLISHED -j FLOWOFFLOAD --hw
+		ip6tables -D FORWARD -p tcp -m conntrack --ctstate	\
+				RELATED,ESTABLISHED -j FLOWOFFLOAD --hw
+		ip6tables -I FORWARD -p tcp -m conntrack --ctstate	\
+				RELATED,ESTABLISHED -j FLOWOFFLOAD --hw
+		#UDP Binding
+		iptables -D FORWARD -p udp -j FLOWOFFLOAD --hw
+		iptables -I FORWARD -p udp -j FLOWOFFLOAD --hw
+		ip6tables -D FORWARD -p udp -j FLOWOFFLOAD --hw
+		ip6tables -I FORWARD -p udp -j FLOWOFFLOAD --hw
+
+		if [[ "$WIFI_RADIO1" -eq "1" ]]; then
+			wifi1_irq=237
+		fi
+	else
+		if [[ "$WIFI_RADIO1" -eq "1" ]]; then
+			wifi1_irq=245
+		fi
 	fi
+
 	# Please update the CPU binding in each cases.
 	# CPU#_AFFINITY="add binding irq number here"
 	# CPU#_RPS="add binding interface name here"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986-fpga.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986-fpga.dtsi
index 12a0234..4b3ca77 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986-fpga.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986-fpga.dtsi
@@ -183,7 +183,7 @@
 		compatible = "mediatek,mt7622-wdt",
 			     "mediatek,mt6589-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
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 e43c306..bf62aa1 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
@@ -213,7 +213,7 @@
 	watchdog: watchdog@1001c000 {
 		compatible = "mediatek,mt7986-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
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 21d8357..0c3e2f4 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
@@ -213,7 +213,7 @@
 	watchdog: watchdog@1001c000 {
 		compatible = "mediatek,mt7986-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-fpga.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-fpga.dtsi
index a803992..27dd30f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-fpga.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-fpga.dtsi
@@ -170,7 +170,7 @@
 		compatible = "mediatek,mt7622-wdt",
 			     "mediatek,mt6589-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi
index ccaf0ad..3b304d5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi
@@ -231,7 +231,7 @@
 		compatible = "mediatek,mt7986-wdt",
 			     "mediatek,mt6589-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-fpga.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-fpga.dtsi
index 12a0234..4b3ca77 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-fpga.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-fpga.dtsi
@@ -183,7 +183,7 @@
 		compatible = "mediatek,mt7622-wdt",
 			     "mediatek,mt6589-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
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 e43c306..bf62aa1 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
@@ -213,7 +213,7 @@
 	watchdog: watchdog@1001c000 {
 		compatible = "mediatek,mt7986-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
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 21d8357..0c3e2f4 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
@@ -213,7 +213,7 @@
 	watchdog: watchdog@1001c000 {
 		compatible = "mediatek,mt7986-wdt";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
index d99c1d5..5d9357d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -430,7 +430,7 @@
 			     "mediatek,mt6589-wdt",
 			     "syscon";
 		reg = <0 0x1001c000 0 0x1000>;
-		interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 	};
 
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 2cf886c..5701c3e 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
@@ -182,10 +182,22 @@
 		reg = <0x1a>;
 	};
 
+	zts8032: zts8032@77 {
+		compatible = "zilltek,zts8032";
+		reg = <0x76>;
+	};
+
 	dps368: dps368@77 {
 		compatible = "infineon,dps310";
 		reg = <0x77>;
 	};
+
+	rtq6056: rtq6056@40 {
+		compatible = "richtek,rtq6056";
+		reg = <0x40>;
+		shunt-resistor-micro-ohms = <10000>;
+		#io-channel-cells = <1>;
+	};
 };
 
 &spi0 {
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 003fb51..32e2b15 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
@@ -178,6 +178,11 @@
 		reg = <0x1a>;
 	};
 
+	zts8032: zts8032@77 {
+		compatible = "zilltek,zts8032";
+		reg = <0x76>;
+	};
+
 	dps368: dps368@77 {
 		compatible = "infineon,dps310";
 		reg = <0x77>;
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 5dcfd58..77eac13 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
@@ -135,10 +135,27 @@
 	pinctrl-0 = <&i2c1_pins>;
 	status = "okay";
 
+	wm8960: wm8960@1a {
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+	};
+
+	zts8032: zts8032@77 {
+		compatible = "zilltek,zts8032";
+		reg = <0x76>;
+	};
+
 	dps368: dps368@77 {
 		compatible = "infineon,dps310";
 		reg = <0x77>;
 	};
+
+	rtq6056: rtq6056@40 {
+		compatible = "richtek,rtq6056";
+		reg = <0x40>;
+		shunt-resistor-micro-ohms = <10000>;
+		#io-channel-cells = <1>;
+	};
 };
 
 &pwm {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/iio/pressure/zts8032.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/iio/pressure/zts8032.c
new file mode 100644
index 0000000..0eae868
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/iio/pressure/zts8032.c
@@ -0,0 +1,847 @@
+// SPDX-License-Identifier: GPL-2.0

+/*

+ * The ZTS8032 is a barometric pressure and temperature sensor.

+ * Currently only reading a single temperature is supported by

+ * this driver.

+ */

+

+#include <linux/i2c.h>

+#include <linux/limits.h>

+#include <linux/math64.h>

+#include <linux/module.h>

+#include <linux/regmap.h>

+

+#include <linux/iio/iio.h>

+#include <linux/iio/sysfs.h>

+

+#define ZTS8032_DEV_NAME	"zts8032"

+

+#define ZTS8032_PRS_B0		0x00

+#define ZTS8032_PRS_B1		0x01

+#define ZTS8032_PRS_B2		0x02

+#define ZTS8032_TMP_B0		0x03

+#define ZTS8032_TMP_B1		0x04

+#define ZTS8032_TMP_B2		0x05

+#define ZTS8032_PRS_CFG		0x06

+#define  ZTS8032_PRS_RATE_BITS	GENMASK(6, 4)

+#define  ZTS8032_PRS_PRC_BITS	GENMASK(3, 0)

+#define ZTS8032_TMP_CFG		0x07

+#define  ZTS8032_TMP_RATE_BITS	GENMASK(6, 4)

+#define  ZTS8032_TMP_PRC_BITS	GENMASK(3, 0)

+#define  ZTS8032_TMP_EXT	BIT(7)

+#define ZTS8032_MEAS_CFG	0x08

+#define  ZTS8032_MEAS_CTRL_BITS	GENMASK(2, 0)

+#define   ZTS8032_PRS_EN	BIT(0)

+#define   ZTS8032_TEMP_EN	BIT(1)

+#define   ZTS8032_BACKGROUND	BIT(2)

+#define  ZTS8032_PRS_RDY	BIT(4)

+#define  ZTS8032_TMP_RDY	BIT(5)

+#define  ZTS8032_SENSOR_RDY	BIT(6)

+#define  ZTS8032_COEF_RDY	BIT(7)

+#define ZTS8032_CFG_REG		0x09

+#define  ZTS8032_INT_HL		BIT(7)

+#define  ZTS8032_TMP_SHIFT_EN	BIT(3)

+#define  ZTS8032_PRS_SHIFT_EN	BIT(4)

+#define  ZTS8032_FIFO_EN	BIT(5)

+#define  ZTS8032_SPI_EN		BIT(6)

+#define ZTS8032_RESET		0x0c

+#define  ZTS8032_RESET_MAGIC	0x09

+#define ZTS8032_COEF_BASE	0x10

+

+/* Make sure sleep time is <= 20ms for usleep_range */

+#define ZTS8032_POLL_SLEEP_US(t)		min(20000, (t) / 8)

+/* Silently handle error in rate value here */

+#define ZTS8032_POLL_TIMEOUT_US(rc)	((rc) <= 0 ? 1000000 : 1000000 / (rc))

+

+#define ZTS8032_PRS_BASE		ZTS8032_PRS_B0

+#define ZTS8032_TMP_BASE		ZTS8032_TMP_B0

+

+/*

+ * These values (defined in the spec) indicate how to scale the raw register

+ * values for each level of precision available.

+ */

+static const int scale_factors[] = {

+	 524288,

+	1572864,

+	3670016,

+	7864320,

+	 253952,

+	 516096,

+	1040384,

+	2088960,

+};

+

+struct zts8032_data {

+	struct i2c_client *client;

+	struct regmap *regmap;

+	struct mutex lock;	/* Lock for sequential HW access functions */

+

+	s32 c0, c1;

+	s32 c00, c10, c20, c30, c40, c01, c11, c21, c31;

+	s32 pressure_raw;

+	s32 temp_raw;

+};

+

+static const struct iio_chan_spec zts8032_channels[] = {

+	{

+		.type = IIO_TEMP,

+		.info_mask_separate = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |

+			BIT(IIO_CHAN_INFO_SAMP_FREQ) |

+			BIT(IIO_CHAN_INFO_PROCESSED),

+	},

+	{

+		.type = IIO_PRESSURE,

+		.info_mask_separate = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |

+			BIT(IIO_CHAN_INFO_SAMP_FREQ) |

+			BIT(IIO_CHAN_INFO_PROCESSED),

+	},

+};

+

+/* To be called after checking the COEF_RDY bit in MEAS_CFG */

+static int zts8032_get_coefs(struct zts8032_data *data)

+{

+	int rc;

+	u8 coef[22];

+	u32 c0, c1;

+	u32 c00, c10, c20, c30, c40, c01, c11, c21, c31;

+

+	/* Read all sensor calibration coefficients from the COEF registers. */

+	rc = regmap_bulk_read(data->regmap, ZTS8032_COEF_BASE, coef,

+			      sizeof(coef));

+	if (rc < 0)

+		return rc;

+

+	/*

+	 * Calculate temperature calibration coefficients c0 and c1. The

+	 * numbers are 12-bit 2's complement numbers.

+	 */

+	c0 = (coef[0] << 4) | (coef[1] >> 4);

+	data->c0 = sign_extend32(c0, 11);

+

+	c1 = ((coef[1] & GENMASK(3, 0)) << 8) | coef[2];

+	data->c1 = sign_extend32(c1, 11);

+

+	/*

+	 * Calculate pressure calibration coefficients. c00 and c10 are 20 bit

+	 * 2's complement numbers, while the rest are 16 bit 2's complement

+	 * numbers.

+	 */

+	c00 = (coef[3] << 12) | (coef[4] << 4) | (coef[5] >> 4);

+	data->c00 = sign_extend32(c00, 19);

+

+	c10 = ((coef[5] & GENMASK(3, 0)) << 16) | (coef[6] << 8) | coef[7];

+	data->c10 = sign_extend32(c10, 19);

+

+	c01 = (coef[8] << 8) | coef[9];

+	data->c01 = sign_extend32(c01, 15);

+

+	c11 = (coef[10] << 8) | coef[11];

+	data->c11 = sign_extend32(c11, 15);

+

+	c20 = (coef[12] << 8) | coef[13];

+	data->c20 = sign_extend32(c20, 15);

+

+	c21 = (coef[14] << 8) | coef[15];

+	data->c21 = sign_extend32(c21, 15);

+

+	c30 = (coef[16] << 8) | coef[17];

+	data->c30 = sign_extend32(c30, 15);

+

+	c31 = (coef[18] << 8) | coef[19];

+	data->c31 = sign_extend32(c31, 15);

+

+	c40 = (coef[20] << 8) | coef[21];

+	data->c40 = sign_extend32(c40, 15);

+

+	return 0;

+}

+

+static int zts8032_get_pres_precision(struct zts8032_data *data)

+{

+	int rc;

+	int val;

+

+	rc = regmap_read(data->regmap, ZTS8032_PRS_CFG, &val);

+	if (rc < 0)

+		return rc;

+

+	return BIT(val & GENMASK(2, 0));

+}

+

+static int zts8032_get_temp_precision(struct zts8032_data *data)

+{

+	int rc;

+	int val;

+

+	rc = regmap_read(data->regmap, ZTS8032_TMP_CFG, &val);

+	if (rc < 0)

+		return rc;

+

+	/*

+	 * Scale factor is bottom 4 bits of the register, but 1111 is

+	 * reserved so just grab bottom three

+	 */

+	return BIT(val & GENMASK(2, 0));

+}

+

+/* Called with lock held */

+static int zts8032_set_pres_precision(struct zts8032_data *data, int val)

+{

+	int rc;

+	u8 shift_en;

+

+	if (val < 0 || val > 128)

+		return -EINVAL;

+

+	shift_en = val >= 16 ? ZTS8032_PRS_SHIFT_EN : 0;

+	rc = regmap_write_bits(data->regmap, ZTS8032_CFG_REG,

+			       ZTS8032_PRS_SHIFT_EN, shift_en);

+	if (rc)

+		return rc;

+

+	return regmap_update_bits(data->regmap, ZTS8032_PRS_CFG,

+				  ZTS8032_PRS_PRC_BITS, ilog2(val));

+}

+

+/* Called with lock held */

+static int zts8032_set_temp_precision(struct zts8032_data *data, int val)

+{

+	int rc;

+	u8 shift_en;

+

+	if (val < 0 || val > 128)

+		return -EINVAL;

+

+	shift_en = val >= 16 ? ZTS8032_TMP_SHIFT_EN : 0;

+	rc = regmap_write_bits(data->regmap, ZTS8032_CFG_REG,

+			       ZTS8032_TMP_SHIFT_EN, shift_en);

+	if (rc)

+		return rc;

+

+	return regmap_update_bits(data->regmap, ZTS8032_TMP_CFG,

+				  ZTS8032_TMP_PRC_BITS, ilog2(val));

+}

+

+/* Called with lock held */

+static int zts8032_set_pres_samp_freq(struct zts8032_data *data, int freq)

+{

+	u8 val;

+

+	if (freq < 0 || freq > 128)

+		return -EINVAL;

+

+	val = ilog2(freq) << 4;

+

+	return regmap_update_bits(data->regmap, ZTS8032_PRS_CFG,

+				  ZTS8032_PRS_RATE_BITS, val);

+}

+

+/* Called with lock held */

+static int zts8032_set_temp_samp_freq(struct zts8032_data *data, int freq)

+{

+	u8 val;

+

+	if (freq < 0 || freq > 128)

+		return -EINVAL;

+

+	val = ilog2(freq) << 4;

+

+	return regmap_update_bits(data->regmap, ZTS8032_TMP_CFG,

+				  ZTS8032_TMP_RATE_BITS, val);

+}

+

+static int zts8032_get_pres_samp_freq(struct zts8032_data *data)

+{

+	int rc;

+	int val;

+

+	rc = regmap_read(data->regmap, ZTS8032_PRS_CFG, &val);

+	if (rc < 0)

+		return rc;

+

+	return BIT((val & ZTS8032_PRS_RATE_BITS) >> 4);

+}

+

+static int zts8032_get_temp_samp_freq(struct zts8032_data *data)

+{

+	int rc;

+	int val;

+

+	rc = regmap_read(data->regmap, ZTS8032_TMP_CFG, &val);

+	if (rc < 0)

+		return rc;

+

+	return BIT((val & ZTS8032_TMP_RATE_BITS) >> 4);

+}

+

+static int zts8032_get_pres_k(struct zts8032_data *data)

+{

+	int rc = zts8032_get_pres_precision(data);

+

+	if (rc < 0)

+		return rc;

+

+	return scale_factors[ilog2(rc)];

+}

+

+static int zts8032_get_temp_k(struct zts8032_data *data)

+{

+	int rc = zts8032_get_temp_precision(data);

+

+	if (rc < 0)

+		return rc;

+

+	return scale_factors[ilog2(rc)];

+}

+

+static int zts8032_read_pres_raw(struct zts8032_data *data)

+{

+	int rc;

+	int rate;

+	int ready;

+	int timeout;

+	s32 raw;

+	u8 val[3];

+

+	if (mutex_lock_interruptible(&data->lock))

+		return -EINTR;

+

+	rate = zts8032_get_pres_samp_freq(data);

+	timeout = ZTS8032_POLL_TIMEOUT_US(rate);

+

+	/* Poll for sensor readiness; base the timeout upon the sample rate. */

+	rc = regmap_read_poll_timeout(data->regmap, ZTS8032_MEAS_CFG, ready,

+				      ready & ZTS8032_PRS_RDY,

+				      ZTS8032_POLL_SLEEP_US(timeout), timeout);

+	if (rc)

+		goto done;

+

+	rc = regmap_bulk_read(data->regmap, ZTS8032_PRS_BASE, val, sizeof(val));

+	if (rc < 0)

+		goto done;

+

+	raw = (val[0] << 16) | (val[1] << 8) | val[2];

+	data->pressure_raw = sign_extend32(raw, 23);

+

+done:

+	mutex_unlock(&data->lock);

+	return rc;

+}

+

+/* Called with lock held */

+static int zts8032_read_temp_ready(struct zts8032_data *data)

+{

+	int rc;

+	u8 val[3];

+	s32 raw;

+

+	rc = regmap_bulk_read(data->regmap, ZTS8032_TMP_BASE, val, sizeof(val));

+	if (rc < 0)

+		return rc;

+

+	raw = (val[0] << 16) | (val[1] << 8) | val[2];

+	data->temp_raw = sign_extend32(raw, 23);

+

+	return 0;

+}

+

+static int zts8032_read_temp_raw(struct zts8032_data *data)

+{

+	int rc;

+	int rate;

+	int ready;

+	int timeout;

+

+	if (mutex_lock_interruptible(&data->lock))

+		return -EINTR;

+

+	rate = zts8032_get_temp_samp_freq(data);

+	timeout = ZTS8032_POLL_TIMEOUT_US(rate);

+

+	/* Poll for sensor readiness; base the timeout upon the sample rate. */

+	rc = regmap_read_poll_timeout(data->regmap, ZTS8032_MEAS_CFG, ready,

+				      ready & ZTS8032_TMP_RDY,

+				      ZTS8032_POLL_SLEEP_US(timeout), timeout);

+	if (rc < 0)

+		goto done;

+

+	rc = zts8032_read_temp_ready(data);

+

+done:

+	mutex_unlock(&data->lock);

+	return rc;

+}

+

+static bool zts8032_is_writeable_reg(struct device *dev, unsigned int reg)

+{

+	switch (reg) {

+	case ZTS8032_PRS_CFG:

+	case ZTS8032_TMP_CFG:

+	case ZTS8032_MEAS_CFG:

+	case ZTS8032_CFG_REG:

+	case ZTS8032_RESET:

+	/* No documentation available on the registers below */

+	case 0x0e:

+	case 0x0f:

+	case 0x62:

+		return true;

+	default:

+		return false;

+	}

+}

+

+static bool zts8032_is_volatile_reg(struct device *dev, unsigned int reg)

+{

+	switch (reg) {

+	case ZTS8032_PRS_B0:

+	case ZTS8032_PRS_B1:

+	case ZTS8032_PRS_B2:

+	case ZTS8032_TMP_B0:

+	case ZTS8032_TMP_B1:

+	case ZTS8032_TMP_B2:

+	case ZTS8032_MEAS_CFG:

+	case 0x32:	/* No documentation available on this register */

+		return true;

+	default:

+		return false;

+	}

+}

+

+static int zts8032_write_raw(struct iio_dev *iio,

+			    struct iio_chan_spec const *chan, int val,

+			    int val2, long mask)

+{

+	int rc;

+	struct zts8032_data *data = iio_priv(iio);

+

+	if (mutex_lock_interruptible(&data->lock))

+		return -EINTR;

+

+	switch (mask) {

+	case IIO_CHAN_INFO_SAMP_FREQ:

+		switch (chan->type) {

+		case IIO_PRESSURE:

+			rc = zts8032_set_pres_samp_freq(data, val);

+			break;

+

+		case IIO_TEMP:

+			rc = zts8032_set_temp_samp_freq(data, val);

+			break;

+

+		default:

+			rc = -EINVAL;

+			break;

+		}

+		break;

+

+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:

+		switch (chan->type) {

+		case IIO_PRESSURE:

+			rc = zts8032_set_pres_precision(data, val);

+			break;

+

+		case IIO_TEMP:

+			rc = zts8032_set_temp_precision(data, val);

+			break;

+

+		default:

+			rc = -EINVAL;

+			break;

+		}

+		break;

+

+	default:

+		rc = -EINVAL;

+		break;

+	}

+

+	mutex_unlock(&data->lock);

+	return rc;

+}

+

+static int zts8032_calculate_pressure(struct zts8032_data *data)

+{

+	int i;

+	int rc;

+	int t_ready;

+	int kpi = zts8032_get_pres_k(data);

+	int kti = zts8032_get_temp_k(data);

+	s64 rem = 0ULL;

+	s64 pressure = 0ULL;

+	s64 p;

+	s64 t;

+	s64 denoms[9];

+	s64 nums[9];

+	s64 rems[9];

+	s64 kp;

+	s64 kt;

+

+	if (kpi < 0)

+		return kpi;

+

+	if (kti < 0)

+		return kti;

+

+	kp = (s64)kpi;

+	kt = (s64)kti;

+

+	/* Refresh temp if it's ready, otherwise just use the latest value */

+	if (mutex_trylock(&data->lock)) {

+		rc = regmap_read(data->regmap, ZTS8032_MEAS_CFG, &t_ready);

+		if (rc >= 0 && t_ready & ZTS8032_TMP_RDY)

+			zts8032_read_temp_ready(data);

+

+		mutex_unlock(&data->lock);

+	}

+

+	p = (s64)data->pressure_raw;

+	t = (s64)data->temp_raw;

+

+	/* Section 4.9.1 of the ZTS8032 spec; algebra'd to avoid underflow */

+	nums[0] = (s64)data->c00;

+	denoms[0] = 1LL;

+	nums[1] = p * (s64)data->c10;

+	denoms[1] = kp;

+	nums[2] = p * p * (s64)data->c20;

+	denoms[2] = kp * kp;

+	nums[3] = p * p * p * (s64)data->c30;

+	denoms[3] = kp * kp * kp;

+	nums[4] = p * p * p * p * (s64)data->c40;

+	denoms[4] = kp * kp * kp * kp;

+	nums[5] = t * (s64)data->c01;

+	denoms[5] = kt;

+	nums[6] = t * p * (s64)data->c11;

+	denoms[6] = kp * kt;

+	nums[7] = t * p * p * (s64)data->c21;

+	denoms[7] = kp * kp * kt;

+	nums[8] = t * p * p * p * (s64)data->c31;

+	denoms[8] = kp * kp * kp * kt;

+

+	/* Kernel lacks a div64_s64_rem function; denoms are all positive */

+	for (i = 0; i < 9; ++i) {

+		u64 irem;

+

+		if (nums[i] < 0LL) {

+			pressure -= div64_u64_rem(-nums[i], denoms[i], &irem);

+			rems[i] = -irem;

+		} else {

+			pressure += div64_u64_rem(nums[i], denoms[i], &irem);

+			rems[i] = (s64)irem;

+		}

+	}

+

+	/* Increase precision and calculate the remainder sum */

+	for (i = 0; i < 9; ++i)

+		rem += div64_s64((s64)rems[i] * 1000000000LL, denoms[i]);

+

+	pressure += div_s64(rem, 1000000000LL);

+	if (pressure < 0LL)

+		return -ERANGE;

+

+	return (int)min_t(s64, pressure, INT_MAX);

+}

+

+static int zts8032_read_pressure(struct zts8032_data *data, int *val, int *val2,

+				long mask)

+{

+	int rc;

+

+	switch (mask) {

+	case IIO_CHAN_INFO_SAMP_FREQ:

+		rc = zts8032_get_pres_samp_freq(data);

+		if (rc < 0)

+			return rc;

+

+		*val = rc;

+		return IIO_VAL_INT;

+

+	case IIO_CHAN_INFO_PROCESSED:

+		rc = zts8032_read_pres_raw(data);

+		if (rc)

+			return rc;

+

+		rc = zts8032_calculate_pressure(data);

+		if (rc < 0)

+			return rc;

+

+		*val = rc;

+		*val2 = 1000; /* Convert Pa to KPa per IIO ABI */

+		return IIO_VAL_FRACTIONAL;

+

+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:

+		rc = zts8032_get_pres_precision(data);

+		if (rc < 0)

+			return rc;

+

+		*val = rc;

+		return IIO_VAL_INT;

+

+	default:

+		return -EINVAL;

+	}

+}

+

+static int zts8032_calculate_temp(struct zts8032_data *data)

+{

+	s64 c0;

+	s64 t;

+	int kt = zts8032_get_temp_k(data);

+

+	if (kt < 0)

+		return kt;

+

+	/* Obtain inverse-scaled offset */

+	c0 = div_s64((s64)kt * (s64)data->c0, 2);

+

+	/* Add the offset to the unscaled temperature */

+	t = c0 + ((s64)data->temp_raw * (s64)data->c1);

+

+	/* Convert to milliCelsius and scale the temperature */

+	return (int)div_s64(t * 1000LL, kt);

+}

+

+static int zts8032_read_temp(struct zts8032_data *data, int *val, int *val2,

+			    long mask)

+{

+	int rc;

+

+	switch (mask) {

+	case IIO_CHAN_INFO_SAMP_FREQ:

+		rc = zts8032_get_temp_samp_freq(data);

+		if (rc < 0)

+			return rc;

+

+		*val = rc;

+		return IIO_VAL_INT;

+

+	case IIO_CHAN_INFO_PROCESSED:

+		rc = zts8032_read_temp_raw(data);

+		if (rc)

+			return rc;

+

+		rc = zts8032_calculate_temp(data);

+		if (rc < 0)

+			return rc;

+

+		*val = rc;

+		return IIO_VAL_INT;

+

+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:

+		rc = zts8032_get_temp_precision(data);

+		if (rc < 0)

+			return rc;

+

+		*val = rc;

+		return IIO_VAL_INT;

+

+	default:

+		return -EINVAL;

+	}

+}

+

+static int zts8032_read_raw(struct iio_dev *iio,

+			   struct iio_chan_spec const *chan,

+			   int *val, int *val2, long mask)

+{

+	struct zts8032_data *data = iio_priv(iio);

+

+	switch (chan->type) {

+	case IIO_PRESSURE:

+		return zts8032_read_pressure(data, val, val2, mask);

+

+	case IIO_TEMP:

+		return zts8032_read_temp(data, val, val2, mask);

+

+	default:

+		return -EINVAL;

+	}

+}

+

+static void zts8032_reset(void *action_data)

+{

+	struct zts8032_data *data = action_data;

+

+	regmap_write(data->regmap, ZTS8032_RESET, ZTS8032_RESET_MAGIC);

+}

+

+static const struct regmap_config zts8032_regmap_config = {

+	.reg_bits = 8,

+	.val_bits = 8,

+	.writeable_reg = zts8032_is_writeable_reg,

+	.volatile_reg = zts8032_is_volatile_reg,

+	.cache_type = REGCACHE_RBTREE,

+	.max_register = 0x62, /* No documentation available on this register */

+};

+

+static const struct iio_info zts8032_info = {

+	.read_raw = zts8032_read_raw,

+	.write_raw = zts8032_write_raw,

+};

+

+/*

+ * Some verions of chip will read temperatures in the ~60C range when

+ * its actually ~20C. This is the manufacturer recommended workaround

+ * to correct the issue. The registers used below are undocumented.

+ */

+static int zts8032_temp_workaround(struct zts8032_data *data)

+{

+	int rc;

+	int reg;

+

+	rc = regmap_read(data->regmap, 0x32, &reg);

+	if (rc < 0)

+		return rc;

+

+	/*

+	 * If bit 1 is set then the device is okay, and the workaround does not

+	 * need to be applied

+	 */

+	if (reg & BIT(1))

+		return 0;

+

+	rc = regmap_write(data->regmap, 0x0e, 0xA5);

+	if (rc < 0)

+		return rc;

+

+	rc = regmap_write(data->regmap, 0x0f, 0x96);

+	if (rc < 0)

+		return rc;

+

+	rc = regmap_write(data->regmap, 0x62, 0x02);

+	if (rc < 0)

+		return rc;

+

+	rc = regmap_write(data->regmap, 0x0e, 0x00);

+	if (rc < 0)

+		return rc;

+

+	return regmap_write(data->regmap, 0x0f, 0x00);

+}

+

+static int zts8032_probe(struct i2c_client *client,

+			const struct i2c_device_id *id)

+{

+	struct zts8032_data *data;

+	struct iio_dev *iio;

+	int rc, ready;

+

+	iio = devm_iio_device_alloc(&client->dev,  sizeof(*data));

+	if (!iio)

+		return -ENOMEM;

+

+	data = iio_priv(iio);

+	data->client = client;

+	mutex_init(&data->lock);

+

+	iio->name = id->name;

+	iio->channels = zts8032_channels;

+	iio->num_channels = ARRAY_SIZE(zts8032_channels);

+	iio->info = &zts8032_info;

+	iio->modes = INDIO_DIRECT_MODE;

+

+	data->regmap = devm_regmap_init_i2c(client, &zts8032_regmap_config);

+	if (IS_ERR(data->regmap))

+		return PTR_ERR(data->regmap);

+

+	/* Register to run the device reset when the device is removed */

+	rc = devm_add_action_or_reset(&client->dev, zts8032_reset, data);

+	if (rc)

+		return rc;

+

+	/*

+	 * Set up pressure sensor in single sample, one measurement per second

+	 * mode

+	 */

+	rc = regmap_write(data->regmap, ZTS8032_PRS_CFG, 0);

+

+	/*

+	 * Set up external (MEMS) temperature sensor in single sample, one

+	 * measurement per second mode

+	 */

+	rc = regmap_write(data->regmap, ZTS8032_TMP_CFG, ZTS8032_TMP_EXT);

+	if (rc < 0)

+		return rc;

+

+	/* Temp and pressure shifts are disabled when PRC <= 8 */

+	rc = regmap_write_bits(data->regmap, ZTS8032_CFG_REG,

+			       ZTS8032_PRS_SHIFT_EN | ZTS8032_TMP_SHIFT_EN, 0);

+	if (rc < 0)

+		return rc;

+

+	/* MEAS_CFG doesn't update correctly unless first written with 0 */

+	rc = regmap_write_bits(data->regmap, ZTS8032_MEAS_CFG,

+			       ZTS8032_MEAS_CTRL_BITS, 0);

+	if (rc < 0)

+		return rc;

+

+	/* Turn on temperature and pressure measurement in the background */

+	rc = regmap_write_bits(data->regmap, ZTS8032_MEAS_CFG,

+			       ZTS8032_MEAS_CTRL_BITS, ZTS8032_PRS_EN |

+			       ZTS8032_TEMP_EN | ZTS8032_BACKGROUND);

+	if (rc < 0)

+		return rc;

+

+	/*

+	 * Calibration coefficients required for reporting temperature.

+	 * They are available 40ms after the device has started

+	 */

+	rc = regmap_read_poll_timeout(data->regmap, ZTS8032_MEAS_CFG, ready,

+				      ready & ZTS8032_COEF_RDY, 10000, 40000);

+	if (rc < 0)

+		return rc;

+

+	rc = zts8032_get_coefs(data);

+	if (rc < 0)

+		return rc;

+

+	rc = zts8032_temp_workaround(data);

+	if (rc < 0)

+		return rc;

+

+	rc = devm_iio_device_register(&client->dev, iio);

+	if (rc)

+		return rc;

+

+	i2c_set_clientdata(client, iio);

+

+	return 0;

+}

+

+static int zts8032_remove(struct i2c_client *client)

+{

+	return 0;

+}

+

+static const struct i2c_device_id zts8032_id[] = {

+	{ ZTS8032_DEV_NAME, 0 },

+	{}

+};

+MODULE_DEVICE_TABLE(i2c, zts8032_id);

+

+static const struct acpi_device_id zts8032_acpi_match[] = {

+	{ "ZTS8032" },

+	{}

+};

+MODULE_DEVICE_TABLE(acpi, zts8032_acpi_match);

+

+static const struct of_device_id zts8032_of_match[] = {

+	{ .compatible = "zilltek,zts8032", },

+	{ }

+};

+MODULE_DEVICE_TABLE(of, zts8032_of_match);

+

+static struct i2c_driver zts8032_driver = {

+	.driver = {

+		.name = ZTS8032_DEV_NAME,

+		.acpi_match_table = zts8032_acpi_match,

+		.of_match_table = zts8032_of_match,

+	},

+	.probe = zts8032_probe,

+	.remove = zts8032_remove,

+	.id_table = zts8032_id,

+};

+module_i2c_driver(zts8032_driver);

+

+MODULE_AUTHOR("Knight Kuo <knight@zilltek.com>");

+MODULE_DESCRIPTION("Zilltek ZTS8032 pressure and temperature sensor");

+MODULE_LICENSE("GPL v2");

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 1c1eb75..c679247 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
@@ -1558,6 +1558,7 @@
 	dma_addr_t phy_ring_tail;
 	int cnt = MTK_DMA_SIZE;
 	dma_addr_t dma_addr;
+	u64 addr64 = 0;
 	int i;
 
 	if (!eth->soc->has_sram) {
@@ -1597,7 +1598,10 @@
 			txd->txd2 = eth->phy_scratch_ring +
 				(i + 1) * soc->txrx.txd_size;
 
+		addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+			  TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0;
+
-		txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
+		txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64;
 		txd->txd4 = 0;
 
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
@@ -2130,45 +2134,9 @@
 	return NETDEV_TX_OK;
 }
 
-static struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth)
-{
-	int i;
-	struct mtk_rx_ring *ring;
-	int idx;
-
-	for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
-		struct mtk_rx_dma *rxd;
-
-		if (!IS_NORMAL_RING(i) && !IS_HW_LRO_RING(i))
-			continue;
-
-		ring = &eth->rx_ring[i];
-		idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
-		rxd = ring->dma + idx * eth->soc->txrx.rxd_size;
-		if (rxd->rxd2 & RX_DMA_DONE) {
-			ring->calc_idx_update = true;
-			return ring;
-		}
-	}
-
-	return NULL;
-}
-
 static void mtk_update_rx_cpu_idx(struct mtk_eth *eth, struct mtk_rx_ring *ring)
 {
-	int i;
-
-	if (!eth->hwlro)
-		mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
-	else {
-		for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
-			ring = &eth->rx_ring[i];
-			if (ring->calc_idx_update) {
-				ring->calc_idx_update = false;
-				mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
-			}
-		}
-	}
+	mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
 }
 
 static int mtk_poll_rx(struct napi_struct *napi, int budget,
@@ -2192,12 +2160,6 @@
 		dma_addr_t dma_addr = 0;
 		int mac = 0;
 
-		if (eth->hwlro)
-			ring = mtk_get_rx_ring(eth);
-
-		if (unlikely(!ring))
-			goto rx_done;
-
 		idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
 		rxd = ring->dma + idx * eth->soc->txrx.rxd_size;
 		data = ring->data[idx];
@@ -2918,6 +2880,17 @@
 	/* no use PPE cpu reason */
 	mtk_w32(eth, 0xffffffff, MTK_PDMA_LRO_CTRL_DW1);
 
+	/* Set perLRO GRP INT */
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2) ||
+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		mtk_m32(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(1)),
+			MTK_RX_DONE_INT(MTK_HW_LRO_RING(1)), MTK_PDMA_INT_GRP1);
+		mtk_m32(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(2)),
+			MTK_RX_DONE_INT(MTK_HW_LRO_RING(2)), MTK_PDMA_INT_GRP2);
+		mtk_m32(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(3)),
+			MTK_RX_DONE_INT(MTK_HW_LRO_RING(3)), MTK_PDMA_INT_GRP3);
+	}
+
 	return 0;
 }
 
@@ -3171,9 +3144,12 @@
 	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
 
 	/* Set perRSS GRP INT */
-	mtk_w32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(1)), MTK_PDMA_INT_GRP1);
-	mtk_w32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(2)), MTK_PDMA_INT_GRP2);
-	mtk_w32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(3)), MTK_PDMA_INT_GRP3);
+	mtk_m32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(0)),
+		MTK_RX_DONE_INT(MTK_RSS_RING(0)), MTK_PDMA_INT_GRP1);
+	mtk_m32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(1)),
+		MTK_RX_DONE_INT(MTK_RSS_RING(1)), MTK_PDMA_INT_GRP2);
+	mtk_m32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(2)),
+		MTK_RX_DONE_INT(MTK_RSS_RING(2)), MTK_PDMA_INT_GRP3);
 
 	/* Set GRP INT */
 	mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
@@ -3306,9 +3282,8 @@
 		return err;
 
 	if (eth->hwlro) {
-		i = (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) ? 1 : 4;
-		for (; i < MTK_MAX_RX_RING_NUM; i++) {
-			err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_HWLRO);
+		for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) {
+			err = mtk_rx_alloc(eth, MTK_HW_LRO_RING(i), MTK_RX_FLAGS_HWLRO);
 			if (err)
 				return err;
 		}
@@ -3318,8 +3293,8 @@
 	}
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-		for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
-			err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_NORMAL);
+		for (i = 0; i < MTK_RX_RSS_NUM; i++) {
+			err = mtk_rx_alloc(eth, MTK_RSS_RING(i), MTK_RX_FLAGS_NORMAL);
 			if (err)
 				return err;
 		}
@@ -3362,16 +3337,15 @@
 	if (eth->hwlro) {
 		mtk_hwlro_rx_uninit(eth);
 
-		i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) ? 4 : 1;
-		for (; i < MTK_MAX_RX_RING_NUM; i++)
-			mtk_rx_clean(eth, &eth->rx_ring[i], 0);
+		for (i = 0; i < MTK_HW_LRO_RING_NUM; i++)
+			mtk_rx_clean(eth, &eth->rx_ring[MTK_HW_LRO_RING(i)], 0);
 	}
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
 		mtk_rss_uninit(eth);
 
-		for (i = 1; i < MTK_RX_NAPI_NUM; i++)
-			mtk_rx_clean(eth, &eth->rx_ring[i], 1);
+		for (i = 0; i < MTK_RX_RSS_NUM; i++)
+			mtk_rx_clean(eth, &eth->rx_ring[MTK_RSS_RING(i)], 1);
 	}
 
 	if (eth->scratch_head) {
@@ -3399,6 +3373,10 @@
 	struct mtk_eth *eth = rx_napi->eth;
 	struct mtk_rx_ring *ring = rx_napi->rx_ring;
 
+	if (unlikely(!(mtk_r32(eth, eth->soc->reg_map->pdma.irq_status) &
+		       MTK_RX_DONE_INT(ring->ring_no))))
+		return IRQ_NONE;
+
 	if (likely(napi_schedule_prep(&rx_napi->napi))) {
 		mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(ring->ring_no));
 		__napi_schedule(&rx_napi->napi);
@@ -3603,12 +3581,19 @@
 		mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0));
 
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-			for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
-				napi_enable(&eth->rx_napi[i].napi);
-				mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(i));
+			for (i = 0; i < MTK_RX_RSS_NUM; i++) {
+				napi_enable(&eth->rx_napi[MTK_RSS_RING(i)].napi);
+				mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(MTK_RSS_RING(i)));
 			}
 		}
 
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
+			for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) {
+				napi_enable(&eth->rx_napi[MTK_HW_LRO_RING(i)].napi);
+				mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i)));
+			}
+		}
+
 		refcount_set(&eth->dma_refcnt, 1);
 	}
 	else
@@ -3717,12 +3702,19 @@
 	napi_disable(&eth->rx_napi[0].napi);
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-		for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
-			mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(i));
-			napi_disable(&eth->rx_napi[i].napi);
+		for (i = 0; i < MTK_RX_RSS_NUM; i++) {
+			mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(MTK_RSS_RING(i)));
+			napi_disable(&eth->rx_napi[MTK_RSS_RING(i)].napi);
 		}
 	}
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
+		for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) {
+			mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i)));
+			napi_disable(&eth->rx_napi[MTK_HW_LRO_RING(i)].napi);
+		}
+	}
+
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
 		mtk_stop_dma(eth, eth->soc->reg_map->qdma.glo_cfg);
 	mtk_stop_dma(eth, eth->soc->reg_map->pdma.glo_cfg);
@@ -3791,14 +3783,23 @@
 	rx_napi->irq_grp_no = 2;
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-		for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
-			rx_napi = &eth->rx_napi[i];
+		for (i = 0; i < MTK_RX_RSS_NUM; i++) {
+			rx_napi = &eth->rx_napi[MTK_RSS_RING(i)];
 			rx_napi->eth = eth;
-			rx_napi->rx_ring = &eth->rx_ring[i];
+			rx_napi->rx_ring = &eth->rx_ring[MTK_RSS_RING(i)];
 			rx_napi->irq_grp_no = 2 + i;
 		}
 	}
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
+		for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) {
+			rx_napi = &eth->rx_napi[MTK_HW_LRO_RING(i)];
+			rx_napi->eth = eth;
+			rx_napi->rx_ring = &eth->rx_ring[MTK_HW_LRO_RING(i)];
+			rx_napi->irq_grp_no = 2;
+		}
+	}
+
 	return 0;
 }
 
@@ -4957,7 +4958,7 @@
 		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
 		if (!err) {
 			err = dma_set_coherent_mask(&pdev->dev,
-						    DMA_BIT_MASK(36));
+						    DMA_BIT_MASK(32));
 			if (err) {
 				dev_err(&pdev->dev, "Wrong DMA config\n");
 				return -EINVAL;
@@ -5131,18 +5132,32 @@
 			goto err_free_dev;
 
 		err = devm_request_irq(eth->dev, eth->irq_pdma[0],
-				       mtk_handle_irq_rx, 0,
+				       mtk_handle_irq_rx, IRQF_SHARED,
 				       dev_name(eth->dev), &eth->rx_napi[0]);
 		if (err)
 			goto err_free_dev;
 
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-			for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
+			for (i = 0; i < MTK_RX_RSS_NUM; i++) {
+				err = devm_request_irq(eth->dev,
+						       eth->irq_pdma[MTK_RSS_RING(i)],
+						       mtk_handle_irq_rx, IRQF_SHARED,
+						       dev_name(eth->dev),
+						       &eth->rx_napi[MTK_RSS_RING(i)]);
+				if (err)
+					goto err_free_dev;
+			}
+		}
+
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
+			i = (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2) ||
+			     MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) ? 0 : 1;
+			for (; i < MTK_HW_LRO_RING_NUM; i++) {
 				err = devm_request_irq(eth->dev,
 						       eth->irq_pdma[i],
-						       mtk_handle_irq_rx, 0,
+						       mtk_handle_irq_rx, IRQF_SHARED,
 						       dev_name(eth->dev),
-						       &eth->rx_napi[i]);
+						       &eth->rx_napi[MTK_HW_LRO_RING(i)]);
 				if (err)
 					goto err_free_dev;
 			}
@@ -5183,9 +5198,16 @@
 		       MTK_NAPI_WEIGHT);
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-		for (i = 1; i < MTK_RX_NAPI_NUM; i++)
-			netif_napi_add(&eth->dummy_dev, &eth->rx_napi[i].napi,
+		for (i = 0; i < MTK_RX_RSS_NUM; i++)
+			netif_napi_add(&eth->dummy_dev, &eth->rx_napi[MTK_RSS_RING(i)].napi,
+				       mtk_napi_rx, MTK_NAPI_WEIGHT);
+	}
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWLRO)) {
+		for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) {
+			netif_napi_add(&eth->dummy_dev, &eth->rx_napi[MTK_HW_LRO_RING(i)].napi,
 				       mtk_napi_rx, MTK_NAPI_WEIGHT);
+		}
 	}
 
 	mtketh_debugfs_init(eth);
@@ -5371,7 +5393,7 @@
 static const struct mtk_soc_data mt7988_data = {
 	.reg_map = &mt7988_reg_map,
 	.ana_rgc3 = 0x128,
-	.caps = MT7988_CAPS,
+	.caps = MT7988_CAPS | MTK_HWLRO,
 	.hw_features = MTK_HW_FEATURES,
 	.required_clks = MT7988_CLKS_BITMAP,
 	.required_pctl = false,
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 737031e..0e658b0 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
@@ -52,7 +52,7 @@
 
 #define MTK_QRX_OFFSET		0x10
 
-#define MTK_HW_LRO_DMA_SIZE	8
+#define MTK_HW_LRO_DMA_SIZE	64
 
 #define	MTK_MAX_LRO_RX_LENGTH		(4096 * 3)
 #define	MTK_MAX_LRO_IP_CNT		2
@@ -220,6 +220,7 @@
 #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_MAX_RX_RING_NUM		(8)
 #define MTK_HW_LRO_RING_NUM		(4)
+#define MTK_HW_LRO_RING(x)		((x) + 4)
 #define IS_HW_LRO_RING(ring_no)		(((ring_no) > 3) && ((ring_no) < 8))
 #define MTK_PDMA_LRO_CTRL_DW0		(PDMA_BASE + 0x408)
 #define MTK_LRO_ALT_SCORE_DELTA		(PDMA_BASE + 0x41c)
@@ -233,6 +234,7 @@
 #else
 #define MTK_MAX_RX_RING_NUM		(4)
 #define MTK_HW_LRO_RING_NUM		(3)
+#define MTK_HW_LRO_RING(x)		((x) + 1)
 #define IS_HW_LRO_RING(ring_no)		(((ring_no) > 0) && ((ring_no) < 4))
 #define MTK_PDMA_LRO_CTRL_DW0		(PDMA_BASE + 0x180)
 #define MTK_LRO_ALT_SCORE_DELTA		(PDMA_BASE + 0x24c)
@@ -266,8 +268,9 @@
 #else
 #define MTK_PDMA_RSS_GLO_CFG		0x2800
 #endif
-#define MTK_RX_NAPI_NUM			(4)
-#define MTK_RSS_RING(x)			(x)
+#define MTK_RX_NAPI_NUM			(8)
+#define MTK_RX_RSS_NUM			(3)
+#define MTK_RSS_RING(x)			((x) + 1)
 #define MTK_RSS_EN			BIT(0)
 #define MTK_RSS_CFG_REQ			BIT(2)
 #define MTK_RSS_IPV6_STATIC_HASH	(0x7 << 8)
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 37d5d20..f575f1b 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
@@ -151,9 +151,11 @@
 			cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE2);
 		else if (CFG_PPE_NUM == 3 && id == NR_GMAC2_PORT)
 			cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE1);
-#endif
+		else
+			cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE);
+#else
 		cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE);
-
+#endif
 		return;
 	}
 
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 800c821..3c16948 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,11 +112,9 @@
 #define skb_hnat_hf(skb) (((struct hnat_desc *)((skb)->head))->hf)
 #define skb_hnat_amsdu(skb) (((struct hnat_desc *)((skb)->head))->amsdu)
 #define skb_hnat_ppe2(skb)						\
-	((skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN2 ||			\
-	 skb_hnat_iface(skb) == FOE_MAGIC_WED2) && CFG_PPE_NUM == 3)
+	((skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN2) && (CFG_PPE_NUM == 3))
 #define skb_hnat_ppe1(skb)						\
-	((skb_hnat_iface(skb) == FOE_MAGIC_GE_WAN && CFG_PPE_NUM == 3) ||	\
-	 (skb_hnat_iface(skb) == FOE_MAGIC_WED1 && CFG_PPE_NUM > 1))
+	((skb_hnat_iface(skb) == FOE_MAGIC_GE_WAN) && (CFG_PPE_NUM == 3))
 #define skb_hnat_ppe(skb)						\
 	(skb_hnat_ppe2(skb) ? 2 : (skb_hnat_ppe1(skb) ? 1 : 0))
 #define headroom_iface(h) (h.iface)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
index ec6efb9..528abb1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
@@ -248,7 +248,7 @@
 index 0000000..27b5be5
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -0,0 +1,510 @@
+@@ -0,0 +1,514 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +/* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
 +
@@ -676,7 +676,7 @@
 +			 MTK_PPE_KEEPALIVE_DISABLE) |
 +	      FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) |
 +	      FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE,
-+			 MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) |
++			 MTK_PPE_SCAN_MODE_CHECK_AGE) |
 +	      FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM,
 +			 MTK_PPE_ENTRIES_SHIFT);
 +	ppe_w32(ppe, MTK_PPE_TB_CFG, val);
@@ -745,19 +745,23 @@
 +
 +	mtk_ppe_cache_enable(ppe, false);
 +
-+	/* disable offload engine */
-+	ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN);
-+	ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0);
-+
 +	/* disable aging */
 +	val = MTK_PPE_TB_CFG_AGE_NON_L4 |
 +	      MTK_PPE_TB_CFG_AGE_UNBIND |
 +	      MTK_PPE_TB_CFG_AGE_TCP |
 +	      MTK_PPE_TB_CFG_AGE_UDP |
-+	      MTK_PPE_TB_CFG_AGE_TCP_FIN;
++	      MTK_PPE_TB_CFG_AGE_TCP_FIN |
++	      MTK_PPE_TB_CFG_SCAN_MODE;
 +	ppe_clear(ppe, MTK_PPE_TB_CFG, val);
 +
-+	return mtk_ppe_wait_busy(ppe);
++	if (mtk_ppe_wait_busy(ppe))
++		return -ETIMEDOUT;
++
++	/* disable offload engine */
++	ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN);
++	ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0);
++
++	return 0;
 +}
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
 new file mode 100644
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 062dace..661b93f 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
@@ -196,22 +196,24 @@
  	u8				ppe_num;
  	struct mtk_ppe			*ppe[MTK_MAX_PPE_NUM];
  	struct rhashtable		flow_table;
-@@ -1936,6 +1967,34 @@ extern const struct of_device_id of_mtk_match[];
+@@ -1936,6 +1967,36 @@ extern const struct of_device_id of_mtk_match[];
  extern u32 mtk_hwlro_stats_ebl;
  extern u32 dbg_show_level;
  
 +static inline void mtk_set_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe, u32 val)
 +{
-+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
-+		foe->ib1 |= FIELD_PREP(MTK_FOE_IB1_UNBIND_SRC_PORT, val);
++#if defined(CONFIG_MEDIATEK_NETSYS_V2)
++	foe->ib1 |= FIELD_PREP(MTK_FOE_IB1_UNBIND_SRC_PORT, val);
++#endif
 +}
 +
 +static inline u32 mtk_get_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe)
 +{
-+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
-+		return FIELD_GET(MTK_FOE_IB1_UNBIND_SRC_PORT, foe->ib1);
-+
++#if defined(CONFIG_MEDIATEK_NETSYS_V2)
++	return FIELD_GET(MTK_FOE_IB1_UNBIND_SRC_PORT, foe->ib1);
++#else
 +	return 0;
++#endif
 +}
 +
 +static inline int
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
index 036f531..ef970de 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
@@ -1,21 +1,22 @@
-From 6a91e5e7304b98d06b589de7f9f09cc34cb9c231 Mon Sep 17 00:00:00 2001
-From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
-Date: Mon, 18 Sep 2023 11:15:14 +0800
-Subject: [PATCH 16/22] ethernet-update-ppe-from-mt7986-to-mt7988
+From 1e2da129898cd45b4196c0aaf2de9d0e9ed46d77 Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Wed, 25 Oct 2023 11:39:09 +0800
+Subject: [PATCH 16/22] ethernet-update-ppe-from-netsys2-to-netsys3
 
 ---
  drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 14 ++++---
  drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  9 +++--
- drivers/net/ethernet/mediatek/mtk_ppe.c       | 18 ++++++---
+ drivers/net/ethernet/mediatek/mtk_ppe.c       | 31 ++++++++++++---
  drivers/net/ethernet/mediatek/mtk_ppe.h       | 38 ++++++++++++++++---
  .../net/ethernet/mediatek/mtk_ppe_offload.c   |  6 ++-
- 5 files changed, 64 insertions(+), 21 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_ppe_regs.h  |  5 +++
+ 6 files changed, 81 insertions(+), 22 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 0f6613b..8bd526a 100644
+index 31c60a0..37355d9 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2286,17 +2286,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2244,17 +2244,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
  			skb_checksum_none_assert(skb);
  		skb->protocol = eth_type_trans(skb, netdev);
  
@@ -37,7 +38,7 @@
  		reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
  		if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
  			for (i = 0; i < eth->ppe_num; i++) {
-@@ -5252,7 +5252,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5262,7 +5262,8 @@ static int mtk_probe(struct platform_device *pdev)
  
  		for (i = 0; i < eth->ppe_num; i++) {
  			eth->ppe[i] = mtk_ppe_init(eth,
@@ -47,7 +48,7 @@
  						   2, eth->soc->hash_way, i,
  						   eth->soc->has_accounting);
  			if (!eth->ppe[i]) {
-@@ -5512,6 +5513,9 @@ static const struct mtk_soc_data mt7988_data = {
+@@ -5529,6 +5530,9 @@ static const struct mtk_soc_data mt7988_data = {
  	.required_clks = MT7988_CLKS_BITMAP,
  	.required_pctl = false,
  	.has_sram = true,
@@ -58,7 +59,7 @@
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 7ea380e..23c5f49 100644
+index 0282d25..48ecdc8 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 @@ -130,9 +130,10 @@
@@ -73,29 +74,62 @@
  #else
  #define MTK_GDMA_TO_PPE0	0x4444
  #endif
-@@ -1969,13 +1970,15 @@ extern u32 dbg_show_level;
+@@ -1972,13 +1973,13 @@ extern u32 dbg_show_level;
  
  static inline void mtk_set_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe, u32 val)
  {
--	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
-+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
-+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
- 		foe->ib1 |= FIELD_PREP(MTK_FOE_IB1_UNBIND_SRC_PORT, val);
+-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
++#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+ 	foe->ib1 |= FIELD_PREP(MTK_FOE_IB1_UNBIND_SRC_PORT, val);
+ #endif
  }
  
  static inline u32 mtk_get_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe)
  {
--	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
-+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
-+	    MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
- 		return FIELD_GET(MTK_FOE_IB1_UNBIND_SRC_PORT, foe->ib1);
- 
+-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
++#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+ 	return FIELD_GET(MTK_FOE_IB1_UNBIND_SRC_PORT, foe->ib1);
+ #else
  	return 0;
+ #endif
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 6d6c1e4..446acca 100755
+index 1ed1b60..5a1036f 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -211,7 +211,7 @@ int mtk_foe_entry_prepare(struct mtk_foe_entry *entry, int type, int l4proto,
+@@ -91,7 +91,7 @@ static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
+ 
+ int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
+ {
+-	u32 val, cnt_r0, cnt_r1, cnt_r2;
++	u32 val, cnt_r0, cnt_r1, cnt_r2, cnt_r3;
+ 	u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high;
+ 
+ 	val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST;
+@@ -104,12 +104,23 @@ int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
+ 	cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1);
+ 	cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2);
+ 
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++	cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3);
++
++	byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0);
++	byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH_V2, cnt_r1);
++	pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_LOW_V2, cnt_r2);
++	pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R3_PKT_CNT_HIGH, cnt_r3);
++	*bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low;
++	*packets = ((u64)pkt_cnt_high << 32) | pkt_cnt_low;
++#else
+ 	byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0);
+ 	byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1);
+ 	pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1);
+ 	pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2);
+ 	*bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low;
+ 	*packets = (pkt_cnt_high << 16) | pkt_cnt_low;
++#endif
+ 
+ 	return 0;
+ }
+@@ -211,7 +222,7 @@ int mtk_foe_entry_prepare(struct mtk_foe_entry *entry, int type, int l4proto,
  	      MTK_FOE_IB1_BIND_CACHE;
  	entry->ib1 = val;
  
@@ -104,7 +138,7 @@
  	val = FIELD_PREP(MTK_FOE_IB2_PORT_AG, 0xf) |
  #else
  	val = FIELD_PREP(MTK_FOE_IB2_PORT_MG, 0x3f) |
-@@ -403,7 +403,7 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+@@ -403,7 +414,7 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
  
  	*ib2 &= ~MTK_FOE_IB2_PORT_MG;
  	*ib2 |= MTK_FOE_IB2_WDMA_WINFO;
@@ -113,7 +147,7 @@
  	*ib2 |=  FIELD_PREP(MTK_FOE_IB2_RX_IDX, txq);
  
  	l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) |
-@@ -422,11 +422,16 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+@@ -422,11 +433,16 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
  
  int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
  {
@@ -130,7 +164,7 @@
  
  	return 0;
  }
-@@ -922,13 +927,16 @@ int mtk_ppe_start(struct mtk_ppe *ppe)
+@@ -922,13 +938,16 @@ int mtk_ppe_start(struct mtk_ppe *ppe)
  	mtk_ppe_init_foe_table(ppe);
  	ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys);
  
@@ -149,7 +183,7 @@
  	      MTK_PPE_TB_CFG_INFO_SEL |
  #endif
  	      FIELD_PREP(MTK_PPE_TB_CFG_SEARCH_MISS,
-@@ -993,7 +1001,7 @@ int mtk_ppe_start(struct mtk_ppe *ppe)
+@@ -993,7 +1012,7 @@ int mtk_ppe_start(struct mtk_ppe *ppe)
  
  	ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0);
  
@@ -273,6 +307,25 @@
  	if (idev && idev->netdev_ops->ndo_fill_receive_path) {
  		ctx.dev = idev;
  		idev->netdev_ops->ndo_fill_receive_path(&ctx, &path);
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
+index 8d3ebe1..f8425df 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
+@@ -155,9 +155,14 @@ enum {
+ #define MTK_PPE_MIB_SER_R1			0x344
+ #define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW		GENMASK(31, 16)
+ #define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH	GENMASK(15, 0)
++#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH_V2	GENMASK(31, 0)
+ 
+ #define MTK_PPE_MIB_SER_R2			0x348
+ #define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH		GENMASK(23, 0)
++#define MTK_PPE_MIB_SER_R2_PKT_CNT_LOW_V2	GENMASK(31, 0)
++
++#define MTK_PPE_MIB_SER_R3			0x34C
++#define MTK_PPE_MIB_SER_R3_PKT_CNT_HIGH		GENMASK(31, 0)
+ 
+ #define MTK_PPE_MIB_CACHE_CTL			0x350
+ #define MTK_PPE_MIB_CACHE_CTL_EN		BIT(0)
 -- 
 2.18.0
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
index 53b5f30..33046cd 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
@@ -547,3 +547,5 @@
 # CONFIG_BPF_KPROBE_OVERRIDE is not set
 # CONFIG_HIST_TRIGGERS is not set
 # CONFIG_FUNCTION_ERROR_INJECTION is not set
+CONFIG_RICHTEK_RTQ6056=y
+CONFIG_ZTS8032=y
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
index fb27f0d..06ec24b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -518,3 +518,5 @@
 # CONFIG_BPF_KPROBE_OVERRIDE is not set
 # CONFIG_HIST_TRIGGERS is not set
 # CONFIG_FUNCTION_ERROR_INJECTION is not set
+CONFIG_RICHTEK_RTQ6056=y
+CONFIG_ZTS8032=y
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2531-iio-add-zts8032-config.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2531-iio-add-zts8032-config.patch
new file mode 100644
index 0000000..f3cb997
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2531-iio-add-zts8032-config.patch
@@ -0,0 +1,43 @@
+From 5b5c99a5cc6b6e2ec0fd3a5477a0e96868d09cd3 Mon Sep 17 00:00:00 2001
+From: Sam Shih <sam.shih@mediatek.com>
+Date: Wed, 11 Oct 2023 13:51:14 +0800
+Subject: [PATCH] add config
+
+---
+ drivers/iio/pressure/Kconfig  | 7 +++++++
+ drivers/iio/pressure/Makefile | 1 +
+ 2 files changed, 8 insertions(+)
+
+diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
+index ba420e4..83bf432 100644
+--- a/drivers/iio/pressure/Kconfig
++++ b/drivers/iio/pressure/Kconfig
+@@ -64,6 +64,13 @@ config DPS310
+ 	  This driver can also be built as a module.  If so, the module will be
+ 	  called dps310.
+ 
++config ZTS8032
++	tristate "Zilltek ZTS8032 barometric pressure sensor"
++	depends on I2C
++	select REGMAP_I2C
++	help
++	  Support for the Zilltek ZTS8032 barometric pressure sensor.
++
+ config HID_SENSOR_PRESS
+ 	depends on HID_SENSOR_HUB
+ 	select IIO_BUFFER
+diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
+index d8f5ace..2433aad 100644
+--- a/drivers/iio/pressure/Makefile
++++ b/drivers/iio/pressure/Makefile
+@@ -10,6 +10,7 @@ bmp280-objs := bmp280-core.o bmp280-regmap.o
+ obj-$(CONFIG_BMP280_I2C) += bmp280-i2c.o
+ obj-$(CONFIG_BMP280_SPI) += bmp280-spi.o
+ obj-$(CONFIG_DPS310) += dps310.o
++obj-$(CONFIG_ZTS8032) += zts8032.o
+ obj-$(CONFIG_IIO_CROS_EC_BARO) += cros_ec_baro.o
+ obj-$(CONFIG_HID_SENSOR_PRESS)   += hid-sensor-press.o
+ obj-$(CONFIG_HP03) += hp03.o
+-- 
+2.18.0
+
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 e4bde13..af8b569 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
@@ -114,6 +114,7 @@
     file://999-2502-cpufreq-add-mt7988a-spim-snand-support.patch \
     file://999-2503-cpufreq-mtk-vbining-add-mt7988-support.patch \
     file://999-2530-add-pmic-config.patch \
+    file://999-2531-iio-add-zts8032-config.patch \
     file://999-2550-dual-image-mount-rootfs.patch \
     file://999-2600-pcie-add-pcie-gen3-upstream-driver.patch \
     file://999-2601-pcie-add-multi-MSI-support.patch \