
Up until now this driver only worked with data cache disabled. To make it work with enabled data cache following changes were required:
* Implement all accesses to shared structures between CPU and GMAC via uncached reads/writes ("readl"/"writel"). * Flush cache for data passed from CPU to GMAC * Invalidate cache for data passed from GMAC to CPU
I tried to implement items above keeping as much code unchanged as possible. So logic of operation is kept as it is.
Signed-off-by: Alexey Brodkin abrodkin@synopsys.com
Cc: Joe Hershberger joe.hershberger@ni.com Cc: Vipin Kumar vipin.kumar@st.com Cc: Stefan Roese sr@denx.de Cc: Mischa Jonker mjonker@synopsys.com --- drivers/net/designware.c | 91 ++++++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 33 deletions(-)
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 22155b4..04ae02c 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -30,26 +30,30 @@ static void tx_descs_init(struct eth_device *dev)
for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) { desc_p = &desc_table_p[idx]; - desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE]; - desc_p->dmamac_next = &desc_table_p[idx + 1]; + writel(&txbuffs[idx * CONFIG_ETH_BUFSIZE], + &desc_p->dmamac_addr); + writel(&desc_table_p[idx + 1], &desc_p->dmamac_next);
#if defined(CONFIG_DW_ALTDESCRIPTOR) - desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST | - DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \ - DESC_TXSTS_TXCHECKINSCTRL | \ - DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS); - - desc_p->txrx_status |= DESC_TXSTS_TXCHAIN; - desc_p->dmamac_cntl = 0; - desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA); + writel(readl(&desc_p->txrx_status) & ~(DESC_TXSTS_TXINT | + DESC_TXSTS_TXLAST | DESC_TXSTS_TXFIRST | + DESC_TXSTS_TXCRCDIS | DESC_TXSTS_TXCHECKINSCTRL | + DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS), + &desc_p->txrx_status); + + writel(readl(&desc_p->txrx_status) | DESC_TXSTS_TXCHAIN, + &desc_p->txrx_status); + writel(0, &desc_p->dmamac_cntl); + writel(readl(&desc_p->txrx_status) & ~(DESC_TXSTS_MSK | + DESC_TXSTS_OWNBYDMA), &desc_p->txrx_status); #else - desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN; - desc_p->txrx_status = 0; + writel(DESC_TXCTRL_TXCHAIN, &desc_p->dmamac_cntl); + writel(0, &desc_p->txrx_status); #endif }
/* Correcting the last pointer of the chain */ - desc_p->dmamac_next = &desc_table_p[0]; + writel(&desc_table_p[0], &desc_p->dmamac_next);
writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr); } @@ -63,20 +67,30 @@ static void rx_descs_init(struct eth_device *dev) struct dmamacdescr *desc_p; u32 idx;
+ /* Before passing buffers to GMAC we need to make sure zeros + * written there right after "priv" structure allocation were + * flushed into RAM. + * Otherwise there's a chance to get some of them flushed in RAM when + * GMAC is already pushing data to RAM via DMA. This way incoming from + * GMAC data will be corrupted. */ + flush_dcache_range((unsigned int)rxbuffs, (unsigned int)rxbuffs + + RX_TOTAL_BUFSIZE); + for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { desc_p = &desc_table_p[idx]; - desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE]; - desc_p->dmamac_next = &desc_table_p[idx + 1];
- desc_p->dmamac_cntl = - (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \ - DESC_RXCTRL_RXCHAIN; + writel(&rxbuffs[idx * CONFIG_ETH_BUFSIZE], + &desc_p->dmamac_addr); + writel(&desc_table_p[idx + 1], &desc_p->dmamac_next); + + writel((MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | + DESC_RXCTRL_RXCHAIN, &desc_p->dmamac_cntl);
- desc_p->txrx_status = DESC_RXSTS_OWNBYDMA; + writel(DESC_RXSTS_OWNBYDMA, &desc_p->txrx_status); }
/* Correcting the last pointer of the chain */ - desc_p->dmamac_next = &desc_table_p[0]; + writel(&desc_table_p[0], &desc_p->dmamac_next);
writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr); } @@ -198,26 +212,32 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length) struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
/* Check if the descriptor is owned by CPU */ - if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) { + if (readl(&desc_p->txrx_status) & DESC_TXSTS_OWNBYDMA) { printf("CPU not owner of tx frame\n"); return -1; }
memcpy((void *)desc_p->dmamac_addr, packet, length);
-#if defined(CONFIG_DW_ALTDESCRIPTOR) - desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST; - desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \ - DESC_TXCTRL_SIZE1MASK; + flush_dcache_range((unsigned long)desc_p->dmamac_addr, + (unsigned long)desc_p->dmamac_addr + length);
- desc_p->txrx_status &= ~(DESC_TXSTS_MSK); - desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA; +#if defined(CONFIG_DW_ALTDESCRIPTOR) + writel(readl(&desc_p->txrx_status) | DESC_TXSTS_TXFIRST | + DESC_TXSTS_TXLAST, &desc_p->txrx_status); + writel(readl(&desc_p->dmamac_cntl) | (length << DESC_TXCTRL_SIZE1SHFT) & + DESC_TXCTRL_SIZE1MASK, &desc_p->dmamac_cntl); + + writel(readl(&desc_p->txrx_status) & ~DESC_TXSTS_MSK, + &desc_p->txrx_status); + writel(readl(&desc_p->txrx_status) | DESC_TXSTS_OWNBYDMA, + &desc_p->txrx_status); #else - desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \ - DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \ - DESC_TXCTRL_TXFIRST; + writel(readl(&desc_p->dmamac_cntl) | + ((length << DESC_TXCTRL_SIZE1SHFT) & DESC_TXCTRL_SIZE1MASK) | + DESC_TXCTRL_TXLAST | DESC_TXCTRL_TXFIRST, &desc_p->dmamac_cntl);
- desc_p->txrx_status = DESC_TXSTS_OWNBYDMA; + writel(DESC_TXSTS_OWNBYDMA, &desc_p->txrx_status); #endif
/* Test the wrap-around condition. */ @@ -238,7 +258,7 @@ static int dw_eth_recv(struct eth_device *dev) u32 desc_num = priv->rx_currdescnum; struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
- u32 status = desc_p->txrx_status; + u32 status = readl(&desc_p->txrx_status); int length = 0;
/* Check if the owner is the CPU */ @@ -247,13 +267,18 @@ static int dw_eth_recv(struct eth_device *dev) length = (status & DESC_RXSTS_FRMLENMSK) >> \ DESC_RXSTS_FRMLENSHFT;
+ invalidate_dcache_range((unsigned long)desc_p->dmamac_addr, + (unsigned long)desc_p->dmamac_addr + + length); + NetReceive(desc_p->dmamac_addr, length);
/* * Make the current descriptor valid again and go to * the next one */ - desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; + writel(readl(&desc_p->txrx_status) | DESC_RXSTS_OWNBYDMA, + &desc_p->txrx_status);
/* Test the wrap-around condition. */ if (++desc_num >= CONFIG_RX_DESCR_NUM)