Currently, Synopsis xgmac driver only works if DMA region is under 4GB. This change enables the DMA buffers allocations above 4GB memory regions.
Signed-off-by: Nikunj Kela <nikunj.k...@sima.ai> --- drivers/net/dwc_eth_xgmac.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/net/dwc_eth_xgmac.c b/drivers/net/dwc_eth_xgmac.c index cf8227b1b4d..03959ea95a5 100644 --- a/drivers/net/dwc_eth_xgmac.c +++ b/drivers/net/dwc_eth_xgmac.c @@ -45,6 +45,7 @@ #include <asm/gpio.h> #include <asm/io.h> #include <linux/delay.h> +#include <linux/kernel.h> #include "dwc_eth_xgmac.h" static void *xgmac_alloc_descs(struct xgmac_priv *xgmac, unsigned int num) @@ -457,7 +458,7 @@ static int xgmac_start(struct udevice *dev) int ret, i; u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; ulong last_rx_desc; - ulong desc_pad; + ulong desc_pad, address; struct xgmac_desc *tx_desc = NULL; struct xgmac_desc *rx_desc = NULL; @@ -702,8 +703,11 @@ static int xgmac_start(struct udevice *dev) for (i = 0; i < XGMAC_DESCRIPTORS_RX; i++) { rx_desc = (struct xgmac_desc *)xgmac_get_desc(xgmac, i, true); - rx_desc->des0 = (uintptr_t)(xgmac->rx_dma_buf + - (i * XGMAC_MAX_PACKET_SIZE)); + address = (uintptr_t)(xgmac->rx_dma_buf + + (i * XGMAC_MAX_PACKET_SIZE)); + + rx_desc->des0 = lower_32_bits(address); + rx_desc->des1 = upper_32_bits(address); rx_desc->des3 = XGMAC_DESC3_OWN; /* Flush the cache to the memory */ mb(); @@ -713,13 +717,17 @@ static int xgmac_start(struct udevice *dev) XGMAC_MAX_PACKET_SIZE); } - writel(0, &xgmac->dma_regs->ch0_txdesc_list_haddress); - writel((ulong)xgmac_get_desc(xgmac, 0, false), + address = (ulong)xgmac_get_desc(xgmac, 0, false); + writel(upper_32_bits(address), + &xgmac->dma_regs->ch0_txdesc_list_haddress); + writel(lower_32_bits(address), &xgmac->dma_regs->ch0_txdesc_list_address); writel(XGMAC_DESCRIPTORS_TX - 1, &xgmac->dma_regs->ch0_txdesc_ring_length); - writel(0, &xgmac->dma_regs->ch0_rxdesc_list_haddress); - writel((ulong)xgmac_get_desc(xgmac, 0, true), + address = (ulong)xgmac_get_desc(xgmac, 0, true); + writel(upper_32_bits(address), + &xgmac->dma_regs->ch0_rxdesc_list_haddress); + writel(lower_32_bits(address), &xgmac->dma_regs->ch0_rxdesc_list_address); writel(XGMAC_DESCRIPTORS_RX - 1, &xgmac->dma_regs->ch0_rxdesc_ring_length); @@ -844,8 +852,8 @@ static int xgmac_send(struct udevice *dev, void *packet, int length) xgmac->tx_desc_idx++; xgmac->tx_desc_idx %= XGMAC_DESCRIPTORS_TX; - tx_desc->des0 = (ulong)xgmac->tx_dma_buf; - tx_desc->des1 = 0; + tx_desc->des0 = lower_32_bits((ulong)xgmac->tx_dma_buf); + tx_desc->des1 = upper_32_bits((ulong)xgmac->tx_dma_buf); tx_desc->des2 = length; /* * Make sure that if HW sees the _OWN write below, it will see all the @@ -901,6 +909,7 @@ static int xgmac_free_pkt(struct udevice *dev, uchar *packet, int length) u32 idx, idx_mask = xgmac->desc_per_cacheline - 1; uchar *packet_expected; struct xgmac_desc *rx_desc; + ulong address; debug("%s(packet=%p, length=%d)\n", __func__, packet, length); @@ -920,13 +929,15 @@ static int xgmac_free_pkt(struct udevice *dev, uchar *packet, int length) idx++) { rx_desc = xgmac_get_desc(xgmac, idx, true); rx_desc->des0 = 0; + rx_desc->des1 = 0; /* Flush the cache to the memory */ mb(); xgmac->config->ops->xgmac_flush_desc(rx_desc); xgmac->config->ops->xgmac_inval_buffer(packet, length); - rx_desc->des0 = (u32)(ulong)(xgmac->rx_dma_buf + - (idx * XGMAC_MAX_PACKET_SIZE)); - rx_desc->des1 = 0; + address = (ulong)(xgmac->rx_dma_buf + + (idx * XGMAC_MAX_PACKET_SIZE)); + rx_desc->des0 = lower_32_bits(address); + rx_desc->des1 = upper_32_bits(address); rx_desc->des2 = 0; /* * Make sure that if HW sees the _OWN write below, -- 2.34.1