net/designware: make driver compatible with data cache
Up until now this driver only worked with data cache disabled. To make it work with enabled data cache following changes were required: * Flush Tx/Rx buffer descriptors their modification * Invalidate Tx/Rx buffer descriptors before reading its values * Flush cache for data passed from CPU to GMAC * Invalidate cache for data passed from GMAC to CPU 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> Cc: Shiraz Hashim <shiraz.hashim@st.com> Cc: Albert ARIBAUD <albert.u.boot@aribaud.net> Cc: Amit Virdi <amit.virdi@st.com> Cc: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
This commit is contained in:
parent
92a190aaab
commit
50b0df814b
@ -119,6 +119,11 @@ static void tx_descs_init(struct eth_device *dev)
|
||||
/* Correcting the last pointer of the chain */
|
||||
desc_p->dmamac_next = &desc_table_p[0];
|
||||
|
||||
/* Flush all Tx buffer descriptors at once */
|
||||
flush_dcache_range((unsigned int)priv->tx_mac_descrtable,
|
||||
(unsigned int)priv->tx_mac_descrtable +
|
||||
sizeof(priv->tx_mac_descrtable));
|
||||
|
||||
writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
|
||||
priv->tx_currdescnum = 0;
|
||||
}
|
||||
@ -132,6 +137,15 @@ 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];
|
||||
@ -147,6 +161,11 @@ static void rx_descs_init(struct eth_device *dev)
|
||||
/* Correcting the last pointer of the chain */
|
||||
desc_p->dmamac_next = &desc_table_p[0];
|
||||
|
||||
/* Flush all Rx buffer descriptors at once */
|
||||
flush_dcache_range((unsigned int)priv->rx_mac_descrtable,
|
||||
(unsigned int)priv->rx_mac_descrtable +
|
||||
sizeof(priv->rx_mac_descrtable));
|
||||
|
||||
writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
|
||||
priv->rx_currdescnum = 0;
|
||||
}
|
||||
@ -261,6 +280,11 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
||||
u32 desc_num = priv->tx_currdescnum;
|
||||
struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
|
||||
|
||||
/* Invalidate only "status" field for the following check */
|
||||
invalidate_dcache_range((unsigned long)&desc_p->txrx_status,
|
||||
(unsigned long)&desc_p->txrx_status +
|
||||
sizeof(desc_p->txrx_status));
|
||||
|
||||
/* Check if the descriptor is owned by CPU */
|
||||
if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
|
||||
printf("CPU not owner of tx frame\n");
|
||||
@ -269,6 +293,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
||||
|
||||
memcpy((void *)desc_p->dmamac_addr, packet, length);
|
||||
|
||||
/* Flush data to be sent */
|
||||
flush_dcache_range((unsigned long)desc_p->dmamac_addr,
|
||||
(unsigned long)desc_p->dmamac_addr + length);
|
||||
|
||||
#if defined(CONFIG_DW_ALTDESCRIPTOR)
|
||||
desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
|
||||
desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
|
||||
@ -284,6 +312,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
||||
desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
|
||||
#endif
|
||||
|
||||
/* Flush modified buffer descriptor */
|
||||
flush_dcache_range((unsigned long)desc_p,
|
||||
(unsigned long)desc_p + sizeof(struct dmamacdescr));
|
||||
|
||||
/* Test the wrap-around condition. */
|
||||
if (++desc_num >= CONFIG_TX_DESCR_NUM)
|
||||
desc_num = 0;
|
||||
@ -299,18 +331,28 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length)
|
||||
static int dw_eth_recv(struct eth_device *dev)
|
||||
{
|
||||
struct dw_eth_dev *priv = dev->priv;
|
||||
u32 desc_num = priv->rx_currdescnum;
|
||||
u32 status, desc_num = priv->rx_currdescnum;
|
||||
struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
|
||||
|
||||
u32 status = desc_p->txrx_status;
|
||||
int length = 0;
|
||||
|
||||
/* Invalidate entire buffer descriptor */
|
||||
invalidate_dcache_range((unsigned long)desc_p,
|
||||
(unsigned long)desc_p +
|
||||
sizeof(struct dmamacdescr));
|
||||
|
||||
status = desc_p->txrx_status;
|
||||
|
||||
/* Check if the owner is the CPU */
|
||||
if (!(status & DESC_RXSTS_OWNBYDMA)) {
|
||||
|
||||
length = (status & DESC_RXSTS_FRMLENMSK) >> \
|
||||
DESC_RXSTS_FRMLENSHFT;
|
||||
|
||||
/* Invalidate received data */
|
||||
invalidate_dcache_range((unsigned long)desc_p->dmamac_addr,
|
||||
(unsigned long)desc_p->dmamac_addr +
|
||||
length);
|
||||
|
||||
NetReceive(desc_p->dmamac_addr, length);
|
||||
|
||||
/*
|
||||
@ -319,6 +361,11 @@ static int dw_eth_recv(struct eth_device *dev)
|
||||
*/
|
||||
desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
|
||||
|
||||
/* Flush only status field - others weren't changed */
|
||||
flush_dcache_range((unsigned long)&desc_p->txrx_status,
|
||||
(unsigned long)&desc_p->txrx_status +
|
||||
sizeof(desc_p->txrx_status));
|
||||
|
||||
/* Test the wrap-around condition. */
|
||||
if (++desc_num >= CONFIG_RX_DESCR_NUM)
|
||||
desc_num = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user