diff options
author | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-07-03 15:24:02 +0000 |
---|---|---|
committer | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-07-03 15:24:02 +0000 |
commit | 641595b79aacc036a21116a578b8cad093bb02b4 (patch) | |
tree | 4414b4d0f6af3c8f0c12d530843fbf900693ed11 /target/linux/ar71xx/files | |
parent | db1a0d339ede0eac49d1f2d2a6574b0fd8f16503 (diff) |
ar71xx: improve MDIO busy wait code
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@32586 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/ar71xx/files')
-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 1b2fe2ee7..eaaf12148 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) |