|
168 | 168 |
|
169 | 169 | #define MPFS_TXTIMEOUT (60 * CLK_TCK)
|
170 | 170 |
|
| 171 | +/* RX timeout: Workaround for LAN8742A rev A and B silicon errata |
| 172 | + * "Cable diagnostics incorrectly returns Open cable connection for |
| 173 | + * terminated cable" |
| 174 | + */ |
| 175 | + |
| 176 | +#if CONFIG_MPFS_PHY_RX_TIMEOUT_WA != 0 |
| 177 | +#define MPFS_RXTIMEOUT (CONFIG_MPFS_PHY_RX_TIMEOUT_WA * CLK_TCK) |
| 178 | +#endif |
| 179 | + |
171 | 180 | /* PHY reset tim in loop counts */
|
172 | 181 |
|
173 | 182 | #define PHY_RESET_WAIT_COUNT (10)
|
@@ -265,6 +274,9 @@ struct mpfs_ethmac_s
|
265 | 274 | uint8_t phyaddr; /* PHY address */
|
266 | 275 | #endif
|
267 | 276 | struct wdog_s txtimeout; /* TX timeout timer */
|
| 277 | +#ifdef MPFS_RXTIMEOUT |
| 278 | + struct wdog_s rxtimeout; /* RX timeout timer */ |
| 279 | +#endif |
268 | 280 | struct work_s irqwork; /* For deferring interrupt work to the work queue */
|
269 | 281 | struct work_s pollwork; /* For deferring poll work to the work queue */
|
270 | 282 | struct work_s timeoutwork; /* For managing timeouts */
|
@@ -387,6 +399,7 @@ static int mpfs_ethconfig(struct mpfs_ethmac_s *priv);
|
387 | 399 | static void mpfs_ethreset(struct mpfs_ethmac_s *priv);
|
388 | 400 |
|
389 | 401 | static void mpfs_interrupt_work(void *arg);
|
| 402 | +static void mpfs_txtimeout_expiry(wdparm_t arg); |
390 | 403 |
|
391 | 404 | /****************************************************************************
|
392 | 405 | * Private Functions
|
@@ -468,6 +481,16 @@ static int mpfs_interrupt_0(int irq, void *context, void *arg)
|
468 | 481 | wd_cancel(&priv->txtimeout);
|
469 | 482 | }
|
470 | 483 |
|
| 484 | +#ifdef MPFS_RXTIMEOUT |
| 485 | + if ((isr & INT_RX) != 0) |
| 486 | + { |
| 487 | + /* If a RX transfer just completed, restart the timeout */ |
| 488 | + |
| 489 | + wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT, |
| 490 | + mpfs_txtimeout_expiry, (wdparm_t)priv); |
| 491 | + } |
| 492 | +#endif |
| 493 | + |
471 | 494 | /* Schedule to perform the interrupt processing on the worker thread. */
|
472 | 495 |
|
473 | 496 | work_queue(ETHWORK, &priv->irqwork, mpfs_interrupt_work, priv, 0);
|
@@ -1556,6 +1579,15 @@ static int mpfs_ifup(struct net_driver_s *dev)
|
1556 | 1579 | up_enable_irq(priv->mac_q_int[2]);
|
1557 | 1580 | up_enable_irq(priv->mac_q_int[3]);
|
1558 | 1581 |
|
| 1582 | +#ifdef MPFS_RXTIMEOUT |
| 1583 | + /* Set up the RX timeout. If we don't receive anything in time, try |
| 1584 | + * to re-initialize |
| 1585 | + */ |
| 1586 | + |
| 1587 | + wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT, |
| 1588 | + mpfs_txtimeout_expiry, (wdparm_t)priv); |
| 1589 | +#endif |
| 1590 | + |
1559 | 1591 | return OK;
|
1560 | 1592 | }
|
1561 | 1593 |
|
@@ -1599,6 +1631,12 @@ static int mpfs_ifdown(struct net_driver_s *dev)
|
1599 | 1631 |
|
1600 | 1632 | wd_cancel(&priv->txtimeout);
|
1601 | 1633 |
|
| 1634 | +#ifdef MPFS_RXTIMEOUT |
| 1635 | + /* Cancel the RX timeout timers */ |
| 1636 | + |
| 1637 | + wd_cancel(&priv->rxtimeout); |
| 1638 | +#endif |
| 1639 | + |
1602 | 1640 | /* Put the MAC in its reset, non-operational state. This should be
|
1603 | 1641 | * a known configuration that will guarantee the mpfs_ifup() always
|
1604 | 1642 | * successfully brings the interface back up.
|
|
0 commit comments