net: ftgmac100: Add Aspeed AST2700 support
Add support of Aspeed AST2700 SoC. AST2700 is based on ARM64 so modify
the DMA address related code to fit both ARM and ARM64. Besides, the
RMII/RGMII mode control register is moved from SCU500 to MAC50 so
initialize the register in ftgmac100_start correspondingly.
Signed-off-by: Jacky Chou <jacky_chou@aspeedtech.com>
Acked-by: Leo Yu-Chi Liang <ycliang@andestech.com>
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index 9d64125..f5ea2e7 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ftgmac100.c
@@ -26,6 +26,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/printk.h>
+#include <linux/bitfield.h>
#include "ftgmac100.h"
@@ -57,6 +58,15 @@
enum ftgmac100_model {
FTGMAC100_MODEL_FARADAY,
FTGMAC100_MODEL_ASPEED,
+ FTGMAC100_MODEL_ASPEED_AST2700,
+};
+
+union ftgmac100_dma_addr {
+ dma_addr_t addr;
+ struct {
+ u32 lo;
+ u32 hi;
+ };
};
/**
@@ -96,6 +106,8 @@
/* End of RX/TX ring buffer bits. Depend on model */
u32 rxdes0_edorr_mask;
u32 txdes0_edotr_mask;
+
+ bool is_ast2700;
};
/*
@@ -320,6 +332,7 @@
struct eth_pdata *plat = dev_get_plat(dev);
struct ftgmac100_data *priv = dev_get_priv(dev);
struct ftgmac100 *ftgmac100 = priv->iobase;
+ union ftgmac100_dma_addr dma_addr = {.hi = 0, .lo = 0};
struct phy_device *phydev = priv->phydev;
unsigned int maccr, dblac, desc_size;
ulong start, end;
@@ -341,6 +354,7 @@
priv->rx_index = 0;
for (i = 0; i < PKTBUFSTX; i++) {
+ priv->txdes[i].txdes2 = 0;
priv->txdes[i].txdes3 = 0;
priv->txdes[i].txdes0 = 0;
}
@@ -351,7 +365,14 @@
flush_dcache_range(start, end);
for (i = 0; i < PKTBUFSRX; i++) {
- priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
+ unsigned int ip_align = 0;
+
+ dma_addr.addr = (dma_addr_t)net_rx_packets[i];
+ priv->rxdes[i].rxdes2 = FIELD_PREP(FTGMAC100_RXDES2_RXBUF_BADR_HI, dma_addr.hi);
+ /* For IP alignment */
+ if ((dma_addr.lo & (PKTALIGN - 1)) == 0)
+ ip_align = 2;
+ priv->rxdes[i].rxdes3 = dma_addr.lo + ip_align;
priv->rxdes[i].rxdes0 = 0;
}
priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
@@ -361,10 +382,14 @@
flush_dcache_range(start, end);
/* transmit ring */
- writel((u32)priv->txdes, &ftgmac100->txr_badr);
+ dma_addr.addr = (dma_addr_t)priv->txdes;
+ writel(dma_addr.lo, &ftgmac100->txr_badr);
+ writel(dma_addr.hi, &ftgmac100->txr_badr_hi);
/* receive ring */
- writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
+ dma_addr.addr = (dma_addr_t)priv->rxdes;
+ writel(dma_addr.lo, &ftgmac100->rxr_badr);
+ writel(dma_addr.hi, &ftgmac100->rxr_badr_hi);
/* Configure TX/RX decsriptor size
* This size is calculated based on cache line.
@@ -393,6 +418,10 @@
FTGMAC100_MACCR_RX_RUNT |
FTGMAC100_MACCR_RX_BROADPKT;
+ if (priv->is_ast2700 && (priv->phydev->interface == PHY_INTERFACE_MODE_RMII ||
+ priv->phydev->interface == PHY_INTERFACE_MODE_NCSI))
+ maccr |= FTGMAC100_MACCR_RMII_ENABLE;
+
writel(maccr, &ftgmac100->maccr);
ret = phy_startup(phydev);
@@ -450,9 +479,11 @@
ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
- ulong data_start = curr_des->rxdes3;
+ union ftgmac100_dma_addr data_start = { .lo = 0, .hi = 0 };
ulong data_end;
+ data_start.hi = FIELD_GET(FTGMAC100_RXDES2_RXBUF_BADR_HI, curr_des->rxdes2);
+ data_start.lo = curr_des->rxdes3;
invalidate_dcache_range(des_start, des_end);
if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
@@ -472,9 +503,9 @@
__func__, priv->rx_index, rxlen);
/* Invalidate received data */
- data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
- invalidate_dcache_range(data_start, data_end);
- *packetp = (uchar *)data_start;
+ data_end = data_start.addr + roundup(rxlen, ARCH_DMA_MINALIGN);
+ invalidate_dcache_range(data_start.addr, data_end);
+ *packetp = (uchar *)data_start.addr;
return rxlen;
}
@@ -500,6 +531,7 @@
struct ftgmac100_data *priv = dev_get_priv(dev);
struct ftgmac100 *ftgmac100 = priv->iobase;
struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
+ union ftgmac100_dma_addr dma_addr;
ulong des_start = ((ulong)curr_des) & ~(ARCH_DMA_MINALIGN - 1);
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
@@ -518,10 +550,12 @@
length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
- curr_des->txdes3 = (unsigned int)packet;
+ dma_addr.addr = (dma_addr_t)packet;
+ curr_des->txdes2 = FIELD_PREP(FTGMAC100_TXDES2_TXBUF_BADR_HI, dma_addr.hi);
+ curr_des->txdes3 = dma_addr.lo;
/* Flush data to be sent */
- data_start = curr_des->txdes3;
+ data_start = (ulong)dma_addr.addr;
data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
flush_dcache_range(data_start, data_end);
@@ -584,6 +618,11 @@
if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) {
priv->rxdes0_edorr_mask = BIT(30);
priv->txdes0_edotr_mask = BIT(30);
+ priv->is_ast2700 = false;
+ } else if (dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED_AST2700) {
+ priv->rxdes0_edorr_mask = BIT(30);
+ priv->txdes0_edotr_mask = BIT(30);
+ priv->is_ast2700 = true;
} else {
priv->rxdes0_edorr_mask = BIT(15);
priv->txdes0_edotr_mask = BIT(15);
@@ -674,10 +713,11 @@
};
static const struct udevice_id ftgmac100_ids[] = {
- { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
- { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
- { .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED },
- { }
+ { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
+ { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
+ { .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_ASPEED },
+ { .compatible = "aspeed,ast2700-mac", .data = FTGMAC100_MODEL_ASPEED_AST2700 },
+ {}
};
U_BOOT_DRIVER(ftgmac100) = {