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

[Description]
bb73e7c [kernel][mt7981/mt7986/mt7988][spi][spi-calibration: Fix caldata wrongly freed]
80cb85d [kernel][common][eth][Update MDI Reversal feature for the Aquantia PHY driver]
37e50ea [kernel][common][eth][Update Airoha EN8801SC 1G PHY driver to v1.1.7 Generic]
f2af383 [openwrt][mt7988][tool][Update smp-mt76.sh 4-RSS scenario]
da7446a [kernel][common][hnat][Fix the issue of mistakenly deleting entries in foe_clear_entry]
e456a0b [kernel][mt7988][bsp][Rename MT7988C DTS to the MT7988D]
8d7521e [kernel][common][eth][Update firmware download feature for the Aquantia PHY driver]
f340eb8 [kernel][mt7988][eth][Refactor PCS programming sequence for the USXGMII]
9f09b66 [openwrt][mt7988][eth][Update Flowblock WED patch]
2732763 [kernel][mt7988][eth][phy: mediatek-2p5ge: Fix LED0/LED1 polarity]
3e8aa56 [openwrt][mt7988][eth][Add Ethernet RSS full support for Jaguar]

[Release-log]

Change-Id: Id277d48f13627d9d2165367218cc5083df430bae
diff --git a/recipes-devtools/smp/files/smp-mt76.sh b/recipes-devtools/smp/files/smp-mt76.sh
index cc5b46b..83d7799 100644
--- a/recipes-devtools/smp/files/smp-mt76.sh
+++ b/recipes-devtools/smp/files/smp-mt76.sh
@@ -96,9 +96,12 @@
 	DEFAULT_RPS=0
 
 	#Physical IRQ# setting
-	eth0_irq=229
-	eth1_irq=230
-	eth2_irq=231
+	#Ethernet RSS feature enables 4 Rx rings
+	eth_irq_rx0=221
+	eth_irq_rx1=222
+	eth_irq_rx2=223
+	eth_irq_rx3=224
+	eth_irq_tx=229
 	wifi1_irq_pcie0=524288
 	wifi1_irq_pcie1=134742016
 	wifi2_irq_pcie0=
@@ -132,10 +135,10 @@
 	# CPU#_AFFINITY="add binding irq number here"
 	# CPU#_RPS="add binding interface name here"
 	if [ "$num_of_wifi" = "0" ]; then
-		CPU0_AFFINITY="$eth0_irq"
-		CPU1_AFFINITY="$eth1_irq"
-		CPU2_AFFINITY="$eth2_irq"
-		CPU3_AFFINITY=""
+		CPU0_AFFINITY="$eth_irq_rx0 $eth_irq_tx"
+		CPU1_AFFINITY="$eth_irq_rx1"
+		CPU2_AFFINITY="$eth_irq_rx2"
+		CPU3_AFFINITY="$eth_irq_rx3"
 
 		CPU0_RPS="$RPS_IF_LIST"
 		CPU1_RPS="$RPS_IF_LIST"
@@ -145,8 +148,8 @@
 		#we bound all wifi card to cpu0 and bound eth to cpu
 		CPU0_AFFINITY=""
 		CPU1_AFFINITY=""
-		CPU2_AFFINITY="$eth1_irq"
-		CPU3_AFFINITY="$eth0_irq $eth2_irq"
+		CPU2_AFFINITY="$eth_irq_rx0 $eth_irq_rx1 $eth_irq_tx"
+		CPU3_AFFINITY="$eth_irq_rx2 $eth_irq_rx3"
 
 		CPU0_RPS="$WIFI_IF_LIST"
 		CPU1_RPS="$WIFI_IF_LIST"
@@ -165,8 +168,8 @@
 	DEFAULT_RPS=0
 
 	#Physical IRQ# setting
-	eth0_irq=229
-	eth1_irq=230
+	eth_irq_rx=221
+	eth_irq_tx=229
 	wifi1_irq=
 	wifi2_irq=
 	wifi3_irq=
@@ -215,8 +218,8 @@
 	# CPU#_AFFINITY="add binding irq number here"
 	# CPU#_RPS="add binding interface name here"
 	if [ "$num_of_wifi" = "0" ]; then
-		CPU0_AFFINITY="$eth0_irq"
-		CPU1_AFFINITY="$eth1_irq"
+		CPU0_AFFINITY="$eth_irq_rx"
+		CPU1_AFFINITY="$eth_irq_tx"
 		CPU2_AFFINITY=""
 		CPU3_AFFINITY=""
 
@@ -226,8 +229,8 @@
 		CPU3_RPS="$RPS_IF_LIST"
 	else
 		#we bound all wifi card to cpu1 and bound eth to cpu0
-		CPU0_AFFINITY="$eth0_irq"
-		CPU1_AFFINITY="$eth1_irq"
+		CPU0_AFFINITY="$eth_irq_rx"
+		CPU1_AFFINITY="$eth_irq_tx"
 		CPU2_AFFINITY="$wifi2_irq $wifi3_irq"
 		CPU3_AFFINITY="$wifi1_irq"
 
@@ -248,8 +251,8 @@
 	DEFAULT_RPS=0
 
 	#Physical IRQ# setting
-	eth0_irq=229
-	eth1_irq=230
+	eth_irq_rx=221
+	eth_irq_tx=229
 	wifi1_irq=
 	wifi2_irq=
 	wifi3_irq=
@@ -261,15 +264,15 @@
 	# CPU#_AFFINITY="add binding irq number here"
 	# CPU#_RPS="add binding interface name here"
 	if [ "$num_of_wifi" = "0" ]; then
-		CPU0_AFFINITY="$eth0_irq"
-		CPU1_AFFINITY="$eth1_irq"
+		CPU0_AFFINITY="$eth_irq_rx"
+		CPU1_AFFINITY="$eth_irq_tx"
 
 		CPU0_RPS="$RPS_IF_LIST"
 		CPU1_RPS="$RPS_IF_LIST"
 	else
 		#we bound all wifi card to cpu0 and bound eth to cpu1
 		CPU0_AFFINITY="$wifi1_irq $wifi2_irq $wifi3_irq"
-		CPU1_AFFINITY="$eth0_irq $eth1_irq"
+		CPU1_AFFINITY="$eth_irq_rx $eth_irq_tx"
 
 		CPU0_RPS="$RPS_IF_LIST"
 		CPU1_RPS="$RPS_IF_LIST"
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 f1ccf54..820e8bb 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
@@ -475,10 +475,14 @@
         eth: ethernet@15100000 {
                 compatible = "mediatek,mt7986-eth";
                 reg = <0 0x15100000 0 0x80000>;
-                interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
                 clocks = <&ethsys CK_ETH_FE_EN>,
                          <&ethsys CK_ETH_GP2_EN>,
                          <&ethsys CK_ETH_GP1_EN>,
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 666fddb..96c68a5 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
@@ -377,10 +377,14 @@
         eth: ethernet@15100000 {
                 compatible = "mediatek,mt7986-eth";
                 reg = <0 0x15100000 0 0x80000>;
-                interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
                 clocks = <&ethsys CK_ETH_FE_EN>,
                          <&ethsys CK_ETH_GP2_EN>,
                          <&ethsys CK_ETH_GP1_EN>,
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 e99ef83..6b47ee6 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
@@ -390,10 +390,14 @@
         eth: ethernet@15100000 {
                 compatible = "mediatek,mt7981-eth";
                 reg = <0 0x15100000 0 0x80000>;
-                interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
                 clocks = <&ethsys CK_ETH_FE_EN>,
                          <&ethsys CK_ETH_GP2_EN>,
                          <&ethsys CK_ETH_GP1_EN>,
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 f1ccf54..820e8bb 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
@@ -475,10 +475,14 @@
         eth: ethernet@15100000 {
                 compatible = "mediatek,mt7986-eth";
                 reg = <0 0x15100000 0 0x80000>;
-                interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
                 clocks = <&ethsys CK_ETH_FE_EN>,
                          <&ethsys CK_ETH_GP2_EN>,
                          <&ethsys CK_ETH_GP1_EN>,
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 666fddb..96c68a5 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
@@ -377,10 +377,14 @@
         eth: ethernet@15100000 {
                 compatible = "mediatek,mt7986-eth";
                 reg = <0 0x15100000 0 0x80000>;
-                interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
-                             <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
                 clocks = <&ethsys CK_ETH_FE_EN>,
                          <&ethsys CK_ETH_GP2_EN>,
                          <&ethsys CK_ETH_GP1_EN>,
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 28cb8eb..98dc4df 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
@@ -774,7 +774,11 @@
 		compatible = "mediatek,mt7988-eth";
 		reg = <0 0x15100000 0 0x80000>,
 		      <0 0x15400000 0 0x380000>;
-		interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
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 3dbbae8..9e2e9a9 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
@@ -426,6 +426,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -434,6 +435,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
index 1011cb3..201f9ee 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
@@ -237,6 +237,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -245,6 +246,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
index 5548023..d664a46 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
@@ -228,6 +228,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -236,6 +237,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
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 eb076ed..c7e83fd 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
@@ -263,6 +263,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -271,6 +272,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
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 d305570..cf117ca 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
@@ -421,6 +421,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -429,6 +430,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
index 62cb90e..a9fc3c5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
@@ -255,6 +255,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -263,6 +264,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
index 3f88986..2a24f7d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
@@ -253,7 +253,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
@@ -263,6 +263,10 @@
 		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>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
index 5969966..fde3572 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
@@ -359,6 +359,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -367,6 +368,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 	};
 };
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 d1371c4..0941b06 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
@@ -392,6 +392,7 @@
 			reset-gpios = <&pio 72 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		phy1: ethernet-phy@8 {
@@ -400,6 +401,7 @@
 			reset-gpios = <&pio 71 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 	};
 };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-emmc.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
index 0e58ac7..ba29680 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
@@ -8,8 +8,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C DSA 10G eMMC RFB";
-	compatible = "mediatek,mt7988c-dsa-10g-emmc",
+	model = "MediaTek MT7988D DSA 10G eMMC RFB";
+	compatible = "mediatek,mt7988d-dsa-10g-emmc",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 	chosen {
@@ -239,7 +239,7 @@
 		clock-frequency = <10500000>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
@@ -252,6 +252,7 @@
 			reset-gpios = <&pio 3 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-sd.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
index d0b4ec3..133da0c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
@@ -8,8 +8,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C DSA 10G SD RFB";
-	compatible = "mediatek,mt7988c-dsa-10g-sd",
+	model = "MediaTek MT7988D DSA 10G SD RFB";
+	compatible = "mediatek,mt7988d-dsa-10g-sd",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 	chosen {
@@ -230,7 +230,7 @@
 		clock-frequency = <10500000>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
@@ -243,6 +243,7 @@
 			reset-gpios = <&pio 3 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
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/mt7988d-dsa-10g-snfi-nand.dts
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
index 6cadcfc..7721c07 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/mt7988d-dsa-10g-snfi-nand.dts
@@ -8,8 +8,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C DSA 10G SNFI-NAND RFB";
-	compatible = "mediatek,mt7988c-dsa-10g-snfi-snand",
+	model = "MediaTek MT7988D DSA 10G SNFI-NAND RFB";
+	compatible = "mediatek,mt7988d-dsa-10g-snfi-snand",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 
@@ -265,7 +265,7 @@
 		clock-frequency = <10500000>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
@@ -278,6 +278,7 @@
 			reset-gpios = <&pio 3 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
similarity index 98%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nand.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
index 564debe..06b5702 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
@@ -8,8 +8,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C DSA 10G SPIM-NAND RFB";
-	compatible = "mediatek,mt7988c-dsa-10g-spim-snand",
+	model = "MediaTek MT7988D DSA 10G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988d-dsa-10g-spim-snand",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 
@@ -405,7 +405,7 @@
 		clock-frequency = <10500000>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
@@ -418,6 +418,7 @@
 			reset-gpios = <&pio 3 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nor.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
index 1c98664..61cdf7b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
@@ -8,8 +8,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C DSA 10G SPIM-NOR RFB";
-	compatible = "mediatek,mt7988c-dsa-10g-spim-nor",
+	model = "MediaTek MT7988D DSA 10G SPIM-NOR RFB";
+	compatible = "mediatek,mt7988d-dsa-10g-spim-nor",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 
@@ -257,7 +257,7 @@
 		clock-frequency = <10500000>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
@@ -270,6 +270,7 @@
 			reset-gpios = <&pio 3 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 
 		switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-e2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
similarity index 98%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-e2p5g-spim-nand.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
index e6a0115..5369716 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-e2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
@@ -8,8 +8,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C DSA external-2.5G SPIM-NAND RFB";
-	compatible = "mediatek,mt7988c-dsa-e2p5g-spim-snand",
+	model = "MediaTek MT7988D DSA external-2.5G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988d-dsa-e2p5g-spim-snand",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 
@@ -335,7 +335,7 @@
 		#size-cells = <0>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-sfp-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
similarity index 98%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-sfp-spim-nand.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
index 2404586..c94247d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-sfp-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
@@ -8,8 +8,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C GSW 10G SFP SPIM-NAND RFB";
-	compatible = "mediatek,mt7988c-gsw-10g-sfp-spim-snand",
+	model = "MediaTek MT7988D GSW 10G SFP SPIM-NAND RFB";
+	compatible = "mediatek,mt7988d-gsw-10g-sfp-spim-snand",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 
@@ -350,7 +350,7 @@
 		#size-cells = <0>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-spim-nand.dts
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
index 3446b6b..a86e77e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
@@ -9,8 +9,8 @@
 #include "mt7988.dtsi"
 
 / {
-	model = "MediaTek MT7988C GSW 10G SPIM-NAND RFB";
-	compatible = "mediatek,mt7988c-gsw-10g-spim-snand",
+	model = "MediaTek MT7988D GSW 10G SPIM-NAND RFB";
+	compatible = "mediatek,mt7988d-gsw-10g-spim-snand",
 		     /* Reserve this for DVFS if creating new dts */
 		     "mediatek,mt7988";
 
@@ -381,7 +381,7 @@
 		clock-frequency = <10500000>;
 
 		phy0: ethernet-phy@0 {
-			pinctrl-names = "default";
+			pinctrl-names = "i2p5gbe-led";
 			pinctrl-0 = <&i2p5gbe_led0_pins>;
 			reg = <15>;
 			compatible = "ethernet-phy-ieee802.3-c45";
@@ -394,6 +394,7 @@
 			reset-gpios = <&pio 3 1>;
 			reset-assert-us = <100000>;
 			reset-deassert-us = <221000>;
+			mdi-reversal = /bits/ 16 <1>;
 		};
 	};
 };
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 6f17fa5..02f1d34 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
@@ -3067,10 +3067,12 @@
 	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
 
 	/* Set perRSS GRP INT */
-	mtk_w32(eth, MTK_RX_DONE_INT(MTK_RSS_RING1), MTK_PDMA_INT_GRP3);
+	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);
 
 	/* Set GRP INT */
-	mtk_w32(eth, 0x21021030, MTK_FE_INT_GRP);
+	mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
 
 	/* Enable RSS delay interrupt */
 	mtk_w32(eth, 0x8f0f8f0f, MTK_PDMA_RSS_DELAY_INT);
@@ -3363,7 +3365,7 @@
 
 	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
 	mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(0));
-	mtk_handle_irq_rx(eth->irq[2], &eth->rx_napi[0]);
+	mtk_handle_irq_rx(eth->irq_fe[2], &eth->rx_napi[0]);
 	mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
 	mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0));
 }
@@ -3784,11 +3786,9 @@
 	mtk_rx_irq_disable(eth, ~0);
 
 	/* FE int grouping */
-	mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp);
-	mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->pdma.int_grp2);
 	mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp);
 	mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->qdma.int_grp2);
-	mtk_w32(eth, 0x21021003, MTK_FE_INT_GRP);
+	mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
 	mtk_w32(eth, MTK_FE_INT_TSO_FAIL |
 		MTK_FE_INT_TSO_ILLEGAL | MTK_FE_INT_TSO_ALIGN |
 		MTK_FE_INT_RFIFO_OV | MTK_FE_INT_RFIFO_UF, MTK_FE_INT_ENABLE);
@@ -4553,7 +4553,7 @@
 	eth->netdev[id]->features |= eth->soc->hw_features;
 	eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
 
-	eth->netdev[id]->irq = eth->irq[0];
+	eth->netdev[id]->irq = eth->irq_fe[0];
 	eth->netdev[id]->dev.of_node = np;
 
 	return 0;
@@ -4710,12 +4710,17 @@
 		}
 	}
 
-	for (i = 0; i < MTK_MAX_IRQ_NUM; i++) {
+	for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
+		eth->irq_pdma[i] = platform_get_irq(pdev, i);
+
+	for (i = 0; i < MTK_FE_IRQ_NUM; i++) {
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0)
-			eth->irq[i] = eth->irq[0];
+			eth->irq_fe[i] = eth->irq_fe[0];
 		else
-			eth->irq[i] = platform_get_irq(pdev, i);
-		if (eth->irq[i] < 0) {
+			eth->irq_fe[i] =
+				platform_get_irq(pdev, i + MTK_PDMA_IRQ_NUM);
+
+		if (eth->irq_fe[i] < 0) {
 			dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
 			return -ENXIO;
 		}
@@ -4765,37 +4770,35 @@
 		goto err_free_dev;
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
-		err = devm_request_irq(eth->dev, eth->irq[0],
+		err = devm_request_irq(eth->dev, eth->irq_fe[0],
 				       mtk_handle_irq, 0,
 				       dev_name(eth->dev), eth);
 	} else {
-		err = devm_request_irq(eth->dev, eth->irq[1],
+		err = devm_request_irq(eth->dev, eth->irq_fe[1],
 				       mtk_handle_irq_tx, 0,
 				       dev_name(eth->dev), eth);
 		if (err)
 			goto err_free_dev;
 
-		err = devm_request_irq(eth->dev, eth->irq[2],
+		err = devm_request_irq(eth->dev, eth->irq_fe[2],
+				       mtk_handle_fe_irq, 0,
+				       dev_name(eth->dev), eth);
+		if (err)
+			goto err_free_dev;
+
+		err = devm_request_irq(eth->dev, eth->irq_pdma[0],
 				       mtk_handle_irq_rx, 0,
 				       dev_name(eth->dev), &eth->rx_napi[0]);
 		if (err)
 			goto err_free_dev;
 
-		if (MTK_MAX_IRQ_NUM > 3) {
-			if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
-				for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
-					err = devm_request_irq(eth->dev,
-							       eth->irq[2 + i],
-							       mtk_handle_irq_rx, 0,
-							       dev_name(eth->dev),
-							       &eth->rx_napi[i]);
-					if (err)
-						goto err_free_dev;
-				}
-			} else {
-				err = devm_request_irq(eth->dev, eth->irq[3],
-						       mtk_handle_fe_irq, 0,
-						       dev_name(eth->dev), eth);
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+			for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
+				err = devm_request_irq(eth->dev,
+						       eth->irq_pdma[i],
+						       mtk_handle_irq_rx, 0,
+						       dev_name(eth->dev),
+						       &eth->rx_napi[i]);
 				if (err)
 					goto err_free_dev;
 			}
@@ -4823,7 +4826,7 @@
 		} else
 			netif_info(eth, probe, eth->netdev[i],
 				   "mediatek frame engine at 0x%08lx, irq %d\n",
-				   eth->netdev[i]->base_addr, eth->irq[0]);
+				   eth->netdev[i]->base_addr, eth->irq_fe[0]);
 	}
 
 	/* we run 2 devices on the same DMA ring so we need a dummy device
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 2082ec6..7465188 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
@@ -86,6 +86,9 @@
 #define MTK_FE_INT_RFIFO_UF	BIT(19)
 #define MTK_GDM1_AF		BIT(28)
 #define MTK_GDM2_AF		BIT(29)
+#define MTK_FE_IRQ_NUM		(4)
+#define MTK_PDMA_IRQ_NUM	(4)
+#define MTK_MAX_IRQ_NUM		(MTK_FE_IRQ_NUM + MTK_PDMA_IRQ_NUM)
 
 /* PDMA HW LRO Alter Flow Timer Register */
 #define MTK_PDMA_LRO_ALT_REFRESH_TIMER	0x1c
@@ -254,14 +257,12 @@
 /* PDMA RSS Control Registers */
 #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
 #define MTK_PDMA_RSS_GLO_CFG		(PDMA_BASE + 0x800)
-#define MTK_RX_NAPI_NUM			(2)
-#define MTK_MAX_IRQ_NUM			(4)
+#define MTK_RX_NAPI_NUM			(4)
 #else
 #define MTK_PDMA_RSS_GLO_CFG		0x2800
 #define MTK_RX_NAPI_NUM			(1)
-#define MTK_MAX_IRQ_NUM			(3)
 #endif
-#define MTK_RSS_RING1			(1)
+#define MTK_RSS_RING(x)			(x)
 #define MTK_RSS_EN			BIT(0)
 #define MTK_RSS_CFG_REQ			BIT(2)
 #define MTK_RSS_IPV6_STATIC_HASH	(0x7 << 8)
@@ -274,7 +275,7 @@
 #define MTK_RSS_INDR_TABLE_DW5		(MTK_PDMA_RSS_GLO_CFG + 0x64)
 #define MTK_RSS_INDR_TABLE_DW6		(MTK_PDMA_RSS_GLO_CFG + 0x68)
 #define MTK_RSS_INDR_TABLE_DW7		(MTK_PDMA_RSS_GLO_CFG + 0x6C)
-#define MTK_RSS_INDR_TABLE_SIZE4	0x44444444
+#define MTK_RSS_INDR_TABLE_SIZE4	0x39393939
 
 /* PDMA Global Configuration Register */
 #define MTK_PDMA_GLO_CFG	(PDMA_BASE + 0x204)
@@ -445,12 +446,13 @@
 /* QDMA Interrupt Status Register */
 #define MTK_QDMA_INT_STATUS	(QDMA_BASE + 0x218)
 #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-#define MTK_RX_DONE_INT(ring_no)					\
+#define MTK_RX_DONE_INT(ring_no)						\
 	(MTK_HAS_CAPS(eth->soc->caps, MTK_RSS) ? (BIT(24 + (ring_no))) :	\
 	 ((ring_no) ? BIT(16 + (ring_no)) : BIT(14)))
 #else
-#define MTK_RX_DONE_INT(ring_no)		\
-	((ring_no)? BIT(24 + (ring_no)) : BIT(30))
+#define MTK_RX_DONE_INT(ring_no)						\
+	(MTK_HAS_CAPS(eth->soc->caps, MTK_RSS) ? (BIT(16 + (ring_no))) :	\
+	 ((ring_no) ? BIT(24 + (ring_no)) : BIT(30)))
 #endif
 #define MTK_RX_DONE_INT3	BIT(19)
 #define MTK_RX_DONE_INT2	BIT(18)
@@ -888,30 +890,36 @@
 /* USXGMII subsystem config registers */
 /* Register to control speed */
 #define RG_PHY_TOP_SPEED_CTRL1	0x80C
-#define RG_USXGMII_RATE_UPDATE_MODE	BIT(31)
-#define RG_MAC_CK_GATED		BIT(29)
-#define RG_IF_FORCE_EN		BIT(28)
-#define RG_RATE_ADAPT_MODE	GENMASK(10, 8)
-#define RG_RATE_ADAPT_MODE_X1	0
-#define RG_RATE_ADAPT_MODE_X2	1
-#define RG_RATE_ADAPT_MODE_X4	2
-#define RG_RATE_ADAPT_MODE_X10	3
-#define RG_RATE_ADAPT_MODE_X100	4
-#define RG_RATE_ADAPT_MODE_X5	5
-#define RG_RATE_ADAPT_MODE_X50	6
-#define RG_XFI_RX_MODE		GENMASK(6, 4)
-#define RG_XFI_RX_MODE_10G	0
-#define RG_XFI_RX_MODE_5G	1
-#define RG_XFI_TX_MODE		GENMASK(2, 0)
-#define RG_XFI_TX_MODE_10G	0
-#define RG_XFI_TX_MODE_5G	1
+#define USXGMII_RATE_UPDATE_MODE	BIT(31)
+#define USXGMII_MAC_CK_GATED	BIT(29)
+#define USXGMII_IF_FORCE_EN	BIT(28)
+#define USXGMII_RATE_ADAPT_MODE	GENMASK(10, 8)
+#define USXGMII_RATE_ADAPT_MODE_X1	0
+#define USXGMII_RATE_ADAPT_MODE_X2	1
+#define USXGMII_RATE_ADAPT_MODE_X4	2
+#define USXGMII_RATE_ADAPT_MODE_X10	3
+#define USXGMII_RATE_ADAPT_MODE_X100	4
+#define USXGMII_RATE_ADAPT_MODE_X5	5
+#define USXGMII_RATE_ADAPT_MODE_X50	6
+#define USXGMII_XFI_RX_MODE	GENMASK(6, 4)
+#define USXGMII_XFI_RX_MODE_10G	0
+#define USXGMII_XFI_RX_MODE_5G	1
+#define USXGMII_XFI_TX_MODE	GENMASK(2, 0)
+#define USXGMII_XFI_TX_MODE_10G	0
+#define USXGMII_XFI_TX_MODE_5G	1
 
 /* Register to control PCS AN */
 #define RG_PCS_AN_CTRL0		0x810
 #define USXGMII_AN_RESTART	BIT(31)
+#define USXGMII_AN_SYNC_CNT	GENMASK(30, 11)
 #define USXGMII_AN_ENABLE	BIT(0)
 
-/* Register to control PCS AN */
+#define RG_PCS_AN_CTRL2		0x818
+#define USXGMII_LINK_TIMER_IDLE_DETECT	GENMASK(29, 20)
+#define USXGMII_LINK_TIMER_COMP_ACK_DETECT	GENMASK(19, 10)
+#define USXGMII_LINK_TIMER_AN_RESTART	GENMASK(9, 0)
+
+/* Register to read PCS AN status */
 #define RG_PCS_AN_STS0		0x81C
 #define USXGMII_LPA_SPEED_MASK	GENMASK(11, 9)
 #define USXGMII_LPA_SPEED_10	0
@@ -1767,7 +1775,8 @@
 	struct net_device		dummy_dev;
 	struct net_device		*netdev[MTK_MAX_DEVS];
 	struct mtk_mac			*mac[MTK_MAX_DEVS];
-	int				irq[MTK_MAX_IRQ_NUM];
+	int				irq_fe[MTK_FE_IRQ_NUM];
+	int				irq_pdma[MTK_PDMA_IRQ_NUM];
 	u8				hwver;
 	u32				msg_enable;
 	unsigned long			sysclk;
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 2e68d3d..95e5e3c 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
@@ -291,7 +291,8 @@
 		for (hash_index = 0; hash_index < hnat_priv->foe_etry_num; hash_index++) {
 			entry = hnat_priv->foe_table_cpu[i] + hash_index;
 			if (entry->bfib1.state == BIND &&
-			    entry->ipv4_hnapt.new_dip == ntohl(dip)) {
+			    entry->ipv4_hnapt.new_dip == ntohl(dip) &&
+			    IS_IPV4_HNAPT(entry)) {
 				*((u32 *)h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
 				*((u16 *)&h_dest[4]) =
 					swab16(entry->ipv4_hnapt.dmac_lo);
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 4841134..c2acab2 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
@@ -161,6 +161,7 @@
 	if (!mpcs->regmap_pextp)
 		return;
 
+	/* Setup operation mode */
 	regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
 			   0x00D9071C);
 	regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
@@ -203,13 +204,17 @@
 			   0x18190000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
 			   0x00FA32FA);
+	/* Force SGDT_OUT off and select PCS */
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
 			   0x80201F21);
+	/* Force GLB_CKDET_OUT */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
 			   0x00050C00);
+	/* Force AEQ on */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
@@ -234,15 +239,18 @@
 			   0x00050000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
 			   0x00000007);
+	/* Release reset */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200E800);
 	udelay(150);
+	/* Switch to P0 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C111);
 	ndelay(1020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C101);
 	udelay(15);
+	/* Switch to Gen2 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0201C111);
 	ndelay(1020);
@@ -263,6 +271,7 @@
 	if (!mpcs->regmap_pextp)
 		return;
 
+	/* Setup operation mode */
 	regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
 			   0x00D9071C);
 	regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
@@ -305,13 +314,17 @@
 			   0x18190000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
 			   0x009C329C);
+	/* Force SGDT_OUT off and select PCS */
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
 			   0x80201F21);
+	/* Force GLB_CKDET_OUT */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
 			   0x00050C00);
+	/* Force AEQ on */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
@@ -334,15 +347,18 @@
 			   0x00050000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
 			   0x00000005);
+	/* Release reset */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200E800);
 	udelay(150);
+	/* Switch to P0 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C111);
 	ndelay(1020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C101);
 	udelay(15);
+	/* Switch to Gen2 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0201C111);
 	ndelay(1020);
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 1bc4912..e6007f6 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
@@ -129,24 +129,12 @@
 	return mac_id;
 }
 
-int mtk_usxgmii_setup_phya_an_10000(struct mtk_usxgmii_pcs *mpcs)
+void mtk_usxgmii_setup_phya_usxgmii(struct mtk_usxgmii_pcs *mpcs)
 {
-	if (!mpcs->regmap || !mpcs->regmap_pextp)
-		return -EINVAL;
-
-	regmap_update_bits(mpcs->regmap, 0x810, GENMASK(31, 0),
-			   0x000FFE6D);
-	regmap_update_bits(mpcs->regmap, 0x818, GENMASK(31, 0),
-			   0x07B1EC7B);
-	regmap_update_bits(mpcs->regmap, 0x80C, GENMASK(31, 0),
-			   0x30000000);
-	ndelay(1020);
-	regmap_update_bits(mpcs->regmap, 0x80C, GENMASK(31, 0),
-			   0x10000000);
-	ndelay(1020);
-	regmap_update_bits(mpcs->regmap, 0x80C, GENMASK(31, 0),
-			   0x00000000);
+	if (!mpcs->regmap_pextp)
+		return;
 
+	/* Setup operation mode */
 	regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
 			   0x00C9071C);
 	regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
@@ -189,13 +177,17 @@
 			   0x18190000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
 			   0x01423342);
+	/* Force SGDT_OUT off and select PCS */
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
 			   0x80201F20);
+	/* Force GLB_CKDET_OUT */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
 			   0x00050C00);
+	/* Force AEQ on */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
@@ -222,15 +214,18 @@
 			   0x00040000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
 			   0x00000001);
+	/* Release reset */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200E800);
 	udelay(150);
+	/* Switch to P0 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C111);
 	ndelay(1020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C101);
 	udelay(15);
+	/* Switch to Gen3 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0202C111);
 	ndelay(1020);
@@ -244,48 +239,14 @@
 	regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
 			   0x30000000);
 	udelay(400);
-
-	return 0;
 }
 
-int mtk_usxgmii_setup_phya_force_5000(struct mtk_usxgmii_pcs *mpcs)
+void mtk_usxgmii_setup_phya_5gbaser(struct mtk_usxgmii_pcs *mpcs)
 {
-	unsigned int val;
-
-	if (!mpcs->regmap || !mpcs->regmap_pextp)
-		return -EINVAL;
-
-	/* Setup USXGMII speed */
-	val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_5G) |
-	      FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_5G);
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	/* Disable USXGMII AN mode */
-	regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
-	val &= ~USXGMII_AN_ENABLE;
-	regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
-
-	/* Gated USXGMII */
-	regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
-	val |= RG_MAC_CK_GATED;
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	ndelay(1020);
-
-	/* USXGMII force mode setting */
-	regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
-	val |= RG_USXGMII_RATE_UPDATE_MODE;
-	val |= RG_IF_FORCE_EN;
-	val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1);
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	/* Un-gated USXGMII */
-	regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
-	val &= ~RG_MAC_CK_GATED;
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	ndelay(1020);
+	if (!mpcs->regmap_pextp)
+		return;
 
+	/* Setup operation mode */
 	regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
 			   0x00D9071C);
 	regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
@@ -328,13 +289,17 @@
 			   0x18000000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
 			   0x00A132A1);
+	/* Force SGDT_OUT off and select PCS */
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
 			   0x80201F20);
+	/* Force GLB_CKDET_OUT */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
 			   0x00050C00);
+	/* Force AEQ on */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
@@ -361,15 +326,18 @@
 			   0x00040000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
 			   0x00000003);
+	/* Release reset */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200E800);
 	udelay(150);
+	/* Switch to P0 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C111);
 	ndelay(1020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C101);
 	udelay(15);
+	/* Switch to Gen3 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0202C111);
 	ndelay(1020);
@@ -383,48 +351,14 @@
 	regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
 			   0x30000000);
 	udelay(400);
-
-	return 0;
 }
 
-int mtk_usxgmii_setup_phya_force_10000(struct mtk_usxgmii_pcs *mpcs)
+void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs)
 {
-	unsigned int val;
-
-	if (!mpcs->regmap || !mpcs->regmap_pextp)
-		return -EINVAL;
-
-	/* Setup USXGMII speed */
-	val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_10G) |
-	      FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_10G);
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	/* Disable USXGMII AN mode */
-	regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
-	val &= ~USXGMII_AN_ENABLE;
-	regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
-
-	/* Gated USXGMII */
-	regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
-	val |= RG_MAC_CK_GATED;
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	ndelay(1020);
-
-	/* USXGMII force mode setting */
-	regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
-	val |= RG_USXGMII_RATE_UPDATE_MODE;
-	val |= RG_IF_FORCE_EN;
-	val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1);
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	/* Un-gated USXGMII */
-	regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
-	val &= ~RG_MAC_CK_GATED;
-	regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
-
-	ndelay(1020);
+	if (!mpcs->regmap_pextp)
+		return;
 
+	/* Setup operation mode */
 	regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
 			   0x00C9071C);
 	regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
@@ -467,13 +401,17 @@
 			   0x18190000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
 			   0x01423342);
+	/* Force SGDT_OUT off and select PCS */
 	regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
 			   0x80201F20);
+	/* Force GLB_CKDET_OUT */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
 			   0x00050C00);
+	/* Force AEQ on */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x02002800);
 	ndelay(1020);
+	/* Setup DA default value */
 	regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
 			   0x00000020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
@@ -503,15 +441,18 @@
 			   0x00040000);
 	regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
 			   0x00000001);
+	/* Release reset */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200E800);
 	udelay(150);
+	/* Switch to P0 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C111);
 	ndelay(1020);
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0200C101);
 	udelay(15);
+	/* Switch to Gen3 */
 	regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
 			   0x0202C111);
 	ndelay(1020);
@@ -525,8 +466,6 @@
 	regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
 			   0x30000000);
 	udelay(400);
-
-	return 0;
 }
 
 void mtk_usxgmii_reset(struct mtk_eth *eth, int id)
@@ -607,22 +546,97 @@
 {
 	struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
 	struct mtk_eth *eth = mpcs->eth;
-	int err = 0;
+	unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0;
+	bool mode_changed = false;
 
-	mpcs->interface = interface;
+	if (interface == PHY_INTERFACE_MODE_USXGMII) {
+		an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) |
+			  USXGMII_AN_ENABLE;
+		link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
+			     FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
+			     FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
+		xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
+			   FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
+	} else if (interface == PHY_INTERFACE_MODE_10GKR) {
+		an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF);
+		link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
+			     FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
+			     FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
+		xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
+			   FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
+		adapt_mode = USXGMII_RATE_UPDATE_MODE;
+	} else if (interface == PHY_INTERFACE_MODE_5GBASER) {
+		an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF);
+		link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) |
+			     FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) |
+			     FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D);
+		xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_5G) |
+			   FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_5G);
+		adapt_mode = USXGMII_RATE_UPDATE_MODE;
+	} else
+		return -EINVAL;
+
+	adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1);
+
+	if (mpcs->interface != interface) {
+		mpcs->interface = interface;
+		mode_changed = true;
+	}
 
 	mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
 	mtk_usxgmii_reset(eth, mpcs->id);
 
+	/* Setup USXGMII AN ctrl */
+	regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL0,
+			   USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE,
+			   an_ctrl);
+
+	regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL2,
+			   USXGMII_LINK_TIMER_IDLE_DETECT |
+			   USXGMII_LINK_TIMER_COMP_ACK_DETECT |
+			   USXGMII_LINK_TIMER_AN_RESTART,
+			   link_timer);
+
+	/* Gated MAC CK */
+	regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
+			   USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED);
+
+	/* Enable interface force mode */
+	regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
+			   USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN);
+
+	/* Setup USXGMII adapt mode */
+	regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
+			   USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE,
+			   adapt_mode);
+
+	/* Setup USXGMII speed */
+	regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
+			   USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE,
+			   xfi_mode);
+
+	udelay(1);
+
+	/* Un-gated MAC CK */
+	regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
+			   USXGMII_MAC_CK_GATED, 0);
+
+	udelay(1);
+
+	/* Disable interface force mode for the AN mode */
+	if (an_ctrl & USXGMII_AN_ENABLE)
+		regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
+				   USXGMII_IF_FORCE_EN, 0);
+
 	/* Setup USXGMIISYS with the determined property */
 	if (interface == PHY_INTERFACE_MODE_USXGMII)
-		err = mtk_usxgmii_setup_phya_an_10000(mpcs);
+		mtk_usxgmii_setup_phya_usxgmii(mpcs);
 	else if (interface == PHY_INTERFACE_MODE_10GKR)
-		err = mtk_usxgmii_setup_phya_force_10000(mpcs);
+		mtk_usxgmii_setup_phya_10gbaser(mpcs);
 	else if (interface == PHY_INTERFACE_MODE_5GBASER)
-		err = mtk_usxgmii_setup_phya_force_5000(mpcs);
+		mtk_usxgmii_setup_phya_5gbaser(mpcs);
 
-	return err;
+	return mode_changed;
 }
 
 static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.c
new file mode 100644
index 0000000..f8c5ad6
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.c
@@ -0,0 +1,1153 @@
+// SPDX-License-Identifier: GPL-2.0
+/* FILE NAME:  en8801sc.c
+ * PURPOSE:
+ *      EN8801SC phy driver for Linux
+ * NOTES:
+ *
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/delay.h>
+
+#include <linux/uaccess.h>
+#include <linux/version.h>
+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
+#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
+#endif
+
+#include "en8801sc.h"
+
+MODULE_DESCRIPTION("Airoha EN8801S PHY drivers for MediaTek SoC");
+MODULE_AUTHOR("Airoha");
+MODULE_LICENSE("GPL");
+
+#define airoha_mdio_lock(bus)   mutex_lock(&((bus)->mdio_lock))
+#define airoha_mdio_unlock(bus) mutex_unlock(&((bus)->mdio_lock))
+
+#if (KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE)
+#define phydev_mdio_bus(_dev) (_dev->bus)
+#define phydev_phy_addr(_dev) (_dev->addr)
+#define phydev_dev(_dev) (&_dev->dev)
+#define phydev_pbus_addr(dev) ((dev)->addr + 1)
+#else
+#define phydev_mdio_bus(_dev) (_dev->mdio.bus)
+#define phydev_phy_addr(_dev) (_dev->mdio.addr)
+#define phydev_dev(_dev) (&_dev->mdio.dev)
+#define phydev_pbus_addr(dev) ((dev)->mdio.addr + 1)
+#endif
+
+enum {
+	PHY_STATE_DONE = 0,
+	PHY_STATE_INIT = 1,
+	PHY_STATE_PROCESS = 2,
+	PHY_STATE_FAIL = 3,
+};
+
+struct en8801s_priv {
+	bool first_init;
+	u16 count;
+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
+	struct gpio_desc *hw_reset;
+#endif
+};
+
+/*
+The following led_cfg example is for reference only.
+LED5 1000M/LINK/ACT   (GPIO5)  <-> BASE_T_LED0,
+LED6 10/100M/LINK/ACT (GPIO9)  <-> BASE_T_LED1,
+LED4 100M/LINK/ACT    (GPIO8)  <-> BASE_T_LED2,
+*/
+/* User-defined.B */
+#define AIR_LED_SUPPORT
+#ifdef AIR_LED_SUPPORT
+static const struct AIR_BASE_T_LED_CFG_S led_cfg[4] = {
+/*
+*   {LED Enable,    GPIO,   LED Polarity,   LED ON, LED Blink}
+*/
+	/* BASE-T LED0 */
+	{LED_ENABLE, 5, AIR_ACTIVE_LOW,
+	 BASE_T_LED0_ON_CFG, BASE_T_LED0_BLK_CFG},
+	/* BASE-T LED1 */
+	{LED_ENABLE, 9, AIR_ACTIVE_LOW,
+	 BASE_T_LED1_ON_CFG, BASE_T_LED1_BLK_CFG},
+	/* BASE-T LED2 */
+	{LED_ENABLE, 8, AIR_ACTIVE_LOW,
+	 BASE_T_LED2_ON_CFG, BASE_T_LED2_BLK_CFG},
+	/* BASE-T LED3 */
+	{LED_DISABLE, 1, AIR_ACTIVE_LOW,
+	 BASE_T_LED3_ON_CFG, BASE_T_LED3_BLK_CFG},
+};
+static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
+#endif
+
+/* User-defined.E */
+
+/************************************************************************
+*                  F U N C T I O N S
+************************************************************************/
+static unsigned int airoha_cl22_read(struct mii_bus *ebus, int phy_addr,
+			unsigned int phy_register, unsigned int *read_data)
+{
+	*read_data = mdiobus_read(ebus, phy_addr, phy_register);
+	return 0;
+}
+
+static int airoha_cl22_write(struct mii_bus *ebus, int phy_addr,
+			unsigned int phy_register, unsigned int write_data)
+{
+	int ret = 0;
+	struct device *dev = &ebus->dev;
+
+	ret = mdiobus_write(ebus, phy_addr, phy_register, write_data);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int __airoha_cl45_write(struct mii_bus *bus, int port,
+			u32 devad, u32 reg, u16 val)
+{
+	int ret = 0;
+	struct device *dev = &bus->dev;
+
+	ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+	ret = __mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+	ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG,
+				MMD_OP_MODE_DATA | devad);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+	ret = __mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, val);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int __airoha_cl45_read(struct mii_bus *bus, int port,
+			u32 devad, u32 reg, u16 *read_data)
+{
+	int ret = 0;
+	struct device *dev = &bus->dev;
+
+	ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+	ret = __mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+	ret = __mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG,
+				MMD_OP_MODE_DATA | devad);
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+	*read_data = __mdiobus_read(bus, port, MII_MMD_ADDR_DATA_REG);
+
+	return ret;
+}
+
+static int airoha_cl45_write(struct mii_bus *bus, int port,
+			u32 devad, u32 reg, u16 val)
+{
+	int ret = 0;
+
+	airoha_mdio_lock(bus);
+	ret = __airoha_cl45_write(bus, port, devad, reg, val);
+	airoha_mdio_unlock(bus);
+
+	return ret;
+}
+
+static int airoha_cl45_read(struct mii_bus *bus, int port,
+			u32 devad, u32 reg, u16 *read_data)
+{
+	int ret = 0;
+
+	airoha_mdio_lock(bus);
+	ret = __airoha_cl45_read(bus, port, devad, reg, read_data);
+	airoha_mdio_unlock(bus);
+
+	return ret;
+}
+
+static int __airoha_pbus_write(struct mii_bus *ebus, int pbus_id,
+			unsigned long pbus_address, unsigned long pbus_data)
+{
+	int ret = 0;
+	struct device *dev = &ebus->dev;
+
+	ret = __mdiobus_write(ebus, pbus_id, 0x1F,
+				(unsigned int)(pbus_address >> 6));
+	if (ret < 0)
+		return ret;
+	ret = __mdiobus_write(ebus, pbus_id,
+				(unsigned int)((pbus_address >> 2) & 0xf),
+				(unsigned int)(pbus_data & 0xFFFF));
+	if (ret < 0)
+		return ret;
+	ret = __mdiobus_write(ebus, pbus_id, 0x10,
+				(unsigned int)(pbus_data >> 16));
+	if (ret < 0)
+		return ret;
+	return ret;
+}
+
+static unsigned long __airoha_pbus_read(struct mii_bus *ebus, int pbus_id,
+			unsigned long pbus_address)
+{
+	unsigned long pbus_data;
+	unsigned int pbus_data_low, pbus_data_high;
+	int ret = 0;
+	struct device *dev = &ebus->dev;
+
+	ret = __mdiobus_write(ebus, pbus_id, 0x1F,
+				(unsigned int)(pbus_address >> 6));
+	if (ret < 0) {
+		dev_err(dev, "%s fail. (ret=%d)\n", __func__, ret);
+		return INVALID_DATA;
+	}
+	pbus_data_low = __mdiobus_read(ebus, pbus_id,
+				(unsigned int)((pbus_address >> 2) & 0xf));
+	pbus_data_high = __mdiobus_read(ebus, pbus_id, 0x10);
+	pbus_data = (pbus_data_high << 16) + pbus_data_low;
+	return pbus_data;
+}
+
+static int airoha_pbus_write(struct mii_bus *ebus, int pbus_id,
+			unsigned long pbus_address, unsigned long pbus_data)
+{
+	int ret = 0;
+
+	airoha_mdio_lock(ebus);
+	ret = __airoha_pbus_write(ebus, pbus_id, pbus_address, pbus_data);
+	airoha_mdio_unlock(ebus);
+
+	return ret;
+}
+
+static unsigned long airoha_pbus_read(struct mii_bus *ebus, int pbus_id,
+			unsigned long pbus_address)
+{
+	unsigned long pbus_data;
+
+	airoha_mdio_lock(ebus);
+	pbus_data = __airoha_pbus_read(ebus, pbus_id, pbus_address);
+	airoha_mdio_unlock(ebus);
+
+	return pbus_data;
+}
+
+/* Airoha Token Ring Write function */
+static int airoha_tr_reg_write(struct phy_device *phydev,
+			unsigned long tr_address, unsigned long tr_data)
+{
+	int ret = 0;
+	int phy_addr = phydev_phy_addr(phydev);
+	struct mii_bus *ebus = phydev_mdio_bus(phydev);
+
+	airoha_mdio_lock(ebus);
+	ret = __mdiobus_write(ebus, phy_addr, 0x1F, 0x52b5); /* page select */
+	ret = __mdiobus_write(ebus, phy_addr, 0x11,
+				(unsigned int)(tr_data & 0xffff));
+	ret = __mdiobus_write(ebus, phy_addr, 0x12,
+				(unsigned int)(tr_data >> 16));
+	ret = __mdiobus_write(ebus, phy_addr, 0x10,
+				(unsigned int)(tr_address | TrReg_WR));
+	ret = __mdiobus_write(ebus, phy_addr, 0x1F, 0x0);    /* page resetore */
+	airoha_mdio_unlock(ebus);
+
+	return ret;
+}
+
+#ifdef AIR_LED_SUPPORT
+static int airoha_led_set_usr_def(struct phy_device *phydev, u8 entity,
+			int polar, u16 on_evt, u16 blk_evt)
+{
+	int ret = 0;
+	int phy_addr = phydev_phy_addr(phydev);
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+
+	if (polar == AIR_ACTIVE_HIGH)
+		on_evt |= LED_ON_POL;
+	else
+		on_evt &= ~LED_ON_POL;
+
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1f,
+				LED_ON_CTRL(entity), on_evt | LED_ON_EN);
+	if (ret < 0)
+		return ret;
+
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1f,
+				LED_BLK_CTRL(entity), blk_evt);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int airoha_led_set_mode(struct phy_device *phydev, u8 mode)
+{
+	u16 cl45_data;
+	int err = 0;
+	int phy_addr = phydev_phy_addr(phydev);
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+
+	err = airoha_cl45_read(mbus, phy_addr, 0x1f, LED_BCR, &cl45_data);
+	if (err < 0)
+		return err;
+
+	switch (mode) {
+	case AIR_LED_MODE_DISABLE:
+		cl45_data &= ~LED_BCR_EXT_CTRL;
+		cl45_data &= ~LED_BCR_MODE_MASK;
+		cl45_data |= LED_BCR_MODE_DISABLE;
+		break;
+	case AIR_LED_MODE_USER_DEFINE:
+		cl45_data |= LED_BCR_EXT_CTRL;
+		cl45_data |= LED_BCR_CLK_EN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = airoha_cl45_write(mbus, phy_addr, 0x1f, LED_BCR, cl45_data);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int airoha_led_set_state(struct phy_device *phydev, u8 entity, u8 state)
+{
+	u16 cl45_data;
+	int err;
+	int phy_addr = phydev_phy_addr(phydev);
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+
+	err = airoha_cl45_read(mbus, phy_addr, 0x1f,
+				LED_ON_CTRL(entity), &cl45_data);
+	if (err < 0)
+		return err;
+	if (state == LED_ENABLE)
+		cl45_data |= LED_ON_EN;
+	else
+		cl45_data &= ~LED_ON_EN;
+
+	err = airoha_cl45_write(mbus, phy_addr, 0x1f,
+				LED_ON_CTRL(entity), cl45_data);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int en8801s_led_init(struct phy_device *phydev)
+{
+
+	unsigned long led_gpio = 0, reg_value = 0;
+	int ret = 0, led_id;
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	int gpio_led_rg[3] = {0x1870, 0x1874, 0x1878};
+	u16 cl45_data = led_dur;
+	struct device *dev = phydev_dev(phydev);
+	int phy_addr = phydev_phy_addr(phydev);
+	int pbus_addr = phydev_pbus_addr(phydev);
+
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1f, LED_BLK_DUR, cl45_data);
+	if (ret < 0)
+		return ret;
+	cl45_data >>= 1;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1f, LED_ON_DUR, cl45_data);
+	if (ret < 0)
+		return ret;
+	ret = airoha_led_set_mode(phydev, AIR_LED_MODE_USER_DEFINE);
+	if (ret != 0) {
+		dev_err(dev, "LED fail to set mode, ret %d !\n", ret);
+		return ret;
+	}
+	for (led_id = 0; led_id < EN8801S_LED_COUNT; led_id++) {
+		reg_value = 0;
+		ret = airoha_led_set_state(phydev, led_id, led_cfg[led_id].en);
+		if (ret != 0) {
+			dev_err(dev, "LED fail to set state, ret %d !\n", ret);
+			return ret;
+		}
+		if (led_cfg[led_id].en == LED_ENABLE) {
+			if ((led_cfg[led_id].gpio < 0)
+				|| led_cfg[led_id].gpio > 9) {
+				dev_err(dev, "GPIO%d is out of range!! GPIO number is 0~9.\n",
+					led_cfg[led_id].gpio);
+				return -EIO;
+			}
+			led_gpio |= BIT(led_cfg[led_id].gpio);
+			reg_value = airoha_pbus_read(mbus, pbus_addr,
+					gpio_led_rg[led_cfg[led_id].gpio / 4]);
+			LED_SET_GPIO_SEL(led_cfg[led_id].gpio,
+					led_id, reg_value);
+			dev_dbg(dev, "[Airoha] gpio%d, reg_value 0x%lx\n",
+					led_cfg[led_id].gpio, reg_value);
+			ret = airoha_pbus_write(mbus, pbus_addr,
+					gpio_led_rg[led_cfg[led_id].gpio / 4],
+					reg_value);
+			if (ret < 0)
+				return ret;
+			ret = airoha_led_set_usr_def(phydev, led_id,
+					led_cfg[led_id].pol,
+					led_cfg[led_id].on_cfg,
+					led_cfg[led_id].blk_cfg);
+			if (ret != 0) {
+				dev_err(dev, "LED fail to set usr def, ret %d !\n",
+				ret);
+				return ret;
+			}
+		}
+	}
+	reg_value = (airoha_pbus_read(mbus, pbus_addr, 0x1880) & ~led_gpio);
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x1880, reg_value);
+	if (ret < 0)
+		return ret;
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x186c, led_gpio);
+	if (ret < 0)
+		return ret;
+	dev_info(dev, "LED initialize OK !\n");
+	return 0;
+}
+#endif
+static int en8801s_phy_process(struct phy_device *phydev)
+{
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	unsigned long reg_value = 0;
+	int ret = 0;
+	int pbus_addr = phydev_pbus_addr(phydev);
+
+	reg_value = airoha_pbus_read(mbus, pbus_addr, 0x19e0);
+	reg_value |= BIT(0);
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x19e0, reg_value);
+	if (ret < 0)
+		return ret;
+	reg_value = airoha_pbus_read(mbus, pbus_addr, 0x19e0);
+	reg_value &= ~BIT(0);
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x19e0, reg_value);
+	if (ret < 0)
+		return ret;
+	return ret;
+}
+
+static int en8801s_phase1_init(struct phy_device *phydev)
+{
+	unsigned long pbus_data;
+	int pbusAddress = EN8801S_PBUS_DEFAULT_ID;
+	u16 reg_value;
+	int retry, ret = 0;
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	struct device *dev = phydev_dev(phydev);
+	struct en8801s_priv *priv = phydev->priv;
+
+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
+	/* Deassert the reset signal */
+	if (priv->hw_reset)
+		gpiod_set_value(priv->hw_reset, 0);
+#endif
+	priv->count = 1;
+	msleep(1000);
+
+	retry = MAX_OUI_CHECK;
+	while (1) {
+		pbus_data = airoha_pbus_read(mbus, pbusAddress,
+				EN8801S_RG_ETHER_PHY_OUI);      /* PHY OUI */
+		if (pbus_data == EN8801S_PBUS_OUI) {
+			dev_info(dev, "PBUS addr 0x%x: Start initialized.\n",
+					pbusAddress);
+			break;
+		}
+		pbusAddress = phydev_pbus_addr(phydev);
+		if (0 == --retry) {
+			dev_err(dev, "Probe fail !\n");
+			return 0;
+		}
+	}
+
+	ret = airoha_pbus_write(mbus, pbusAddress, EN8801S_RG_BUCK_CTL, 0x03);
+	if (ret < 0)
+		return ret;
+	mdelay(10);
+	pbus_data = (airoha_pbus_read(mbus, pbusAddress, EN8801S_RG_LTR_CTL)
+				 & 0xfffffffc) | BIT(2);
+	ret = airoha_pbus_write(mbus, pbusAddress,
+				EN8801S_RG_LTR_CTL, pbus_data);
+	if (ret < 0)
+		return ret;
+	mdelay(500);
+	pbus_data = (pbus_data & ~BIT(2)) |
+				EN8801S_RX_POLARITY_NORMAL |
+				EN8801S_TX_POLARITY_NORMAL;
+	ret = airoha_pbus_write(mbus, pbusAddress,
+				EN8801S_RG_LTR_CTL, pbus_data);
+	if (ret < 0)
+		return ret;
+	mdelay(500);
+
+	pbus_data = airoha_pbus_read(mbus, pbusAddress,
+				EN8801S_RG_SMI_ADDR); /* SMI ADDR */
+	pbus_data = (pbus_data & 0xffff0000) |
+				(unsigned long)(phydev_pbus_addr(phydev) << 8) |
+				(unsigned long)(phydev_phy_addr(phydev));
+	dev_info(phydev_dev(phydev), "SMI_ADDR=%lx (renew)\n", pbus_data);
+	ret = airoha_pbus_write(mbus, pbusAddress,
+				EN8801S_RG_SMI_ADDR, pbus_data);
+	mdelay(10);
+
+	retry = MAX_RETRY;
+	while (1) {
+		mdelay(10);
+		reg_value = phy_read(phydev, MII_PHYSID2);
+		if (reg_value == EN8801S_PHY_ID2)
+			break;    /* wait GPHY ready */
+
+		retry--;
+		if (retry == 0) {
+			dev_err(dev, "Initialize fail !\n");
+			return 0;
+		}
+	}
+	/* Software Reset PHY */
+	reg_value = phy_read(phydev, MII_BMCR);
+	reg_value |= BMCR_RESET;
+	ret = phy_write(phydev, MII_BMCR, reg_value);
+	if (ret < 0)
+		return ret;
+	retry = MAX_RETRY;
+	do {
+		mdelay(10);
+		reg_value = phy_read(phydev, MII_BMCR);
+		retry--;
+		if (retry == 0) {
+			dev_err(dev, "Reset fail !\n");
+			return 0;
+		}
+	} while (reg_value & BMCR_RESET);
+
+	phydev->dev_flags = PHY_STATE_INIT;
+
+	dev_info(dev, "Phase1 initialize OK ! (%s)\n", EN8801S_DRIVER_VERSION);
+
+	return 0;
+}
+
+static int en8801s_phase2_init(struct phy_device *phydev)
+{
+	union gephy_all_REG_LpiReg1Ch      GPHY_RG_LPI_1C;
+	union gephy_all_REG_dev1Eh_reg324h GPHY_RG_1E_324;
+	union gephy_all_REG_dev1Eh_reg012h GPHY_RG_1E_012;
+	union gephy_all_REG_dev1Eh_reg017h GPHY_RG_1E_017;
+	unsigned long pbus_data;
+	int phy_addr = phydev_phy_addr(phydev);
+	int pbus_addr = phydev_pbus_addr(phydev);
+	u16 cl45_value;
+	int retry, ret = 0;
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	struct device *dev = phydev_dev(phydev);
+	struct en8801s_priv *priv = phydev->priv;
+
+	pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1690);
+	pbus_data |= BIT(31);
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x1690, pbus_data);
+	if (ret < 0)
+		return ret;
+
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00);
+	if (ret < 0)
+		return ret;
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x10, 0xD801);
+	if (ret < 0)
+		return ret;
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x0,  0x9140);
+	if (ret < 0)
+		return ret;
+
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14, 0x0003);
+	if (ret < 0)
+		return ret;
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x0600, 0x0c000c00);
+	if (ret < 0)
+		return ret;
+	/* Set FCM control */
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x1404, 0x004b);
+	if (ret < 0)
+		return ret;
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x140c, 0x0007);
+	if (ret < 0)
+		return ret;
+
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x142c, 0x05050505);
+	if (ret < 0)
+		return ret;
+	pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1440);
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x1440, pbus_data & ~BIT(11));
+	if (ret < 0)
+		return ret;
+
+	pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1408);
+	ret = airoha_pbus_write(mbus, pbus_addr, 0x1408, pbus_data | BIT(5));
+	if (ret < 0)
+		return ret;
+
+	/* Set GPHY Perfomance*/
+	/* Token Ring */
+	ret = airoha_tr_reg_write(phydev, RgAddr_R1000DEC_15h, 0x0055A0);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_R1000DEC_17h, 0x07FF3F);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_PMA_00h,      0x00001E);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_PMA_01h,      0x6FB90A);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_PMA_17h,      0x060671);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_PMA_18h,      0x0E2F00);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_TR_26h,       0x444444);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_03h,     0x000000);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_06h,     0x2EBAEF);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_08h,     0x00000B);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Ch,     0x00504D);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Dh,     0x02314F);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_0Fh,     0x003028);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_10h,     0x005010);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_11h,     0x040001);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_13h,     0x018670);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_14h,     0x00024A);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_1Bh,     0x000072);
+	if (ret < 0)
+		return ret;
+	ret = airoha_tr_reg_write(phydev, RgAddr_DSPF_1Ch,     0x003210);
+	if (ret < 0)
+		return ret;
+
+	/* CL22 & CL45 */
+	ret = phy_write(phydev, 0x1f, 0x03);
+	if (ret < 0)
+		return ret;
+	GPHY_RG_LPI_1C.DATA = phy_read(phydev, RgAddr_LPI_1Ch);
+	GPHY_RG_LPI_1C.DataBitField.smi_deton_th = 0x0C;
+	ret = phy_write(phydev, RgAddr_LPI_1Ch, GPHY_RG_LPI_1C.DATA);
+	if (ret < 0)
+		return ret;
+	ret = phy_write(phydev, RgAddr_LPI_1Ch, 0xC92);
+	if (ret < 0)
+		return ret;
+	ret = phy_write(phydev, RgAddr_AUXILIARY_1Dh, 0x1);
+	if (ret < 0)
+		return ret;
+	ret = phy_write(phydev, 0x1f, 0x0);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x120, 0x8014);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x122, 0xffff);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x123, 0xffff);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x144, 0x0200);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x14A, 0xEE20);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x189, 0x0110);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x19B, 0x0111);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x234, 0x0181);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x238, 0x0120);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x239, 0x0117);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x268, 0x07F4);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x2D1, 0x0733);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x323, 0x0011);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x324, 0x013F);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x326, 0x0037);
+	if (ret < 0)
+		return ret;
+
+	ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x324, &cl45_value);
+	if (ret < 0)
+		return ret;
+	GPHY_RG_1E_324.DATA = cl45_value;
+	GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = 0;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x324,
+				GPHY_RG_1E_324.DATA);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x19E, 0xC2);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x013, 0x0);
+	if (ret < 0)
+		return ret;
+
+	/* EFUSE */
+	airoha_pbus_write(mbus, pbus_addr, 0x1C08, 0x40000040);
+	retry = MAX_RETRY;
+	while (retry != 0) {
+		mdelay(1);
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C08);
+		if ((pbus_data & BIT(30)) == 0)
+			break;
+
+		retry--;
+	}
+	pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C38); /* RAW#2 */
+	ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x12, &cl45_value);
+	if (ret < 0)
+		return ret;
+	GPHY_RG_1E_012.DATA = cl45_value;
+	GPHY_RG_1E_012.DataBitField.da_tx_i2mpb_a_tbt =
+				(u16)(pbus_data & 0x03f);
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x12,
+				GPHY_RG_1E_012.DATA);
+	if (ret < 0)
+		return ret;
+	ret = airoha_cl45_read(mbus, phy_addr, 0x1E, 0x17, &cl45_value);
+	if (ret < 0)
+		return ret;
+	GPHY_RG_1E_017.DATA = cl45_value;
+	GPHY_RG_1E_017.DataBitField.da_tx_i2mpb_b_tbt =
+				(u16)((pbus_data >> 8) & 0x03f);
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x17,
+				GPHY_RG_1E_017.DATA);
+	if (ret < 0)
+		return ret;
+
+	airoha_pbus_write(mbus, pbus_addr, 0x1C08, 0x40400040);
+	retry = MAX_RETRY;
+	while (retry != 0) {
+		mdelay(1);
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C08);
+		if ((pbus_data & BIT(30)) == 0)
+			break;
+
+		retry--;
+	}
+	pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1C30); /* RAW#16 */
+	GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off =
+				(u16)((pbus_data >> 12) & 0x01);
+	ret = airoha_cl45_write(mbus, phy_addr, 0x1E, 0x324,
+				GPHY_RG_1E_324.DATA);
+	if (ret < 0)
+		return ret;
+#ifdef AIR_LED_SUPPORT
+	ret = en8801s_led_init(phydev);
+	if (ret != 0)
+		dev_err(dev, "en8801s_led_init fail (ret:%d) !\n", ret);
+#endif
+
+	ret = airoha_cl45_read(mbus, phy_addr, MDIO_MMD_AN,
+				MDIO_AN_EEE_ADV, &cl45_value);
+	if (ret < 0)
+		return ret;
+	if (cl45_value == 0) {
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1960);
+		if (0xA == ((pbus_data & 0x07c00000) >> 22)) {
+			pbus_data = (pbus_data & 0xf83fffff) | (0xC << 22);
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1960,
+						pbus_data);
+			if (ret < 0)
+				return ret;
+			mdelay(10);
+			pbus_data = (pbus_data & 0xf83fffff) | (0xE << 22);
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1960,
+						pbus_data);
+			if (ret < 0)
+				return ret;
+			mdelay(10);
+		}
+	} else {
+		pbus_data = airoha_pbus_read(mbus, pbus_addr, 0x1960);
+		if (0xE == ((pbus_data & 0x07c00000) >> 22)) {
+			pbus_data = (pbus_data & 0xf83fffff) | (0xC << 22);
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1960,
+						pbus_data);
+			if (ret < 0)
+				return ret;
+			mdelay(10);
+			pbus_data = (pbus_data & 0xf83fffff) | (0xA << 22);
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1960,
+						pbus_data);
+			if (ret < 0)
+				return ret;
+			mdelay(10);
+		}
+	}
+
+	priv->first_init = false;
+	dev_info(phydev_dev(phydev), "Phase2 initialize OK !\n");
+	return 0;
+}
+
+static int en8801s_read_status(struct phy_device *phydev)
+{
+	int ret = 0, preSpeed = phydev->speed;
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	u32 reg_value;
+	struct device *dev = phydev_dev(phydev);
+	int pbus_addr = phydev_pbus_addr(phydev);
+	struct en8801s_priv *priv = phydev->priv;
+
+	ret = genphy_read_status(phydev);
+	if (phydev->link == LINK_DOWN)
+		preSpeed = phydev->speed = 0;
+
+	if (phydev->dev_flags == PHY_STATE_PROCESS) {
+		en8801s_phy_process(phydev);
+		phydev->dev_flags = PHY_STATE_DONE;
+	}
+
+	if (phydev->dev_flags == PHY_STATE_INIT) {
+		dev_dbg(dev, "phydev->link %d, count %d\n",
+					phydev->link, priv->count);
+		if ((phydev->link) || (priv->count == 5)) {
+			ret = en8801s_phase2_init(phydev);
+			if (ret != 0) {
+				dev_info(dev, "en8801_phase2_init failed\n");
+				phydev->dev_flags = PHY_STATE_FAIL;
+				return 0;
+			}
+			phydev->dev_flags = PHY_STATE_PROCESS;
+		}
+		priv->count++;
+	}
+
+	if ((preSpeed != phydev->speed) && (phydev->link == LINK_UP)) {
+		preSpeed = phydev->speed;
+
+		if (preSpeed == SPEED_10) {
+			reg_value = airoha_pbus_read(mbus, pbus_addr, 0x1694);
+			reg_value |= BIT(31);
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1694,
+					reg_value);
+			if (ret < 0)
+				return ret;
+			phydev->dev_flags = PHY_STATE_PROCESS;
+		} else {
+			reg_value = airoha_pbus_read(mbus, pbus_addr, 0x1694);
+			reg_value &= ~BIT(31);
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1694,
+					reg_value);
+			if (ret < 0)
+				return ret;
+			phydev->dev_flags = PHY_STATE_PROCESS;
+		}
+
+		airoha_pbus_write(mbus, pbus_addr, 0x0600,
+				0x0c000c00);
+		if (preSpeed == SPEED_1000) {
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x10,
+					0xD801);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0,
+					0x9140);
+			if (ret < 0)
+				return ret;
+
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14,
+					0x0003);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0600,
+					0x0c000c00);
+			if (ret < 0)
+				return ret;
+			mdelay(2);      /* delay 2 ms */
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1404,
+					0x004b);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x140c,
+					0x0007);
+			if (ret < 0)
+				return ret;
+		} else if (preSpeed == SPEED_100) {
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x10,
+					0xD401);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0,
+					0x9140);
+			if (ret < 0)
+				return ret;
+
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14,
+					0x0007);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0600,
+					0x0c11);
+			if (ret < 0)
+				return ret;
+			mdelay(2);      /* delay 2 ms */
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1404,
+					0x0027);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x140c,
+					0x0007);
+			if (ret < 0)
+				return ret;
+		} else if (preSpeed == SPEED_10) {
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x10,
+					0xD001);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0,
+					0x9140);
+			if (ret < 0)
+				return ret;
+
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0A14,
+					0x000b);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x0600,
+					0x0c11);
+			if (ret < 0)
+				return ret;
+			mdelay(2);      /* delay 2 ms */
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x1404,
+					0x0027);
+			if (ret < 0)
+				return ret;
+			ret = airoha_pbus_write(mbus, pbus_addr, 0x140c,
+					0x0007);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return ret;
+}
+
+static int en8801s_probe(struct phy_device *phydev)
+{
+	struct en8801s_priv *priv;
+	unsigned long phy_addr = phydev_phy_addr(phydev);
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	struct device *dev = &mbus->dev;
+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
+	struct gpio_desc *en8801s_reset;
+	int err = 0;
+#else
+	struct mdio_device *mdiodev = &phydev->mdio;
+#endif
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->count = 0;
+	priv->first_init = true;
+
+#if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
+	/* Assert the optional reset signal */
+	en8801s_reset = gpiod_get_optional(&phydev->dev,
+				"reset", GPIOD_OUT_HIGH);
+	err = PTR_ERR_OR_ZERO(en8801s_reset);
+	if (err) {
+		dev_dbg(phydev_dev(phydev),
+				"PHY %lx have no reset pin in device tree.\n",
+				phy_addr);
+	} else {
+		dev_dbg(phydev_dev(phydev),
+				"Assert PHY %lx HWRST until config_init\n",
+				phy_addr);
+		priv->hw_reset = en8801s_reset;
+	}
+
+#else
+	if (mdiodev->reset_gpio) {
+		dev_dbg(phydev_dev(phydev),
+				"Assert PHY %lx HWRST until phy_init_hw\n",
+				phy_addr);
+		phy_device_reset(phydev, 1);
+	}
+#endif
+
+	phydev->priv = priv;
+
+	return 0;
+}
+
+#if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE)
+static int airoha_mmd_read(struct phy_device *phydev,
+			int devad, u16 reg)
+{
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	int phy_addr = phydev_phy_addr(phydev);
+	int ret = 0;
+	u16 cl45_value;
+
+	ret = __airoha_cl45_read(mbus, phy_addr, devad, reg, &cl45_value);
+	if (ret < 0)
+		return ret;
+
+	return cl45_value;
+}
+
+static int airoha_mmd_write(struct phy_device *phydev,
+			int devad, u16 reg, u16 val)
+{
+	struct mii_bus *mbus = phydev_mdio_bus(phydev);
+	int phy_addr = phydev_phy_addr(phydev);
+	int pbus_addr = phydev_pbus_addr(phydev);
+	unsigned long pbus_data;
+	int ret = 0;
+
+	if (MDIO_MMD_AN == devad && MDIO_AN_EEE_ADV == reg) {
+		if (val == 0) {
+			pbus_data = __airoha_pbus_read(mbus, pbus_addr, 0x1960);
+			if (0xA == ((pbus_data & 0x07c00000) >> 22)) {
+				pbus_data = (pbus_data & 0xf83fffff) |
+							(0xC << 22);
+				__airoha_pbus_write(mbus, pbus_addr, 0x1960,
+							pbus_data);
+				mdelay(10);
+				pbus_data = (pbus_data & 0xf83fffff) |
+							(0xE << 22);
+				__airoha_pbus_write(mbus, pbus_addr, 0x1960,
+							pbus_data);
+				mdelay(10);
+			}
+		} else {
+			pbus_data = __airoha_pbus_read(mbus, pbus_addr, 0x1960);
+			if (0xE == ((pbus_data & 0x07c00000) >> 22)) {
+				pbus_data = (pbus_data & 0xf83fffff) |
+							(0xC << 22);
+				__airoha_pbus_write(mbus, pbus_addr, 0x1960,
+							pbus_data);
+				mdelay(10);
+				pbus_data = (pbus_data & 0xf83fffff) |
+							(0xA << 22);
+				__airoha_pbus_write(mbus, pbus_addr, 0x1960,
+							pbus_data);
+				mdelay(10);
+			}
+		}
+	}
+
+	ret = __airoha_cl45_write(mbus, phy_addr, devad, reg, val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+#endif
+
+static struct phy_driver Airoha_driver[] = {
+	{
+		.phy_id         = EN8801SC_PHY_ID,
+		.name           = "Airoha EN8801SC",
+		.phy_id_mask    = 0x0ffffff0,
+		.features       = PHY_GBIT_FEATURES,
+		.probe          = en8801s_probe,
+		.config_init    = en8801s_phase1_init,
+		.config_aneg    = genphy_config_aneg,
+		.read_status    = en8801s_read_status,
+		.suspend        = genphy_suspend,
+		.resume         = genphy_resume,
+#if (KERNEL_VERSION(4, 5, 0) < LINUX_VERSION_CODE)
+		.read_mmd       = airoha_mmd_read,
+		.write_mmd      = airoha_mmd_write,
+#endif
+	}
+};
+
+module_phy_driver(Airoha_driver);
+
+static struct mdio_device_id __maybe_unused Airoha_tbl[] = {
+	{ EN8801SC_PHY_ID, 0x0ffffff0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(mdio, Airoha_tbl);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.h
new file mode 100644
index 0000000..0a077c3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/en8801sc.h
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0
+/* FILE NAME:  en8801sc.h
+ * PURPOSE:
+ *      Define EN8801SC driver function
+ *
+ * NOTES:
+ *
+ */
+
+#ifndef __EN8801SC_H
+#define __EN8801SC_H
+
+/* NAMING DECLARATIONS
+ */
+#define EN8801S_DRIVER_VERSION  "1.1.7_Generic"
+#define EN8801S_PBUS_DEFAULT_ID 0x1e
+#define EN8801S_RG_ETHER_PHY_OUI 0x19a4
+#define EN8801S_RG_SMI_ADDR      0x19a8
+#define EN8801S_RG_BUCK_CTL      0x1a20
+#define EN8801S_RG_LTR_CTL       0x0cf8
+
+#define EN8801S_PBUS_OUI        0x17a5
+#define EN8801S_PHY_ID1         0x03a2
+#define EN8801S_PHY_ID2         0x9461
+#define EN8801SC_PHY_ID         0x03a29471
+
+#define LED_ON_CTRL(i)              (0x024 + ((i)*2))
+#define LED_ON_EN                   (1 << 15)
+#define LED_ON_POL                  (1 << 14)
+#define LED_ON_EVT_MASK             (0x7f)
+/* LED ON Event Option.B */
+#define LED_ON_EVT_FORCE            (1 << 6)
+#define LED_ON_EVT_LINK_DOWN        (1 << 3)
+#define LED_ON_EVT_LINK_10M         (1 << 2)
+#define LED_ON_EVT_LINK_100M        (1 << 1)
+#define LED_ON_EVT_LINK_1000M       (1 << 0)
+/* LED ON Event Option.E */
+
+#define LED_BLK_CTRL(i)             (0x025 + ((i)*2))
+#define LED_BLK_EVT_MASK            (0x3ff)
+/* LED Blinking Event Option.B*/
+#define LED_BLK_EVT_FORCE           (1 << 9)
+#define LED_BLK_EVT_10M_RX_ACT      (1 << 5)
+#define LED_BLK_EVT_10M_TX_ACT      (1 << 4)
+#define LED_BLK_EVT_100M_RX_ACT     (1 << 3)
+#define LED_BLK_EVT_100M_TX_ACT     (1 << 2)
+#define LED_BLK_EVT_1000M_RX_ACT    (1 << 1)
+#define LED_BLK_EVT_1000M_TX_ACT    (1 << 0)
+/* LED Blinking Event Option.E*/
+#define LED_ENABLE                  1
+#define LED_DISABLE                 0
+
+#define LINK_UP                 1
+#define LINK_DOWN               0
+
+/*
+SFP Sample for verification
+Tx Reverse, Rx Reverse
+*/
+#define EN8801S_TX_POLARITY_NORMAL   0x0
+#define EN8801S_TX_POLARITY_REVERSE  0x1
+
+#define EN8801S_RX_POLARITY_NORMAL   (0x1 << 1)
+#define EN8801S_RX_POLARITY_REVERSE  (0x0 << 1)
+
+/*
+The following led_cfg example is for reference only.
+LED5 1000M/LINK/ACT  (GPIO5)  <-> BASE_T_LED0,
+LED6 10/100M/LINK/ACT(GPIO9)  <-> BASE_T_LED1,
+LED4 100M/LINK/ACT   (GPIO8)  <-> BASE_T_LED2,
+*/
+/* User-defined.B */
+#define BASE_T_LED0_ON_CFG      (LED_ON_EVT_LINK_1000M)
+#define BASE_T_LED0_BLK_CFG \
+			(LED_BLK_EVT_1000M_TX_ACT | \
+			LED_BLK_EVT_1000M_RX_ACT)
+#define BASE_T_LED1_ON_CFG \
+			(LED_ON_EVT_LINK_100M | \
+			 LED_ON_EVT_LINK_10M)
+#define BASE_T_LED1_BLK_CFG \
+			(LED_BLK_EVT_100M_TX_ACT | \
+			 LED_BLK_EVT_100M_RX_ACT | \
+			 LED_BLK_EVT_10M_TX_ACT | \
+			 LED_BLK_EVT_10M_RX_ACT)
+#define BASE_T_LED2_ON_CFG \
+			(LED_ON_EVT_LINK_100M)
+#define BASE_T_LED2_BLK_CFG \
+			(LED_BLK_EVT_100M_TX_ACT | \
+			 LED_BLK_EVT_100M_RX_ACT)
+#define BASE_T_LED3_ON_CFG      (0x0)
+#define BASE_T_LED3_BLK_CFG     (0x0)
+/* User-defined.E */
+
+#define EN8801S_LED_COUNT       4
+
+#define MAX_RETRY               5
+#define MAX_OUI_CHECK           2
+/* CL45 MDIO control */
+#define MII_MMD_ACC_CTL_REG     0x0d
+#define MII_MMD_ADDR_DATA_REG   0x0e
+#define MMD_OP_MODE_DATA        BIT(14)
+
+#define MAX_TRG_COUNTER         5
+
+/* CL22 Reg Support Page Select */
+#define RgAddr_Reg1Fh        0x1f
+#define CL22_Page_Reg        0x0000
+#define CL22_Page_ExtReg     0x0001
+#define CL22_Page_MiscReg    0x0002
+#define CL22_Page_LpiReg     0x0003
+#define CL22_Page_tReg       0x02A3
+#define CL22_Page_TrReg      0x52B5
+
+/* CL45 Reg Support DEVID */
+#define DEVID_03             0x03
+#define DEVID_07             0x07
+#define DEVID_1E             0x1E
+#define DEVID_1F             0x1F
+
+/* TokenRing Reg Access */
+#define TrReg_PKT_XMT_STA    0x8000
+#define TrReg_WR             0x8000
+#define TrReg_RD             0xA000
+
+#define RgAddr_LPI_1Ch       0x1c
+#define RgAddr_AUXILIARY_1Dh 0x1d
+#define RgAddr_PMA_00h       0x0f80
+#define RgAddr_PMA_01h       0x0f82
+#define RgAddr_PMA_17h       0x0fae
+#define RgAddr_PMA_18h       0x0fb0
+#define RgAddr_DSPF_03h      0x1686
+#define RgAddr_DSPF_06h      0x168c
+#define RgAddr_DSPF_08h      0x1690
+#define RgAddr_DSPF_0Ch      0x1698
+#define RgAddr_DSPF_0Dh      0x169a
+#define RgAddr_DSPF_0Fh      0x169e
+#define RgAddr_DSPF_10h      0x16a0
+#define RgAddr_DSPF_11h      0x16a2
+#define RgAddr_DSPF_13h      0x16a6
+#define RgAddr_DSPF_14h      0x16a8
+#define RgAddr_DSPF_1Bh      0x16b6
+#define RgAddr_DSPF_1Ch      0x16b8
+#define RgAddr_TR_26h        0x0ecc
+#define RgAddr_R1000DEC_15h  0x03aa
+#define RgAddr_R1000DEC_17h  0x03ae
+
+#define LED_BCR                     (0x021)
+#define LED_BCR_EXT_CTRL            (1 << 15)
+#define LED_BCR_CLK_EN              (1 << 3)
+#define LED_BCR_TIME_TEST           (1 << 2)
+#define LED_BCR_MODE_MASK           (3)
+#define LED_BCR_MODE_DISABLE        (0)
+
+#define LED_ON_DUR                  (0x022)
+#define LED_ON_DUR_MASK             (0xffff)
+
+#define LED_BLK_DUR                 (0x023)
+#define LED_BLK_DUR_MASK            (0xffff)
+
+#define LED_GPIO_SEL_MASK 0x7FFFFFF
+
+#define UNIT_LED_BLINK_DURATION     1024
+
+/* Invalid data */
+#define INVALID_DATA            0xffffffff
+
+#define LED_SET_EVT(reg, cod, result, bit) do         \
+	{                                                 \
+		if (reg & cod) {                              \
+			result |= bit;                            \
+		}                                             \
+	} while (0)
+
+#define LED_SET_GPIO_SEL(gpio, led, val)             \
+			(val |= (led << (8 * (gpio % 4))))       \
+
+
+/* DATA TYPE DECLARATIONS
+ */
+struct AIR_BASE_T_LED_CFG_S {
+	u16 en;
+	u16 gpio;
+	u16 pol;
+	u16 on_cfg;
+	u16 blk_cfg;
+};
+
+union gephy_all_REG_LpiReg1Ch {
+	struct {
+		/* b[15:00] */
+		u16 smi_deton_wt                             : 3;
+		u16 smi_det_mdi_inv                          : 1;
+		u16 smi_detoff_wt                            : 3;
+		u16 smi_sigdet_debouncing_en                 : 1;
+		u16 smi_deton_th                             : 6;
+		u16 rsv_14                                   : 2;
+	} DataBitField;
+	u16 DATA;
+};
+
+union gephy_all_REG_dev1Eh_reg324h {
+	struct {
+		/* b[15:00] */
+		u16 rg_smi_detcnt_max                        : 6;
+		u16 rsv_6                                    : 2;
+		u16 rg_smi_det_max_en                        : 1;
+		u16 smi_det_deglitch_off                     : 1;
+		u16 rsv_10                                   : 6;
+	} DataBitField;
+	u16 DATA;
+};
+
+union gephy_all_REG_dev1Eh_reg012h {
+	struct {
+		/* b[15:00] */
+		u16 da_tx_i2mpb_a_tbt                        : 6;
+		u16 rsv_6                                    : 4;
+		u16 da_tx_i2mpb_a_gbe                        : 6;
+	} DataBitField;
+	u16 DATA;
+};
+
+union gephy_all_REG_dev1Eh_reg017h {
+	struct {
+		/* b[15:00] */
+		u16 da_tx_i2mpb_b_tbt                        : 6;
+		u16 rsv_6                                    : 2;
+		u16 da_tx_i2mpb_b_gbe                        : 6;
+		u16 rsv_14                                   : 2;
+	} DataBitField;
+	u16 DATA;
+};
+
+enum {
+	AIR_LED_BLK_DUR_32M,
+	AIR_LED_BLK_DUR_64M,
+	AIR_LED_BLK_DUR_128M,
+	AIR_LED_BLK_DUR_256M,
+	AIR_LED_BLK_DUR_512M,
+	AIR_LED_BLK_DUR_1024M,
+	AIR_LED_BLK_DUR_LAST
+};
+
+enum {
+	AIR_ACTIVE_LOW,
+	AIR_ACTIVE_HIGH,
+};
+
+enum {
+	AIR_LED_MODE_DISABLE,
+	AIR_LED_MODE_USER_DEFINE,
+	AIR_LED_MODE_LAST
+};
+
+#endif /* End of __EN8801SC_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
index 32ae8ea..2825a36 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
@@ -28,8 +28,17 @@
 
 /* Registers on MDIO_MMD_VEND2 */
 #define MTK_PHY_LED0_ON_CTRL			(0x24)
+#define   MTK_PHY_LED0_ON_LINK1000		BIT(0)
+#define   MTK_PHY_LED0_ON_LINK100		BIT(1)
+#define   MTK_PHY_LED0_ON_LINK10		BIT(2)
+#define   MTK_PHY_LED0_ON_LINK2500		BIT(7)
 #define   MTK_PHY_LED0_POLARITY			BIT(14)
 
+#define MTK_PHY_LED1_ON_CTRL			(0x26)
+#define   MTK_PHY_LED1_ON_FDX			BIT(4)
+#define   MTK_PHY_LED1_ON_HDX			BIT(5)
+#define   MTK_PHY_LED1_POLARITY			BIT(14)
+
 enum {
 	PHY_AUX_SPD_10 = 0,
 	PHY_AUX_SPD_100,
@@ -37,22 +46,6 @@
 	PHY_AUX_SPD_2500,
 };
 
-static int mt798x_2p5ge_phy_probe(struct phy_device *phydev)
-{
-	struct pinctrl *pinctrl;
-
-	phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
-			 MTK_PHY_LED0_POLARITY);
-
-	pinctrl = devm_pinctrl_get_select_default(&phydev->mdio.dev);
-	if (IS_ERR(pinctrl)) {
-		dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
-		return PTR_ERR(pinctrl);
-	}
-
-	return 0;
-}
-
 static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
 {
 	int ret;
@@ -64,6 +57,8 @@
 	void __iomem *pmb_addr;
 	void __iomem *mcucsr_base;
 	u16 reg;
+	struct pinctrl *pinctrl;
+
 
 	np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
 	if (!np)
@@ -103,6 +98,20 @@
 	writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG);
 	dev_info(dev, "Firmware loading/trigger ok.\n");
 
+	/* Setup LED */
+	phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
+			 MTK_PHY_LED0_POLARITY | MTK_PHY_LED0_ON_LINK10 |
+			 MTK_PHY_LED0_ON_LINK100 | MTK_PHY_LED0_ON_LINK1000 |
+			 MTK_PHY_LED0_ON_LINK2500);
+	phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
+			 MTK_PHY_LED1_ON_FDX | MTK_PHY_LED1_ON_HDX);
+
+	pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
+	if (IS_ERR(pinctrl)) {
+		dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
+		return PTR_ERR(pinctrl);
+	}
+
 	return 0;
 }
 
@@ -221,7 +230,6 @@
 	{
 		PHY_ID_MATCH_EXACT(0x00339c11),
 		.name		= "MediaTek MT798x 2.5GbE PHY",
-		.probe		= mt798x_2p5ge_phy_probe,
 		.config_init	= mt798x_2p5ge_phy_config_init,
 		.config_aneg    = mt798x_2p5ge_phy_config_aneg,
 		.get_features	= mt798x_2p5ge_phy_get_features,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
index 04e4edc..201a629 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
@@ -208,9 +208,9 @@
 +		mtk_wed_add_hw(np, eth, wdma, i);
 +	}
 +
- 	for (i = 0; i < MTK_MAX_IRQ_NUM; i++) {
- 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0)
- 			eth->irq[i] = eth->irq[0];
+ 	for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
+		eth->irq_pdma[i] = platform_get_irq(pdev, i);
+
 @@ -4320,10 +4397,11 @@ static int mtk_probe(struct platform_dev
  	}
  
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 e542a51..e706419 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -7,7 +7,6 @@
 CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_GANG=y
 # CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_SINGLE is not set
 CONFIG_AQUANTIA_PHY_FW_FILE="Rhe-05.06-Candidate9-AQR_Mediatek_23B_P5_ID45824_LCLVER1.cld"
-# CONFIG_AQUANTIA_PHY_MDI_SWAP is not set
 CONFIG_ARCH_CLOCKSOURCE_DATA=y
 CONFIG_ARCH_DMA_ADDR_T_64BIT=y
 CONFIG_ARCH_KEEP_MEMBLOCK=y
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-en8801sc-gphy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-en8801sc-gphy-support.patch
index b50a7bb..6de04c3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-en8801sc-gphy-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/745-en8801sc-gphy-support.patch
@@ -1,1021 +1,3 @@
-Index: drivers/net/phy/en8801sc.c
-===================================================================
---- /dev/null
-+++ b/drivers/net/phy/en8801sc.c
-@@ -0,0 +1,732 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* FILE NAME:  en8801sc.c
-+ * PURPOSE:
-+ *      EN8801SC phy driver for Linux
-+ * NOTES:
-+ *
-+ */
-+
-+/* INCLUDE FILE DECLARATIONS
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/errno.h>
-+#include <linux/unistd.h>
-+#include <linux/interrupt.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/spinlock.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/mii.h>
-+#include <linux/ethtool.h>
-+#include <linux/phy.h>
-+#include <linux/delay.h>
-+
-+#include <linux/uaccess.h>
-+#include <linux/version.h>
-+
-+#include "en8801sc.h"
-+
-+MODULE_DESCRIPTION("Airoha EN8801S PHY drivers for MediaTek SoC");
-+MODULE_AUTHOR("Airoha");
-+MODULE_LICENSE("GPL");
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
-+#define phydev_mdio_bus(dev) ((dev)->bus)
-+#else
-+#define phydev_mdio_bus(dev) ((dev)->mdio.bus)
-+#endif
-+
-+enum {
-+    PHY_STATE_DONE = 0,
-+    PHY_STATE_INIT = 1,
-+    PHY_STATE_PROCESS = 2,
-+    PHY_STATE_SS_FAIL = 3,
-+    PHY_STATE_FAIL = 4
-+};
-+
-+/*
-+The following led_cfg example is for reference only.
-+LED5 1000M/LINK/ACT   (GPIO5)  <-> BASE_T_LED0,
-+LED6 10/100M/LINK/ACT (GPIO9)  <-> BASE_T_LED1,
-+LED4 100M/LINK/ACT    (GPIO8)  <-> BASE_T_LED2,
-+*/
-+/* User-defined.B */
-+#define AIR_LED_SUPPORT
-+#ifdef AIR_LED_SUPPORT
-+static const AIR_BASE_T_LED_CFG_T led_cfg[4] =
-+{
-+    /*
-+     *    LED Enable,     GPIO,       LED Polarity,            LED ON,               LED Blink
-+     */
-+         {LED_ENABLE,       5,       AIR_ACTIVE_LOW,      BASE_T_LED0_ON_CFG,    BASE_T_LED0_BLK_CFG}, /* BASE-T LED0 */
-+         {LED_ENABLE,       9,       AIR_ACTIVE_LOW,      BASE_T_LED1_ON_CFG,    BASE_T_LED1_BLK_CFG}, /* BASE-T LED1 */
-+         {LED_ENABLE,       8,       AIR_ACTIVE_LOW,      BASE_T_LED2_ON_CFG,    BASE_T_LED2_BLK_CFG}, /* BASE-T LED2 */
-+         {LED_DISABLE,      1,       AIR_ACTIVE_LOW,      BASE_T_LED3_ON_CFG,    BASE_T_LED3_BLK_CFG}  /* BASE-T LED3 */
-+};
-+static const u16 led_dur = UNIT_LED_BLINK_DURATION << AIR_LED_BLK_DUR_64M;
-+#endif
-+/* User-defined.E */
-+
-+/************************************************************************
-+*                  F U N C T I O N S
-+************************************************************************/
-+static int airoha_cl45_write(struct mii_bus *bus, u32 port, u32 devad, u32 reg, u16 val)
-+{
-+    int ret = 0;
-+    struct device *dev = &bus->dev;
-+
-+    ret = mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    ret = mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    ret = mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    ret = mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, val);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    return ret;
-+}
-+
-+static int airoha_cl45_read(struct mii_bus *bus, u32 port, u32 devad, u32 reg, u16 *read_data)
-+{
-+    int ret = 0;
-+    struct device *dev = &bus->dev;
-+
-+    ret = mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, devad);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    ret = mdiobus_write(bus, port, MII_MMD_ADDR_DATA_REG, reg);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    ret = mdiobus_write(bus, port, MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    *read_data = mdiobus_read(bus, port, MII_MMD_ADDR_DATA_REG);
-+    return 0;
-+}
-+
-+static unsigned int airoha_cl22_read(struct mii_bus *ebus, unsigned int phy_addr, unsigned int phy_register, unsigned int *read_data)
-+{
-+    *read_data = mdiobus_read(ebus, phy_addr, phy_register);
-+    return 0;
-+}
-+
-+static int airoha_cl22_write(struct mii_bus *ebus, unsigned int phy_addr, unsigned int phy_register, unsigned int write_data)
-+{
-+    int ret = 0;
-+    struct device *dev = &ebus->dev;
-+
-+    ret = mdiobus_write(ebus, phy_addr, phy_register, write_data);
-+    AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+    return ret;
-+}
-+
-+static int airoha_pbus_write(struct mii_bus *ebus, unsigned long pbus_id, unsigned long pbus_address, unsigned long pbus_data)
-+{
-+    int ret = 0;
-+
-+    ret = airoha_cl22_write(ebus, pbus_id, 0x1F, (unsigned int)(pbus_address >> 6));
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl22_write(ebus, pbus_id, (unsigned int)((pbus_address >> 2) & 0xf), (unsigned int)(pbus_data & 0xFFFF));
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl22_write(ebus, pbus_id, 0x10, (unsigned int)(pbus_data >> 16));
-+    AIR_RTN_ERR(ret);
-+    return ret;
-+}
-+
-+static unsigned long airoha_pbus_read(struct mii_bus *ebus, unsigned long pbus_id, unsigned long pbus_address)
-+{
-+    unsigned long pbus_data;
-+    unsigned int pbus_data_low, pbus_data_high;
-+    int ret = 0;
-+    struct device *dev = &ebus->dev;
-+    ret = airoha_cl22_write(ebus, pbus_id, 0x1F, (unsigned int)(pbus_address >> 6));
-+    if ( ret < 0) {
-+        AIR_RTN_ON_ERR_MSG(ret < 0, ret, "%s fail. (ret=%d)\n", __func__, ret);
-+        return INVALID_DATA;
-+    }
-+    airoha_cl22_read(ebus, pbus_id, (unsigned int)((pbus_address >> 2) & 0xf), &pbus_data_low);
-+    airoha_cl22_read(ebus, pbus_id, 0x10, &pbus_data_high);
-+    pbus_data = (pbus_data_high << 16) + pbus_data_low;
-+    return pbus_data;
-+}
-+
-+/* Airoha Token Ring Write function */
-+static int airoha_tr_reg_write(struct mii_bus *ebus, unsigned long tr_address, unsigned long tr_data)
-+{
-+    int ret = 0;
-+    ret = airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x52b5);       /* page select */
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x11, (unsigned int)(tr_data & 0xffff));
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x12, (unsigned int)(tr_data >> 16));
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x10, (unsigned int)(tr_address | TrReg_WR));
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x0);          /* page resetore */
-+    AIR_RTN_ERR(ret);
-+    return ret;
-+}
-+
-+#if 0
-+/* Airoha Token Ring Read function */
-+static unsigned long airoha_tr_reg_read(struct mii_bus *ebus, unsigned long tr_address)
-+{
-+    unsigned long tr_data;
-+    unsigned int tr_data_low, tr_data_high;
-+
-+    airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x52b5);       /* page select */
-+    airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x10, (unsigned int)(tr_address | TrReg_RD));
-+    airoha_cl22_read(ebus, EN8801S_MDIO_PHY_ID, 0x11, &tr_data_low);
-+    airoha_cl22_read(ebus, EN8801S_MDIO_PHY_ID, 0x12, &tr_data_high);
-+    airoha_cl22_write(ebus, EN8801S_MDIO_PHY_ID, 0x1F, 0x0);          /* page resetore */
-+    tr_data = (tr_data_high << 16) + tr_data_low;
-+    return tr_data;
-+}
-+#endif
-+#ifdef AIR_LED_SUPPORT
-+static int airoha_led_set_usr_def(struct mii_bus *mbus, u8 entity, int polar,
-+                                   u16 on_evt, u16 blk_evt)
-+{
-+    int ret = 0;
-+    if (AIR_ACTIVE_HIGH == polar) {
-+        on_evt |= LED_ON_POL;
-+    } else {
-+        on_evt &= ~LED_ON_POL;
-+    }
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_ON_CTRL(entity), on_evt | LED_ON_EN);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_BLK_CTRL(entity), blk_evt);
-+    AIR_RTN_ERR(ret);
-+    return 0;
-+}
-+
-+static int airoha_led_set_mode(struct mii_bus *mbus, u8 mode)
-+{
-+    u16 cl45_data;
-+    int err = 0;
-+
-+    err = airoha_cl45_read(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_BCR, &cl45_data);
-+    AIR_RTN_ERR(err);
-+
-+    switch (mode) {
-+    case AIR_LED_MODE_DISABLE:
-+        cl45_data &= ~LED_BCR_EXT_CTRL;
-+        cl45_data &= ~LED_BCR_MODE_MASK;
-+        cl45_data |= LED_BCR_MODE_DISABLE;
-+        break;
-+    case AIR_LED_MODE_USER_DEFINE:
-+        cl45_data |= LED_BCR_EXT_CTRL;
-+        cl45_data |= LED_BCR_CLK_EN;
-+        break;
-+    default:
-+        return -EINVAL;
-+    }
-+
-+    err = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_BCR, cl45_data);
-+    AIR_RTN_ERR(err);
-+    return 0;
-+}
-+
-+static int airoha_led_set_state(struct mii_bus *mbus, u8 entity, u8 state)
-+{
-+    u16 cl45_data;
-+    int err;
-+
-+    err = airoha_cl45_read(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_ON_CTRL(entity), &cl45_data);
-+    AIR_RTN_ERR(err);
-+    if (LED_ENABLE == state) {
-+        cl45_data |= LED_ON_EN;
-+    } else {
-+        cl45_data &= ~LED_ON_EN;
-+    }
-+
-+    err = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_ON_CTRL(entity), cl45_data);
-+    AIR_RTN_ERR(err);
-+    return 0;
-+}
-+
-+static int en8801s_led_init(struct phy_device *phydev)
-+{
-+
-+    unsigned long led_gpio = 0, reg_value = 0;
-+    int ret = 0, led_id;
-+    struct mii_bus *mbus = phydev_mdio_bus(phydev);
-+    int gpio_led_rg[3] = {0x1870, 0x1874, 0x1878};
-+    u16 cl45_data = led_dur;
-+    struct device *dev = &mbus->dev;
-+
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_BLK_DUR, cl45_data);
-+    AIR_RTN_ERR(ret);
-+    cl45_data >>= 1;
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1f, LED_ON_DUR, cl45_data);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_led_set_mode(mbus, AIR_LED_MODE_USER_DEFINE);
-+    if (ret != 0) {
-+        dev_err(dev, "LED fail to set mode, ret %d !\n", ret);
-+        return ret;
-+    }
-+    for(led_id = 0; led_id < EN8801S_LED_COUNT; led_id++)
-+    {
-+        reg_value = 0;
-+        ret = airoha_led_set_state(mbus, led_id, led_cfg[led_id].en);
-+        if (ret != 0)
-+        {
-+            dev_err(dev, "LED fail to set state, ret %d !\n", ret);
-+            return ret;
-+        }
-+        if (LED_ENABLE == led_cfg[led_id].en)
-+        {
-+            if ( (led_cfg[led_id].gpio < 0) || led_cfg[led_id].gpio > 9)
-+            {
-+                dev_err(dev, "GPIO%d is out of range!! GPIO number is 0~9.\n", led_cfg[led_id].gpio);
-+                return -EIO;
-+            }
-+            led_gpio |= BIT(led_cfg[led_id].gpio);
-+            reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, gpio_led_rg[led_cfg[led_id].gpio / 4]);
-+            LED_SET_GPIO_SEL(led_cfg[led_id].gpio, led_id, reg_value);
-+            dev_dbg(dev, "[Airoha] gpio%d, reg_value 0x%lx\n", led_cfg[led_id].gpio, reg_value);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, gpio_led_rg[led_cfg[led_id].gpio / 4], reg_value);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_led_set_usr_def(mbus, led_id, led_cfg[led_id].pol, led_cfg[led_id].on_cfg, led_cfg[led_id].blk_cfg);
-+            if (ret != 0)
-+            {
-+                dev_err(dev, "LED fail to set usr def, ret %d !\n", ret);
-+                return ret;
-+            }
-+        }
-+    }
-+    reg_value = (airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1880) & ~led_gpio);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1880, reg_value);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x186c, led_gpio);
-+    AIR_RTN_ERR(ret);
-+
-+    dev_info(dev, "LED initialize OK !\n");
-+    return 0;
-+}
-+#endif
-+static int en8801s_phy_process(struct phy_device *phydev)
-+{
-+    struct mii_bus *mbus = phydev_mdio_bus(phydev);
-+    unsigned long reg_value = 0;
-+    int ret = 0;
-+
-+    reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x19e0);
-+    reg_value |= BIT(0);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x19e0, reg_value);
-+    AIR_RTN_ERR(ret);
-+    reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x19e0);
-+    reg_value &= ~BIT(0);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x19e0, reg_value);
-+    AIR_RTN_ERR(ret);
-+    return ret;
-+}
-+
-+static int en8801s_phase1_init(struct phy_device *phydev)
-+{
-+    unsigned long pbus_data;
-+    unsigned int pbusAddress;
-+    u16 reg_value;
-+    int retry, ret = 0;
-+    struct mii_bus *mbus = phydev_mdio_bus(phydev);
-+    struct device *dev = &mbus->dev;
-+    msleep(1500);
-+
-+    pbusAddress = EN8801S_PBUS_DEFAULT_ID;
-+    retry = MAX_OUI_CHECK;
-+    while (1) {
-+        pbus_data = airoha_pbus_read(mbus, pbusAddress, EN8801S_RG_ETHER_PHY_OUI);      /* PHY OUI */
-+        if (EN8801S_PBUS_OUI == pbus_data) {
-+            pbus_data = airoha_pbus_read(mbus, pbusAddress, EN8801S_RG_SMI_ADDR);       /* SMI ADDR */
-+            pbus_data = (pbus_data & 0xffff0000) | (unsigned long)(EN8801S_PBUS_PHY_ID << 8) | (unsigned long)(EN8801S_MDIO_PHY_ID);
-+            dev_info(dev, "SMI_ADDR=%lx (renew)\n", pbus_data);
-+            ret = airoha_pbus_write(mbus, pbusAddress, EN8801S_RG_SMI_ADDR, pbus_data);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_BUCK_CTL, 0x03);
-+            AIR_RTN_ERR(ret);
-+            mdelay(10);
-+            break;
-+        } else {
-+            pbusAddress = EN8801S_PBUS_PHY_ID;
-+        }
-+        if (0 == --retry) {
-+            dev_err(dev, "Probe fail !\n");
-+            return 0;
-+        }
-+    }
-+
-+    pbus_data = (airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL) & 0xfffffffc) | 0x10 | (EN8801S_RX_POLARITY << 1) | EN8801S_TX_POLARITY;
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, pbus_data);
-+    AIR_RTN_ERR(ret);
-+    mdelay(10);
-+    pbus_data &= ~BIT(4);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, pbus_data);
-+    AIR_RTN_ERR(ret);
-+
-+    retry = MAX_RETRY;
-+    while (1) {
-+        mdelay(10);
-+        reg_value = phy_read(phydev, MII_PHYSID2);
-+        if (reg_value == EN8801S_PHY_ID2) {
-+            break;    /* wait GPHY ready */
-+        }
-+        retry--;
-+        if (0 == retry) {
-+            dev_err(dev, "Initialize fail !\n");
-+            return 0;
-+        }
-+    }
-+    /* Software Reset PHY */
-+    reg_value = phy_read(phydev, MII_BMCR);
-+    reg_value |= BMCR_RESET;
-+    ret = phy_write(phydev, MII_BMCR, reg_value);
-+    AIR_RTN_ERR(ret);
-+    retry = MAX_RETRY;
-+    do {
-+        mdelay(10);
-+        reg_value = phy_read(phydev, MII_BMCR);
-+        retry--;
-+        if (0 == retry) {
-+            dev_err(dev, "Reset fail !\n");
-+            return 0;
-+        }
-+    } while (reg_value & BMCR_RESET);
-+
-+    phydev->dev_flags = PHY_STATE_INIT;
-+
-+    dev_info(dev, "Phase1 initialize OK ! (%s)\n", EN8801S_DRIVER_VERSION);
-+    return 0;
-+}
-+
-+static int en8801s_phase2_init(struct phy_device *phydev)
-+{
-+    gephy_all_REG_LpiReg1Ch      GPHY_RG_LPI_1C;
-+    gephy_all_REG_dev1Eh_reg324h GPHY_RG_1E_324;
-+    gephy_all_REG_dev1Eh_reg012h GPHY_RG_1E_012;
-+    gephy_all_REG_dev1Eh_reg017h GPHY_RG_1E_017;
-+    unsigned long pbus_data;
-+    u16 cl45_value;
-+    int retry, ret = 0;
-+    struct mii_bus *mbus = phydev_mdio_bus(phydev);
-+    struct device *dev = &mbus->dev;
-+
-+    pbus_data = (airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL) & 0xfffffffc) | 0x10 | (EN8801S_RX_POLARITY << 1) | EN8801S_TX_POLARITY;
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, pbus_data);
-+    AIR_RTN_ERR(ret);
-+    mdelay(10);
-+    pbus_data &= 0xffffffef;
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, EN8801S_RG_LTR_CTL, pbus_data);
-+    AIR_RTN_ERR(ret);
-+
-+    pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1690);
-+    pbus_data |= BIT(31);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1690, pbus_data);
-+    AIR_RTN_ERR(ret);
-+
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD801);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0,  0x9140);
-+    AIR_RTN_ERR(ret);
-+
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x0003);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
-+    AIR_RTN_ERR(ret);
-+    /* Set FCM control */
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x004b);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
-+    AIR_RTN_ERR(ret);
-+
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x142c, 0x05050505);
-+    AIR_RTN_ERR(ret);
-+    pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1440);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1440, pbus_data & ~BIT(11));
-+    AIR_RTN_ERR(ret);
-+
-+    pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1408);
-+    ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1408, pbus_data | BIT(5));
-+    AIR_RTN_ERR(ret);
-+
-+    /* Set GPHY Perfomance*/
-+    /* Token Ring */
-+    ret = airoha_tr_reg_write(mbus, RgAddr_R1000DEC_15h, 0x0055A0);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_R1000DEC_17h, 0x07FF3F);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_PMA_00h,      0x00001E);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_PMA_01h,      0x6FB90A);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_PMA_17h,      0x060671);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_PMA_18h,      0x0E2F00);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_TR_26h,       0x444444);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_03h,     0x000000);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_06h,     0x2EBAEF);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_08h,     0x00000B);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_0Ch,     0x00504D);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_0Dh,     0x02314F);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_0Fh,     0x003028);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_10h,     0x005010);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_11h,     0x040001);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_13h,     0x018670);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_14h,     0x00024A);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_1Bh,     0x000072);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_tr_reg_write(mbus, RgAddr_DSPF_1Ch,     0x003210);
-+    AIR_RTN_ERR(ret);
-+
-+    /* CL22 & CL45 */
-+    ret = phy_write(phydev, 0x1f, 0x03);
-+    AIR_RTN_ERR(ret);
-+    GPHY_RG_LPI_1C.DATA = phy_read(phydev, RgAddr_LPI_1Ch);
-+    GPHY_RG_LPI_1C.DataBitField.smi_deton_th = 0x0C;
-+    ret = phy_write(phydev, RgAddr_LPI_1Ch, GPHY_RG_LPI_1C.DATA);
-+    AIR_RTN_ERR(ret);
-+    ret = phy_write(phydev, RgAddr_LPI_1Ch, 0xC92);
-+    AIR_RTN_ERR(ret);
-+    ret = phy_write(phydev, RgAddr_AUXILIARY_1Dh, 0x1);
-+    AIR_RTN_ERR(ret);
-+    ret = phy_write(phydev, 0x1f, 0x0);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x120, 0x8014);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x122, 0xffff);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x123, 0xffff);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x144, 0x0200);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x14A, 0xEE20);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x189, 0x0110);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x19B, 0x0111);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x234, 0x0181);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x238, 0x0120);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x239, 0x0117);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x268, 0x07F4);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x2D1, 0x0733);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x323, 0x0011);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, 0x013F);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x326, 0x0037);
-+    AIR_RTN_ERR(ret);
-+
-+    ret = airoha_cl45_read(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, &cl45_value);
-+    AIR_RTN_ERR(ret);
-+    GPHY_RG_1E_324.DATA = cl45_value;
-+    GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = 0;
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, GPHY_RG_1E_324.DATA);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x19E, 0xC2);
-+    AIR_RTN_ERR(ret);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x013, 0x0);
-+    AIR_RTN_ERR(ret);
-+
-+    /* EFUSE */
-+    airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1C08, 0x40000040);
-+    retry = MAX_RETRY;
-+    while (0 != retry) {
-+        mdelay(1);
-+        pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C08);
-+        if ((pbus_data & BIT(30)) == 0) {
-+            break;
-+        }
-+        retry--;
-+    }
-+    pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C38);          /* RAW#2 */
-+    GPHY_RG_1E_012.DataBitField.da_tx_i2mpb_a_tbt = (u16)(pbus_data & 0x03f);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x12, GPHY_RG_1E_012.DATA);
-+    AIR_RTN_ERR(ret);
-+    GPHY_RG_1E_017.DataBitField.da_tx_i2mpb_b_tbt = (u16)((pbus_data >> 8) & 0x03f);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x12, GPHY_RG_1E_017.DATA);
-+    AIR_RTN_ERR(ret);
-+
-+    airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1C08, 0x40400040);
-+    retry = MAX_RETRY;
-+    while (0 != retry) {
-+        mdelay(1);
-+        pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C08);
-+        if ((pbus_data & BIT(30)) == 0) {
-+            break;
-+        }
-+        retry--;
-+    }
-+    pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1C30);          /* RAW#16 */
-+    GPHY_RG_1E_324.DataBitField.smi_det_deglitch_off = (u16)((pbus_data >> 12) & 0x01);
-+    ret = airoha_cl45_write(mbus, EN8801S_MDIO_PHY_ID, 0x1E, 0x324, GPHY_RG_1E_324.DATA);
-+    AIR_RTN_ERR(ret);
-+#ifdef AIR_LED_SUPPORT
-+    ret = en8801s_led_init(phydev);
-+    if (ret != 0){
-+        dev_err(dev, "en8801s_led_init fail (ret:%d) !\n", ret);
-+    }
-+#endif
-+    pbus_data = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1960);
-+    pbus_data -= (2 << 22);
-+    airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1960, pbus_data);
-+    mdelay(10);
-+    pbus_data -= (2 << 22);
-+    airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1960, pbus_data);
-+
-+    dev_info(dev, "Phase2 initialize OK !\n");
-+    return 0;
-+}
-+
-+static int en8801s_read_status(struct phy_device *phydev)
-+{
-+    int ret = 0, preSpeed = phydev->speed, retry = MAX_RETRY;
-+    struct mii_bus *mbus = phydev_mdio_bus(phydev);
-+    u32 reg_value;
-+    struct device *dev = &mbus->dev;
-+
-+    ret = genphy_read_status(phydev);
-+    if (LINK_DOWN == phydev->link) preSpeed = phydev->speed = 0;
-+
-+    if (phydev->dev_flags == PHY_STATE_PROCESS) {
-+        en8801s_phy_process(phydev);
-+        phydev->dev_flags = PHY_STATE_DONE;
-+    }
-+
-+    if (phydev->dev_flags == PHY_STATE_INIT) {
-+        do {
-+            mdelay(100);
-+            reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0xb04);
-+            dev_dbg(dev, "[Airoha] 0xB04, reg_value 0x%x\n", reg_value);
-+            reg_value &= 0x21;
-+            if(reg_value == 0x21) {
-+                ret = en8801s_phase2_init(phydev);
-+                if (ret != 0) {
-+                    dev_info(dev, "en8801_phase2_init failed\n");
-+                    phydev->dev_flags = PHY_STATE_FAIL;
-+                    return -1;
-+                } else {
-+                    phydev->dev_flags = PHY_STATE_PROCESS;
-+                    break;
-+                }
-+
-+            }
-+            if(0 == --retry) {
-+                dev_err(dev, "0xB04 return 0x%x !\n", reg_value);
-+                phydev->dev_flags = PHY_STATE_SS_FAIL;
-+                return -1;
-+            }
-+        } while(retry);
-+    }
-+
-+    if ((preSpeed != phydev->speed) && (LINK_UP == phydev->link)) {
-+        preSpeed = phydev->speed;
-+
-+        if (preSpeed == SPEED_10) {
-+            reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1694);
-+            reg_value |= BIT(31);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1694, reg_value);
-+            AIR_RTN_ERR(ret);
-+            phydev->dev_flags = PHY_STATE_PROCESS;
-+        } else {
-+            reg_value = airoha_pbus_read(mbus, EN8801S_PBUS_PHY_ID, 0x1694);
-+            reg_value &= ~BIT(31);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1694, reg_value);
-+            AIR_RTN_ERR(ret);
-+            phydev->dev_flags = PHY_STATE_PROCESS;
-+        }
-+
-+        airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
-+        if (SPEED_1000 == preSpeed) {
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD801);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0,  0x9140);
-+            AIR_RTN_ERR(ret);
-+
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x0003);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c000c00);
-+            AIR_RTN_ERR(ret);
-+            mdelay(2);      /* delay 2 ms */
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x004b);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
-+            AIR_RTN_ERR(ret);
-+        } else if (SPEED_100 == preSpeed) {
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD401);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0,  0x9140);
-+            AIR_RTN_ERR(ret);
-+
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x0007);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c11);
-+            AIR_RTN_ERR(ret);
-+            mdelay(2);      /* delay 2 ms */
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x0027);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
-+            AIR_RTN_ERR(ret);
-+        } else if (SPEED_10 == preSpeed) {
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x10, 0xD001);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0,  0x9140);
-+            AIR_RTN_ERR(ret);
-+
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0A14, 0x000b);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x0600, 0x0c11);
-+            AIR_RTN_ERR(ret);
-+            mdelay(2);      /* delay 2 ms */
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x1404, 0x0027);
-+            AIR_RTN_ERR(ret);
-+            ret = airoha_pbus_write(mbus, EN8801S_PBUS_PHY_ID, 0x140c, 0x0007);
-+            AIR_RTN_ERR(ret);
-+        }
-+    }
-+    return ret;
-+}
-+
-+static struct phy_driver Airoha_driver[] = {
-+    {
-+        .phy_id         = EN8801SC_PHY_ID,
-+        .name           = "Airoha EN8801SC",
-+        .phy_id_mask    = 0x0ffffff0,
-+        .features       = PHY_GBIT_FEATURES,
-+        .config_init    = en8801s_phase1_init,
-+        .config_aneg    = genphy_config_aneg,
-+        .read_status    = en8801s_read_status,
-+        .suspend        = genphy_suspend,
-+        .resume         = genphy_resume,
-+    }
-+};
-+
-+module_phy_driver(Airoha_driver);
-+
-+static struct mdio_device_id __maybe_unused Airoha_tbl[] = {
-+    { EN8801SC_PHY_ID, 0x0ffffff0 },
-+    { }
-+};
-+
-+MODULE_DEVICE_TABLE(mdio, Airoha_tbl);
-Index: drivers/net/phy/en8801sc.h
-===================================================================
---- /dev/null
-+++ b/drivers/net/phy/en8801sc.h
-@@ -0,0 +1,276 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* FILE NAME:  en8801sc.h
-+ * PURPOSE:
-+ *      Define EN8801SC driver function
-+ *
-+ * NOTES:
-+ *
-+ */
-+
-+#ifndef __EN8801SC_H
-+#define __EN8801SC_H
-+
-+/* NAMING DECLARATIONS
-+ */
-+#define EN8801S_DRIVER_VERSION  "1.1.5"
-+
-+#define PHY_ADDRESS_RANGE       0x18
-+#define EN8801S_PBUS_DEFAULT_ID 0x1e
-+#define EN8801S_MDIO_PHY_ID     0x18       /* Range PHY_ADDRESS_RANGE .. 0x1e */
-+#define EN8801S_PBUS_PHY_ID     (EN8801S_MDIO_PHY_ID + 1)
-+
-+#define EN8801S_RG_ETHER_PHY_OUI 0x19a4
-+#define EN8801S_RG_SMI_ADDR      0x19a8
-+#define EN8801S_RG_BUCK_CTL      0x1a20
-+#define EN8801S_RG_LTR_CTL      0x0cf8
-+
-+#define EN8801S_PBUS_OUI        0x17a5
-+#define EN8801S_PHY_ID1         0x03a2
-+#define EN8801S_PHY_ID2         0x9461
-+#define EN8801SC_PHY_ID         0x03a29471
-+
-+#define LED_ON_CTRL(i)              (0x024 + ((i)*2))
-+#define LED_ON_EN                   (1 << 15)
-+#define LED_ON_POL                  (1 << 14)
-+#define LED_ON_EVT_MASK             (0x7f)
-+/* LED ON Event Option.B */
-+#define LED_ON_EVT_FORCE            (1 << 6)
-+#define LED_ON_EVT_LINK_DOWN        (1 << 3)
-+#define LED_ON_EVT_LINK_10M         (1 << 2)
-+#define LED_ON_EVT_LINK_100M        (1 << 1)
-+#define LED_ON_EVT_LINK_1000M       (1 << 0)
-+/* LED ON Event Option.E */
-+
-+#define LED_BLK_CTRL(i)             (0x025 + ((i)*2))
-+#define LED_BLK_EVT_MASK            (0x3ff)
-+/* LED Blinking Event Option.B*/
-+#define LED_BLK_EVT_FORCE           (1 << 9)
-+#define LED_BLK_EVT_10M_RX_ACT      (1 << 5)
-+#define LED_BLK_EVT_10M_TX_ACT      (1 << 4)
-+#define LED_BLK_EVT_100M_RX_ACT     (1 << 3)
-+#define LED_BLK_EVT_100M_TX_ACT     (1 << 2)
-+#define LED_BLK_EVT_1000M_RX_ACT    (1 << 1)
-+#define LED_BLK_EVT_1000M_TX_ACT    (1 << 0)
-+/* LED Blinking Event Option.E*/
-+#define LED_ENABLE                  1
-+#define LED_DISABLE                 0
-+
-+#define LINK_UP                 1
-+#define LINK_DOWN               0
-+
-+//#define TEST_BOARD
-+#if defined(TEST_BOARD)
-+/* SFP sample for verification */
-+#define EN8801S_TX_POLARITY     1
-+#define EN8801S_RX_POLARITY     0
-+#else
-+/* chip on board */
-+#define EN8801S_TX_POLARITY     0
-+#define EN8801S_RX_POLARITY     1       /* The pin default assignment is set to 1 */
-+#endif
-+
-+/*
-+The following led_cfg example is for reference only.
-+LED5 1000M/LINK/ACT  (GPIO5)  <-> BASE_T_LED0,
-+LED6 10/100M/LINK/ACT(GPIO9)  <-> BASE_T_LED1,
-+LED4 100M/LINK/ACT   (GPIO8)  <-> BASE_T_LED2,
-+*/
-+/* User-defined.B */
-+#define BASE_T_LED0_ON_CFG      (LED_ON_EVT_LINK_1000M)
-+#define BASE_T_LED0_BLK_CFG     (LED_BLK_EVT_1000M_TX_ACT | LED_BLK_EVT_1000M_RX_ACT)
-+#define BASE_T_LED1_ON_CFG      (LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M)
-+#define BASE_T_LED1_BLK_CFG     (LED_BLK_EVT_100M_TX_ACT | LED_BLK_EVT_100M_RX_ACT | \
-+                                 LED_BLK_EVT_10M_TX_ACT | LED_BLK_EVT_10M_RX_ACT )
-+#define BASE_T_LED2_ON_CFG      (LED_ON_EVT_LINK_100M)
-+#define BASE_T_LED2_BLK_CFG     (LED_BLK_EVT_100M_TX_ACT | LED_BLK_EVT_100M_RX_ACT)
-+#define BASE_T_LED3_ON_CFG      (0x0)
-+#define BASE_T_LED3_BLK_CFG     (0x0)
-+/* User-defined.E */
-+
-+#define EN8801S_LED_COUNT       4
-+
-+#define MAX_RETRY               5
-+#define MAX_OUI_CHECK           2
-+/* CL45 MDIO control */
-+#define MII_MMD_ACC_CTL_REG     0x0d
-+#define MII_MMD_ADDR_DATA_REG   0x0e
-+#define MMD_OP_MODE_DATA        BIT(14)
-+
-+#define MAX_TRG_COUNTER         5
-+
-+/* CL22 Reg Support Page Select */
-+#define RgAddr_Reg1Fh        0x1f
-+#define CL22_Page_Reg        0x0000
-+#define CL22_Page_ExtReg     0x0001
-+#define CL22_Page_MiscReg    0x0002
-+#define CL22_Page_LpiReg     0x0003
-+#define CL22_Page_tReg       0x02A3
-+#define CL22_Page_TrReg      0x52B5
-+
-+/* CL45 Reg Support DEVID */
-+#define DEVID_03             0x03
-+#define DEVID_07             0x07
-+#define DEVID_1E             0x1E
-+#define DEVID_1F             0x1F
-+
-+/* TokenRing Reg Access */
-+#define TrReg_PKT_XMT_STA    0x8000
-+#define TrReg_WR             0x8000
-+#define TrReg_RD             0xA000
-+
-+#define RgAddr_LPI_1Ch       0x1c
-+#define RgAddr_AUXILIARY_1Dh 0x1d
-+#define RgAddr_PMA_00h       0x0f80
-+#define RgAddr_PMA_01h       0x0f82
-+#define RgAddr_PMA_17h       0x0fae
-+#define RgAddr_PMA_18h       0x0fb0
-+#define RgAddr_DSPF_03h      0x1686
-+#define RgAddr_DSPF_06h      0x168c
-+#define RgAddr_DSPF_08h      0x1690
-+#define RgAddr_DSPF_0Ch      0x1698
-+#define RgAddr_DSPF_0Dh      0x169a
-+#define RgAddr_DSPF_0Fh      0x169e
-+#define RgAddr_DSPF_10h      0x16a0
-+#define RgAddr_DSPF_11h      0x16a2
-+#define RgAddr_DSPF_13h      0x16a6
-+#define RgAddr_DSPF_14h      0x16a8
-+#define RgAddr_DSPF_1Bh      0x16b6
-+#define RgAddr_DSPF_1Ch      0x16b8
-+#define RgAddr_TR_26h        0x0ecc
-+#define RgAddr_R1000DEC_15h  0x03aa
-+#define RgAddr_R1000DEC_17h  0x03ae
-+
-+#define LED_BCR                     (0x021)
-+#define LED_BCR_EXT_CTRL            (1 << 15)
-+#define LED_BCR_CLK_EN              (1 << 3)
-+#define LED_BCR_TIME_TEST           (1 << 2)
-+#define LED_BCR_MODE_MASK           (3)
-+#define LED_BCR_MODE_DISABLE        (0)
-+
-+#define LED_ON_DUR                  (0x022)
-+#define LED_ON_DUR_MASK             (0xffff)
-+
-+#define LED_BLK_DUR                 (0x023)
-+#define LED_BLK_DUR_MASK            (0xffff)
-+
-+#define LED_GPIO_SEL_MASK 0x7FFFFFF
-+
-+#define UNIT_LED_BLINK_DURATION     1024
-+
-+/* Invalid data */
-+#define INVALID_DATA            0xffffffff
-+
-+#define AIR_RTN_ON_ERR(cond, err)  \
-+    do { if ((cond)) return (err); } while(0)
-+
-+#define AIR_RTN_ERR(err)                       AIR_RTN_ON_ERR(err < 0, err)
-+#define AIR_RTN_ON_ERR_MSG(cond, err, msg...) \
-+    do { if ((cond)) { dev_err(dev, ##msg); return (err); } } while(0)
-+
-+#define LED_SET_EVT(reg, cod, result, bit) do         \
-+    {                                                 \
-+        if(reg & cod) {                               \
-+            result |= bit;                            \
-+        }                                             \
-+    } while(0)
-+
-+#define LED_SET_GPIO_SEL(gpio, led, val) do           \
-+    {                                                 \
-+            val |= (led << (8 * (gpio % 4)));         \
-+    } while(0)
-+
-+/* DATA TYPE DECLARATIONS
-+ */
-+typedef struct AIR_BASE_T_LED_CFG_S
-+{
-+    u16 en;
-+    u16 gpio;
-+    u16 pol;
-+    u16 on_cfg;
-+    u16 blk_cfg;
-+}AIR_BASE_T_LED_CFG_T;
-+
-+typedef struct
-+{
-+    u16 DATA_Lo;
-+    u16 DATA_Hi;
-+}TR_DATA_T;
-+
-+typedef union
-+{
-+    struct
-+    {
-+        /* b[15:00] */
-+        u16 smi_deton_wt                             : 3;
-+        u16 smi_det_mdi_inv                          : 1;
-+        u16 smi_detoff_wt                            : 3;
-+        u16 smi_sigdet_debouncing_en                 : 1;
-+        u16 smi_deton_th                             : 6;
-+        u16 rsv_14                                   : 2;
-+    } DataBitField;
-+    u16 DATA;
-+} gephy_all_REG_LpiReg1Ch, *Pgephy_all_REG_LpiReg1Ch;
-+
-+typedef union
-+{
-+    struct
-+    {
-+        /* b[15:00] */
-+        u16 rg_smi_detcnt_max                        : 6;
-+        u16 rsv_6                                    : 2;
-+        u16 rg_smi_det_max_en                        : 1;
-+        u16 smi_det_deglitch_off                     : 1;
-+        u16 rsv_10                                   : 6;
-+    } DataBitField;
-+    u16 DATA;
-+} gephy_all_REG_dev1Eh_reg324h, *Pgephy_all_REG_dev1Eh_reg324h;
-+
-+typedef union
-+{
-+    struct
-+    {
-+        /* b[15:00] */
-+        u16 da_tx_i2mpb_a_tbt                        : 6;
-+        u16 rsv_6                                    : 4;
-+        u16 da_tx_i2mpb_a_gbe                        : 6;
-+    } DataBitField;
-+    u16 DATA;
-+} gephy_all_REG_dev1Eh_reg012h, *Pgephy_all_REG_dev1Eh_reg012h;
-+
-+typedef union
-+{
-+    struct
-+    {
-+        /* b[15:00] */
-+        u16 da_tx_i2mpb_b_tbt                        : 6;
-+        u16 rsv_6                                    : 2;
-+        u16 da_tx_i2mpb_b_gbe                        : 6;
-+        u16 rsv_14                                   : 2;
-+    } DataBitField;
-+    u16 DATA;
-+} gephy_all_REG_dev1Eh_reg017h, *Pgephy_all_REG_dev1Eh_reg017h;
-+
-+typedef enum
-+{
-+    AIR_LED_BLK_DUR_32M,
-+    AIR_LED_BLK_DUR_64M,
-+    AIR_LED_BLK_DUR_128M,
-+    AIR_LED_BLK_DUR_256M,
-+    AIR_LED_BLK_DUR_512M,
-+    AIR_LED_BLK_DUR_1024M,
-+    AIR_LED_BLK_DUR_LAST
-+} AIR_LED_BLK_DUT_T;
-+
-+typedef enum
-+{
-+    AIR_ACTIVE_LOW,
-+    AIR_ACTIVE_HIGH,
-+} AIR_LED_POLARITY;
-+typedef enum
-+{
-+    AIR_LED_MODE_DISABLE,
-+    AIR_LED_MODE_USER_DEFINE,
-+    AIR_LED_MODE_LAST
-+} AIR_LED_MODE_T;
-+
-+#endif /* End of __EN8801SC_H */
 Index: drivers/net/phy/Kconfig
 ===================================================================
 --- a/drivers/net/phy/Kconfig
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
index 28248f4..0e38dad 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
@@ -2,31 +2,13 @@
 index 7b49c94..5a79af2 100644
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -372,7 +372,56 @@ config AMD_PHY
+@@ -372,7 +372,38 @@ config AMD_PHY
  config AQUANTIA_PHY
  	tristate "Aquantia PHYs"
  	---help---
 -	  Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
 +	  Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405, AQR113C
 +
-+config AQUANTIA_PHY_MDI_SWAP
-+	tristate "MDI Swap Enable"
-+	depends on AQUANTIA_PHY
-+	---help---
-+	  Currently supports the Aquantia AQR113C
-+
-+choice
-+	prompt "Swap mode"
-+	default AQUANTIA_PHY_MDI_REVERSED
-+	depends on AQUANTIA_PHY_MDI_SWAP
-+
-+	config AQUANTIA_PHY_MDI_NORMAL
-+		bool "Normal"
-+
-+	config AQUANTIA_PHY_MDI_REVERSED
-+		bool "Reversed"
-+endchoice
-+
 +config AQUANTIA_PHY_FW_DOWNLOAD
 +	tristate "Firmware Download Enable"
 +	depends on AQUANTIA_PHY
@@ -74,13 +56,15 @@
  obj-$(CONFIG_AIROHA_EN8801SC_PHY)	+= en8801sc.o
  obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia.o
 diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
-index 5a16caa..912bbe6 100644
+index 5a16caa..ab1c241 100644
 --- a/drivers/net/phy/aquantia.h
 +++ b/drivers/net/phy/aquantia.h
-@@ -9,8 +9,66 @@
+@@ -9,8 +9,72 @@
  #include <linux/device.h>
  #include <linux/phy.h>
  
++#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT		4
++
 +#define PMAPMD_RSVD_VEND_PROV				0xe400
 +#define PMAPMD_RSVD_VEND_PROV_MDI_CONF			BIT(0)
 +
@@ -122,12 +106,15 @@
 +#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
 +	struct phy_device *phydevs[1];
 +	struct task_struct *heartbeat_thread;
++	spinlock_t lock;
 +	bool fw_initialized;
 +	int fw_dl_mode;
 +	u16 heartbeat;
 +#endif
 +};
 +
++int aqr107_set_downshift(struct phy_device *phydev, u8 cnt);
++void aqr107_chip_info(struct phy_device *phydev);
 +int aqr107_config_mdi(struct phy_device *phydev);
 +
  #if IS_REACHABLE(CONFIG_HWMON)
@@ -142,14 +129,15 @@
 +	FW_DL_GNAGLOAD,
 +};
 +
++int aqr_firmware_heartbeat_thread(void *data);
 +int aqr_firmware_download(struct phy_device *phydev);
 +#endif
 diff --git a/drivers/net/phy/aquantia_firmware.c b/drivers/net/phy/aquantia_firmware.c
 new file mode 100644
-index 0000000..7aeec86
+index 0000000..622557c
 --- /dev/null
 +++ b/drivers/net/phy/aquantia_firmware.c
-@@ -0,0 +1,1096 @@
+@@ -0,0 +1,1090 @@
 +// SPDX-License-Identifier: GPL-2.0
 +/* FW download driver for Aquantia PHY
 + */
@@ -1037,15 +1025,17 @@
 +	if (ret < 0)
 +		return ret;
 +
++	/* heartbeat stopped if the current heartbeat is equal to the previous */
 +	if (priv->heartbeat == ret)
 +		stopped = 1;
 +
++	/* update heartbeat to the private data */
 +	priv->heartbeat = ret;
 +
 +	return stopped;
 +}
 +
-+static int aqr_firmware_heartbeat_thread(void *data)
++int aqr_firmware_heartbeat_thread(void *data)
 +{
 +	struct phy_device *phydev = data;
 +	struct aqr107_priv *priv = phydev->priv;
@@ -1058,10 +1048,11 @@
 +		if (kthread_should_stop())
 +			break;
 +
-+		if (phydev->state != PHY_HALTED &&
++		if (priv->fw_initialized == true &&
 +		    aqr_firmware_check_heartbeat(phydev) == 1) {
 +			dev_err(dev, "Detect heartbeat stopped, start to realod firmware...\n");
 +			priv->fw_initialized = false;
++			priv->fw_dl_mode = FW_DL_SINGLE;
 +			aqr_firmware_download_single(phydev);
 +		}
 +
@@ -1076,7 +1067,7 @@
 +{
 +	struct phy_device **phydevs = context;
 +	struct phy_device *gandload_phydev = phydevs[0];
-+	struct device *dev;
++	struct device *dev = &phydevs[0]->mdio.dev;
 +	struct aqr107_priv *priv = phydevs[0]->priv;
 +	int result[MAX_GANGLOAD_DEVICES];
 +	int i, num_phydevs = 0, ret = 0;
@@ -1089,7 +1080,6 @@
 +
 +retry:
 +	if (gandload_phydev->state == PHY_HALTED) {
-+		dev = &phydevs[0]->mdio.dev;
 +		dev_info(dev, "Detect PHY power down, stop to reload firmware...\n");
 +		goto out;
 +	}
@@ -1115,30 +1105,21 @@
 +
 +	for (i = 0; i < num_phydevs; i++) {
 +		if (result[i] == 0) {
++			dev = &phydevs[i]->mdio.dev;
 +			priv = phydevs[i]->priv;
 +			priv->fw_initialized = true;
 +
++			aqr107_chip_info(phydevs[i]);
++
-+#ifdef CONFIG_AQUANTIA_PHY_MDI_SWAP
 +			aqr107_config_mdi(phydevs[i]);
-+#endif
 +
-+			if (priv->fw_dl_mode == FW_DL_GNAGLOAD) {
++			aqr107_set_downshift(phydevs[i],
++					     MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
++
++			if (phy_is_started(phydevs[i])) {
 +				phydevs[i]->state = PHY_UP;
 +				phy_queue_state_machine(phydevs[i], 0);
 +			}
-+
-+			/* create a thread for monitor heartbeat status */
-+			if (!priv->heartbeat_thread) {
-+				priv->heartbeat_thread = kthread_create(aqr_firmware_heartbeat_thread,
-+									phydevs[i],
-+									"aqr_firmware_heartbeat_thread");
-+				if (IS_ERR(priv->heartbeat_thread)) {
-+					dev_err(dev,
-+						"%s Failed to create thread for aqr_firmware_heartbeat_thread\n",
-+						__func__);
-+				}
-+				wake_up_process(priv->heartbeat_thread);
-+			}
 +		}
 +	}
 +out:
@@ -1155,13 +1136,14 @@
 +	if (priv->fw_initialized == true)
 +		return 0;
 +
++	spin_lock_init(&priv->lock);
 +	priv->fw_dl_mode = FW_DL_SINGLE;
 +	priv->phydevs[0] = phydev;
 +	priv->heartbeat = -1;
 +
 +	ret = request_firmware(&fw, AQR_FIRMWARE, dev);
 +	if (ret) {
-+		dev_err(dev, "failed to load firmware %s, ret: %d\n",
++		dev_err(dev, "failed to request firmware %s, ret: %d\n",
 +			AQR_FIRMWARE, ret);
 +	}
 +
@@ -1185,7 +1167,7 @@
 +			ret = request_firmware_nowait(THIS_MODULE, true, AQR_FIRMWARE, dev,
 +						      GFP_KERNEL, phydevs, aqr_firmware_download_cb);
 +			if (ret) {
-+				dev_err(dev, "failed to load firmware %s, ret: %d\n",
++				dev_err(dev, "failed to request firmware %s, ret: %d\n",
 +					AQR_FIRMWARE, ret);
 +			}
 +			break;
@@ -1214,8 +1196,7 @@
 +						  "aqr_firmware_gandload_thread");
 +		if (IS_ERR(gangload_kthread)) {
 +			dev_err(dev,
-+				"%s Failed to create thread for aqr_firmware_gandload_thread\n",
-+				__func__);
++				"failed to create aqr_firmware_gandload_thread\n");
 +			return PTR_ERR(gangload_kthread);
 +		}
 +		wake_up_process(gangload_kthread);
@@ -1223,11 +1204,12 @@
 +
 +	for (i = 0; i < gangload; i++) {
 +		if (gangload_phydevs[i] == phydev) {
-+			dev_err(dev, "Detect duplicate gangload phydev\n");
++			dev_warn(dev, "Detect duplicate gangload phydev\n");
 +			return -EINVAL;
 +		}
 +	}
 +
++	spin_lock_init(&priv->lock);
 +	priv->fw_dl_mode = FW_DL_GNAGLOAD;
 +	priv->heartbeat = -1;
 +	gangload_phydevs[gangload] = phydev;
@@ -1247,17 +1229,30 @@
 +	return ret;
 +}
 diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
-index ac8dd8e..421cdd3 100644
+index a8c828b..d98757f 100644
 --- a/drivers/net/phy/aquantia_main.c
 +++ b/drivers/net/phy/aquantia_main.c
-@@ -8,6 +8,7 @@
+@@ -8,10 +8,12 @@
   */
-
+ 
  #include <linux/kernel.h>
 +#include <linux/kthread.h>
  #include <linux/module.h>
  #include <linux/delay.h>
  #include <linux/bitfield.h>
+ #include <linux/phy.h>
++#include <linux/of.h>
+ 
+ #include "aquantia.h"
+ 
+@@ -39,7 +40,6 @@
+ #define MDIO_AN_VEND_PROV_2500BASET_FULL	BIT(10)
+ #define MDIO_AN_VEND_PROV_DOWNSHIFT_EN		BIT(4)
+ #define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK	GENMASK(3, 0)
+-#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT	4
+ 
+ #define MDIO_AN_TX_VEND_STATUS1			0xc800
+ #define MDIO_AN_TX_VEND_STATUS1_RATE_MASK	GENMASK(3, 1)
 @@ -73,18 +73,6 @@
  #define MDIO_AN_RX_VEND_STAT3			0xe832
  #define MDIO_AN_RX_VEND_STAT3_AFR		BIT(0)
@@ -1309,60 +1304,96 @@
  static int aqr107_get_sset_count(struct phy_device *phydev)
  {
  	return AQR107_SGMII_STAT_SZ;
-@@ -498,6 +461,17 @@ static void aqr107_chip_info(struct phy_device *phydev)
+@@ -422,7 +361,7 @@ static int aqr107_get_downshift(struct phy_device *phydev, u8 *data)
+ 	return 0;
+ }
+ 
+-static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt)
++int aqr107_set_downshift(struct phy_device *phydev, u8 cnt)
+ {
+ 	int val = 0;
+ 
+@@ -482,7 +421,7 @@ static int aqr107_wait_reset_complete(struct phy_device *phydev)
+ 	return val ? 0 : -ETIMEDOUT;
+ }
+ 
+-static void aqr107_chip_info(struct phy_device *phydev)
++void aqr107_chip_info(struct phy_device *phydev)
+ {
+ 	u8 fw_major, fw_minor, build_id, prov_id;
+ 	int val;
+@@ -505,6 +444,21 @@ static void aqr107_chip_info(struct phy_device *phydev)
  		   fw_major, fw_minor, build_id, prov_id);
  }
  
 +int aqr107_config_mdi(struct phy_device *phydev)
 +{
-+#ifdef CONFIG_AQUANTIA_PHY_MDI_REVERSED
-+	return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_RSVD_VEND_PROV,
-+			     PMAPMD_RSVD_VEND_PROV_MDI_CONF, 1);
-+#else
++	struct device_node *np = phydev->mdio.dev.of_node;
++	u16 val;
++
++	if (of_property_read_u16(np, "mdi-reversal", &val))
++		return -ENOENT;
++
++	if (!FIELD_FIT(PMAPMD_RSVD_VEND_PROV_MDI_CONF, val))
++		return -E2BIG;
++
 +	return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_RSVD_VEND_PROV,
-+			     PMAPMD_RSVD_VEND_PROV_MDI_CONF, 0);
-+#endif
++			     PMAPMD_RSVD_VEND_PROV_MDI_CONF, val);
 +}
 +
  static int aqr107_config_init(struct phy_device *phydev)
  {
  	int ret;
-@@ -517,6 +491,14 @@ static int aqr107_config_init(struct phy_device *phydev)
+@@ -520,6 +470,12 @@ static int aqr107_config_init(struct phy_device *phydev)
+ 	ret = aqr107_wait_reset_complete(phydev);
  	if (!ret)
  		aqr107_chip_info(phydev);
- 
-+#if !defined(CONFIG_AQUANTIA_PHY_FW_DOWNLOAD) && defined(CONFIG_AQUANTIA_PHY_MDI_SWAP)
-+	aqr107_config_mdi(phydev);
-+#endif
-+
 +#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
-+	aqr_firmware_download(phydev);
++	else
++		return aqr_firmware_download(phydev);
 +#endif
 +
++	aqr107_config_mdi(phydev);
+ 
  	return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
  }
+@@ -604,12 +556,39 @@ static void aqr107_link_change_notify(struct phy_device *phydev)
  
-@@ -605,6 +609,15 @@ static int aqr107_resume(struct phy_device *phydev)
- 				  MDIO_CTRL1_LPOWER);
- }
-
-+static void aqr107_remove(struct phy_device *phydev)
-+{
+ static int aqr107_suspend(struct phy_device *phydev)
+ {
 +#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
 +	struct aqr107_priv *priv = phydev->priv;
 +
-+	kthread_stop(priv->heartbeat_thread);
++	spin_lock(&priv->lock);
++	if (priv->heartbeat_thread) {
++		kthread_stop(priv->heartbeat_thread);
++		priv->heartbeat_thread = NULL;
++		priv->heartbeat = -1;
++	}
++	spin_unlock(&priv->lock);
 +#endif
-+}
-+
- static int aqr107_probe(struct phy_device *phydev)
- {
- 	phydev->priv = devm_kzalloc(&phydev->mdio.dev,
-@@ -711,6 +737,7 @@ static struct phy_driver aqr_driver[] = {
- 	.get_strings    = aqr107_get_strings,
- 	.get_stats      = aqr107_get_stats,
- 	.link_change_notify = aqr107_link_change_notify,
-+	.remove         = aqr107_remove,
- },
- };
+ 	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
+ 				MDIO_CTRL1_LPOWER);
+ }
  
+ static int aqr107_resume(struct phy_device *phydev)
+ {
++#ifdef CONFIG_AQUANTIA_PHY_FW_DOWNLOAD
++	struct aqr107_priv *priv = phydev->priv;
++
++	spin_lock(&priv->lock);
++	if (!priv->heartbeat_thread) {
++		priv->heartbeat_thread = kthread_create(aqr_firmware_heartbeat_thread,
++							phydev,
++							"aqr_firmware_heartbeat_thread");
++		if (IS_ERR(priv->heartbeat_thread)) {
++			phydev_err(phydev,
++				   "Failed to create aqr_firmware_heartbeat_thread\n");
++		}
++		wake_up_process(priv->heartbeat_thread);
++	}
++	spin_unlock(&priv->lock);
++#endif
+ 	return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
+ 				  MDIO_CTRL1_LPOWER);
+ }
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch
index 17102ea..750c87b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9014-drivers-spi-Add-support-for-dynamic-calibration.patch
@@ -11,7 +11,7 @@
 
 --- a/drivers/spi/spi.c
 +++ b/drivers/spi/spi.c
-@@ -1109,6 +1109,73 @@ static int spi_transfer_wait(struct spi_
+@@ -1109,6 +1109,74 @@ static int spi_transfer_wait(struct spi_
  	return 0;
  }
  
@@ -22,7 +22,7 @@
 +	u8 *buf;
 +	int ret;
 +	int i;
-+	struct list_head *cal_head, *listptr;
++	struct list_head *pos, *tmp;
 +	struct spi_cal_target *target;
 +
 +	/* Calculate calibration result */
@@ -43,9 +43,8 @@
 +	if (ret)
 +		goto cal_end;
 +
-+	cal_head = ctlr->cal_target;
-+	list_for_each(listptr, cal_head) {
-+		target = list_entry(listptr, struct spi_cal_target, list);
++	list_for_each_safe(pos, tmp, ctlr->cal_target) {
++		target = list_entry(pos, struct spi_cal_target, list);
 +
 +		hit = false;
 +		hit_val = 0;
@@ -73,8 +72,10 @@
 +			dev_warn(&spi->dev, "calibration failed, fallback to default: 0x%x", origin);
 +			ret = -EIO;
 +		}
++
++		list_del(pos);
++		kfree(target);
 +	}
-+	list_del(&target->list);
 +
 +cal_end:
 +	kfree(buf);
@@ -85,7 +86,7 @@
  static void _spi_transfer_delay_ns(u32 ns)
  {
  	if (!ns)
-@@ -1720,6 +1787,75 @@ void spi_flush_queue(struct spi_controll
+@@ -1720,6 +1788,75 @@ void spi_flush_queue(struct spi_controll
  /*-------------------------------------------------------------------------*/
  
  #if defined(CONFIG_OF)
@@ -161,7 +162,7 @@
  static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
  			   struct device_node *nc)
  {
-@@ -1841,6 +1977,10 @@ of_register_spi_device(struct spi_contro
+@@ -1841,6 +1978,10 @@ of_register_spi_device(struct spi_contro
  	if (rc)
  		goto err_out;