aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/gianfar.c40
-rw-r--r--drivers/net/gianfar.h1
2 files changed, 38 insertions, 3 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index c2fabc1853ad..fccb7a371cc8 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -947,6 +947,11 @@ static void gfar_detect_errata(struct gfar_private *priv)
947 (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0)) 947 (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
948 priv->errata |= GFAR_ERRATA_76; 948 priv->errata |= GFAR_ERRATA_76;
949 949
950 /* MPC8313 and MPC837x all rev */
951 if ((pvr == 0x80850010 && mod == 0x80b0) ||
952 (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
953 priv->errata |= GFAR_ERRATA_A002;
954
950 if (priv->errata) 955 if (priv->errata)
951 dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", 956 dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
952 priv->errata); 957 priv->errata);
@@ -1570,6 +1575,29 @@ static void init_registers(struct net_device *dev)
1570 gfar_write(&regs->minflr, MINFLR_INIT_SETTINGS); 1575 gfar_write(&regs->minflr, MINFLR_INIT_SETTINGS);
1571} 1576}
1572 1577
1578static int __gfar_is_rx_idle(struct gfar_private *priv)
1579{
1580 u32 res;
1581
1582 /*
1583 * Normaly TSEC should not hang on GRS commands, so we should
1584 * actually wait for IEVENT_GRSC flag.
1585 */
1586 if (likely(!gfar_has_errata(priv, GFAR_ERRATA_A002)))
1587 return 0;
1588
1589 /*
1590 * Read the eTSEC register at offset 0xD1C. If bits 7-14 are
1591 * the same as bits 23-30, the eTSEC Rx is assumed to be idle
1592 * and the Rx can be safely reset.
1593 */
1594 res = gfar_read((void __iomem *)priv->gfargrp[0].regs + 0xd1c);
1595 res &= 0x7f807f80;
1596 if ((res & 0xffff) == (res >> 16))
1597 return 1;
1598
1599 return 0;
1600}
1573 1601
1574/* Halt the receive and transmit queues */ 1602/* Halt the receive and transmit queues */
1575static void gfar_halt_nodisable(struct net_device *dev) 1603static void gfar_halt_nodisable(struct net_device *dev)
@@ -1593,12 +1621,18 @@ static void gfar_halt_nodisable(struct net_device *dev)
1593 tempval = gfar_read(&regs->dmactrl); 1621 tempval = gfar_read(&regs->dmactrl);
1594 if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) 1622 if ((tempval & (DMACTRL_GRS | DMACTRL_GTS))
1595 != (DMACTRL_GRS | DMACTRL_GTS)) { 1623 != (DMACTRL_GRS | DMACTRL_GTS)) {
1624 int ret;
1625
1596 tempval |= (DMACTRL_GRS | DMACTRL_GTS); 1626 tempval |= (DMACTRL_GRS | DMACTRL_GTS);
1597 gfar_write(&regs->dmactrl, tempval); 1627 gfar_write(&regs->dmactrl, tempval);
1598 1628
1599 spin_event_timeout(((gfar_read(&regs->ievent) & 1629 do {
1600 (IEVENT_GRSC | IEVENT_GTSC)) == 1630 ret = spin_event_timeout(((gfar_read(&regs->ievent) &
1601 (IEVENT_GRSC | IEVENT_GTSC)), -1, 0); 1631 (IEVENT_GRSC | IEVENT_GTSC)) ==
1632 (IEVENT_GRSC | IEVENT_GTSC)), 1000000, 0);
1633 if (!ret && !(gfar_read(&regs->ievent) & IEVENT_GRSC))
1634 ret = __gfar_is_rx_idle(priv);
1635 } while (!ret);
1602 } 1636 }
1603} 1637}
1604 1638
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index c414374f407f..710810e2adb4 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -1028,6 +1028,7 @@ struct gfar_priv_grp {
1028enum gfar_errata { 1028enum gfar_errata {
1029 GFAR_ERRATA_74 = 0x01, 1029 GFAR_ERRATA_74 = 0x01,
1030 GFAR_ERRATA_76 = 0x02, 1030 GFAR_ERRATA_76 = 0x02,
1031 GFAR_ERRATA_A002 = 0x04,
1031}; 1032};
1032 1033
1033/* Struct stolen almost completely (and shamelessly) from the FCC enet source 1034/* Struct stolen almost completely (and shamelessly) from the FCC enet source