|
@@ -947,6 +947,11 @@ static void gfar_detect_errata(struct gfar_private *priv)
|
|
|
(pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
|
|
|
priv->errata |= GFAR_ERRATA_76;
|
|
|
|
|
|
+ /* MPC8313 and MPC837x all rev */
|
|
|
+ if ((pvr == 0x80850010 && mod == 0x80b0) ||
|
|
|
+ (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
|
|
|
+ priv->errata |= GFAR_ERRATA_A002;
|
|
|
+
|
|
|
if (priv->errata)
|
|
|
dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
|
|
|
priv->errata);
|
|
@@ -1570,6 +1575,29 @@ static void init_registers(struct net_device *dev)
|
|
|
gfar_write(®s->minflr, MINFLR_INIT_SETTINGS);
|
|
|
}
|
|
|
|
|
|
+static int __gfar_is_rx_idle(struct gfar_private *priv)
|
|
|
+{
|
|
|
+ u32 res;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Normaly TSEC should not hang on GRS commands, so we should
|
|
|
+ * actually wait for IEVENT_GRSC flag.
|
|
|
+ */
|
|
|
+ if (likely(!gfar_has_errata(priv, GFAR_ERRATA_A002)))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Read the eTSEC register at offset 0xD1C. If bits 7-14 are
|
|
|
+ * the same as bits 23-30, the eTSEC Rx is assumed to be idle
|
|
|
+ * and the Rx can be safely reset.
|
|
|
+ */
|
|
|
+ res = gfar_read((void __iomem *)priv->gfargrp[0].regs + 0xd1c);
|
|
|
+ res &= 0x7f807f80;
|
|
|
+ if ((res & 0xffff) == (res >> 16))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
/* Halt the receive and transmit queues */
|
|
|
static void gfar_halt_nodisable(struct net_device *dev)
|
|
@@ -1593,12 +1621,18 @@ static void gfar_halt_nodisable(struct net_device *dev)
|
|
|
tempval = gfar_read(®s->dmactrl);
|
|
|
if ((tempval & (DMACTRL_GRS | DMACTRL_GTS))
|
|
|
!= (DMACTRL_GRS | DMACTRL_GTS)) {
|
|
|
+ int ret;
|
|
|
+
|
|
|
tempval |= (DMACTRL_GRS | DMACTRL_GTS);
|
|
|
gfar_write(®s->dmactrl, tempval);
|
|
|
|
|
|
- spin_event_timeout(((gfar_read(®s->ievent) &
|
|
|
- (IEVENT_GRSC | IEVENT_GTSC)) ==
|
|
|
- (IEVENT_GRSC | IEVENT_GTSC)), -1, 0);
|
|
|
+ do {
|
|
|
+ ret = spin_event_timeout(((gfar_read(®s->ievent) &
|
|
|
+ (IEVENT_GRSC | IEVENT_GTSC)) ==
|
|
|
+ (IEVENT_GRSC | IEVENT_GTSC)), 1000000, 0);
|
|
|
+ if (!ret && !(gfar_read(®s->ievent) & IEVENT_GRSC))
|
|
|
+ ret = __gfar_is_rx_idle(priv);
|
|
|
+ } while (!ret);
|
|
|
}
|
|
|
}
|
|
|
|