summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/fec.c55
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)