diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/fec.c | 55 |
1 files changed, 31 insertions, 24 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index d0e2e690b66e..c49e64e8abcc 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -119,10 +119,10 @@ #define FEC_ENET_TS_TIMER ((uint)0x00008000) #if defined(CONFIG_FEC_1588) && defined(CONFIG_ARCH_MX28) -#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | \ +#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | \ FEC_ENET_TS_AVAIL | FEC_ENET_TS_TIMER) #else -#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII) +#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF) #endif /* The FEC stores dest/src/type, data, and checksum for receive packets. @@ -195,7 +195,6 @@ struct fec_enet_private { int index; int link; int full_duplex; - struct completion mdio_done; struct fec_ptp_private *ptp_priv; uint ptimer_present; @@ -223,7 +222,7 @@ static void fec_stop(struct net_device *dev); #define FEC_MMFR_TA (2 << 16) #define FEC_MMFR_DATA(v) (v & 0xffff) -#define FEC_MII_TIMEOUT 1000 +#define FEC_MII_TIMEOUT 10000 /* Transmitter timeout */ #define TX_TIMEOUT (2 * HZ) @@ -390,10 +389,6 @@ fec_enet_interrupt(int irq, void * dev_id) fpp->prtc++; } - if (int_events & FEC_ENET_MII) { - ret = IRQ_HANDLED; - complete(&fep->mdio_done); - } } while (int_events); return ret; @@ -710,13 +705,18 @@ spin_unlock: phy_print_status(phy_dev); } +/* + * NOTE: a MII transaction is during around 25 us, so polling it... + */ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct fec_enet_private *fep = bus->priv; - unsigned long time_left; + int timeout = FEC_MII_TIMEOUT; fep->mii_timeout = 0; - init_completion(&fep->mdio_done); + + /* clear MII end of transfer bit*/ + writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); /* start a read op */ writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | @@ -724,12 +724,13 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); /* wait for end of transfer */ - time_left = wait_for_completion_timeout(&fep->mdio_done, - usecs_to_jiffies(FEC_MII_TIMEOUT)); - if (time_left == 0) { - fep->mii_timeout = 1; - printk(KERN_ERR "FEC: MDIO read timeout\n"); - return -ETIMEDOUT; + while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { + cpu_relax(); + if (timeout-- < 0) { + fep->mii_timeout = 1; + printk(KERN_ERR "FEC: MDIO read timeout\n"); + return -ETIMEDOUT; + } } /* return value */ return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); @@ -739,10 +740,12 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct fec_enet_private *fep = bus->priv; - unsigned long time_left; + int timeout = FEC_MII_TIMEOUT; fep->mii_timeout = 0; - init_completion(&fep->mdio_done); + + /* clear MII end of transfer bit*/ + writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); /* start a write op */ writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | @@ -751,12 +754,13 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, fep->hwp + FEC_MII_DATA); /* wait for end of transfer */ - time_left = wait_for_completion_timeout(&fep->mdio_done, - usecs_to_jiffies(FEC_MII_TIMEOUT)); - if (time_left == 0) { - fep->mii_timeout = 1; - printk(KERN_ERR "FEC: MDIO write timeout\n"); - return -ETIMEDOUT; + while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) { + cpu_relax(); + if (timeout-- < 0) { + fep->mii_timeout = 1; + printk(KERN_ERR "FEC: MDIO write timeout\n"); + return -ETIMEDOUT; + } } return 0; @@ -1409,6 +1413,9 @@ fec_stop(struct net_device *dev) writel(1, fep->hwp + FEC_ECNTRL); udelay(10); + /* Clear outstanding MII command interrupts. */ + writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); + #ifdef CONFIG_ARCH_MXS /* Check MII or RMII */ if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) |