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.
Signed-off-by: Ilya Yanok <ya...@emcraft.com> --- drivers/net/davinci_emac.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 222a0d0..b787213 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -96,6 +96,40 @@ static volatile u_int8_t active_phy_addr = 0xff; phy_t phy; +#ifdef DAVINCI_EMAC_DCACHE +static inline void davinci_flush(void *addr, int size) +{ + flush_dcache_range((unsigned long)addr, + (unsigned long)addr + size); +} + +static inline void davinci_invalidate(void *addr, int size) +{ + invalidate_dcache_range((unsigned long)addr, + (unsigned long)addr + size); +} +#else +#define davinci_flush(addr, size) do {} while (0) +#define davinci_invalidate(addr, size) do {} while (0) +#endif + +static inline void davinci_flush_rx_descs(void) +{ + davinci_flush((void *)emac_rx_desc, EMAC_MAX_RX_BUFFERS * + sizeof(emac_desc)); +} + +static inline void davinci_invalidate_rx_descs(void) +{ + davinci_invalidate((void *)emac_rx_desc, EMAC_MAX_RX_BUFFERS * + sizeof(emac_desc)); +} + +static inline void davinci_flush_desc(emac_desc *desc) +{ + davinci_flush((void *)desc, sizeof(*desc)); +} + static int davinci_eth_set_mac_addr(struct eth_device *dev) { unsigned long mac_hi; @@ -412,6 +446,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); @@ -568,6 +604,10 @@ static int davinci_eth_send_packet (struct eth_device *dev, EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | EMAC_CPPI_EOP_BIT); + + davinci_flush((void *)packet, length); + davinci_flush_desc(emac_tx_desc); + /* Send the packet */ writel(BD_TO_HW((unsigned long)emac_tx_desc), &adap_emac->TX0HDP); @@ -600,6 +640,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)) { @@ -607,6 +649,8 @@ 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 { + davinci_invalidate(rx_curr_desc->buffer, + rx_curr_desc->buff_off_len & 0xffff); NetReceive (rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff)); ret = rx_curr_desc->buff_off_len & 0xffff; @@ -632,6 +676,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"); @@ -649,11 +694,13 @@ static int davinci_eth_rcv_packet (struct eth_device *dev) tail_desc->next = BD_TO_HW((unsigned int) curr_desc); status = tail_desc->pkt_flag_len; if (status & EMAC_CPPI_EOQ_BIT) { + davinci_flush_desc(tail_desc); writel(BD_TO_HW((unsigned long)curr_desc), &adap_emac->RX0HDP); status &= ~EMAC_CPPI_EOQ_BIT; tail_desc->pkt_flag_len = status; } + davinci_flush_desc(tail_desc); } return (ret); } -- 1.7.6.2 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot