aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mediatek')
-rw-r--r--target/linux/mediatek/patches-5.15/731-net-phy-hack-mxl-gpy-disable-sgmii-an.patch166
1 files changed, 166 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-5.15/731-net-phy-hack-mxl-gpy-disable-sgmii-an.patch b/target/linux/mediatek/patches-5.15/731-net-phy-hack-mxl-gpy-disable-sgmii-an.patch
new file mode 100644
index 0000000000..2e39ca3c26
--- /dev/null
+++ b/target/linux/mediatek/patches-5.15/731-net-phy-hack-mxl-gpy-disable-sgmii-an.patch
@@ -0,0 +1,166 @@
+--- 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;
+ }
+ }