From: Markus Niebel <[email protected]>

Disable the support due to chip errata and call genphy_config_aneg
instead of genphy_config. For a complete describtion look at the
KSZ9031 errata sheets: DS80000691D or DS80000692D.

Micrel KSZ9021 has no errata, but has the same issue with Asymmetric Pause.
This patch apply the same workaround as the one for KSZ9031.

This follows linux implementation in commits
3aed3e2a143c ("net: phy: micrel: add Asym Pause workaround")
407d8098cb1a ("net: phy: micrel: add Asym Pause workaround for KSZ9021")

Signed-off-by: Markus Niebel <[email protected]>
Signed-off-by: Max Merchel <[email protected]>
---
 drivers/net/phy/micrel_ksz90x1.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c
index a02dbe900b8..a669a5789b9 100644
--- a/drivers/net/phy/micrel_ksz90x1.c
+++ b/drivers/net/phy/micrel_ksz90x1.c
@@ -217,6 +217,31 @@ static int ksz9031_center_flp_timing(struct phy_device 
*phydev)
        return ret;
 }
 
+static void ksz90x1_workaround_asymmetric_pause(struct phy_device *phydev)
+{
+       u32 features = phydev->drv->features;
+
+       /* Silicon Errata Sheet (DS80000691D or DS80000692D):
+        * Whenever the device's Asymmetric Pause capability is set to 1,
+        * link-up may fail after a link-up to link-down transition.
+        *
+        * The Errata Sheet is for ksz9031, but ksz9021 has the same issue
+        *
+        * Workaround:
+        * Do not enable the Asymmetric Pause capability bit.
+        */
+       features &= ~ADVERTISE_PAUSE_ASYM;
+
+       /* We force setting the Pause capability as the core will force the
+        * Asymmetric Pause capability to 1 otherwise.
+        */
+       features |= ADVERTISE_PAUSE_CAP;
+
+       /* update feature support and forward to advertised features */
+       phydev->supported = features;
+       phydev->advertising = phydev->supported;
+}
+
 /*
  * KSZ9021
  */
@@ -260,6 +285,8 @@ static int ksz9021_config(struct phy_device *phydev)
        if (ret)
                return ret;
 
+       ksz90x1_workaround_asymmetric_pause(phydev);
+
        if (env_get("disable_giga"))
                features &= ~(SUPPORTED_1000baseT_Half |
                SUPPORTED_1000baseT_Full);
@@ -345,6 +372,8 @@ static int ksz9031_config(struct phy_device *phydev)
        if (ret)
                return ret;
 
+       ksz90x1_workaround_asymmetric_pause(phydev);
+
        /* add an option to disable the gigabit feature of this PHY */
        if (env_get("disable_giga")) {
                unsigned features;
-- 
2.43.0

Reply via email to