diff options
-rw-r--r-- | target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c index 1b2fe2ee7a..eaaf121485 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c @@ -47,53 +47,62 @@ static void ag71xx_mdio_dump_regs(struct ag71xx_mdio *am) ag71xx_mdio_rr(am, AG71XX_REG_MII_IND)); } +static int ag71xx_mdio_wait_busy(struct ag71xx_mdio *am) +{ + int i; + + for (i = 0; i < AG71XX_MDIO_RETRY; i++) { + u32 busy; + + udelay(AG71XX_MDIO_DELAY); + + busy = ag71xx_mdio_rr(am, AG71XX_REG_MII_IND); + if (!busy) + return 0; + + udelay(AG71XX_MDIO_DELAY); + } + + pr_err("%s: MDIO operation timed out\n", am->mii_bus->name); + + return -ETIMEDOUT; +} + int ag71xx_mdio_mii_read(struct ag71xx_mdio *am, int addr, int reg) { + int err; int ret; - int i; + + err = ag71xx_mdio_wait_busy(am); + if (err) + return 0xffff; ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE); ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR, ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff)); ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_READ); - i = AG71XX_MDIO_RETRY; - while (ag71xx_mdio_rr(am, AG71XX_REG_MII_IND) & MII_IND_BUSY) { - if (i-- == 0) { - pr_err("%s: mii_read timed out\n", am->mii_bus->name); - ret = 0xffff; - goto out; - } - udelay(AG71XX_MDIO_DELAY); - } + err = ag71xx_mdio_wait_busy(am); + if (err) + return 0xffff; ret = ag71xx_mdio_rr(am, AG71XX_REG_MII_STATUS) & 0xffff; ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE); DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, ret); -out: return ret; } void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, int addr, int reg, u16 val) { - int i; - DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val); ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR, ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff)); ag71xx_mdio_wr(am, AG71XX_REG_MII_CTRL, val); - i = AG71XX_MDIO_RETRY; - while (ag71xx_mdio_rr(am, AG71XX_REG_MII_IND) & MII_IND_BUSY) { - if (i-- == 0) { - pr_err("%s: mii_write timed out\n", am->mii_bus->name); - break; - } - udelay(AG71XX_MDIO_DELAY); - } + ag71xx_mdio_wait_busy(am); } static int ag71xx_mdio_reset(struct mii_bus *bus) |