From f3558be91e5086f1673d47ba8c430e7640b32e71 Mon Sep 17 00:00:00 2001 From: Andy Chiu Date: Tue, 1 Nov 2022 11:58:00 +0800 Subject: 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 Reviewed-by: Greentime Hu Link: https://lore.kernel.org/r/20221101035800.912644-3-andy.chiu@sifive.com Signed-off-by: Michal Simek --- drivers/net/xilinx_axi_emac.c | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index 5a4d838812..3e9919993d 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; -- cgit v1.2.3