summaryrefslogtreecommitdiff
path: root/target/linux
diff options
context:
space:
mode:
authorjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-07-03 15:24:02 +0000
committerjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-07-03 15:24:02 +0000
commit641595b79aacc036a21116a578b8cad093bb02b4 (patch)
tree4414b4d0f6af3c8f0c12d530843fbf900693ed11 /target/linux
parentdb1a0d339ede0eac49d1f2d2a6574b0fd8f16503 (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')
-rw-r--r--target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c51
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)