Signed-off-by: Cédric Le Goater <c...@kaod.org>
Reviewed-by: Joel Stanley <j...@jms.id.au>
---

 Changes since v3 :

 - introduced a ftgmac100_wait_for_txdone() function similar to the
   wait_for_bit_*() macros.

 drivers/net/ftgmac100.c | 44 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index bf8600814690..9adfe109ebc2 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ftgmac100.c
@@ -14,6 +14,7 @@
 #include <dm.h>
 #include <miiphy.h>
 #include <net.h>
+#include <wait_bit.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 
@@ -28,6 +29,9 @@
 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
 #define PKTBUFSTX      4       /* must be power of 2 */
 
+/* Timeout for transmit */
+#define FTGMAC100_TX_TIMEOUT_MS                1000
+
 /* Timeout for a mdio read/write operation */
 #define FTGMAC100_MDIO_TIMEOUT_USEC    10000
 
@@ -401,6 +405,41 @@ static int ftgmac100_recv(struct udevice *dev, int flags, 
uchar **packetp)
        return rxlen;
 }
 
+/*
+ * The wait_for_bit_*() macros require a register value. This define a
+ * similar routine which loops on the in-memory transmit descriptor to
+ * wait for the MAC to clear the DMA_OWN bit.
+ */
+static int ftgmac100_wait_for_txdone(struct ftgmac100_txdes *txdes,
+                                    const unsigned int timeout_ms,
+                                    const bool breakable)
+{
+       ulong des_start = (ulong)txdes;
+       ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
+       ulong start = get_timer(0);
+
+       while (1) {
+               invalidate_dcache_range(des_start, des_end);
+
+               if (!(txdes->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN))
+                       return 0;
+
+               if (get_timer(start) > timeout_ms)
+                       break;
+
+               if (breakable && ctrlc()) {
+                       puts("Abort\n");
+                       return -EINTR;
+               }
+
+               udelay(1);
+               WATCHDOG_RESET();
+       }
+
+       dev_err(dev, "transmit timeout\n");
+       return -ETIMEDOUT;
+}
+
 /*
  * Send a data block via Ethernet
  */
@@ -414,6 +453,7 @@ static int ftgmac100_send(struct udevice *dev, void 
*packet, int length)
                roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
        ulong data_start;
        ulong data_end;
+       int rc;
 
        invalidate_dcache_range(des_start, des_end);
 
@@ -446,6 +486,10 @@ static int ftgmac100_send(struct udevice *dev, void 
*packet, int length)
        /* Start transmit */
        writel(1, &ftgmac100->txpd);
 
+       rc = ftgmac100_wait_for_txdone(curr_des, FTGMAC100_TX_TIMEOUT_MS, true);
+       if (rc)
+               return rc;
+
        debug("%s(): packet sent\n", __func__);
 
        /* Move to next descriptor */
-- 
2.17.2

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to