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

[Description]
8bbd77c [kernel][common][eth][Add 1000basex AN support for the SGMII]
ea141fa [mt7988][dts][Change mt7988 snfi dts to change ubi partition size align with spim]
1f40e40 [kernel][common][eth][Update power level parse function for the SFP]
1c921c6 [kernel][common][eth][Fix MINI-GBIC-GT v8.1 SFP IOT issue]
f1c42d3 [kernel][common][eth][Add 10000baseCR_Full capability to USXGMII for the SFP+]
9186b59 [kernel][mt7981][eth][mediatek-ge: Change TX amplitude from 89% to 100% on MT7981 now]
a0af641 [kernel][mt7988][Fix USXGMII to SGMII mode change issue]
c0f7841 [kernel][mt7988][eth][Refactor SER triggering condition for the XGDM to GDM dynamically change]
21e3d36 [kernel][mt7988][Fix SGMII to USXGMII mode change issue for the 10G SFP+ optical module]
7814223 [openwrt][mt7988][eth][Add HW version check for MT7988]
f1f4a6a [kernel][common][hnat][Fix the conditions for NAT66 binding]
8a3d83f [mt7988][gps][Add uart1 to gsw for Airoha gnss server anld]
c95912a [kernel][mt7988][dts][add dts to limit mt7988a pcie and cpu as mt7988d]
632cbdc [Add PCIe max link width adjustment feature]

[Release-log]

Change-Id: I9e24aab6e06280fe5a50febf490bf1ce704e1757
diff --git a/recipes-devtools/smp/files/smp-mt76.sh b/recipes-devtools/smp/files/smp-mt76.sh
index c76e2f8..cc5b46b 100644
--- a/recipes-devtools/smp/files/smp-mt76.sh
+++ b/recipes-devtools/smp/files/smp-mt76.sh
@@ -14,7 +14,8 @@
 WIFI_RADIO3=0
 WED_ENABLE=0
 
-module_param=/sys/module/mt7915e/parameters/wed_enable
+WIFI_MODULE_LIST='mt7915e mt7996e'
+
 get_if_info()
 {
 	# try to get all wifi and eth net interface.
@@ -54,15 +55,15 @@
 		fi
 	done;
 
-	WED_ENABLE_LIST=
-	if [[ -f "$module_param" ]]; then
-		WED_ENABLE_LIST=`cat $module_param`
-	fi
-	for v in $WED_ENABLE_LIST;
+
+	for v in $WIFI_MODULE_LIST;
 	do
-		dbg2 "wed enable ori info $v"
-		if [[ $v == "Y" ]]; then
-			WED_ENABLE=1
+		if [[ -f "/sys/module/$v/parameters/wed_enable" ]]; then
+			WED_ENABLE_LIST=`cat /sys/module/$v/parameters/wed_enable`
+			dbg2 "wed enable ori info $v $WED_ENABLE_LIST"
+			if [[ $WED_ENABLE_LIST == "Y" ]]; then
+				WED_ENABLE=1
+			fi
 		fi
 	done;
 	dbg2 "NUM_WIFI_CARD = $NUM_WIFI_CARD"
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 c9da613..28cb8eb 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
@@ -127,6 +127,11 @@
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
 	};
 
+	hwver: hwver {
+		compatible = "mediatek,hwver", "syscon";
+		reg = <0 0x8000000 0 0x1000>;
+	};
+
 	thermal-zones {
 		cpu_thermal: cpu-thermal {
 			polling-delay-passive = <1000>;
@@ -841,6 +846,7 @@
 		mediatek,xfi_pll = <&xfi_pll>;
 		mediatek,infracfg = <&topmisc>;
 		mediatek,toprgu = <&watchdog>;
+		mediatek,hwver = <&hwver>;
 		#reset-cells = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
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
new file mode 100644
index 0000000..8aa687e
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
@@ -0,0 +1,532 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+	model = "MediaTek MT7988A as 88D DSA 10G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988a-88d-10g-spim-snand",
+		     /* Reserve this for DVFS if creating new dts */
+		     "mediatek,mt7988";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n1 loglevel=8  \
+			    earlycon=uart8250,mmio32,0x11000000 \
+			    pci=pcie_bus_perf";
+	};
+
+	cpus {
+		/delete-node/ cpu@3;
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x10000000>;
+	};
+
+	nmbm_spim_nand {
+		compatible = "generic,nmbm";
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		lower-mtd-device = <&spi_nand>;
+		forced-create;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "BL2";
+				reg = <0x00000 0x0100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "u-boot-env";
+				reg = <0x0100000 0x0080000>;
+			};
+
+			factory: partition@180000 {
+				label = "Factory";
+				reg = <0x180000 0x0400000>;
+			};
+
+			partition@580000 {
+				label = "FIP";
+				reg = <0x580000 0x0200000>;
+			};
+
+			partition@780000 {
+				label = "ubi";
+				reg = <0x780000 0x7080000>;
+			};
+		};
+	};
+
+	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>;
+	};
+
+	sound_wm8960 {
+		compatible = "mediatek,mt79xx-wm8960-machine";
+		mediatek,platform = <&afe>;
+		audio-routing = "Headphone", "HP_L",
+				"Headphone", "HP_R",
+				"LINPUT1", "AMIC",
+				"RINPUT1", "AMIC";
+		mediatek,audio-codec = <&wm8960>;
+		status = "disabled";
+	};
+
+	sound_si3218x {
+		compatible = "mediatek,mt79xx-si3218x-machine";
+		mediatek,platform = <&afe>;
+		mediatek,ext-codec = <&proslic_spi>;
+		status = "disabled";
+	};
+};
+
+&fan {
+	pwms = <&pwm 0 50000 0>;
+	status = "okay";
+};
+
+&afe {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcm_pins>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	rt5190a_64: rt5190a@64 {
+		compatible = "richtek,rt5190a";
+		reg = <0x64>;
+		/*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
+		vin2-supply = <&rt5190_buck1>;
+		vin3-supply = <&rt5190_buck1>;
+		vin4-supply = <&rt5190_buck1>;
+
+		regulators {
+			rt5190_buck1: buck1 {
+				regulator-name = "rt5190a-buck1";
+				regulator-min-microvolt = <5090000>;
+				regulator-max-microvolt = <5090000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			buck2 {
+				regulator-name = "vcore";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck3 {
+				regulator-name = "proc";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+			};
+			buck4 {
+				regulator-name = "rt5190a-buck4";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-allowed-modes =
+				<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+				regulator-boot-on;
+			};
+			ldo {
+				regulator-name = "rt5190a-ldo";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+
+	wm8960: wm8960@1a {
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+	};
+
+	dps368: dps368@77 {
+		compatible = "infineon,dps310";
+		reg = <0x77>;
+	};
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_flash_pins>;
+	status = "okay";
+
+	spi_nand: spi_nand@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-nand";
+		spi-cal-enable;
+		spi-cal-mode = "read-data";
+		spi-cal-datalen = <7>;
+		spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+		spi-cal-addrlen = <5>;
+		spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+		reg = <0>;
+		spi-max-frequency = <52000000>;
+		spi-tx-buswidth = <4>;
+		spi-rx-buswidth = <4>;
+	};
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	/* pin shared with snfi */
+	pinctrl-0 = <&spic_pins>;
+	status = "disabled";
+
+	proslic_spi: proslic_spi@0 {
+		compatible = "silabs,proslic_spi";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+		spi-cpha = <1>;
+		spi-cpol = <1>;
+		channel_count = <1>;
+		debug_level = <4>;       /* 1 = TRC, 2 = DBG, 4 = ERR */
+		reset_gpio = <&pio 54 0>;
+		ig,enable-spi = <1>;     /* 1: Enable, 0: Disable */
+	};
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_pins>;
+	max-link-width = <1>;
+	status = "okay";
+};
+
+&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_8mA>;
+		};
+	};
+
+	gbe_led0_pins: gbe-pins {
+		mux {
+			function = "led";
+			groups = "gbe_led0";
+		};
+	};
+
+	i2c0_pins: i2c0-pins-g0 {
+		mux {
+			function = "i2c";
+			groups = "i2c0_1";
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+				 "pcie_wake_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";
+		};
+	};
+
+	spi0_flash_pins: spi0-pins {
+		mux {
+			function = "spi";
+			groups = "spi0", "spi0_wp_hold";
+		};
+	};
+
+	spic_pins: spi1-pins {
+		mux {
+			function = "spi";
+			groups = "spi1";
+		};
+	};
+
+	i2c1_pins: i2c1-pins {
+		mux {
+			function = "i2c";
+			groups = "i2c1_0";
+		};
+	};
+
+	i2s_pins: i2s-pins {
+		mux {
+			function = "audio";
+			groups = "i2s";
+		};
+	};
+
+	pcm_pins: pcm-pins {
+		mux {
+			function = "audio";
+			groups = "pcm";
+		};
+	};
+
+	uart1_pins: uart1-pins {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
+};
+
+&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 = "usxgmii";
+		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 {
+			reg = <0>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 72 1>;
+			reset-assert-us = <100000>;
+			reset-deassert-us = <221000>;
+		};
+
+		phy1: ethernet-phy@8 {
+			reg = <8>;
+			compatible = "ethernet-phy-ieee802.3-c45";
+			reset-gpios = <&pio 71 1>;
+			reset-assert-us = <100000>;
+			reset-deassert-us = <221000>;
+		};
+
+		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>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&gbe_led0_pins>;
+
+				sphy0: switch_phy0@0 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <0>;
+					phy-mode = "gmii";
+					rext = "efuse";
+					tx_r50 = "efuse";
+					nvmem-cells = <&phy_calibration_p0>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy1: switch_phy1@1 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <1>;
+					phy-mode = "gmii";
+					rext = "efuse";
+					tx_r50 = "efuse";
+					nvmem-cells = <&phy_calibration_p1>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy2: switch_phy2@2 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <2>;
+					phy-mode = "gmii";
+					rext = "efuse";
+					tx_r50 = "efuse";
+					nvmem-cells = <&phy_calibration_p2>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+
+				sphy3: switch_phy3@3 {
+					compatible = "ethernet-phy-id03a2.9481";
+					reg = <3>;
+					phy-mode = "gmii";
+					rext = "efuse";
+					tx_r50 = "efuse";
+					nvmem-cells = <&phy_calibration_p3>;
+					nvmem-cell-names = "phy-cal-data";
+				};
+			};
+		};
+	};
+};
+
+&hnat {
+	mtketh-wan = "eth1";
+	mtketh-lan = "lan";
+	mtketh-lan2 = "eth2";
+	mtketh-max-gmac = <3>;
+	status = "okay";
+};
+
+&slot0 {
+	mt7996@0,0 {
+		reg = <0x0000 0 0 0 0>;
+		device_type = "pci";
+		mediatek,mtd-eeprom = <&factory 0x0>;
+	};
+};
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 c4b2721..adbfb7c 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
@@ -61,7 +61,7 @@
 
 			partition@780000 {
 				label = "ubi";
-				reg = <0x780000 0x4000000>;
+				reg = <0x780000 0x7080000>;
 			};
 		};
 	};
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 407b8ed..de90f42 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
@@ -161,6 +161,12 @@
 	status = "okay";
 };
 
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
+
 &spi0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&spi0_flash_pins>;
@@ -307,6 +313,13 @@
 			groups = "spi1";
 		};
 	};
+
+	uart1_pins: uart1-pins {
+		mux {
+			function = "uart";
+			groups = "uart1_2";
+		};
+	};
 };
 
 &watchdog {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts
index 53b9668..972452f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts
@@ -61,7 +61,7 @@
 
 			partition@780000 {
 				label = "ubi";
-				reg = <0x780000 0x4000000>;
+				reg = <0x780000 0x7080000>;
 			};
 		};
 	};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index b70fc72..ec7167b 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -28,6 +28,7 @@
 #define MTK_FE_CDM6_FSM			0x328
 #define MTK_FE_GDM1_FSM			0x228
 #define MTK_FE_GDM2_FSM			0x22C
+#define MTK_FE_GDM3_FSM			0x23C
 #define MTK_FE_PSE_FREE			0x240
 #define MTK_FE_DROP_FQ			0x244
 #define MTK_FE_DROP_FC			0x248
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 05a5595..686ddda 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -40,7 +40,6 @@
 static int mtk_msg_level = -1;
 atomic_t reset_lock = ATOMIC_INIT(0);
 atomic_t force = ATOMIC_INIT(0);
-atomic_t reset_pending = ATOMIC_INIT(0);
 
 module_param_named(msg_level, mtk_msg_level, int, 0);
 MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)");
@@ -462,6 +461,28 @@
 	mtk_w32(eth, val, MTK_GSW_CFG);
 }
 
+static bool mtk_check_gmac23_idle(struct mtk_mac *mac)
+{
+	u32 mac_fsm, gdm_fsm;
+
+	mac_fsm = mtk_r32(mac->hw, MTK_MAC_FSM(mac->id));
+
+	switch (mac->id) {
+	case MTK_GMAC2_ID:
+		gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM2_FSM);
+		break;
+	case MTK_GMAC3_ID:
+		gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM3_FSM);
+		break;
+	};
+
+	if ((mac_fsm & 0xFFFF0000) == 0x01010000 &&
+	    (gdm_fsm & 0xFFFF0000) == 0x00000000)
+		return true;
+
+	return false;
+}
+
 static void mtk_setup_eee(struct mtk_mac *mac, bool enable)
 {
 	struct mtk_eth *eth = mac->hw;
@@ -500,6 +521,34 @@
 		mtk_w32(eth, mcr, MTK_MAC_MCR(mac->id));
 }
 
+static int mtk_get_hwver(struct mtk_eth *eth)
+{
+	struct device_node *np;
+	struct regmap *hwver;
+	u32 info = 0;
+
+	eth->hwver = MTK_HWID_V1;
+
+	np = of_parse_phandle(eth->dev->of_node, "mediatek,hwver", 0);
+	if (!np)
+		return -EINVAL;
+
+	hwver = syscon_node_to_regmap(np);
+	if (IS_ERR(hwver))
+		return PTR_ERR(hwver);
+
+	regmap_read(hwver, 0x8, &info);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+		eth->hwver = FIELD_GET(HWVER_BIT_NETSYS_3, info);
+	else
+		eth->hwver = FIELD_GET(HWVER_BIT_NETSYS_1_2, info);
+
+	of_node_put(np);
+
+	return 0;
+}
+
 static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
 					      phy_interface_t interface)
 {
@@ -737,13 +786,11 @@
 		 * when swtiching XGDM to GDM. Therefore, here trigger an SER
 		 * to let GDM go back to the initial state.
 		 */
-		if (mac->type != mac_type) {
-			if (atomic_read(&reset_pending) == 0) {
+		if (mac->type != mac_type && !mtk_check_gmac23_idle(mac)) {
+			if (!test_bit(MTK_RESETTING, &mac->hw->state)) {
 				atomic_inc(&force);
 				schedule_work(&eth->pending_work);
-				atomic_inc(&reset_pending);
-			} else
-				atomic_dec(&reset_pending);
+			}
 		}
 	}
 
@@ -1037,6 +1084,7 @@
 		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) {
 			phylink_set(mask, 10000baseKR_Full);
 			phylink_set(mask, 10000baseT_Full);
+			phylink_set(mask, 10000baseCR_Full);
 			phylink_set(mask, 10000baseSR_Full);
 			phylink_set(mask, 10000baseLR_Full);
 			phylink_set(mask, 10000baseLRM_Full);
@@ -3744,6 +3792,12 @@
 		MTK_FE_INT_RFIFO_OV | MTK_FE_INT_RFIFO_UF, MTK_FE_INT_ENABLE);
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+		/* PSE dummy page mechanism */
+		if (eth->soc->caps != MT7988_CAPS || eth->hwver != MTK_HWID_V1)
+			mtk_w32(eth, PSE_DUMMY_WORK_GDM(1) |
+				PSE_DUMMY_WORK_GDM(2) |	PSE_DUMMY_WORK_GDM(3) |
+				DUMMY_PAGE_THR, PSE_DUMY_REQ);
+
 		/* PSE should not drop port1, port8 and port9 packets */
 		mtk_w32(eth, 0x00000302, PSE_NO_DROP_CFG);
 
@@ -4568,6 +4622,8 @@
 		eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET;
 	}
 
+	mtk_get_hwver(eth);
+
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
 		eth->ip_align = NET_IP_ALIGN;
 
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 03c18f0..2082ec6 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -761,6 +761,10 @@
 #define GPIO_BIAS_CTRL		0xed0
 #define GPIO_DRV_SEL10		0xf00
 
+/* SoC hardware version register */
+#define HWVER_BIT_NETSYS_1_2	BIT(0)
+#define HWVER_BIT_NETSYS_3	BIT(8)
+
 /* ethernet subsystem chip id register */
 #define ETHSYS_CHIPID0_3	0x0
 #define ETHSYS_CHIPID4_7	0x4
@@ -1230,6 +1234,12 @@
 	MTK_GDM_TYPE_MAX
 };
 
+enum mtk_hw_id {
+	MTK_HWID_V1 = 0,
+	MTK_HWID_V2,
+	MTK_HWID_MAX
+};
+
 static inline const char *gdm_type(int type)
 {
 	switch (type) {
@@ -1758,6 +1768,7 @@
 	struct net_device		*netdev[MTK_MAX_DEVS];
 	struct mtk_mac			*mac[MTK_MAX_DEVS];
 	int				irq[MTK_MAX_IRQ_NUM];
+	u8				hwver;
 	u32				msg_enable;
 	unsigned long			sysclk;
 	struct regmap			*ethsys;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index a30ec1e..2e68d3d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -1368,8 +1368,8 @@
 					foe->ipv6_5t_route.dport;
 			}
 
-#if defined(CONFIG_MEDIATEK_NETSYS_V3)
 			if (ct && (ct->status & IPS_SRC_NAT)) {
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
 				entry.bfib1.pkt_type = IPV6_HNAPT;
 
 				if (IS_WAN(dev) || IS_DSA_WAN(dev)) {
@@ -1404,8 +1404,10 @@
 
 				entry.ipv6_hnapt.new_sport = ntohs(pptr->src);
 				entry.ipv6_hnapt.new_dport = ntohs(pptr->dst);
-			}
+#else
+				return -1;
 #endif
+			}
 
 			entry.ipv6_5t_route.iblk2.dscp =
 				(ip6h->priority << 4 |
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 9aef092..4841134 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -144,6 +144,18 @@
 	mdelay(1);
 }
 
+int mtk_sgmii_need_powerdown(struct mtk_sgmii_pcs *mpcs)
+{
+	u32 val;
+
+	/* need to power down sgmii if link down */
+	regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+	if (!(val & SGMII_LINK_STATYS))
+		return true;
+
+	return false;
+}
+
 void mtk_sgmii_setup_phya_gen1(struct mtk_sgmii_pcs *mpcs)
 {
 	if (!mpcs->regmap_pextp)
@@ -412,6 +424,17 @@
 		sgm_mode = SGMII_IF_MODE_SGMII |
 			   SGMII_REMOTE_FAULT_DIS |
 			   SGMII_SPEED_DUPLEX_AN;
+	} else if (phylink_autoneg_inband(mode)) {
+		/* 1000base-X or HSGMII with autoneg */
+		if (interface == PHY_INTERFACE_MODE_2500BASEX)
+			return -EINVAL;
+
+		bmcr = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+					 advertising) ? SGMII_AN_ENABLE : 0;
+		if (bmcr)
+			sgm_mode = SGMII_SPEED_DUPLEX_AN;
+		else
+			speed = SGMII_SPEED_1000;
 	} else {
 		/* 1000base-X or HSGMII without autoneg */
 		speed = SGMII_SPEED_1000;
@@ -419,7 +442,8 @@
 			sgm_mode = SGMII_IF_MODE_SGMII;
 	}
 
-	if (mpcs->interface != interface) {
+	if (mpcs->interface != interface ||
+	    mtk_sgmii_need_powerdown(mpcs)) {
 		link_timer = phylink_get_link_timer_ns(interface);
 		if (link_timer < 0)
 			return link_timer;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
index 73f84f6..3deb616 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
@@ -597,6 +597,31 @@
 	mdelay(10);
 }
 
+static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+				  phy_interface_t interface,
+				  const unsigned long *advertising,
+				  bool permit_pause_to_mac)
+{
+	struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
+	struct mtk_eth *eth = mpcs->eth;
+	int err = 0;
+
+	mpcs->interface = interface;
+
+	mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
+	mtk_usxgmii_reset(eth, mpcs->id);
+
+	/* Setup USXGMIISYS with the determined property */
+	if (interface == PHY_INTERFACE_MODE_USXGMII)
+		err = mtk_usxgmii_setup_phya_an_10000(mpcs);
+	else if (interface == PHY_INTERFACE_MODE_10GKR)
+		err = mtk_usxgmii_setup_phya_force_10000(mpcs);
+	else if (interface == PHY_INTERFACE_MODE_5GBASER)
+		err = mtk_usxgmii_setup_phya_force_5000(mpcs);
+
+	return err;
+}
+
 static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
 				    struct phylink_link_state *state)
 {
@@ -664,31 +689,10 @@
 		state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, val);
 		state->duplex = DUPLEX_FULL;
 	}
-}
-
-static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
-				  phy_interface_t interface,
-				  const unsigned long *advertising,
-				  bool permit_pause_to_mac)
-{
-	struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
-	struct mtk_eth *eth = mpcs->eth;
-	int err = 0;
-
-	mpcs->interface = interface;
 
-	mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
-	mtk_usxgmii_reset(eth, mpcs->id);
-
-	/* Setup USXGMIISYS with the determined property */
-	if (interface == PHY_INTERFACE_MODE_USXGMII)
-		err = mtk_usxgmii_setup_phya_an_10000(mpcs);
-	else if (interface == PHY_INTERFACE_MODE_10GKR)
-		err = mtk_usxgmii_setup_phya_force_10000(mpcs);
-	else if (interface == PHY_INTERFACE_MODE_5GBASER)
-		err = mtk_usxgmii_setup_phya_force_5000(mpcs);
-
-	return err;
+	if (state->link == 0)
+		mtk_usxgmii_pcs_config(pcs, MLO_AN_INBAND,
+				       state->interface, NULL, false);
 }
 
 void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
index b99ee0b..7a1233a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
@@ -510,17 +510,6 @@
 		 * GBE: +7, TBT: +1, HBT: +4, TST: +7
 		 */
 		memcpy(bias, (const void *)vals_9461, sizeof(bias));
-		for (i = 0; i <= 12; i += 4) {
-			if (likely(buf[i >> 2] + bias[i] >= 32)) {
-				bias[i] -= 13;
-			} else {
-				phy_modify_mmd(phydev, MDIO_MMD_VEND1,
-					       0x5c, 0x7 << i, bias[i] << i);
-				bias[i + 1] += 13;
-				bias[i + 2] += 13;
-				bias[i + 3] += 13;
-			}
-		}
 		break;
 	case MTK_GPHY_ID_MT7988:
 		memcpy(bias, (const void *)vals_9481, sizeof(bias));
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 0e01fde..4012dba 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
@@ -142,6 +142,7 @@
 	int num_clks;
 
 	int irq;
+	int max_link_width;
 	int direct_msi_enable;
 	int direct_msi[PCIE_MSI_IRQS_PER_SET];
 	u32 saved_irq_state;
@@ -211,6 +212,26 @@
 	.write = mtk_pcie_config_write,
 };
 
+/**
+ * This function will try to find the limitation of link width by finding
+ * a property called "max-link-width" of the given device node.
+ *
+ * @node: device tree node with the max link width information
+ *
+ * Returns the associated max link width from DT, or a negative value if the
+ * required property is not found or is invalid.
+ */
+int of_pci_get_max_link_width(struct device_node *node)
+{
+	u32 max_link_width = 0;
+
+	if (of_property_read_u32(node, "max-link-width", &max_link_width) ||
+	    max_link_width == 0 || max_link_width > 2)
+		return -EINVAL;
+
+	return max_link_width;
+}
+
 static int mtk_pcie_set_trans_table(struct mtk_pcie_port *port,
 				    resource_size_t cpu_addr,
 				    resource_size_t pci_addr,
@@ -292,6 +313,16 @@
 	val |= PCIE_RC_MODE;
 	writel_relaxed(val, port->base + PCIE_SETTING_REG);
 
+	/* Set link width*/
+	val = readl_relaxed(port->base + PCIE_SETTING_REG);
+	if (port->max_link_width == 1) {
+		val &= ~GENMASK(11, 8);
+	} else if (port->max_link_width == 2) {
+		val &= ~GENMASK(11, 8);
+		val |= BIT(8);
+	}
+	writel_relaxed(val, port->base + PCIE_SETTING_REG);
+
 	/* Set class code */
 	val = readl_relaxed(port->base + PCIE_PCI_IDS_1);
 	val &= ~GENMASK(31, 8);
@@ -872,6 +903,10 @@
 		return port->num_clks;
 	}
 
+	port->max_link_width = of_pci_get_max_link_width(dev->of_node);
+	if (port->max_link_width < 0)
+		dev_err(dev, "failed to get max link width\n");
+
 	return 0;
 }
 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
index a7a4481..5f85133 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
@@ -676,7 +676,7 @@
  
  #if IS_ENABLED(CONFIG_HWMON)
  	struct sfp_diag diag;
-@@ -303,6 +313,144 @@ static const struct of_device_id sfp_of_
+@@ -303,6 +313,155 @@ static const struct of_device_id sfp_of_
  };
  MODULE_DEVICE_TABLE(of, sfp_of_match);
  
@@ -690,6 +690,11 @@
 +	sfp->tx_fault_ignore = true;
 +}
 +
++static void sfp_fixup_ruijie_gbic(struct sfp *sfp)
++{
++	sfp->mdio_protocol = MDIO_I2C_NONE;
++}
++
 +static void sfp_fixup_halny_gsfp(struct sfp *sfp)
 +{
 +	/* Ignore the TX_FAULT and LOS signals on this module.
@@ -738,44 +743,48 @@
 +	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
 +}
 +
-+#define SFP_QUIRK(_v, _p, _m, _f) \
-+	{ .vendor = _v, .part = _p, .modes = _m, .fixup = _f, }
-+#define SFP_QUIRK_M(_v, _p, _m) SFP_QUIRK(_v, _p, _m, NULL)
-+#define SFP_QUIRK_F(_v, _p, _f) SFP_QUIRK(_v, _p, NULL, _f)
++#define SFP_QUIRK(_v, _p, _r, _m, _f) \
++	{ .vendor = _v, .part = _p, .revision = _r, .modes = _m, .fixup = _f, }
++#define SFP_QUIRK_M(_v, _p, _r, _m) SFP_QUIRK(_v, _p, _r, _m, NULL)
++#define SFP_QUIRK_F(_v, _p, _r, _f) SFP_QUIRK(_v, _p, _r, NULL, _f)
 +
 +static const struct sfp_quirk sfp_quirks[] = {
++	// Ruijie MINI-GBIC-GT81 has a RL8211F PHY device, but it cannot
++	// reflect correct BMSR/ADVERTISE from the PHY.
++	SFP_QUIRK_F("RUIJIE", "MINI-GBIC-GT", "81", sfp_fixup_ruijie_gbic),
++
 +	// Alcatel Lucent G-010S-P can operate at 2500base-X, but incorrectly
 +	// report 2500MBd NRZ in their EEPROM
-+	SFP_QUIRK_M("ALCATELLUCENT", "G010SP", sfp_quirk_2500basex),
++	SFP_QUIRK_M("ALCATELLUCENT", "G010SP", '\0', sfp_quirk_2500basex),
 +
 +	// Alcatel Lucent G-010S-A can operate at 2500base-X, but report 3.2GBd
 +	// NRZ in their EEPROM
-+	SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
++	SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", '\0', sfp_quirk_2500basex,
 +		  sfp_fixup_long_startup),
 +
-+	SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp),
++	SFP_QUIRK_F("HALNy", "HL-GSFP", '\0', sfp_fixup_halny_gsfp),
 +
 +	// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in
 +	// their EEPROM
-+	SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
++	SFP_QUIRK("HUAWEI", "MA5671A", '\0', sfp_quirk_2500basex,
 +		  sfp_fixup_ignore_tx_fault),
 +
 +	// Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report
 +	// 2500MBd NRZ in their EEPROM
-+	SFP_QUIRK_M("Lantech", "8330-262D-E", sfp_quirk_2500basex),
++	SFP_QUIRK_M("Lantech", "8330-262D-E", '\0', sfp_quirk_2500basex),
 +
-+	SFP_QUIRK_M("CISCO-JDSU", "PLRXPL-VC-S43-CG", sfp_quirk_10000baseSR),
++	SFP_QUIRK_M("CISCO-JDSU", "PLRXPL-VC-S43-CG", '\0', sfp_quirk_10000baseSR),
 +
-+	SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
++	SFP_QUIRK_M("UBNT", "UF-INSTANT", '\0', sfp_quirk_ubnt_uf_instant),
 +
-+	SFP_QUIRK_F("ETU", "ESP-T5-R", sfp_fixup_rollball_cc),
-+	SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
-+	SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
-+	SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),
-+	SFP_QUIRK_F("OEM", "TNBYV02-C0X-C3", sfp_fixup_rollball_cc),
-+	SFP_QUIRK_F("Turris", "RTSFP-10", sfp_fixup_rollball),
-+	SFP_QUIRK_F("Turris", "RTSFP-10G", sfp_fixup_rollball),
-+	SFP_QUIRK_F("JESS-LINK", "P60000BBC001-1", sfp_fixup_rollball),
++	SFP_QUIRK_F("ETU", "ESP-T5-R", '\0', sfp_fixup_rollball_cc),
++	SFP_QUIRK_F("OEM", "SFP-10G-T", '\0', sfp_fixup_rollball_cc),
++	SFP_QUIRK_F("OEM", "RTSFP-10", '\0', sfp_fixup_rollball_cc),
++	SFP_QUIRK_F("OEM", "RTSFP-10G", '\0', sfp_fixup_rollball_cc),
++	SFP_QUIRK_F("OEM", "TNBYV02-C0X-C3", '\0', sfp_fixup_rollball_cc),
++	SFP_QUIRK_F("Turris", "RTSFP-10", '\0', sfp_fixup_rollball),
++	SFP_QUIRK_F("Turris", "RTSFP-10G", '\0', sfp_fixup_rollball),
++	SFP_QUIRK_F("JESS-LINK", "P60000BBC001-1", '\0', sfp_fixup_rollball),
 +};
 +
 +static size_t sfp_strlen(const char *str, size_t maxlen)
@@ -805,14 +814,16 @@
 +{
 +	const struct sfp_quirk *q;
 +	unsigned int i;
-+	size_t vs, ps;
++	size_t vs, ps, rs;
 +
 +	vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
 +	ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
++	rs = sfp_strlen(id->base.vendor_rev, ARRAY_SIZE(id->base.vendor_rev));
 +
 +	for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
 +		if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
-+		    sfp_match(q->part, id->base.vendor_pn, ps))
++		    sfp_match(q->part, id->base.vendor_pn, ps) &&
++		    sfp_match(q->revision, id->base.vendor_rev, rs))
 +			return q;
 +
 +	return NULL;
@@ -967,6 +978,65 @@
  	return err;
  }
  
+@@ -1755,17 +1783,29 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
+ static int sfp_module_parse_power(struct sfp *sfp)
+ {
+ 	u32 power_mW = 1000;
++	bool supports_a2;
+ 
+-	if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_POWER_DECL))
++	if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV10_2 &&
++	    sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_POWER_DECL))
+ 		power_mW = 1500;
+-	if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_HIGH_POWER_LEVEL))
++	/* Added in Rev 11.9, but there is no compliance code for this */
++	if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV11_4 &&
++	    sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_HIGH_POWER_LEVEL))
+ 		power_mW = 2000;
+ 
++	/* Power level 1 modules (max. 1W) are always supported. */
++	if (power_mW <= 1000) {
++		sfp->module_power_mW = power_mW;
++		return 0;
++	}
++
++	supports_a2 = sfp->id.ext.sff8472_compliance !=
++				SFP_SFF8472_COMPLIANCE_NONE ||
++		      sfp->id.ext.diagmon & SFP_DIAGMON_DDM;
++
+ 	if (power_mW > sfp->max_power_mW) {
+ 		/* Module power specification exceeds the allowed maximum. */
+-		if (sfp->id.ext.sff8472_compliance ==
+-			SFP_SFF8472_COMPLIANCE_NONE &&
+-		    !(sfp->id.ext.diagmon & SFP_DIAGMON_DDM)) {
++		if (!supports_a2) {
+ 			/* The module appears not to implement bus address
+ 			 * 0xa2, so assume that the module powers up in the
+ 			 * indicated mode.
+@@ -1782,13 +1822,21 @@ static int sfp_module_parse_power(struct sfp *sfp)
+ 		}
+ 	}
+ 
++	if (!supports_a2) {
++		/* The module power level is below the host maximum and the
++		 * module appears not to implement bus address 0xa2, so assume
++		 * that the module powers up in the indicated mode.
++		 */
++		return 0;
++	}
++
+ 	/* If the module requires a higher power mode, but also requires
+ 	 * an address change sequence, warn the user that the module may
+ 	 * not be functional.
+ 	 */
+-	if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE && power_mW > 1000) {
++	if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE) {
+ 		dev_warn(sfp->dev,
+-			 "Address Change Sequence not supported but module requies %u.%uW, module may not be functional\n",
++			 "Address Change Sequence not supported but module requires %u.%uW, module may not be functional\n",
+ 			 power_mW / 1000, (power_mW / 100) % 10);
+ 		return 0;
+ 	}
 @@ -1819,11 +1984,33 @@ static int sfp_sm_mod_probe(struct sfp *
  	if (ret < 0)
  		return ret;
@@ -1072,13 +1142,14 @@
  
 --- a/drivers/net/phy/sfp.h
 +++ b/drivers/net/phy/sfp.h
-@@ -6,6 +6,13 @@
+@@ -6,6 +6,14 @@
  
  struct sfp;
  
 +struct sfp_quirk {
 +	const char *vendor;
 +	const char *part;
++	const char *revision;
 +	void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
 +	void (*fixup)(struct sfp *sfp);
 +};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/757-net-phy-add-phylink-pcs-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/757-net-phy-add-phylink-pcs-support.patch
index 83da92d..99e4141 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/757-net-phy-add-phylink-pcs-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/757-net-phy-add-phylink-pcs-support.patch
@@ -517,6 +517,15 @@
  			val = phylink_mii_emul_read(reg, &state);
  		}
  		break;
+@@ -2010,7 +2010,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
+ 
+ 	if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
+ 				 &pl->phylink_disable_state))
+-		phylink_mac_config(pl, &pl->link_config);
++		phylink_mac_initial_config(pl, false);
+ 
+ 	return ret;
+ }
 diff --git a/include/linux/phylink.h b/include/linux/phylink.h
 index 8229f56..ba0f09d 100644
 --- a/include/linux/phylink.h