DaVinci EMAC is present on TI AM35xx SoCs (ARMv7) which run with D-Cache
enabled by default. So we have to take care and flush/invalidate the
cache before/after the DMA operations.

Please note that the receive buffer alignment to 32 byte boundary comes
from the old driver version I don't know if it is really needed or
alignment to cache line size is enough.

!!!NOTE!!! This actually breaks builds for all DaVinci boards that use
this driver (as there is no {invalidate,flush}_dcache_range for
ARM926EJS).

Signed-off-by: Ilya Yanok <ya...@emcraft.com>
---
 drivers/net/davinci_emac.c |   41 +++++++++++++++++++++++++++++++++++++++--
 drivers/net/davinci_emac.h |    5 +++--
 2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 0e9fbc2..ed6f89e 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -41,6 +41,7 @@
 #include <net.h>
 #include <miiphy.h>
 #include <malloc.h>
+#include <linux/compiler.h>
 #include <asm/arch/emac_defs.h>
 #include <asm/io.h>
 #include "davinci_emac.h"
@@ -100,7 +101,8 @@ static volatile emac_desc   *emac_rx_active_tail = 0;
 static int                     emac_rx_queue_active = 0;
 
 /* Receive packet buffers */
-static unsigned char           emac_rx_buffers[EMAC_MAX_RX_BUFFERS * 
(EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
+static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * EMAC_RXBUF_SIZE]
+                               __aligned(CONFIG_SYS_CACHELINE_SIZE);
 
 #define MAX_PHY                3
 
@@ -112,6 +114,26 @@ static u_int8_t    num_phy;
 
 phy_t                          phy[MAX_PHY];
 
+static inline void davinci_flush_rx_descs(void)
+{
+       /* flush the whole RX descs area */
+       flush_dcache_range(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE,
+                       EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
+}
+
+static inline void davinci_invalidate_rx_descs(void)
+{
+       /* invalidate the whole RX descs area */
+       invalidate_dcache_range(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE,
+                       EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
+}
+
+static inline void davinci_flush_desc(emac_desc *desc)
+{
+       flush_dcache_range((unsigned long)desc,
+                       (unsigned long)desc + sizeof(*desc));
+}
+
 static int davinci_eth_set_mac_addr(struct eth_device *dev)
 {
        unsigned long           mac_hi;
@@ -457,7 +479,7 @@ static int davinci_eth_open(struct eth_device *dev, bd_t 
*bis)
        emac_rx_active_head = emac_rx_desc;
        for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
                rx_desc->next = BD_TO_HW((u_int32_t)(rx_desc + 1));
-               rx_desc->buffer = &emac_rx_buffers[cnt * 
(EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
+               rx_desc->buffer = &emac_rx_buffers[cnt * EMAC_RXBUF_SIZE];
                rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
                rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
                rx_desc++;
@@ -469,6 +491,8 @@ static int davinci_eth_open(struct eth_device *dev, bd_t 
*bis)
        emac_rx_active_tail = rx_desc;
        emac_rx_queue_active = 1;
 
+       davinci_flush_rx_descs();
+
        /* Enable TX/RX */
        writel(EMAC_MAX_ETHERNET_PKT_SIZE, &adap_emac->RXMAXLEN);
        writel(0, &adap_emac->RXBUFFEROFFSET);
@@ -626,6 +650,11 @@ static int davinci_eth_send_packet (struct eth_device *dev,
                                      EMAC_CPPI_SOP_BIT |
                                      EMAC_CPPI_OWNERSHIP_BIT |
                                      EMAC_CPPI_EOP_BIT);
+
+       flush_dcache_range((unsigned long)packet,
+                       (unsigned long)packet + length);
+       davinci_flush_desc(emac_tx_desc);
+
        /* Send the packet */
        writel(BD_TO_HW((unsigned long)emac_tx_desc), &adap_emac->TX0HDP);
 
@@ -658,6 +687,8 @@ static int davinci_eth_rcv_packet (struct eth_device *dev)
        volatile emac_desc *tail_desc;
        int status, ret = -1;
 
+       davinci_invalidate_rx_descs();
+
        rx_curr_desc = emac_rx_active_head;
        status = rx_curr_desc->pkt_flag_len;
        if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
@@ -665,6 +696,9 @@ static int davinci_eth_rcv_packet (struct eth_device *dev)
                        /* Error in packet - discard it and requeue desc */
                        printf ("WARN: emac_rcv_pkt: Error in packet\n");
                } else {
+                       unsigned long tmp = (unsigned long)rx_curr_desc->buffer;
+
+                       invalidate_dcache_range(tmp, tmp + EMAC_RXBUF_SIZE);
                        NetReceive (rx_curr_desc->buffer,
                                    (rx_curr_desc->buff_off_len & 0xffff));
                        ret = rx_curr_desc->buff_off_len & 0xffff;
@@ -690,6 +724,7 @@ static int davinci_eth_rcv_packet (struct eth_device *dev)
                rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
                rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
                rx_curr_desc->next = 0;
+               davinci_flush_desc(rx_curr_desc);
 
                if (emac_rx_active_head == 0) {
                        printf ("INFO: emac_rcv_pkt: active queue head = 0\n");
@@ -707,11 +742,13 @@ static int davinci_eth_rcv_packet (struct eth_device *dev)
                        tail_desc->next = BD_TO_HW((ulong) curr_desc);
                        status = tail_desc->pkt_flag_len;
                        if (status & EMAC_CPPI_EOQ_BIT) {
+                               davinci_flush_desc(tail_desc);
                                writel(BD_TO_HW((ulong)curr_desc),
                                       &adap_emac->RX0HDP);
                                status &= ~EMAC_CPPI_EOQ_BIT;
                                tail_desc->pkt_flag_len = status;
                        }
+                       davinci_flush_desc(tail_desc);
                }
                return (ret);
        }
diff --git a/drivers/net/davinci_emac.h b/drivers/net/davinci_emac.h
index a42c93a..4e453e8 100644
--- a/drivers/net/davinci_emac.h
+++ b/drivers/net/davinci_emac.h
@@ -24,8 +24,9 @@
 /* Ethernet Min/Max packet size */
 #define EMAC_MIN_ETHERNET_PKT_SIZE     60
 #define EMAC_MAX_ETHERNET_PKT_SIZE     1518
-/* 1518 + 18 = 1536 (packet aligned on 32 byte boundry) */
-#define EMAC_PKT_ALIGN                 18
+/* Buffer size (should be aligned on 32 byte and cache line) */
+#define EMAC_RXBUF_SIZE        ALIGN(ALIGN(EMAC_MAX_ETHERNET_PKT_SIZE, 32),\
+                               CONFIG_SYS_CACHELINE_SIZE)
 
 /* Number of RX packet buffers
  * NOTE: Only 1 buffer supported as of now
-- 
1.7.6.4

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

Reply via email to