summaryrefslogtreecommitdiff
path: root/drivers/net/ftgmac100.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ftgmac100.c')
-rw-r--r--drivers/net/ftgmac100.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index 9d64125bfcb..f5ea2e72d1b 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 @@ struct ftgmac100_data {
/* 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 @@ static int ftgmac100_start(struct udevice *dev)
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 @@ static int ftgmac100_start(struct udevice *dev)
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 @@ static int ftgmac100_start(struct udevice *dev)
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 @@ static int ftgmac100_start(struct udevice *dev)
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 @@ static int ftgmac100_start(struct udevice *dev)
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 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
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 @@ static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
__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 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
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 @@ static int ftgmac100_send(struct udevice *dev, void *packet, int length)
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 @@ static int ftgmac100_of_to_plat(struct udevice *dev)
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 eth_ops ftgmac100_ops = {
};
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) = {