[][High][kernel][mt7981/mt7988][eth][net: phy: mediatek: Introduce mtk-phy-lib and add 2.5Gphy support]
[Description]
Add mtk-phy-lib and add 2.5Gphy support:
This patch series integrate MediaTek's built-in Ethernet PHY helper functions
into mtk-phy-lib and add more functions into it. Also, add support for 2.5Gphy
on MT7988 SoC:
1. Re-organize MediaTek ethernet phy driver files and get ready to integrate
some common functions and add new 2.5G phy driver.
mtk-ge.c: MT7530 Gphy on MT7621 & MT7531 Gphy
mtk-ge-soc.c: Built-in Gphy on MT7981 & Built-in switch Gphy on MT7988
mtk-2p5ge.c: Planned for built-in 2.5G phy on MT7988
2. Fix spelling errors which comes from mediatek-ge-soc.c and
rearrange variables with reverse Xmas tree order.
3. Create mtk-phy-lib.c & mtk-phy.h and integrates mtk-ge-soc.c's
LED helper functions so that we can use those helper functions in other
MTK's ethernet phy driver. However, we won't use this in kernel-5.4
because this needs newer LED framework.
4. Integrate read/write page helper functions as MTK phy lib.
5. Add MT7530 & MT7531's PHY ID macros in mtk-ge.c so that
it follows the same rule of mtk-ge-soc.c.
6. Shrink mtk-ge-soc.c line wrapping to 80 characters.
7. Adds TR(token ring) manipulations and adds correct
macro names for those magic numbers. TR is a way to access
proprietary registers on page 52b5. Use these helper functions
so we can see which fields we're going to modify/set/clear.
8. We observe that some 10G devices' (mostly Marvell's chips inside) 1G
training time violates specification, which may last 2230ms and affect
later TX/RX link pulse time. This will invalidate MediaTek series
gigabit Ethernet PHYs' hardware auto downshift mechanism.
Without this patch, if someone is trying to use "4-wire" cable to
connect above devices, MediaTek' gigabit Ethernet PHYs may fail
to downshift to 100Mbps. (If partner 10G devices' downshift mechanism
stops at 1G)
This patch extends our 1G TX/RX link pulse time so that we can still
link up with those 10G devices.
Tested device:
- Netgear GS110EMX's 10G port (Marvell 88X3340P)
- QNAP QSW-M408-4C
[Release-log]
N/A
Change-Id: Ife6f87f0248bd42c87dd7e2d6cf753ca1751a7bf
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9510450
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
index f38b2b7..b2b2fde 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -471,12 +471,6 @@
#reset-cells = <1>;
};
- phyfw: phy-firmware@f000000 {
- compatible = "mediatek,2p5gphy-fw";
- reg = <0 0x0f100000 0 0x20000>,
- <0 0x0f0f0018 0 0x20>;
- };
-
boottrap: boottrap@1001f6f0 {
compatible = "mediatek,boottrap";
reg = <0 0x1001f6f0 0 0x20>;
@@ -817,7 +811,7 @@
};
pio: pinctrl@1001f000 {
- compatible = "mediatek,mt7988-pinctrl";
+ compatible = "mediatek,mt7988-pinctrl", "syscon";
reg = <0 0x1001f000 0 0x1000>,
<0 0x11c10000 0 0x1000>,
<0 0x11d00000 0 0x1000>,
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
index c558535..8398be6 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
@@ -521,6 +521,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dts
index f07aa6e..6a6bcb5 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dts
@@ -623,6 +623,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-nand.dts
index f4511b9..caed45a 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-nand.dts
@@ -626,6 +626,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dts
index ef6e6ec..6291a1b 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dts
@@ -614,6 +614,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
index 1fb43e5..11913fe 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
@@ -363,6 +363,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
index c41aa57..5bee34a 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
@@ -354,6 +354,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts
index 8fbe9c5..87f30e7 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sfp-spim-nand.dts
@@ -440,6 +440,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
index cde918b..af7eaec 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
@@ -392,6 +392,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
index 834eb41..e4a586b 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
@@ -516,6 +516,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
index 224583a..6468c9d 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
@@ -516,6 +516,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
index 24c7799..e0f1326 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
@@ -384,6 +384,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
index 4562413..b9d8ac7 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
@@ -423,6 +423,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
index 2803b7b..59cced9 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
@@ -386,6 +386,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
index a922d57..db2f9ec 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-sfp-spim-nand.dts
@@ -404,6 +404,7 @@
mdio1: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
gsw_phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
index 4ee16fd..e534f9b 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
@@ -409,6 +409,7 @@
mdio1: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
gsw_phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
index b084812..f7252ec 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
@@ -441,6 +441,7 @@
mdio1: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
gsw_phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
index 2f32e45..638c3a1 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
@@ -373,6 +373,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
index d7e41c5..5e38b0b 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
@@ -364,6 +364,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
index 356ff3a..318f2a8 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
@@ -430,6 +430,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
index bd4326f..24cce49 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
@@ -402,6 +402,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
index 42efe94..04b7b28 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
@@ -496,6 +496,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
index 3e2c564..fe946d9 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
@@ -496,6 +496,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
index f72c5d3..3df84cc 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
@@ -394,6 +394,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
index 71c2e3d..f53544f 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-emmc.dts
@@ -373,6 +373,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
index 7a3d9a6..cacdc4f 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
@@ -496,6 +496,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
index 78847ef..787114e 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
@@ -412,6 +412,7 @@
compatible = "mediatek,dsa-slave-mdio";
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
sphy0: switch_phy0@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
index 18bbfcc..35804c2 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
@@ -400,6 +400,7 @@
mdio1: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
gsw_phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
index 1f5ea1f..da0dc8a 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
+++ b/21.02/files/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
@@ -438,6 +438,7 @@
mdio1: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
+ mediatek,pio = <&pio>;
gsw_phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id03a2.9481";
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/Kconfig b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/Kconfig
new file mode 100644
index 0000000..1490352
--- /dev/null
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/Kconfig
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config MTK_NET_PHYLIB
+ tristate
+
+config MEDIATEK_GE_PHY
+ tristate "MediaTek Gigabit Ethernet PHYs"
+ select MTK_NET_PHYLIB
+ help
+ Supports the MediaTek non-built-in Gigabit Ethernet PHYs.
+
+ Non-built-in Gigabit Ethernet PHYs include mt7530/mt7531.
+ You may find mt7530 inside mt7621. This driver shares some
+ common operations with MediaTek SoC built-in Gigabit
+ Ethernet PHYs.
+
+config MEDIATEK_GE_SOC_PHY
+ tristate "MediaTek SoC Ethernet PHYs"
+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+ select NVMEM_MTK_EFUSE
+ select MTK_NET_PHYLIB
+ help
+ Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+
+ Include support for built-in Ethernet PHYs which are present in
+ the MT7981 and MT7988 SoCs. These PHYs need calibration data
+ present in the SoCs efuse and will dynamically calibrate VCM
+ (common-mode voltage) during startup.
+
+config MEDIATEK_2P5GE_PHY
+ tristate "MediaTek 2.5Gb Ethernet PHYs"
+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+ select MTK_NET_PHYLIB
+ help
+ Supports MediaTek SoC built-in 2.5Gb Ethernet PHYs.
+
+ This will load necessary firmware and add appropriate time delay.
+ Accelerate this procedure through internal pbus instead of MDIO
+ bus. Certain link-up issues will also be fixed here.
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/Makefile b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/Makefile
new file mode 100644
index 0000000..c6db8ab
--- /dev/null
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_MTK_NET_PHYLIB) += mtk-phy-lib.o
+obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o
+obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o
+obj-$(CONFIG_MEDIATEK_2P5GE_PHY) += mtk-2p5ge.o
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-2p5ge.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-2p5ge.c
index 4a60a68..e3bb20f 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-2p5ge.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-2p5ge.c
@@ -10,11 +10,17 @@
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
-#define MT7988_2P5GE_PMB "mediatek/mt7988/i2p5ge-phy-pmb.bin"
+#include "mtk.h"
-#define MD32_EN BIT(0)
-#define PMEM_PRIORITY BIT(8)
-#define DMEM_PRIORITY BIT(16)
+#define MTK_2P5GPHY_ID_MT7988 (0x00339c11)
+
+#define MT7988_2P5GE_PMB_FW "mediatek/mt7988/i2p5ge-phy-pmb.bin"
+#define MT7988_2P5GE_PMB_FW_SIZE (0x20000)
+#define MT7988_2P5GE_PMB_FW_BASE (0x0f100000)
+#define MT7988_2P5GE_PMB_FW_LEN (0x20000)
+#define MT7988_2P5GE_MD32_EN_CFG_BASE (0x0f0f0018)
+#define MT7988_2P5GE_MD32_EN_CFG_LEN (0x20)
+#define MD32_EN BIT(0)
#define BASE100T_STATUS_EXTEND (0x10)
#define BASE1000T_STATUS_EXTEND (0x11)
@@ -24,42 +30,15 @@
#define PHY_AUX_DPX_MASK GENMASK(5, 5)
#define PHY_AUX_SPEED_MASK GENMASK(4, 2)
-/* Registers on MDIO_MMD_VEND1 */
-#define MTK_PHY_LINK_STATUS_MISC (0xa2)
-#define MTK_PHY_FDX_ENABLE BIT(5)
-
#define MTK_PHY_LPI_PCS_DSP_CTRL (0x121)
#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8)
-/* 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)
-
-#define MTK_EXT_PAGE_ACCESS 0x1f
-#define MTK_PHY_PAGE_STANDARD 0x0000
-#define MTK_PHY_PAGE_EXTENDED_1 0x1
-#define MTK_PHY_AUX_CTRL_AND_STATUS (0x14)
-#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4)
-
/* Registers on Token Ring debug nodes */
-#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
-
/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
#define AUTO_NP_10XEN BIT(6)
struct mtk_i2p5ge_phy_priv {
bool fw_loaded;
- u16 tr_low;
- u16 tr_high;
};
enum {
@@ -69,189 +48,136 @@
PHY_AUX_SPD_2500,
};
-static void tr_access(struct phy_device *phydev, bool read, u8 ch_addr, u8 node_addr, u8 data_addr)
-{
- u16 tr_cmd = BIT(15); /* bit 14 & 0 are reserved */
-
- if (read)
- tr_cmd |= BIT(13);
-
- tr_cmd |= (((ch_addr & 0x3) << 11) |
- ((node_addr & 0xf) << 7) |
- ((data_addr & 0x3f) << 1));
- dev_dbg(&phydev->mdio.dev, "tr_cmd: 0x%x\n", tr_cmd);
- __phy_write(phydev, 0x10, tr_cmd);
-}
-
-static void __tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr, u8 data_addr)
+static int mt798x_2p5ge_phy_load_fw(struct phy_device *phydev)
{
struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
-
- tr_access(phydev, true, ch_addr, node_addr, data_addr);
- priv->tr_low = __phy_read(phydev, 0x11);
- priv->tr_high = __phy_read(phydev, 0x12);
- dev_dbg(&phydev->mdio.dev, "tr_high read: 0x%x, tr_low read: 0x%x\n",
- priv->tr_high, priv->tr_low);
-}
+ void __iomem *md32_en_cfg_base, *pmb_addr;
+ struct device *dev = &phydev->mdio.dev;
+ const struct firmware *fw;
+ int ret, i;
+ u16 reg;
-static void tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr, u8 data_addr)
-{
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- __tr_read(phydev, ch_addr, node_addr, data_addr);
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-}
+ if (priv->fw_loaded)
+ return 0;
-static void __tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr, u8 data_addr,
- u32 tr_data)
-{
- __phy_write(phydev, 0x11, tr_data & 0xffff);
- __phy_write(phydev, 0x12, tr_data >> 16);
- tr_access(phydev, false, ch_addr, node_addr, data_addr);
-}
+ pmb_addr = ioremap(MT7988_2P5GE_PMB_FW_BASE, MT7988_2P5GE_PMB_FW_LEN);
+ if (!pmb_addr)
+ return -ENOMEM;
+ md32_en_cfg_base = ioremap(MT7988_2P5GE_MD32_EN_CFG_BASE,
+ MT7988_2P5GE_MD32_EN_CFG_LEN);
+ if (!md32_en_cfg_base) {
+ ret = -ENOMEM;
+ goto free_pmb;
+ }
-static void tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr, u8 data_addr, u32 tr_data)
-{
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- __tr_write(phydev, ch_addr, node_addr, data_addr, tr_data);
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-}
+ ret = request_firmware(&fw, MT7988_2P5GE_PMB_FW, dev);
+ if (ret) {
+ dev_err(dev, "failed to load firmware: %s, ret: %d\n",
+ MT7988_2P5GE_PMB_FW, ret);
+ goto free;
+ }
-static void tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr, u8 data_addr,
- u32 mask, u32 set)
-{
- u32 tr_data;
- struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
+ if (fw->size != MT7988_2P5GE_PMB_FW_SIZE) {
+ dev_err(dev, "Firmware size 0x%zx != 0x%x\n",
+ fw->size, MT7988_2P5GE_PMB_FW_SIZE);
+ ret = -EINVAL;
+ goto release_fw;
+ }
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- __tr_read(phydev, ch_addr, node_addr, data_addr);
- tr_data = (priv->tr_high << 16) | priv->tr_low;
- tr_data = (tr_data & ~mask) | set;
- __tr_write(phydev, ch_addr, node_addr, data_addr, tr_data);
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
-}
+ reg = readw(md32_en_cfg_base);
+ if (reg & MD32_EN) {
+ phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
+ usleep_range(10000, 11000);
+ }
+ phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
-static int mtk_2p5ge_phy_read_page(struct phy_device *phydev)
-{
- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
-}
+ /* Write magic number to safely stall MCU */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800e, 0x1100);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800f, 0x00df);
-static int mtk_2p5ge_phy_write_page(struct phy_device *phydev, int page)
-{
- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
-}
+ for (i = 0; i < MT7988_2P5GE_PMB_FW_SIZE - 1; i += 4)
+ writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
+ dev_info(dev, "Firmware date code: %x/%x/%x, version: %x.%x\n",
+ be16_to_cpu(*((__be16 *)(fw->data +
+ MT7988_2P5GE_PMB_FW_SIZE - 8))),
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 6),
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 5),
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 2),
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 1));
-static int mt7988_2p5ge_phy_probe(struct phy_device *phydev)
-{
- struct mtk_i2p5ge_phy_priv *priv;
+ writew(reg & ~MD32_EN, md32_en_cfg_base);
+ writew(reg | MD32_EN, md32_en_cfg_base);
+ phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
+ /* We need a delay here to stabilize initialization of MCU */
+ usleep_range(7000, 8000);
+ dev_info(dev, "Firmware loading/trigger ok.\n");
- priv = devm_kzalloc(&phydev->mdio.dev,
- sizeof(struct mtk_i2p5ge_phy_priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ priv->fw_loaded = true;
- phydev->priv = priv;
+release_fw:
+ release_firmware(fw);
+free:
+ iounmap(md32_en_cfg_base);
+free_pmb:
+ iounmap(pmb_addr);
- return 0;
+ return ret;
}
-static int mt7988_2p5ge_phy_config_init(struct phy_device *phydev)
+static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
{
- int ret, i;
- const struct firmware *fw;
- struct device *dev = &phydev->mdio.dev;
- struct device_node *np;
- void __iomem *pmb_addr;
- void __iomem *md32_en_cfg_base;
- struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
- u16 reg;
struct pinctrl *pinctrl;
-
- if (!priv->fw_loaded) {
- np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
- if (!np)
- return -ENOENT;
- pmb_addr = of_iomap(np, 0);
- if (!pmb_addr)
- return -ENOMEM;
- md32_en_cfg_base = of_iomap(np, 1);
- if (!md32_en_cfg_base)
- return -ENOMEM;
-
- ret = request_firmware(&fw, MT7988_2P5GE_PMB, dev);
- if (ret) {
- dev_err(dev, "failed to load firmware: %s, ret: %d\n",
- MT7988_2P5GE_PMB, ret);
- return ret;
- }
-
- reg = readw(md32_en_cfg_base);
- if (reg & MD32_EN) {
- phy_set_bits(phydev, 0, BIT(15));
- usleep_range(10000, 11000);
- }
- phy_set_bits(phydev, 0, BIT(11));
-
- /* Write magic number to safely stall MCU */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800e, 0x1100);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800f, 0x00df);
-
- for (i = 0; i < fw->size - 1; i += 4)
- writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
- release_firmware(fw);
+ int ret;
- writew(reg & ~MD32_EN, md32_en_cfg_base);
- writew(reg | MD32_EN, md32_en_cfg_base);
- phy_set_bits(phydev, 0, BIT(15));
- /* We need a delay here to stabilize initialization of MCU */
- usleep_range(7000, 8000);
- dev_info(dev, "Firmware loading/trigger ok.\n");
+ /* Check if PHY interface type is compatible */
+ if (phydev->interface != PHY_INTERFACE_MODE_INTERNAL)
+ return -ENODEV;
- priv->fw_loaded = true;
- }
+ ret = mt798x_2p5ge_phy_load_fw(phydev);
+ if (ret < 0)
+ return ret;
/* 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);
+ MTK_PHY_LED_ON_POLARITY | MTK_PHY_LED_ON_LINK10 |
+ MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK1000 |
+ MTK_PHY_LED_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);
+ MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX);
+ /* Switch pinctrl after setting polarity to avoid bogus blinking */
pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
- if (IS_ERR(pinctrl)) {
+ if (IS_ERR(pinctrl))
dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
- return PTR_ERR(pinctrl);
- }
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL,
MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0);
- /* Enable 16-bit next page exchange bit if 1000-BT isn't advertizing */
- tr_modify(phydev, 0x0, 0xf, 0x3c, AUTO_NP_10XEN,
- FIELD_PREP(AUTO_NP_10XEN, 0x1));
+ /* Enable 16-bit next page exchange bit if 1000-BT isn't advertising */
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, AUTO_NP_10XEN,
+ FIELD_PREP(AUTO_NP_10XEN, 0x1));
- /* Enable downshift */
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_1);
- __phy_set_bits(phydev, MTK_PHY_AUX_CTRL_AND_STATUS, MTK_PHY_ENABLE_DOWNSHIFT);
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+ /* Enable HW auto downshift */
+ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
+ MTK_PHY_AUX_CTRL_AND_STATUS,
+ 0, MTK_PHY_ENABLE_DOWNSHIFT);
return 0;
}
-static int mt7988_2p5ge_phy_config_aneg(struct phy_device *phydev)
+static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev)
{
bool changed = false;
u32 adv;
int ret;
- if (phydev->autoneg == AUTONEG_DISABLE) {
- /* Configure half duplex with genphy_setup_forced,
- * because genphy_c45_pma_setup_forced does not support.
- */
- return phydev->duplex != DUPLEX_FULL
- ? genphy_setup_forced(phydev)
- : genphy_c45_pma_setup_forced(phydev);
- }
+ /* In fact, if we disable autoneg, we can't link up correctly:
+ * 2.5G/1G: Need AN to exchange master/slave information.
+ * 100M/10M: Without AN, link starts at half duplex (According to
+ * IEEE 802.3-2018), which this phy doesn't support.
+ */
+ if (phydev->autoneg == AUTONEG_DISABLE)
+ return -EOPNOTSUPP;
ret = genphy_c45_an_config_aneg(phydev);
if (ret < 0)
@@ -259,10 +185,11 @@
if (ret > 0)
changed = true;
+ /* Clause 45 doesn't define 1000BaseT support. Use Clause 22 instead in
+ * our design.
+ */
adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
- ret = phy_modify_changed(phydev, MII_CTRL1000,
- ADVERTISE_1000FULL | ADVERTISE_1000HALF,
- adv);
+ ret = phy_modify_changed(phydev, MII_CTRL1000, ADVERTISE_1000FULL, adv);
if (ret < 0)
return ret;
if (ret > 0)
@@ -271,35 +198,32 @@
return genphy_c45_check_and_restart_aneg(phydev, changed);
}
-static int mt7988_2p5ge_phy_get_features(struct phy_device *phydev)
+static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev)
{
int ret;
- ret = genphy_read_abilities(phydev);
+ ret = genphy_c45_pma_read_abilities(phydev);
if (ret)
return ret;
- /* We don't support HDX at MAC layer on mt7988.
- * So mask phy's HDX capabilities, too.
+ /* This phy can't handle collision, and neither can (XFI)MAC it's
+ * connected to. Although it can do HDX handshake, it doesn't support
+ * CSMA/CD that HDX requires.
*/
- linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
- phydev->supported);
- linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
- phydev->supported);
- linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
- phydev->supported);
- linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
- phydev->supported);
- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ phydev->supported);
return 0;
}
-static int mt7988_2p5ge_phy_read_status(struct phy_device *phydev)
+static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
{
int ret;
- u16 status;
+ /* When MDIO_STAT1_LSTATUS is raised genphy_c45_read_link(), this phy
+ * actually hasn't finished AN. So use CL22's link update function
+ * instead.
+ */
ret = genphy_update_link(phydev);
if (ret)
return ret;
@@ -309,12 +233,18 @@
phydev->pause = 0;
phydev->asym_pause = 0;
+ /* We'll read link speed through vendor specific registers down below.
+ * So remove phy_resolve_aneg_linkmode (AN on) & genphy_c45_read_pma
+ * (AN off).
+ */
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
ret = genphy_c45_read_lpa(phydev);
if (ret < 0)
return ret;
- /* Read the link partner's 1G advertisement */
+ /* Clause 45 doesn't define 1000BaseT support. Read the link
+ * partner's 1G advertisement via Clause 22.
+ */
ret = phy_read(phydev, MII_STAT1000);
if (ret < 0)
return ret;
@@ -323,8 +253,7 @@
linkmode_zero(phydev->lp_advertising);
}
- status = phy_read(phydev, MII_BMSR);
- if (status & BMSR_LSTATUS) {
+ if (phydev->link) {
ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
if (ret < 0)
return ret;
@@ -344,43 +273,67 @@
break;
}
- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC);
- if (ret < 0)
- return ret;
- phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF;
- /* FIXME: The current firmware always enables rate adaptation mode. */
+ phydev->duplex = DUPLEX_FULL;
+ /* FIXME:
+ * The current firmware always enables rate adaptation mode.
+ */
phydev->rate_matching = RATE_MATCH_PAUSE;
}
return 0;
}
-static int mt7988_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
+static int mt798x_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
phy_interface_t iface)
{
- if (iface == PHY_INTERFACE_MODE_XGMII)
- return RATE_MATCH_PAUSE;
- return RATE_MATCH_NONE;
+ return RATE_MATCH_PAUSE;
+}
+
+static int mt798x_2p5ge_phy_probe(struct phy_device *phydev)
+{
+ struct mtk_i2p5ge_phy_priv *priv;
+
+ priv = devm_kzalloc(&phydev->mdio.dev,
+ sizeof(struct mtk_i2p5ge_phy_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ switch (phydev->drv->phy_id) {
+ case MTK_2P5GPHY_ID_MT7988:
+ /* The original hardware only sets MDIO_DEVS_PMAPMD */
+ phydev->c45_ids.devices_in_package |= MDIO_DEVS_PCS |
+ MDIO_DEVS_AN |
+ MDIO_DEVS_VEND1 |
+ MDIO_DEVS_VEND2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ priv->fw_loaded = false;
+ phydev->priv = priv;
+
+ return 0;
}
-static struct phy_driver mtk_gephy_driver[] = {
+static struct phy_driver mtk_2p5gephy_driver[] = {
{
- PHY_ID_MATCH_MODEL(0x00339c11),
- .name = "MediaTek MT798x 2.5GbE PHY",
- .probe = mt7988_2p5ge_phy_probe,
- .config_init = mt7988_2p5ge_phy_config_init,
- .config_aneg = mt7988_2p5ge_phy_config_aneg,
- .get_features = mt7988_2p5ge_phy_get_features,
- .read_status = mt7988_2p5ge_phy_read_status,
- .get_rate_matching = mt7988_2p5ge_phy_get_rate_matching,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
- .read_page = mtk_2p5ge_phy_read_page,
- .write_page = mtk_2p5ge_phy_write_page,
+ PHY_ID_MATCH_MODEL(MTK_2P5GPHY_ID_MT7988),
+ .name = "MediaTek MT7988 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,
+ .read_status = mt798x_2p5ge_phy_read_status,
+ .get_rate_matching = mt798x_2p5ge_phy_get_rate_matching,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
},
};
-module_phy_driver(mtk_gephy_driver);
+module_phy_driver(mtk_2p5gephy_driver);
static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = {
{ PHY_ID_MATCH_VENDOR(0x00339c00) },
@@ -392,3 +345,4 @@
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl);
+MODULE_FIRMWARE(MT7988_2P5GE_PMB_FW);
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge-soc.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge-soc.c
index 40a5e0f..2c2a879 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge-soc.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge-soc.c
@@ -1,11 +1,14 @@
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitfield.h>
+#include <linux/bitmap.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/phy.h>
+#include <linux/regmap.h>
+
+#include "mtk.h"
#define MTK_GPHY_ID_MT7981 0x03a29461
#define MTK_GPHY_ID_MT7988 0x03a29481
@@ -21,7 +24,108 @@
#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8)
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
-#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
+
+/* Registers on Token Ring debug nodes */
+/* ch_addr = 0x0, node_addr = 0x7, data_addr = 0x15 */
+/* NormMseLoThresh */
+#define NORMAL_MSE_LO_THRESH_MASK GENMASK(15, 8)
+
+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
+/* RemAckCntLimitCtrl */
+#define REMOTE_ACK_COUNT_LIMIT_CTRL_MASK GENMASK(2, 1)
+
+/* ch_addr = 0x1, node_addr = 0xd, data_addr = 0x20 */
+/* VcoSlicerThreshBitsHigh */
+#define VCO_SLICER_THRESH_HIGH_MASK GENMASK(23, 0)
+
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x0 */
+/* DfeTailEnableVgaThresh1000 */
+#define DFE_TAIL_EANBLE_VGA_TRHESH_1000 GENMASK(5, 1)
+
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x1 */
+/* MrvlTrFix100Kp */
+#define MRVL_TR_FIX_100KP_MASK GENMASK(22, 20)
+/* MrvlTrFix100Kf */
+#define MRVL_TR_FIX_100KF_MASK GENMASK(19, 17)
+/* MrvlTrFix1000Kp */
+#define MRVL_TR_FIX_1000KP_MASK GENMASK(16, 14)
+/* MrvlTrFix1000Kf */
+#define MRVL_TR_FIX_1000KF_MASK GENMASK(13, 11)
+
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x12 */
+/* VgaDecRate */
+#define VGA_DECIMATION_RATE_MASK GENMASK(8, 5)
+
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
+/* SlvDSPreadyTime */
+#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15)
+/* MasDSPreadyTime */
+#define MASTER_DSP_READY_TIME_MASK GENMASK(14, 7)
+
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x18 */
+/* EnabRandUpdTrig */
+#define ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER BIT(8)
+
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */
+/* ResetSyncOffset */
+#define RESET_SYNC_OFFSET_MASK GENMASK(11, 8)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x0 */
+/* FfeUpdGainForceVal */
+#define FFE_UPDATE_GAIN_FORCE_VAL_MASK GENMASK(9, 7)
+/* FfeUpdGainForce */
+#define FFE_UPDATE_GAIN_FORCE BIT(6)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x3 */
+/* TrFreeze */
+#define TR_FREEZE_MASK GENMASK(11, 0)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */
+/* SS: Steady-state, KP: Proportional Gain */
+/* SSTrKp100 */
+#define SS_TR_KP100_MASK GENMASK(21, 19)
+/* SSTrKf100 */
+#define SS_TR_KF100_MASK GENMASK(18, 16)
+/* SSTrKp1000Mas */
+#define SS_TR_KP1000_MASTER_MASK GENMASK(15, 13)
+/* SSTrKf1000Mas */
+#define SS_TR_KF1000_MASTER_MASK GENMASK(12, 10)
+/* SSTrKp1000Slv */
+#define SS_TR_KP1000_SLAVE_MASK GENMASK(9, 7)
+/* SSTrKf1000Slv */
+#define SS_TR_KF1000_SLAVE_MASK GENMASK(6, 4)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x8 */
+/* clear this bit if wanna select from AFE */
+/* Regsigdet_sel_1000 */
+#define EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE BIT(4)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */
+/* RegEEE_st2TrKf1000 */
+#define EEE1000_STAGE2_TR_KF_MASK GENMASK(13, 11)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xf */
+/* RegEEE_slv_waketr_timer_tar */
+#define SLAVE_WAKETR_TIMER_MASK GENMASK(20, 11)
+/* RegEEE_slv_remtx_timer_tar */
+#define SLAVE_REMTX_TIMER_MASK GENMASK(10, 1)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x10 */
+/* RegEEE_slv_wake_int_timer_tar */
+#define SLAVE_WAKEINT_TIMER_MASK GENMASK(10, 1)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x14 */
+/* RegEEE_trfreeze_timer2 */
+#define TR_FREEZE_TIMER2_MASK GENMASK(9, 0)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x1c */
+/* RegEEE100Stg1_tar */
+#define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK GENMASK(8, 0)
+
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x25 */
+/* REGEEE_wake_slv_tr_wait_dfesigdet_en */
+#define WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN BIT(11)
+
#define ANALOG_INTERNAL_OPERATION_MAX_US 20
#define TXRESERVE_MIN 0
@@ -209,57 +313,15 @@
#define MTK_PHY_DA_TX_R50_PAIR_D 0x540
/* Registers on MDIO_MMD_VEND2 */
-#define MTK_PHY_LED0_ON_CTRL 0x24
-#define MTK_PHY_LED0_ON_MASK GENMASK(6, 0)
-#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_LINKDOWN BIT(3)
-#define MTK_PHY_LED0_ON_FDX BIT(4) /* Full duplex */
-#define MTK_PHY_LED0_ON_HDX BIT(5) /* Half duplex */
-#define MTK_PHY_LED0_FORCE_ON BIT(6)
-#define MTK_PHY_LED0_POLARITY BIT(14)
-#define MTK_PHY_LED0_ENABLE BIT(15)
-
-#define MTK_PHY_LED0_BLINK_CTRL 0x25
-#define MTK_PHY_LED0_1000TX BIT(0)
-#define MTK_PHY_LED0_1000RX BIT(1)
-#define MTK_PHY_LED0_100TX BIT(2)
-#define MTK_PHY_LED0_100RX BIT(3)
-#define MTK_PHY_LED0_10TX BIT(4)
-#define MTK_PHY_LED0_10RX BIT(5)
-#define MTK_PHY_LED0_COLLISION BIT(6)
-#define MTK_PHY_LED0_RX_CRC_ERR BIT(7)
-#define MTK_PHY_LED0_RX_IDLE_ERR BIT(8)
-#define MTK_PHY_LED0_FORCE_BLINK BIT(9)
-
-#define MTK_PHY_LED1_ON_CTRL 0x26
-#define MTK_PHY_LED1_ON_MASK GENMASK(6, 0)
-#define MTK_PHY_LED1_ON_LINK1000 BIT(0)
-#define MTK_PHY_LED1_ON_LINK100 BIT(1)
-#define MTK_PHY_LED1_ON_LINK10 BIT(2)
-#define MTK_PHY_LED1_ON_LINKDOWN BIT(3)
-#define MTK_PHY_LED1_ON_FDX BIT(4) /* Full duplex */
-#define MTK_PHY_LED1_ON_HDX BIT(5) /* Half duplex */
-#define MTK_PHY_LED1_FORCE_ON BIT(6)
-#define MTK_PHY_LED1_POLARITY BIT(14)
-#define MTK_PHY_LED1_ENABLE BIT(15)
-
-#define MTK_PHY_LED1_BLINK_CTRL 0x27
-#define MTK_PHY_LED1_1000TX BIT(0)
-#define MTK_PHY_LED1_1000RX BIT(1)
-#define MTK_PHY_LED1_100TX BIT(2)
-#define MTK_PHY_LED1_100RX BIT(3)
-#define MTK_PHY_LED1_10TX BIT(4)
-#define MTK_PHY_LED1_10RX BIT(5)
-#define MTK_PHY_LED1_COLLISION BIT(6)
-#define MTK_PHY_LED1_RX_CRC_ERR BIT(7)
-#define MTK_PHY_LED1_RX_IDLE_ERR BIT(8)
-#define MTK_PHY_LED1_FORCE_BLINK BIT(9)
+#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1)
#define MTK_PHY_RG_BG_RASEL 0x115
#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0)
+/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */
+#define RG_GPIO_MISC_TPBANK0 0x6f0
+#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8)
+
/* These macro privides efuse parsing for internal phy. */
#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0))
#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0))
@@ -312,20 +374,10 @@
SW_M
};
-struct mtk_socphy_shared_priv {
+struct mtk_socphy_shared {
u32 boottrap;
};
-static int mtk_socphy_read_page(struct phy_device *phydev)
-{
- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
-}
-
-static int mtk_socphy_write_page(struct phy_device *phydev, int page)
-{
- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
-}
-
/* One calibration cycle consists of:
* 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
* until AD_CAL_COMP is ready to output calibration result.
@@ -346,7 +398,8 @@
ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
MTK_PHY_RG_AD_CAL_CLK, reg_val,
reg_val & MTK_PHY_DA_CAL_CLK, 500,
- ANALOG_INTERNAL_OPERATION_MAX_US, false);
+ ANALOG_INTERNAL_OPERATION_MAX_US,
+ false);
if (ret) {
phydev_err(phydev, "Calibration cycle timeout\n");
return ret;
@@ -355,7 +408,7 @@
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
MTK_PHY_DA_CALIN_FLAG);
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
- MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
return ret;
@@ -412,16 +465,17 @@
static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
{
- int i;
- int bias[16] = {};
- const int vals_9461[16] = { 7, 1, 4, 7,
- 7, 1, 4, 7,
- 7, 1, 4, 7,
- 7, 1, 4, 7 };
const int vals_9481[16] = { 10, 6, 6, 10,
10, 6, 6, 10,
10, 6, 6, 10,
10, 6, 6, 10 };
+ const int vals_9461[16] = { 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7 };
+ int bias[16] = {};
+ int i;
+
switch (phydev->drv->phy_id) {
case MTK_GPHY_ID_MT7981:
/* We add some calibration to efuse values
@@ -444,38 +498,46 @@
}
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
- MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
+ (buf[0] + bias[0]) << 10);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
- MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
+ (buf[0] + bias[2]) << 10);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
- MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
+ (buf[1] + bias[4]) << 8);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
- MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
+ (buf[1] + bias[6]) << 8);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
- MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
+ (buf[2] + bias[8]) << 8);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
- MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
+ (buf[2] + bias[10]) << 8);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
- MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
+ (buf[3] + bias[12]) << 8);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
- MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
+ (buf[3] + bias[14]) << 8);
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
@@ -666,7 +728,8 @@
goto restore;
/* We calibrate TX-VCM in different logic. Check upper index and then
- * lower index. If this calibration is valid, apply lower index's result.
+ * lower index. If this calibration is valid, apply lower index's
+ * result.
*/
ret = upper_ret - lower_ret;
if (ret == 1) {
@@ -679,7 +742,7 @@
MTK_PHY_DA_RX_PSBN_LP_MASK,
upper_idx << 12 | upper_idx << 8 |
upper_idx << 4 | upper_idx);
- phydev_info(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
+ phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
} else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
lower_ret == 1) {
ret = 0;
@@ -695,7 +758,8 @@
} else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
lower_ret == 0) {
ret = 0;
- phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n",
+ phydev_warn(phydev,
+ "TX-VCM SW cal result at high margin 0x%x\n",
upper_idx);
} else {
ret = -EINVAL;
@@ -718,40 +782,36 @@
static void mt798x_phy_common_finetune(struct phy_device *phydev)
{
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
- __phy_write(phydev, 0x11, 0xc71);
- __phy_write(phydev, 0x12, 0xc);
- __phy_write(phydev, 0x10, 0x8fae);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x17,
+ SLAVE_DSP_READY_TIME_MASK | MASTER_DSP_READY_TIME_MASK,
+ FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x18) |
+ FIELD_PREP(MASTER_DSP_READY_TIME_MASK, 0x18));
- /* EnabRandUpdTrig = 1 */
- __phy_write(phydev, 0x11, 0x2f00);
- __phy_write(phydev, 0x12, 0xe);
- __phy_write(phydev, 0x10, 0x8fb0);
+ __mtk_tr_set_bits(phydev, 0x1, 0xf, 0x18,
+ ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER);
- /* NormMseLoThresh = 85 */
- __phy_write(phydev, 0x11, 0x55a0);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x83aa);
+ __mtk_tr_modify(phydev, 0x0, 0x7, 0x15,
+ NORMAL_MSE_LO_THRESH_MASK,
+ FIELD_PREP(NORMAL_MSE_LO_THRESH_MASK, 0x55));
- /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */
- __phy_write(phydev, 0x11, 0x240);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x9680);
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x0,
+ FFE_UPDATE_GAIN_FORCE_VAL_MASK,
+ FIELD_PREP(FFE_UPDATE_GAIN_FORCE_VAL_MASK, 0x4) |
+ FFE_UPDATE_GAIN_FORCE);
- /* TrFreeze = 0 (mt7988 default) */
- __phy_write(phydev, 0x11, 0x0);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x9686);
+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x3, TR_FREEZE_MASK);
- /* SSTrKp100 = 5 */
- /* SSTrKf100 = 6 */
- /* SSTrKp1000Mas = 5 */
- /* SSTrKf1000Mas = 6 */
- /* SSTrKp1000Slv = 5 */
- /* SSTrKf1000Slv = 6 */
- __phy_write(phydev, 0x11, 0xbaef);
- __phy_write(phydev, 0x12, 0x2e);
- __phy_write(phydev, 0x10, 0x968c);
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x6,
+ SS_TR_KP100_MASK | SS_TR_KF100_MASK |
+ SS_TR_KP1000_MASTER_MASK | SS_TR_KF1000_MASTER_MASK |
+ SS_TR_KP1000_SLAVE_MASK | SS_TR_KF1000_SLAVE_MASK,
+ FIELD_PREP(SS_TR_KP100_MASK, 0x5) |
+ FIELD_PREP(SS_TR_KF100_MASK, 0x6) |
+ FIELD_PREP(SS_TR_KP1000_MASTER_MASK, 0x5) |
+ FIELD_PREP(SS_TR_KF1000_MASTER_MASK, 0x6) |
+ FIELD_PREP(SS_TR_KP1000_SLAVE_MASK, 0x5) |
+ FIELD_PREP(SS_TR_KF1000_SLAVE_MASK, 0x6));
+
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
}
@@ -774,32 +834,35 @@
}
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- /* ResetSyncOffset = 6 */
- __phy_write(phydev, 0x11, 0x600);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x8fc0);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x20,
+ RESET_SYNC_OFFSET_MASK,
+ FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x6));
- /* VgaDecRate = 1 */
- __phy_write(phydev, 0x11, 0x4c2a);
- __phy_write(phydev, 0x12, 0x3e);
- __phy_write(phydev, 0x10, 0x8fa4);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x12,
+ VGA_DECIMATION_RATE_MASK,
+ FIELD_PREP(VGA_DECIMATION_RATE_MASK, 0x1));
/* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
* MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
*/
- __phy_write(phydev, 0x11, 0xd10a);
- __phy_write(phydev, 0x12, 0x34);
- __phy_write(phydev, 0x10, 0x8f82);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x1,
+ MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK |
+ MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK,
+ FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x3) |
+ FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x2) |
+ FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x3) |
+ FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x2));
/* VcoSlicerThreshBitsHigh */
- __phy_write(phydev, 0x11, 0x5555);
- __phy_write(phydev, 0x12, 0x55);
- __phy_write(phydev, 0x10, 0x8ec0);
+ __mtk_tr_modify(phydev, 0x1, 0xd, 0x20,
+ VCO_SLICER_THRESH_HIGH_MASK,
+ FIELD_PREP(VCO_SLICER_THRESH_HIGH_MASK, 0x555555));
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK |
+ MTK_PHY_LPF_X_AVERAGE_MASK,
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
/* rg_tr_lpf_cnt_val = 512 */
@@ -828,7 +891,6 @@
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
/* Adjust LDO output voltage */
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
-
}
static void mt7988_phy_finetune(struct phy_device *phydev)
@@ -846,35 +908,33 @@
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- /* ResetSyncOffset = 5 */
- __phy_write(phydev, 0x11, 0x500);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x8fc0);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x20,
+ RESET_SYNC_OFFSET_MASK,
+ FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x5));
/* VgaDecRate is 1 at default on mt7988 */
- /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7,
- * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7
- */
- __phy_write(phydev, 0x11, 0xb90a);
- __phy_write(phydev, 0x12, 0x6f);
- __phy_write(phydev, 0x10, 0x8f82);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x1,
+ MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK |
+ MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK,
+ FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x6) |
+ FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x7) |
+ FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x6) |
+ FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x7));
- /* RemAckCntLimitCtrl = 1 */
- __phy_write(phydev, 0x11, 0xfbba);
- __phy_write(phydev, 0x12, 0xc3);
- __phy_write(phydev, 0x10, 0x87f8);
-
+ __mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
+ REMOTE_ACK_COUNT_LIMIT_CTRL_MASK,
+ FIELD_PREP(REMOTE_ACK_COUNT_LIMIT_CTRL_MASK, 0x1));
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK |
+ MTK_PHY_LPF_X_AVERAGE_MASK,
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
/* rg_tr_lpf_cnt_val = 1023 */
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff);
-
}
static void mt798x_phy_eee(struct phy_device *phydev)
@@ -940,49 +1000,42 @@
MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- /* Regsigdet_sel_1000 = 0 */
- __phy_write(phydev, 0x11, 0xb);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x9690);
+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x8,
+ EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE);
- /* REG_EEE_st2TrKf1000 = 2 */
- __phy_write(phydev, 0x11, 0x114f);
- __phy_write(phydev, 0x12, 0x2);
- __phy_write(phydev, 0x10, 0x969a);
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0xd,
+ EEE1000_STAGE2_TR_KF_MASK,
+ FIELD_PREP(EEE1000_STAGE2_TR_KF_MASK, 0x2));
- /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
- __phy_write(phydev, 0x11, 0x3028);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x969e);
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0xf,
+ SLAVE_WAKETR_TIMER_MASK | SLAVE_REMTX_TIMER_MASK,
+ FIELD_PREP(SLAVE_WAKETR_TIMER_MASK, 0x6) |
+ FIELD_PREP(SLAVE_REMTX_TIMER_MASK, 0x14));
- /* RegEEE_slv_wake_int_timer_tar = 8 */
- __phy_write(phydev, 0x11, 0x5010);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96a0);
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x10,
+ SLAVE_WAKEINT_TIMER_MASK,
+ FIELD_PREP(SLAVE_WAKEINT_TIMER_MASK, 0x8));
- /* RegEEE_trfreeze_timer2 = 586 */
- __phy_write(phydev, 0x11, 0x24a);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96a8);
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x14,
+ TR_FREEZE_TIMER2_MASK,
+ FIELD_PREP(TR_FREEZE_TIMER2_MASK, 0x24a));
- /* RegEEE100Stg1_tar = 16 */
- __phy_write(phydev, 0x11, 0x3210);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96b8);
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x1c,
+ EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK,
+ FIELD_PREP(EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK,
+ 0x10));
- /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
- __phy_write(phydev, 0x11, 0x1463);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x96ca);
+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x25,
+ WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN);
- /* DfeTailEnableVgaThresh1000 = 27 */
- __phy_write(phydev, 0x11, 0x36);
- __phy_write(phydev, 0x12, 0x0);
- __phy_write(phydev, 0x10, 0x8f80);
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x0,
+ DFE_TAIL_EANBLE_VGA_TRHESH_1000,
+ FIELD_PREP(DFE_TAIL_EANBLE_VGA_TRHESH_1000, 0x1b));
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
- __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
+ __phy_modify(phydev, MTK_PHY_LPI_REG_14,
+ MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
__phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
@@ -992,11 +1045,12 @@
phy_modify_mmd(phydev, MDIO_MMD_VEND1,
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ 0xff));
}
static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
- u8 start_pair, u8 end_pair)
+ u8 start_pair, u8 end_pair)
{
u8 pair_n;
int ret;
@@ -1017,7 +1071,7 @@
}
static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
- u8 start_pair, u8 end_pair, u32 *buf)
+ u8 start_pair, u8 end_pair, u32 *buf)
{
u8 pair_n;
int ret;
@@ -1075,10 +1129,10 @@
static int mt798x_phy_calibration(struct phy_device *phydev)
{
+ struct nvmem_cell *cell;
int ret = 0;
- u32 *buf;
size_t len;
- struct nvmem_cell *cell;
+ u32 *buf;
cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
if (IS_ERR(cell)) {
@@ -1133,45 +1187,45 @@
mt798x_phy_common_finetune(phydev);
mt798x_phy_eee(phydev);
- return 0;
+ return mt798x_phy_calibration(phydev);
}
static int mt7988_phy_setup_led(struct phy_device *phydev)
{
- struct mtk_socphy_shared_priv *priv = phydev->shared->priv;
+ struct mtk_socphy_shared *shared = phydev->shared->priv;
int port = phydev->mdio.addr;
- u32 reg = priv->boottrap;
+ u32 reg = shared->boottrap;
struct pinctrl *pinctrl;
phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
- MTK_PHY_LED0_ENABLE | MTK_PHY_LED0_POLARITY |
- MTK_PHY_LED0_ON_LINK10 |
- MTK_PHY_LED0_ON_LINK100 |
- MTK_PHY_LED0_ON_LINK1000);
+ MTK_PHY_LED_ON_ENABLE | MTK_PHY_LED_ON_POLARITY |
+ MTK_PHY_LED_ON_LINK10 |
+ MTK_PHY_LED_ON_LINK100 |
+ MTK_PHY_LED_ON_LINK1000);
phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
- MTK_PHY_LED1_ENABLE | MTK_PHY_LED1_POLARITY |
- MTK_PHY_LED1_ON_LINK10 |
- MTK_PHY_LED1_ON_LINK100 |
- MTK_PHY_LED1_ON_LINK1000);
+ MTK_PHY_LED_ON_ENABLE | MTK_PHY_LED_ON_POLARITY |
+ MTK_PHY_LED_ON_LINK10 |
+ MTK_PHY_LED_ON_LINK100 |
+ MTK_PHY_LED_ON_LINK1000);
- if ((port == GPHY_PORT0 && reg & BIT(8)) ||
- (port == GPHY_PORT1 && reg & BIT(9)) ||
- (port == GPHY_PORT2 && reg & BIT(10)) ||
- (port == GPHY_PORT3 && reg & BIT(11))) {
+ if ((port == GPHY_PORT0 && reg & BIT(0)) ||
+ (port == GPHY_PORT1 && reg & BIT(1)) ||
+ (port == GPHY_PORT2 && reg & BIT(2)) ||
+ (port == GPHY_PORT3 && reg & BIT(3))) {
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
- MTK_PHY_LED0_POLARITY);
+ MTK_PHY_LED_ON_POLARITY);
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
- MTK_PHY_LED1_POLARITY);
+ MTK_PHY_LED_ON_POLARITY);
}
phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL,
- MTK_PHY_LED0_1000TX | MTK_PHY_LED0_1000RX |
- MTK_PHY_LED0_100TX | MTK_PHY_LED0_100RX |
- MTK_PHY_LED0_10TX | MTK_PHY_LED0_10RX);
+ MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_1000RX |
+ MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_100RX |
+ MTK_PHY_LED_BLINK_10TX | MTK_PHY_LED_BLINK_10RX);
phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_BLINK_CTRL,
- MTK_PHY_LED1_1000TX | MTK_PHY_LED1_1000RX |
- MTK_PHY_LED1_100TX | MTK_PHY_LED1_100RX |
- MTK_PHY_LED1_10TX | MTK_PHY_LED1_10RX);
+ MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_1000RX |
+ MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_100RX |
+ MTK_PHY_LED_BLINK_10TX | MTK_PHY_LED_BLINK_10RX);
pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
if (IS_ERR(pinctrl)) {
@@ -1184,38 +1238,47 @@
static int mt7988_phy_probe_shared(struct phy_device *phydev)
{
- struct mtk_socphy_shared_priv *priv = phydev->shared->priv;
- void __iomem *boottrap;
- struct device_node *np;
+ struct device_node *np = dev_of_node(&phydev->mdio.bus->dev);
+ struct mtk_socphy_shared *shared = phydev->shared->priv;
+ struct regmap *regmap;
u32 reg;
-
- np = of_find_compatible_node(NULL, NULL, "mediatek,boottrap");
- if (!np)
- return -ENOENT;
+ int ret;
- boottrap = of_iomap(np, 0);
- if (!boottrap)
- return -ENOMEM;
+ /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B,
+ * LED_C and LED_D respectively. At the same time those pins are used to
+ * bootstrap configuration of the reference clock source (LED_A),
+ * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
+ * In practice this is done using a LED and a resistor pulling the pin
+ * either to GND or to VIO.
+ * The detected value at boot time is accessible at run-time using the
+ * TPBANK0 register located in the gpio base of the pinctrl, in order
+ * to read it here it needs to be referenced by a phandle called
+ * 'mediatek,pio' in the MDIO bus hosting the PHY.
+ * The 4 bits in TPBANK0 are kept as package shared data and are used to
+ * set LED polarity for each of the LED0.
+ */
+ regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio");
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
- reg = readl(boottrap);
- iounmap(boottrap);
+ ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, ®);
+ if (ret)
+ return ret;
- priv->boottrap = reg;
+ shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg);
return 0;
}
-static int mt7981_phy_probe(struct phy_device *phydev)
-{
- return mt798x_phy_calibration(phydev);
-}
-
static int mt7988_phy_probe(struct phy_device *phydev)
{
int err;
+ if (phydev->mdio.addr > 3)
+ return -EINVAL;
+
err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0,
- sizeof(struct mtk_socphy_shared_priv));
+ sizeof(struct mtk_socphy_shared));
if (err)
return err;
@@ -1237,30 +1300,37 @@
return mt798x_phy_calibration(phydev);
}
+static int mt7981_phy_probe(struct phy_device *phydev)
+{
+ return mt798x_phy_calibration(phydev);
+}
+
static struct phy_driver mtk_socphy_driver[] = {
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
- .name = "MediaTek MT7981 PHY",
- .config_init = mt798x_phy_config_init,
- .config_intr = genphy_no_config_intr,
+ .name = "MediaTek MT7981 PHY",
+ .config_init = mt798x_phy_config_init,
+ .read_status = mtk_gphy_cl22_read_status,
+ .config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_no_ack_interrupt,
- .probe = mt7981_phy_probe,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
- .read_page = mtk_socphy_read_page,
- .write_page = mtk_socphy_write_page,
+ .probe = mt7981_phy_probe,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
},
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
- .name = "MediaTek MT7988 PHY",
- .config_init = mt798x_phy_config_init,
- .config_intr = genphy_no_config_intr,
+ .name = "MediaTek MT7988 PHY",
+ .config_init = mt798x_phy_config_init,
+ .read_status = mtk_gphy_cl22_read_status,
+ .config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_no_ack_interrupt,
- .probe = mt7988_phy_probe,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
- .read_page = mtk_socphy_read_page,
- .write_page = mtk_socphy_write_page,
+ .probe = mt7988_phy_probe,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
},
};
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge.c
index 60ef22c..ff5aac8 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-ge.c
@@ -3,48 +3,63 @@
#include <linux/module.h>
#include <linux/phy.h>
-#define MTK_EXT_PAGE_ACCESS 0x1f
-#define MTK_PHY_PAGE_STANDARD 0x0000
-#define MTK_PHY_PAGE_EXTENDED 0x0001
-#define MTK_PHY_PAGE_EXTENDED_2 0x0002
-#define MTK_PHY_PAGE_EXTENDED_3 0x0003
-#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
-#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
+#include "mtk.h"
-#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7
-#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0)
-#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8)
+#define MTK_GPHY_ID_MT7530 0x03a29412
+#define MTK_GPHY_ID_MT7531 0x03a29441
-static int mtk_gephy_read_page(struct phy_device *phydev)
-{
- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
-}
+#define MTK_PHY_PAGE_EXTENDED_2 0x0002
+#define MTK_PHY_PAGE_EXTENDED_3 0x0003
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11 0x11
-static int mtk_gephy_write_page(struct phy_device *phydev, int page)
-{
- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
-}
+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
+
+/* Registers on Token Ring debug nodes */
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
+#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15)
+
+/* Registers on MDIO_MMD_VEND1 */
+#define MTK_PHY_GBE_MODE_TX_DELAY_SEL 0x13
+#define MTK_PHY_TEST_MODE_TX_DELAY_SEL 0x14
+#define MTK_TX_DELAY_PAIR_B_MASK GENMASK(10, 8)
+#define MTK_TX_DELAY_PAIR_D_MASK GENMASK(2, 0)
+
+#define MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL 0xa6
+#define MTK_MCC_NEARECHO_OFFSET_MASK GENMASK(15, 8)
+
+#define MTK_PHY_RXADC_CTRL_RG7 0xc6
+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
+
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123 0x123
+#define MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK GENMASK(15, 8)
+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK GENMASK(7, 0)
static void mtk_gephy_config_init(struct phy_device *phydev)
{
- /* Disable EEE */
- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
-
/* Enable HW auto downshift */
- phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
+ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
+ MTK_PHY_AUX_CTRL_AND_STATUS,
+ 0, MTK_PHY_ENABLE_DOWNSHIFT);
/* Increase SlvDPSready time */
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
- __phy_write(phydev, 0x10, 0xafae);
- __phy_write(phydev, 0x12, 0x2f);
- __phy_write(phydev, 0x10, 0x8fae);
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+ mtk_tr_modify(phydev, 0x1, 0xf, 0x17, SLAVE_DSP_READY_TIME_MASK,
+ FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x5e));
/* Adjust 100_mse_threshold */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123,
+ MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK |
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK,
+ 0xff) |
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
+ 0xff));
- /* Disable mcc */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
+ /* If echo time is narrower than 0x3, it will be regarded as noise */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL,
+ MTK_MCC_NEARECHO_OFFSET_MASK,
+ FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3));
}
static int mt7530_phy_config_init(struct phy_device *phydev)
@@ -52,7 +67,8 @@
mtk_gephy_config_init(phydev);
/* Increase post_update_timer */
- phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
+ phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b);
return 0;
}
@@ -63,55 +79,60 @@
/* PHY link down power saving enable */
phy_set_bits(phydev, 0x17, BIT(4));
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK,
+ FIELD_PREP(MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3));
/* Set TX Pair delay selection */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
-
- /* Adjust RX min/max gain to fix CH395 100Mbps link up fail */
- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
- FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
- FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_GBE_MODE_TX_DELAY_SEL,
+ MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
+ FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
+ FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TEST_MODE_TX_DELAY_SEL,
+ MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
+ FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
+ FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
return 0;
}
static struct phy_driver mtk_gephy_driver[] = {
{
- PHY_ID_MATCH_EXACT(0x03a29412),
- .name = "MediaTek MT7530 PHY",
- .config_init = mt7530_phy_config_init,
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
+ .name = "MediaTek MT7530 PHY",
+ .config_init = mt7530_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
* itself.
*/
- .config_intr = genphy_no_config_intr,
+ .config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_no_ack_interrupt,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
- .read_page = mtk_gephy_read_page,
- .write_page = mtk_gephy_write_page,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
},
{
- PHY_ID_MATCH_EXACT(0x03a29441),
- .name = "MediaTek MT7531 PHY",
- .config_init = mt7531_phy_config_init,
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
+ .name = "MediaTek MT7531 PHY",
+ .config_init = mt7531_phy_config_init,
+ .read_status = mtk_gphy_cl22_read_status,
/* Interrupts are handled by the switch, not the PHY
* itself.
*/
- .config_intr = genphy_no_config_intr,
+ .config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_no_ack_interrupt,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
- .read_page = mtk_gephy_read_page,
- .write_page = mtk_gephy_write_page,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
},
};
module_phy_driver(mtk_gephy_driver);
static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
- { PHY_ID_MATCH_VENDOR(0x03a29400) },
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
{ }
};
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-phy-lib.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-phy-lib.c
new file mode 100644
index 0000000..9b85c8b
--- /dev/null
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk-phy-lib.c
@@ -0,0 +1,452 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/phy.h>
+#include <linux/module.h>
+
+#include <linux/netdevice.h>
+
+#include "mtk.h"
+
+/* Difference between functions with mtk_tr* and __mtk_tr* prefixes is
+ * mtk_tr* functions: wrapped by page switching operations
+ * __mtk_tr* functions: no page switching operations
+ */
+
+static void __mtk_tr_access(struct phy_device *phydev, bool read, u8 ch_addr,
+ u8 node_addr, u8 data_addr)
+{
+ u16 tr_cmd = BIT(15); /* bit 14 & 0 are reserved */
+
+ if (read)
+ tr_cmd |= BIT(13);
+
+ tr_cmd |= (((ch_addr & 0x3) << 11) |
+ ((node_addr & 0xf) << 7) |
+ ((data_addr & 0x3f) << 1));
+ dev_dbg(&phydev->mdio.dev, "tr_cmd: 0x%x\n", tr_cmd);
+ __phy_write(phydev, 0x10, tr_cmd);
+}
+
+static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u16 *tr_high, u16 *tr_low)
+{
+ __mtk_tr_access(phydev, true, ch_addr, node_addr, data_addr);
+ *tr_low = __phy_read(phydev, 0x11);
+ *tr_high = __phy_read(phydev, 0x12);
+ dev_dbg(&phydev->mdio.dev, "tr_high read: 0x%x, tr_low read: 0x%x\n",
+ *tr_high, *tr_low);
+}
+
+u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr)
+{
+ u16 tr_high;
+ u16 tr_low;
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ __mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ return (tr_high << 16) | tr_low;
+}
+EXPORT_SYMBOL_GPL(mtk_tr_read);
+
+static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 tr_data)
+{
+ __phy_write(phydev, 0x11, tr_data & 0xffff);
+ __phy_write(phydev, 0x12, tr_data >> 16);
+ dev_dbg(&phydev->mdio.dev, "tr_high write: 0x%x, tr_low write: 0x%x\n",
+ tr_data >> 16, tr_data & 0xffff);
+ __mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr);
+}
+
+void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 mask, u32 set)
+{
+ u32 tr_data;
+ u16 tr_high;
+ u16 tr_low;
+
+ __mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
+ tr_data = (tr_high << 16) | tr_low;
+ tr_data = (tr_data & ~mask) | set;
+ __mtk_tr_write(phydev, ch_addr, node_addr, data_addr, tr_data);
+}
+EXPORT_SYMBOL_GPL(__mtk_tr_modify);
+
+void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 mask, u32 set)
+{
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, mask, set);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+EXPORT_SYMBOL_GPL(mtk_tr_modify);
+
+void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 set)
+{
+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, 0, set);
+}
+EXPORT_SYMBOL_GPL(__mtk_tr_set_bits);
+
+void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 clr)
+{
+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, clr, 0);
+}
+EXPORT_SYMBOL_GPL(__mtk_tr_clr_bits);
+
+int mtk_phy_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_read_page);
+
+int mtk_phy_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_write_page);
+
+/* This function deals with the case that 1G AN starts but isn't completed. We
+ * set AN_NEW_LP_CNT_LIMIT with different values time after time to let our
+ * 1G->100Mbps hardware automatic downshift to fit more partner devices.
+ */
+static int extend_an_new_lp_cnt_limit(struct phy_device *phydev)
+{
+ int mmd_read_ret;
+ u32 reg_val;
+ int timeout;
+
+ /* According to table 28-9 & Figure 28-18 in IEEE 802.3,
+ * link_fail_inhibit_timer of 10/100/1000 Mbps devices ranges from 750
+ * to "1000ms". Once MTK_PHY_FINAL_SPEED_1000 is set, it means that we
+ * enter "FLP LINK GOOD CHECK" state, link_fail_inhibit_timer starts and
+ * this PHY's 1G training starts. If 1G training never starts, we do
+ * nothing but leave.
+ */
+ timeout = read_poll_timeout(mmd_read_ret = phy_read_mmd, reg_val,
+ (mmd_read_ret < 0) ||
+ reg_val & MTK_PHY_FINAL_SPEED_1000,
+ 10000, 1000000, false, phydev,
+ MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC);
+ if (mmd_read_ret < 0)
+ return mmd_read_ret;
+
+ if (!timeout) {
+ /* Once we found MTK_PHY_FINAL_SPEED_1000 is set, no matter 1G
+ * AN is completed or not, we'll set AN_NEW_LP_CNT_LIMIT again
+ * and again.
+ */
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, AN_NEW_LP_CNT_LIMIT_MASK,
+ FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK, 0xf));
+ mdelay(1500);
+
+ timeout = read_poll_timeout(mtk_tr_read, reg_val,
+ (reg_val & AN_STATE_MASK) !=
+ (AN_STATE_TX_DISABLE <<
+ AN_STATE_SHIFT),
+ 10000, 1000000, false, phydev,
+ 0x0, 0xf, 0x2);
+ if (!timeout) {
+ mdelay(625);
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
+ AN_NEW_LP_CNT_LIMIT_MASK,
+ FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK,
+ 0x8));
+ mdelay(500);
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
+ AN_NEW_LP_CNT_LIMIT_MASK,
+ FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK,
+ 0xf));
+ } else {
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+int mtk_gphy_cl22_read_status(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_read_status(phydev);
+ if (ret)
+ return ret;
+
+ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete) {
+ ret = phy_read_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
+ MTK_PHY_AUX_CTRL_AND_STATUS);
+ if (ret < 0)
+ return ret;
+
+ /* Once LP_DETECTED is set, it means that"ability_match" in
+ * IEEE 802.3 Figure 28-18 is set. This happens after we plug in
+ * cable. Also, LP_DETECTED will be cleared after AN complete.
+ */
+ if (!FIELD_GET(MTK_PHY_LP_DETECTED_MASK, ret))
+ return 0;
+
+ ret = phy_read(phydev, MII_CTRL1000);
+ if (ret & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) {
+ ret = extend_an_new_lp_cnt_limit(phydev);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_gphy_cl22_read_status);
+
+#if 0
+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules,
+ unsigned long supported_triggers)
+{
+ if (index > 1)
+ return -EINVAL;
+
+ /* All combinations of the supported triggers are allowed */
+ if (rules & ~supported_triggers)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported);
+
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules, unsigned long *led_state,
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
+{
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+ (index ? 16 : 0);
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+ int on, blink;
+
+ if (index > 1)
+ return -EINVAL;
+
+ on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
+
+ if (on < 0)
+ return -EIO;
+
+ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ index ? MTK_PHY_LED1_BLINK_CTRL :
+ MTK_PHY_LED0_BLINK_CTRL);
+ if (blink < 0)
+ return -EIO;
+
+ if ((on & (on_set | MTK_PHY_LED_ON_FDX |
+ MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
+ (blink & (rx_blink_set | tx_blink_set)))
+ set_bit(bit_netdev, led_state);
+ else
+ clear_bit(bit_netdev, led_state);
+
+ if (on & MTK_PHY_LED_ON_FORCE_ON)
+ set_bit(bit_on, led_state);
+ else
+ clear_bit(bit_on, led_state);
+
+ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
+ set_bit(bit_blink, led_state);
+ else
+ clear_bit(bit_blink, led_state);
+
+ if (!rules)
+ return 0;
+
+ if (on & on_set)
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
+
+ if (on & MTK_PHY_LED_ON_LINK10)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
+
+ if (on & MTK_PHY_LED_ON_LINK100)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
+
+ if (on & MTK_PHY_LED_ON_LINK1000)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
+
+ if (on & MTK_PHY_LED_ON_LINK2500)
+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
+
+ if (on & MTK_PHY_LED_ON_FDX)
+ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
+
+ if (on & MTK_PHY_LED_ON_HDX)
+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
+
+ if (blink & rx_blink_set)
+ *rules |= BIT(TRIGGER_NETDEV_RX);
+
+ if (blink & tx_blink_set)
+ *rules |= BIT(TRIGGER_NETDEV_TX);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get);
+
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
+ unsigned long rules, unsigned long *led_state,
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
+{
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
+ u16 on = 0, blink = 0;
+ int ret;
+
+ if (index > 1)
+ return -EINVAL;
+
+ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
+ on |= MTK_PHY_LED_ON_FDX;
+
+ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
+ on |= MTK_PHY_LED_ON_HDX;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK10;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK100;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK1000;
+
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
+ on |= MTK_PHY_LED_ON_LINK2500;
+
+ if (rules & BIT(TRIGGER_NETDEV_RX)) {
+ if (on & on_set) {
+ if (on & MTK_PHY_LED_ON_LINK10)
+ blink |= MTK_PHY_LED_BLINK_10RX;
+ if (on & MTK_PHY_LED_ON_LINK100)
+ blink |= MTK_PHY_LED_BLINK_100RX;
+ if (on & MTK_PHY_LED_ON_LINK1000)
+ blink |= MTK_PHY_LED_BLINK_1000RX;
+ if (on & MTK_PHY_LED_ON_LINK2500)
+ blink |= MTK_PHY_LED_BLINK_2500RX;
+ } else {
+ blink |= rx_blink_set;
+ }
+ }
+
+ if (rules & BIT(TRIGGER_NETDEV_TX)) {
+ if (on & on_set) {
+ if (on & MTK_PHY_LED_ON_LINK10)
+ blink |= MTK_PHY_LED_BLINK_10TX;
+ if (on & MTK_PHY_LED_ON_LINK100)
+ blink |= MTK_PHY_LED_BLINK_100TX;
+ if (on & MTK_PHY_LED_ON_LINK1000)
+ blink |= MTK_PHY_LED_BLINK_1000TX;
+ if (on & MTK_PHY_LED_ON_LINK2500)
+ blink |= MTK_PHY_LED_BLINK_2500TX;
+ } else {
+ blink |= tx_blink_set;
+ }
+ }
+
+ if (blink || on)
+ set_bit(bit_netdev, led_state);
+ else
+ clear_bit(bit_netdev, led_state);
+
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
+ MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | on_set,
+ on);
+
+ if (ret)
+ return ret;
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_BLINK_CTRL :
+ MTK_PHY_LED0_BLINK_CTRL, blink);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set);
+
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
+ unsigned long *delay_off, bool *blinking)
+{
+ if (index > 1)
+ return -EINVAL;
+
+ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
+ *blinking = true;
+ *delay_on = 50;
+ *delay_off = 50;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg);
+
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
+ unsigned long *led_state, u16 led_on_mask, bool on)
+{
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
+ bool changed;
+
+ if (on)
+ changed = !test_and_set_bit(bit_on, led_state);
+ else
+ changed = !!test_and_clear_bit(bit_on, led_state);
+
+ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
+ (index ? 16 : 0), led_state);
+ if (changed)
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_ON_CTRL :
+ MTK_PHY_LED0_ON_CTRL,
+ led_on_mask,
+ on ? MTK_PHY_LED_ON_FORCE_ON : 0);
+ else
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set);
+
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
+ unsigned long *led_state, bool blinking)
+{
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
+ (index ? 16 : 0);
+ bool changed;
+
+ if (blinking)
+ changed = !test_and_set_bit(bit_blink, led_state);
+ else
+ changed = !!test_and_clear_bit(bit_blink, led_state);
+
+ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
+ (index ? 16 : 0), led_state);
+ if (changed)
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
+ MTK_PHY_LED1_BLINK_CTRL :
+ MTK_PHY_LED0_BLINK_CTRL,
+ blinking ?
+ MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
+ else
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set);
+
+void mtk_phy_leds_state_init(struct phy_device *phydev)
+{
+ int i;
+
+ for (i = 0; i < 2; ++i)
+ phydev->drv->led_hw_control_get(phydev, i, NULL);
+}
+EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);
+#endif
+
+MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
+MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_LICENSE("GPL");
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk.h
new file mode 100644
index 0000000..2a50bf2
--- /dev/null
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek/mtk.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Common definition for Mediatek Ethernet PHYs
+ * Author: SkyLake Huang <SkyLake.Huang@mediatek.com>
+ * Copyright (c) 2024 MediaTek Inc.
+ */
+
+#ifndef _MTK_EPHY_H_
+#define _MTK_EPHY_H_
+
+#define MTK_EXT_PAGE_ACCESS 0x1f
+#define MTK_PHY_PAGE_STANDARD 0x0000
+#define MTK_PHY_PAGE_EXTENDED_1 0x0001
+#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14
+/* suprv_media_select_RefClk */
+#define MTK_PHY_LP_DETECTED_MASK GENMASK(7, 6)
+#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4)
+
+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
+
+/* Registers on Token Ring debug nodes */
+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x2 */
+#define AN_STATE_MASK GENMASK(22, 19)
+#define AN_STATE_SHIFT 19
+#define AN_STATE_TX_DISABLE 1
+
+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
+#define AN_NEW_LP_CNT_LIMIT_MASK GENMASK(23, 20)
+#define AUTO_NP_10XEN BIT(6)
+
+/* Registers on MDIO_MMD_VEND1 */
+#define MTK_PHY_LINK_STATUS_MISC (0xa2)
+#define MTK_PHY_FINAL_SPEED_1000 BIT(3)
+
+/* Registers on MDIO_MMD_VEND2 */
+#define MTK_PHY_LED0_ON_CTRL 0x24
+#define MTK_PHY_LED1_ON_CTRL 0x26
+#define MTK_GPHY_LED_ON_MASK GENMASK(6, 0)
+#define MTK_2P5GPHY_LED_ON_MASK GENMASK(7, 0)
+#define MTK_PHY_LED_ON_LINK1000 BIT(0)
+#define MTK_PHY_LED_ON_LINK100 BIT(1)
+#define MTK_PHY_LED_ON_LINK10 BIT(2)
+#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
+#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
+#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
+#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
+#define MTK_PHY_LED_ON_LINK2500 BIT(7)
+#define MTK_PHY_LED_ON_POLARITY BIT(14)
+#define MTK_PHY_LED_ON_ENABLE BIT(15)
+
+#define MTK_PHY_LED0_BLINK_CTRL 0x25
+#define MTK_PHY_LED1_BLINK_CTRL 0x27
+#define MTK_PHY_LED_BLINK_1000TX BIT(0)
+#define MTK_PHY_LED_BLINK_1000RX BIT(1)
+#define MTK_PHY_LED_BLINK_100TX BIT(2)
+#define MTK_PHY_LED_BLINK_100RX BIT(3)
+#define MTK_PHY_LED_BLINK_10TX BIT(4)
+#define MTK_PHY_LED_BLINK_10RX BIT(5)
+#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
+#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
+#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
+#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
+#define MTK_PHY_LED_BLINK_2500TX BIT(10)
+#define MTK_PHY_LED_BLINK_2500RX BIT(11)
+
+#define MTK_GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK1000 | \
+ MTK_PHY_LED_ON_LINK100 | \
+ MTK_PHY_LED_ON_LINK10)
+#define MTK_GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
+ MTK_PHY_LED_BLINK_100RX | \
+ MTK_PHY_LED_BLINK_10RX)
+#define MTK_GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
+ MTK_PHY_LED_BLINK_100RX | \
+ MTK_PHY_LED_BLINK_10RX)
+
+#define MTK_2P5GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK2500 | \
+ MTK_GPHY_LED_ON_SET)
+#define MTK_2P5GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
+ MTK_GPHY_LED_RX_BLINK_SET)
+#define MTK_2P5GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
+ MTK_GPHY_LED_TX_BLINK_SET)
+
+#define MTK_PHY_LED_STATE_FORCE_ON 0
+#define MTK_PHY_LED_STATE_FORCE_BLINK 1
+#define MTK_PHY_LED_STATE_NETDEV 2
+
+u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr);
+void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 mask, u32 set);
+void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 mask, u32 set);
+void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 set);
+void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
+ u8 data_addr, u32 clr);
+
+int mtk_phy_read_page(struct phy_device *phydev);
+int mtk_phy_write_page(struct phy_device *phydev, int page);
+
+int mtk_gphy_cl22_read_status(struct phy_device *phydev);
+/*int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules,
+ unsigned long supported_triggers);
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
+ unsigned long rules, unsigned long *led_state,
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules, unsigned long *led_state,
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
+ unsigned long *delay_off, bool *blinking);
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
+ unsigned long *led_state, u16 led_on_mask, bool on);
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
+ unsigned long *led_state, bool blinking);
+void mtk_phy_leds_state_init(struct phy_device *phydev);*/
+
+#endif /* _MTK_EPHY_H_ */
diff --git a/21.02/files/target/linux/mediatek/patches-5.4/999-2718-backport-6.1x-mediatek-net-internal-phy-drivers.patch b/21.02/files/target/linux/mediatek/patches-5.4/999-2718-backport-6.1x-mediatek-net-internal-phy-drivers.patch
new file mode 100644
index 0000000..eae6d72
--- /dev/null
+++ b/21.02/files/target/linux/mediatek/patches-5.4/999-2718-backport-6.1x-mediatek-net-internal-phy-drivers.patch
@@ -0,0 +1,44 @@
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -592,27 +592,7 @@ config MESON_GXL_PHY
+ ---help---
+ Currently has a driver for the Amlogic Meson GXL Internal PHY
+
+-config MEDIATEK_GE_PHY
+- tristate "MediaTek Gigabit Ethernet PHYs"
+- help
+- Supports the MediaTek Gigabit Ethernet PHYs.
+-
+-config MEDIATEK_GE_SOC_PHY
+- bool "MediaTek SoC Ethernet PHYs"
+- depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+- select NVMEM_MTK_EFUSE
+- help
+- Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+-
+- Include support for built-in Ethernet PHYs which are present in
+- the MT7981 and MT7988 SoCs. These PHYs need calibration data
+- present in the SoCs efuse and will dynamically calibrate VCM
+- (common-mode voltage) during startup.
+-
+-config MEDIATEK_2P5GE_PHY
+- tristate "MediaTek 2.5Gb Ethernet PHYs"
+- ---help---
+- Supports MediaTek internal 2.5Gb Ethernet PHYs.
++source "drivers/net/phy/mediatek/Kconfig"
+
+ config MICREL_PHY
+ tristate "Micrel PHYs"
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -105,9 +105,7 @@ obj-$(CONFIG_LXT_PHY) += lxt.o
+ obj-$(CONFIG_MARVELL_PHY) += marvell.o
+ obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
+ obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
+-obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
+-obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
+-obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
++obj-y += mediatek/
+ obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
+ obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
+ obj-$(CONFIG_MICREL_PHY) += micrel.o