[][kernel][mt7988][i2.5gphy][net: phy: Fix 2.5G FDX & rewrite read status flow]

[Description]
Fix 2.5G FDX & rewrite read status flow

[Release-log]
N/A

Change-Id: I8afa089c2d9116026e3532382d9b954770206d4c
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6990490
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
index 544bb50..805dbd5 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
@@ -17,6 +17,17 @@
 #define BASE1000T_STATUS_EXTEND		(0x11)
 #define EXTEND_CTRL_AND_STATUS		(0x16)
 
+#define PHY_AUX_CTRL_STATUS		(0x1d)
+#define   PHY_AUX_DPX_MASK		GENMASK(5, 5)
+#define   PHY_AUX_SPEED_MASK		GENMASK(4, 2)
+
+enum {
+	PHY_AUX_SPD_10 = 0,
+	PHY_AUX_SPD_100,
+	PHY_AUX_SPD_1000,
+	PHY_AUX_SPD_2500,
+};
+
 static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
 {
 	int ret;
@@ -97,33 +108,53 @@
 static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
 {
 	int ret;
-	u16 reg;
 
-	ret = genphy_read_status(phydev);
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
 
-	reg = phy_read(phydev, BASE1000T_STATUS_EXTEND);
-	if (FIELD_GET(BIT(2), reg)) {
-		phydev->speed = SPEED_2500;
-		goto end;
-	} else if (FIELD_GET(BIT(12), reg)) {
-		phydev->speed = SPEED_1000;
-		goto end;
-	}
+	phydev->speed = SPEED_UNKNOWN;
+	phydev->duplex = DUPLEX_UNKNOWN;
+	phydev->pause = 0;
+	phydev->asym_pause = 0;
 
-	reg = phy_read(phydev, BASE100T_STATUS_EXTEND);
-	if (FIELD_GET(BIT(12), reg)) {
-		phydev->speed = SPEED_100;
-		goto end;
+	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 */
+		ret = phy_read(phydev, MII_STAT1000);
+		if (ret < 0)
+			return ret;
+		mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
+	} else if (phydev->autoneg == AUTONEG_DISABLE) {
+		linkmode_zero(phydev->lp_advertising);
 	}
 
+	ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
+	if (ret < 0)
+		return ret;
+
-	reg = phy_read(phydev, EXTEND_CTRL_AND_STATUS);
-	if (FIELD_GET(BIT(6), reg)) {
+	/* Actually this phy supports only FDX */
+	phydev->duplex = (ret & PHY_AUX_DPX_MASK) ? DUPLEX_FULL : DUPLEX_HALF;
+	switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
+	case PHY_AUX_SPD_10:
 		phydev->speed = SPEED_10;
-		goto end;
+		break;
+	case PHY_AUX_SPD_100:
+		phydev->speed = SPEED_100;
+		break;
+	case PHY_AUX_SPD_1000:
+		phydev->speed = SPEED_1000;
+		break;
+	case PHY_AUX_SPD_2500:
+		phydev->speed = SPEED_2500;
+		phydev->duplex = DUPLEX_FULL; /* 2.5G must be FDX */
+		break;
 	}
 
-end:
-	return ret;
+	return 0;
 }
 
 static struct phy_driver mtk_gephy_driver[] = {