diff options
author | Andy Chiu <andy.chiu@sifive.com> | 2022-11-01 11:58:00 +0800 |
---|---|---|
committer | Michal Simek <michal.simek@amd.com> | 2022-12-05 08:55:54 +0100 |
commit | f3558be91e5086f1673d47ba8c430e7640b32e71 (patch) | |
tree | db75fa9d753979e3f672b956c3091c75d06b9b9a | |
parent | e23544cffe7057d678846498ec0fbf21eff9bc95 (diff) | |
download | u-boot-f3558be91e5086f1673d47ba8c430e7640b32e71.zip u-boot-f3558be91e5086f1673d47ba8c430e7640b32e71.tar.gz u-boot-f3558be91e5086f1673d47ba8c430e7640b32e71.tar.bz2 |
net: xilinx_axi: check PCS/PMA PHY status in setup_phy
Both PCS/PMA PHY and the external PHY need to have a valid link status
in order to have Ethernet traffic. Check and wait this status at
setup_phy() so that we could diagnose if there is a PHY issue.
Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
Reviewed-by: Greentime Hu <greentime.hu@sifive.com>
Link: https://lore.kernel.org/r/20221101035800.912644-3-andy.chiu@sifive.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
-rw-r--r-- | drivers/net/xilinx_axi_emac.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index 5a4d838..3e99199 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -342,6 +342,45 @@ static int axiemac_phy_init(struct udevice *dev) return 0; } +static int pcs_pma_startup(struct axidma_priv *priv) +{ + u32 rc, retry_cnt = 0; + u16 mii_reg; + + rc = phyread(priv, priv->pcsaddr, MII_BMCR, &mii_reg); + if (rc) + goto failed_mdio; + + if (!(mii_reg & BMCR_ANENABLE)) { + mii_reg |= BMCR_ANENABLE; + if (phywrite(priv, priv->pcsaddr, MII_BMCR, mii_reg)) + goto failed_mdio; + } + + /* + * Check the internal PHY status and warn user if the link between it + * and the external PHY is not obtained. + */ + debug("axiemac: waiting for link status of the PCS/PMA PHY"); + while (retry_cnt * 10 < PHY_ANEG_TIMEOUT) { + rc = phyread(priv, priv->pcsaddr, MII_BMSR, &mii_reg); + if ((mii_reg & BMSR_LSTATUS) && mii_reg != 0xffff && !rc) { + debug(".Done\n"); + return 0; + } + if ((retry_cnt++ % 10) == 0) + debug("."); + mdelay(10); + } + debug("\n"); + printf("axiemac: Warning, PCS/PMA PHY@%d is not ready, link is down\n", + priv->pcsaddr); + return 1; +failed_mdio: + printf("axiemac: MDIO to the PCS/PMA PHY has failed\n"); + return 1; +} + /* Setting axi emac and phy to proper setting */ static int setup_phy(struct udevice *dev) { @@ -373,6 +412,11 @@ static int setup_phy(struct udevice *dev) phydev->dev->name); return 0; } + if (priv->interface == PHY_INTERFACE_MODE_SGMII || + priv->interface == PHY_INTERFACE_MODE_1000BASEX) { + if (pcs_pma_startup(priv)) + return 0; + } if (!phydev->link) { printf("%s: No link.\n", phydev->dev->name); return 0; |