diff options
Diffstat (limited to 'drivers/net/miidev.c')
-rw-r--r-- | drivers/net/miidev.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/drivers/net/miidev.c b/drivers/net/miidev.c index d721aac9de..3b73133201 100644 --- a/drivers/net/miidev.c +++ b/drivers/net/miidev.c @@ -30,23 +30,37 @@ int miidev_restart_aneg(struct mii_device *mdev) { - uint16_t status; - int timeout; + int status, timeout; + uint64_t start; + + status = mii_write(mdev, mdev->address, MII_BMCR, BMCR_RESET); + if (status) + return status; - /* - * Reset PHY, then delay 300ns - */ - mii_write(mdev, mdev->address, MII_BMCR, BMCR_RESET); + start = get_time_ns(); + do { + status = mii_read(mdev, mdev->address, MII_BMCR); + if (status < 0) + return status; + + if (is_timeout(start, SECOND)) + return -ETIMEDOUT; + + } while (status & BMCR_RESET); if (mdev->flags & MIIDEV_FORCE_LINK) return 0; - udelay(1000); - if (mdev->flags & MIIDEV_FORCE_10) { printf("Forcing 10 Mbps ethernet link... "); + status = mii_read(mdev, mdev->address, MII_BMSR); - mii_write(mdev, mdev->address, MII_BMCR, BMCR_FULLDPLX | BMCR_CTST); + if (status < 0) + return status; + + status = mii_write(mdev, mdev->address, MII_BMCR, BMCR_FULLDPLX | BMCR_CTST); + if (status) + return status; timeout = 20; do { /* wait for link status to go down */ @@ -56,6 +70,8 @@ int miidev_restart_aneg(struct mii_device *mdev) break; } status = mii_read(mdev, mdev->address, MII_BMSR); + if (status < 0) + return status; } while (status & BMSR_LSTATUS); } else { /* MII100 */ @@ -63,10 +79,18 @@ int miidev_restart_aneg(struct mii_device *mdev) * Set the auto-negotiation advertisement register bits */ status = mii_read(mdev, mdev->address, MII_ADVERTISE); + if (status < 0) + return status; + status |= ADVERTISE_ALL; - mii_write(mdev, mdev->address, MII_ADVERTISE, status); - mii_write(mdev, mdev->address, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); + status = mii_write(mdev, mdev->address, MII_ADVERTISE, status); + if (status) + return status; + + status = mii_write(mdev, mdev->address, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); + if (status) + return status; } return 0; @@ -74,27 +98,22 @@ int miidev_restart_aneg(struct mii_device *mdev) int miidev_wait_aneg(struct mii_device *mdev) { - uint64_t start; int status; + uint64_t start = get_time_ns(); if (mdev->flags & MIIDEV_FORCE_LINK) return 0; - /* - * Wait for AN completion - */ - start = get_time_ns(); do { + status = mii_read(mdev, mdev->address, MII_BMSR); + if (status < 0) + return status; + if (is_timeout(start, 5 * SECOND)) { printf("%s: Autonegotiation timeout\n", mdev->cdev.name); - return -1; + return -ETIMEDOUT; } - status = mii_read(mdev, mdev->address, MII_BMSR); - if (status < 0) { - printf("%s: Autonegotiation failed. status: 0x%04x\n", mdev->cdev.name, status); - return -1; - } } while (!(status & BMSR_LSTATUS)); return 0; |