net: phy: nxp-c45-tja11xx: reset PCS if the link goes down
authorRadu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
Mon, 31 Jul 2023 09:16:19 +0000 (12:16 +0300)
committerJakub Kicinski <kuba@kernel.org>
Wed, 2 Aug 2023 04:06:26 +0000 (21:06 -0700)
During PTP testing on early TJA1120 engineering samples I observed that
if the link is lost and recovered, the tx timestamps will be randomly
lost. To avoid this HW issue, the PCS should be reset.

Resetting the PCS will break the link and we should reset the PCS on
LINK UP -> LINK DOWN transition, otherwise we will trigger and infinite
loop of LINK UP -> LINK DOWN events.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20230731091619.77961-12-radu-nicolae.pirea@oss.nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/nxp-c45-tja11xx.c

index 4865730..7ab080f 100644 (file)
@@ -56,6 +56,9 @@
 #define VEND1_PHY_CONFIG               0x8108
 #define PHY_CONFIG_AUTO                        BIT(0)
 
+#define TJA1120_EPHY_RESETS            0x810A
+#define EPHY_PCS_RESET                 BIT(3)
+
 #define VEND1_SIGNAL_QUALITY           0x8320
 #define SQI_VALID                      BIT(14)
 #define SQI_MASK                       GENMASK(2, 0)
@@ -1371,6 +1374,19 @@ static int nxp_c45_get_sqi(struct phy_device *phydev)
        return reg;
 }
 
+static void tja1120_link_change_notify(struct phy_device *phydev)
+{
+       /* Bug workaround for TJA1120 enegineering samples: fix egress
+        * timestamps lost after link recovery.
+        */
+       if (phydev->state == PHY_NOLINK) {
+               phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+                                TJA1120_EPHY_RESETS, EPHY_PCS_RESET);
+               phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+                                  TJA1120_EPHY_RESETS, EPHY_PCS_RESET);
+       }
+}
+
 static int nxp_c45_get_sqi_max(struct phy_device *phydev)
 {
        return MAX_SQI;
@@ -1932,6 +1948,7 @@ static struct phy_driver nxp_c45_driver[] = {
                .config_intr            = tja1120_config_intr,
                .handle_interrupt       = nxp_c45_handle_interrupt,
                .read_status            = genphy_c45_read_status,
+               .link_change_notify     = tja1120_link_change_notify,
                .suspend                = genphy_c45_pma_suspend,
                .resume                 = genphy_c45_pma_resume,
                .get_sset_count         = nxp_c45_get_sset_count,