diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index a13b48c..9d9397a 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -21,6 +21,7 @@ * */ #include +#include #include #ifndef CONFIG_PHYLIB_10G @@ -43,6 +44,38 @@ int tn2020_config(struct phy_device *phydev) int tn2020_startup(struct phy_device *phydev) { + unsigned int timeout = 5 * 1000; /* 5 second timeout */ + +#define MDIO_PHYXS_LANE_READY (MDIO_PHYXS_LNSTAT_SYNC0 | \ + MDIO_PHYXS_LNSTAT_SYNC1 | \ + MDIO_PHYXS_LNSTAT_SYNC2 | \ + MDIO_PHYXS_LNSTAT_SYNC3 | \ + MDIO_PHYXS_LNSTAT_ALIGN) + + /* + * Wait for the XAUI-SERDES lanes to align first. Under normal + * circumstances, this can take up to three seconds. + */ + while (--timeout) { + int reg = phy_read(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_LNSTAT); + if (reg < 0) { + printf("TN2020: Error reading from PHY at " + "address %u\n", phydev->addr); + break; + } + if ((reg & MDIO_PHYXS_LANE_READY) == MDIO_PHYXS_LANE_READY) + break; + udelay(1000); + } + if (!timeout) { + /* + * A timeout is bad, but it may not be fatal, so don't + * return an error. Display a warning instead. + */ + printf("TN2020: Timeout waiting for PHY at address %u to " + "align.\n", phydev->addr); + } + if (phydev->port != PORT_FIBRE) return gen10g_startup(phydev);