mediatek: replace hack for MaxLinear 2.5G PHY

Replace hack with proper patch also for Linux 5.15.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2023-07-08 17:31:24 +01:00
parent f321a49fd5
commit 712fa3eff8
3 changed files with 63 additions and 166 deletions

View File

@ -1,166 +0,0 @@
--- a/drivers/net/phy/mxl-gpy.c
+++ b/drivers/net/phy/mxl-gpy.c
@@ -126,6 +126,12 @@ static int gpy_config_init(struct phy_de
if (ret < 0)
return ret;
+ /* Disable SGMII auto-negotiation */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
+ VSPEC1_SGMII_CTRL_ANEN, 0);
+ if (ret < 0)
+ return ret;
+
return gpy_led_write(phydev);
}
@@ -151,65 +157,6 @@ static int gpy_probe(struct phy_device *
return 0;
}
-static bool gpy_sgmii_need_reaneg(struct phy_device *phydev)
-{
- int fw_ver, fw_type, fw_minor;
- size_t i;
-
- fw_ver = phy_read(phydev, PHY_FWV);
- if (fw_ver < 0)
- return true;
-
- fw_type = FIELD_GET(PHY_FWV_TYPE_MASK, fw_ver);
- fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, fw_ver);
-
- for (i = 0; i < ARRAY_SIZE(ver_need_sgmii_reaneg); i++) {
- if (fw_type != ver_need_sgmii_reaneg[i].type)
- continue;
- if (fw_minor < ver_need_sgmii_reaneg[i].minor)
- return true;
- break;
- }
-
- return false;
-}
-
-static bool gpy_2500basex_chk(struct phy_device *phydev)
-{
- int ret;
-
- ret = phy_read(phydev, PHY_MIISTAT);
- if (ret < 0) {
- phydev_err(phydev, "Error: MDIO register access failed: %d\n",
- ret);
- return false;
- }
-
- if (!(ret & PHY_MIISTAT_LS) ||
- FIELD_GET(PHY_MIISTAT_SPD_MASK, ret) != PHY_MIISTAT_SPD_2500)
- return false;
-
- phydev->speed = SPEED_2500;
- phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_CTRL_ANEN, 0);
- return true;
-}
-
-static bool gpy_sgmii_aneg_en(struct phy_device *phydev)
-{
- int ret;
-
- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL);
- if (ret < 0) {
- phydev_err(phydev, "Error: MMD register access failed: %d\n",
- ret);
- return true;
- }
-
- return (ret & VSPEC1_SGMII_CTRL_ANEN) ? true : false;
-}
-
static int gpy_config_aneg(struct phy_device *phydev)
{
bool changed = false;
@@ -248,53 +195,11 @@ static int gpy_config_aneg(struct phy_de
phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
return 0;
- /* No need to trigger re-ANEG if link speed is 2.5G or SGMII ANEG is
- * disabled.
- */
- if (!gpy_sgmii_need_reaneg(phydev) || gpy_2500basex_chk(phydev) ||
- !gpy_sgmii_aneg_en(phydev))
- return 0;
-
- /* There is a design constraint in GPY2xx device where SGMII AN is
- * only triggered when there is change of speed. If, PHY link
- * partner`s speed is still same even after PHY TPI is down and up
- * again, SGMII AN is not triggered and hence no new in-band message
- * from GPY to MAC side SGMII.
- * This could cause an issue during power up, when PHY is up prior to
- * MAC. At this condition, once MAC side SGMII is up, MAC side SGMII
- * wouldn`t receive new in-band message from GPY with correct link
- * status, speed and duplex info.
- *
- * 1) If PHY is already up and TPI link status is still down (such as
- * hard reboot), TPI link status is polled for 4 seconds before
- * retriggerring SGMII AN.
- * 2) If PHY is already up and TPI link status is also up (such as soft
- * reboot), polling of TPI link status is not needed and SGMII AN is
- * immediately retriggered.
- * 3) Other conditions such as PHY is down, speed change etc, skip
- * retriggering SGMII AN. Note: in case of speed change, GPY FW will
- * initiate SGMII AN.
- */
-
- if (phydev->state != PHY_UP)
- return 0;
-
- ret = phy_read_poll_timeout(phydev, MII_BMSR, ret, ret & BMSR_LSTATUS,
- 20000, 4000000, false);
- if (ret == -ETIMEDOUT)
- return 0;
- else if (ret < 0)
- return ret;
-
- /* Trigger SGMII AN. */
- return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_CTRL_ANRS, VSPEC1_SGMII_CTRL_ANRS);
+ return 0;
}
static void gpy_update_interface(struct phy_device *phydev)
{
- int ret;
-
/* Interface mode is fixed for USXGMII and integrated PHY */
if (phydev->interface == PHY_INTERFACE_MODE_USXGMII ||
phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
@@ -306,29 +211,11 @@ static void gpy_update_interface(struct
switch (phydev->speed) {
case SPEED_2500:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_CTRL_ANEN, 0);
- if (ret < 0)
- phydev_err(phydev,
- "Error: Disable of SGMII ANEG failed: %d\n",
- ret);
break;
case SPEED_1000:
case SPEED_100:
case SPEED_10:
phydev->interface = PHY_INTERFACE_MODE_SGMII;
- if (gpy_sgmii_aneg_en(phydev))
- break;
- /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed
- * if ANEG is disabled (in 2500-BaseX mode).
- */
- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_ANEN_ANRS,
- VSPEC1_SGMII_ANEN_ANRS);
- if (ret < 0)
- phydev_err(phydev,
- "Error: Enable of SGMII ANEG failed: %d\n",
- ret);
break;
}
}

View File

@ -0,0 +1,63 @@
From a969b663c866129ed9eb217785a6574fbe826f1d Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 6 Apr 2023 23:36:50 +0100
Subject: [PATCH] net: phy: mxl-gpy: don't use SGMII AN if using phylink
MAC drivers using phylink expect SGMII in-band-status to be switched off
when attached to a PHY. Make sure this is the case also for mxl-gpy which
keeps SGMII in-band-status in case of SGMII interface mode is used.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/phy/mxl-gpy.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
--- a/drivers/net/phy/mxl-gpy.c
+++ b/drivers/net/phy/mxl-gpy.c
@@ -191,8 +191,11 @@ static bool gpy_2500basex_chk(struct phy
phydev->speed = SPEED_2500;
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_CTRL_ANEN, 0);
+
+ if (!phydev->phylink)
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
+ VSPEC1_SGMII_CTRL_ANEN, 0);
+
return true;
}
@@ -216,6 +219,14 @@ static int gpy_config_aneg(struct phy_de
u32 adv;
int ret;
+ /* Disable SGMII auto-negotiation if using phylink */
+ if (phydev->phylink) {
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
+ VSPEC1_SGMII_CTRL_ANEN, 0);
+ if (ret < 0)
+ return ret;
+ }
+
if (phydev->autoneg == AUTONEG_DISABLE) {
/* Configure half duplex with genphy_setup_forced,
* because genphy_c45_pma_setup_forced does not support.
@@ -306,6 +317,8 @@ static void gpy_update_interface(struct
switch (phydev->speed) {
case SPEED_2500:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
+ if (phydev->phylink)
+ break;
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
VSPEC1_SGMII_CTRL_ANEN, 0);
if (ret < 0)
@@ -317,7 +330,7 @@ static void gpy_update_interface(struct
case SPEED_100:
case SPEED_10:
phydev->interface = PHY_INTERFACE_MODE_SGMII;
- if (gpy_sgmii_aneg_en(phydev))
+ if (phydev->phylink || gpy_sgmii_aneg_en(phydev))
break;
/* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed
* if ANEG is disabled (in 2500-BaseX mode).