Do not poll forever when the hardware does not behave like we want to. Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> --- drivers/net/davinci_emac.c | 47 ++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 2f6091d155..bda62214ef 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -105,13 +105,40 @@ static void davinci_eth_mdio_enable(struct davinci_emac_priv *priv) while (readl(priv->adap_mdio + EMAC_MDIO_CONTROL) & MDIO_CONTROL_IDLE); } +/* wait until hardware is ready for another user access */ +static int wait_for_user_access(struct davinci_emac_priv *priv, uint32_t *val) +{ + u32 tmp; + uint64_t start = get_time_ns(); + + do { + tmp = readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0); + + if (!(tmp & MDIO_USERACCESS0_GO)) + break; + + if (is_timeout(start, 100 * MSECOND)) { + dev_err(priv->dev, "timeout waiting for user access\n"); + return -ETIMEDOUT; + } + } while (1); + + if (val) + *val = tmp; + + return 0; +} + + static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg) { struct davinci_emac_priv *priv = bus->priv; uint16_t value; - int tmp; + int tmp, ret; - while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); + ret = wait_for_user_access(priv, NULL); + if (ret) + return ret; writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ | @@ -119,8 +146,9 @@ static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg) ((addr & 0x1f) << 16), priv->adap_mdio + EMAC_MDIO_USERACCESS0); - /* Wait for command to complete */ - while ((tmp = readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0)) & MDIO_USERACCESS0_GO); + ret = wait_for_user_access(priv, &tmp); + if (ret) + return ret; if (tmp & MDIO_USERACCESS0_ACK) { value = tmp & 0xffff; @@ -135,7 +163,11 @@ static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg) static int davinci_miibus_write(struct mii_bus *bus, int addr, int reg, u16 value) { struct davinci_emac_priv *priv = bus->priv; - while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); + int ret; + + ret = wait_for_user_access(priv, NULL); + if (ret) + return ret; dev_dbg(priv->dev, "davinci_miibus_write: addr=0x%02x reg=0x%02x value=0x%04x\n", addr, reg, value); @@ -146,10 +178,7 @@ static int davinci_miibus_write(struct mii_bus *bus, int addr, int reg, u16 valu (value & 0xffff), priv->adap_mdio + EMAC_MDIO_USERACCESS0); - /* Wait for command to complete */ - while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); - - return 0; + return wait_for_user_access(priv, NULL); } static int davinci_emac_get_ethaddr(struct eth_device *edev, unsigned char *adr) -- 2.19.1 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox