diff options
| -rw-r--r-- | drivers/net/gianfar.c | 40 | ||||
| -rw-r--r-- | drivers/net/gianfar.h | 1 | 
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(®s->minflr, MINFLR_INIT_SETTINGS); | 1575 | gfar_write(®s->minflr, MINFLR_INIT_SETTINGS); | 
| 1571 | } | 1576 | } | 
| 1572 | 1577 | ||
| 1578 | static 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 */ | 
| 1575 | static void gfar_halt_nodisable(struct net_device *dev) | 1603 | static 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(®s->dmactrl); | 1621 | tempval = gfar_read(®s->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(®s->dmactrl, tempval); | 1627 | gfar_write(®s->dmactrl, tempval); | 
| 1598 | 1628 | ||
| 1599 | spin_event_timeout(((gfar_read(®s->ievent) & | 1629 | do { | 
| 1600 | (IEVENT_GRSC | IEVENT_GTSC)) == | 1630 | ret = spin_event_timeout(((gfar_read(®s->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(®s->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 { | |||
| 1028 | enum gfar_errata { | 1028 | enum 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 | 
