summaryrefslogtreecommitdiffstats
path: root/drivers/net/macb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/macb.c')
-rw-r--r--drivers/net/macb.c170
1 files changed, 95 insertions, 75 deletions
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 511846122a..f5b2fa74dc 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -53,7 +53,7 @@
#define GEM_Q1_DESC_BYTES (sizeof(struct macb_dma_desc) * GEM_Q1_DESCS)
struct macb_config {
- int (*txclk_init)(struct device_d *dev, struct clk **tx_clk);
+ int (*txclk_init)(struct device *dev, struct clk **tx_clk);
};
struct macb_device {
@@ -63,9 +63,13 @@ struct macb_device {
unsigned int tx_head;
void *rx_buffer;
+ dma_addr_t rx_buffer_phys;
void *tx_buffer;
+ void *rx_packet_buf;
struct macb_dma_desc *rx_ring;
+ dma_addr_t rx_ring_phys;
struct macb_dma_desc *tx_ring;
+ dma_addr_t tx_ring_phys;
struct macb_dma_desc *gem_q1_descs;
int rx_buffer_size;
@@ -74,7 +78,7 @@ struct macb_device {
int phy_addr;
struct clk *pclk, *hclk, *txclk, *rxclk;
- const struct device_d *dev;
+ struct device *dev;
struct eth_device netdev;
phy_interface_t interface;
@@ -104,6 +108,7 @@ static int macb_send(struct eth_device *edev, void *packet,
int ret = 0;
uint64_t start;
unsigned int tx_head = macb->tx_head;
+ dma_addr_t packet_dma;
ctrl = MACB_BF(TX_FRMLEN, length);
ctrl |= MACB_BIT(TX_LAST);
@@ -115,23 +120,25 @@ static int macb_send(struct eth_device *edev, void *packet,
macb->tx_head++;
}
- macb->tx_ring[tx_head].ctrl = ctrl;
- macb->tx_ring[tx_head].addr = (ulong)packet;
- barrier();
- dma_sync_single_for_device((unsigned long)packet, length, DMA_TO_DEVICE);
+ packet_dma = dma_map_single(macb->dev, packet, length, DMA_TO_DEVICE);
+ if (dma_mapping_error(macb->dev, packet_dma))
+ return -EFAULT;
+
+ writel(ctrl, &macb->tx_ring[tx_head].ctrl);
+ writel(packet_dma, &macb->tx_ring[tx_head].addr);
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
start = get_time_ns();
ret = -ETIMEDOUT;
do {
- barrier();
- ctrl = macb->tx_ring[0].ctrl;
+ ctrl = readl(&macb->tx_ring[0].ctrl);
if (ctrl & MACB_BIT(TX_USED)) {
ret = 0;
break;
}
} while (!is_timeout(start, 100 * MSECOND));
- dma_sync_single_for_cpu((unsigned long)packet, length, DMA_TO_DEVICE);
+
+ dma_unmap_single(macb->dev, packet_dma, length, DMA_TO_DEVICE);
if (ctrl & MACB_BIT(TX_UNDERRUN))
dev_err(macb->dev, "TX underrun\n");
@@ -150,44 +157,40 @@ static void reclaim_rx_buffers(struct macb_device *macb,
i = macb->rx_tail;
while (i > new_tail) {
- macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED);
+ clrbits_le32(&macb->rx_ring[i].addr, MACB_BIT(RX_USED));
i++;
if (i > macb->rx_ring_size)
i = 0;
}
while (i < new_tail) {
- macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED);
+ clrbits_le32(&macb->rx_ring[i].addr, MACB_BIT(RX_USED));
i++;
}
- barrier();
macb->rx_tail = new_tail;
}
static int gem_recv(struct eth_device *edev)
{
struct macb_device *macb = edev->priv;
- void *buffer;
+ dma_addr_t buffer;
int length;
u32 status;
for (;;) {
- barrier();
- if (!(macb->rx_ring[macb->rx_tail].addr & MACB_BIT(RX_USED)))
+ if (!(readl(&macb->rx_ring[macb->rx_tail].addr) & MACB_BIT(RX_USED)))
return -1;
- barrier();
- status = macb->rx_ring[macb->rx_tail].ctrl;
+ status = readl(&macb->rx_ring[macb->rx_tail].ctrl);
length = MACB_BFEXT(RX_FRMLEN, status);
- buffer = macb->rx_buffer + macb->rx_buffer_size * macb->rx_tail;
- dma_sync_single_for_cpu((unsigned long)buffer, length,
- DMA_FROM_DEVICE);
- net_receive(edev, buffer, length);
- dma_sync_single_for_device((unsigned long)buffer, length,
- DMA_FROM_DEVICE);
- macb->rx_ring[macb->rx_tail].addr &= ~MACB_BIT(RX_USED);
- barrier();
+ buffer = macb->rx_buffer_phys + macb->rx_buffer_size * macb->rx_tail;
+ dma_sync_single_for_cpu(macb->dev, buffer, length, DMA_FROM_DEVICE);
+ net_receive(edev,
+ macb->rx_buffer + macb->rx_buffer_size * macb->rx_tail,
+ length);
+ dma_sync_single_for_device(macb->dev, buffer, length, DMA_FROM_DEVICE);
+ clrbits_le32(&macb->rx_ring[macb->rx_tail].addr, MACB_BIT(RX_USED));
macb->rx_tail++;
if (macb->rx_tail >= macb->rx_ring_size)
@@ -201,18 +204,16 @@ static int macb_recv(struct eth_device *edev)
{
struct macb_device *macb = edev->priv;
unsigned int rx_tail = macb->rx_tail;
- void *buffer;
+ dma_addr_t buffer;
int length;
int wrapped = 0;
u32 status;
for (;;) {
- barrier();
- if (!(macb->rx_ring[rx_tail].addr & MACB_BIT(RX_USED)))
+ if (!(readl(&macb->rx_ring[rx_tail].addr) & MACB_BIT(RX_USED)))
return -1;
- barrier();
- status = macb->rx_ring[rx_tail].ctrl;
+ status = readl(&macb->rx_ring[rx_tail].ctrl);
if (status & MACB_BIT(RX_SOF)) {
if (rx_tail != macb->rx_tail)
reclaim_rx_buffers(macb, rx_tail);
@@ -220,7 +221,7 @@ static int macb_recv(struct eth_device *edev)
}
if (status & MACB_BIT(RX_EOF)) {
- buffer = macb->rx_buffer + macb->rx_buffer_size * macb->rx_tail;
+ buffer = macb->rx_buffer_phys + macb->rx_buffer_size * macb->rx_tail;
length = MACB_BFEXT(RX_FRMLEN, status);
if (wrapped) {
unsigned int headlen, taillen;
@@ -228,26 +229,24 @@ static int macb_recv(struct eth_device *edev)
headlen = macb->rx_buffer_size * (macb->rx_ring_size
- macb->rx_tail);
taillen = length - headlen;
- dma_sync_single_for_cpu((unsigned long)buffer,
- headlen, DMA_FROM_DEVICE);
- memcpy((void *)NetRxPackets[0], buffer, headlen);
- dma_sync_single_for_cpu((unsigned long)macb->rx_buffer,
+ dma_sync_single_for_cpu(macb->dev, buffer, headlen, DMA_FROM_DEVICE);
+ memcpy(macb->rx_packet_buf,
+ macb->rx_buffer + macb->rx_buffer_size * macb->rx_tail,
+ headlen);
+ dma_sync_single_for_cpu(macb->dev, macb->rx_buffer_phys,
taillen, DMA_FROM_DEVICE);
- memcpy((void *)NetRxPackets[0] + headlen,
- macb->rx_buffer, taillen);
- dma_sync_single_for_device((unsigned long)buffer,
- headlen, DMA_FROM_DEVICE);
- dma_sync_single_for_device((unsigned long)macb->rx_buffer,
+ memcpy(macb->rx_packet_buf + headlen, macb->rx_buffer, taillen);
+ dma_sync_single_for_device(macb->dev, buffer, headlen, DMA_FROM_DEVICE);
+ dma_sync_single_for_device(macb->dev, macb->rx_buffer_phys,
taillen, DMA_FROM_DEVICE);
- net_receive(edev, NetRxPackets[0], length);
+ net_receive(edev, macb->rx_packet_buf, length);
} else {
- dma_sync_single_for_cpu((unsigned long)buffer, length,
- DMA_FROM_DEVICE);
- net_receive(edev, buffer, length);
- dma_sync_single_for_device((unsigned long)buffer, length,
- DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(macb->dev, buffer, length, DMA_FROM_DEVICE);
+ net_receive(edev,
+ macb->rx_buffer + macb->rx_buffer_size * macb->rx_tail,
+ length);
+ dma_sync_single_for_device(macb->dev, buffer, length, DMA_FROM_DEVICE);
}
- barrier();
if (++rx_tail >= macb->rx_ring_size)
rx_tail = 0;
reclaim_rx_buffers(macb, rx_tail);
@@ -367,9 +366,9 @@ static int gmac_init_dummy_tx_queues(struct macb_device *macb)
if (queue_mask & (1 << i))
num_queues++;
- macb->gem_q1_descs[0].addr = 0;
- macb->gem_q1_descs[0].ctrl = MACB_BIT(TX_WRAP) |
- MACB_BIT(TX_LAST) | MACB_BIT(TX_USED);
+ writel(0, &macb->gem_q1_descs[0].addr);
+ writel(MACB_BIT(TX_WRAP) | MACB_BIT(TX_LAST) | MACB_BIT(TX_USED),
+ &macb->gem_q1_descs[0].ctrl);
for (i = 1; i < num_queues; i++)
gem_writel_queue_TBQP(macb, (ulong)macb->gem_q1_descs, i - 1);
@@ -377,7 +376,7 @@ static int gmac_init_dummy_tx_queues(struct macb_device *macb)
return 0;
}
-static void macb_init(struct macb_device *macb)
+static int macb_init(struct macb_device *macb)
{
unsigned long paddr, val = 0;
int i;
@@ -386,21 +385,26 @@ static void macb_init(struct macb_device *macb)
* macb_halt should have been called at some point before now,
* so we'll assume the controller is idle.
*/
+ macb->rx_buffer_phys = dma_map_single(macb->dev, macb->rx_buffer,
+ macb->rx_buffer_size * macb->rx_ring_size,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(macb->dev, macb->rx_buffer_phys))
+ return -EFAULT;
/* initialize DMA descriptors */
paddr = (ulong)macb->rx_buffer;
for (i = 0; i < macb->rx_ring_size; i++) {
- macb->rx_ring[i].addr = paddr;
- macb->rx_ring[i].ctrl = 0;
+ writel(paddr, &macb->rx_ring[i].addr);
+ writel(0, &macb->rx_ring[i].ctrl);
paddr += macb->rx_buffer_size;
}
- macb->rx_ring[macb->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP);
+ setbits_le32(&macb->rx_ring[macb->rx_ring_size - 1].addr, MACB_BIT(RX_WRAP));
for (i = 0; i < TX_RING_SIZE; i++) {
- macb->tx_ring[i].addr = 0;
- macb->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+ writel(0, &macb->tx_ring[i].addr);
+ writel(MACB_BIT(TX_USED), &macb->tx_ring[i].ctrl);
}
- macb->tx_ring[TX_RING_SIZE - 1].addr |= MACB_BIT(TX_WRAP);
+ setbits_le32(&macb->tx_ring[TX_RING_SIZE - 1].addr, MACB_BIT(TX_WRAP));
macb->rx_tail = macb->tx_head = 0;
@@ -413,9 +417,8 @@ static void macb_init(struct macb_device *macb)
gmac_init_dummy_tx_queues(macb);
/* Disable the second priority rx queue */
- macb->gem_q1_descs[1].addr = MACB_BIT(RX_USED) |
- MACB_BIT(RX_WRAP);
- macb->gem_q1_descs[1].ctrl = 0;
+ writel(MACB_BIT(RX_USED) | MACB_BIT(RX_WRAP), &macb->gem_q1_descs[1].addr);
+ writel(0, &macb->gem_q1_descs[1].ctrl);
gem_writel(macb, RQ1, (ulong)&macb->gem_q1_descs[1]);
}
@@ -442,6 +445,7 @@ static void macb_init(struct macb_device *macb)
macb_or_gem_writel(macb, USRIO, val);
+ return 0;
}
static void macb_halt(struct eth_device *edev)
@@ -460,6 +464,13 @@ static void macb_halt(struct eth_device *edev)
/* Disable TX and RX, and clear statistics */
macb_writel(macb, NCR, MACB_BIT(CLRSTAT));
+
+ dma_unmap_single(macb->dev, macb->rx_buffer_phys,
+ macb->rx_buffer_size * macb->rx_ring_size,
+ DMA_FROM_DEVICE);
+ free(macb->rx_buffer);
+ dma_free_coherent((void *)macb->rx_ring, macb->rx_ring_phys, RX_RING_BYTES(macb));
+ dma_free_coherent((void *)macb->tx_ring, macb->tx_ring_phys, TX_RING_BYTES);
}
static int macb_phy_read(struct mii_bus *bus, int addr, int reg)
@@ -730,7 +741,7 @@ static const struct clk_ops fu540_c000_ops = {
.set_rate = fu540_macb_tx_set_rate,
};
-static int fu540_c000_txclk_init(struct device_d *dev, struct clk **tx_clk)
+static int fu540_c000_txclk_init(struct device *dev, struct clk **tx_clk)
{
struct clk *clk;
struct resource *res;
@@ -766,13 +777,13 @@ static int fu540_c000_txclk_init(struct device_d *dev, struct clk **tx_clk)
return 0;
}
#else
-static int fu540_c000_txclk_init(struct device_d *dev, struct clk **tx_clk)
+static int fu540_c000_txclk_init(struct device *dev, struct clk **tx_clk)
{
return -ENOSYS;
}
#endif
-static int macb_probe(struct device_d *dev)
+static int macb_probe(struct device *dev)
{
struct resource *iores;
struct eth_device *edev;
@@ -780,6 +791,7 @@ static int macb_probe(struct device_d *dev)
const char *pclk_name, *hclk_name;
const struct macb_config *config = NULL;
u32 ncfgr;
+ int ret;
macb = xzalloc(sizeof(*macb));
edev = &macb->netdev;
@@ -815,19 +827,19 @@ static int macb_probe(struct device_d *dev)
macb->phy_flags = pdata->phy_flags;
pclk_name = "macb_clk";
hclk_name = NULL;
- } else if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) {
+ } else if (IS_ENABLED(CONFIG_OFDEVICE) && dev->of_node) {
int ret;
struct device_node *mdiobus;
- ret = of_get_phy_mode(dev->device_node);
+ ret = of_get_phy_mode(dev->of_node);
if (ret < 0)
macb->interface = PHY_INTERFACE_MODE_MII;
else
macb->interface = ret;
- mdiobus = of_get_child_by_name(dev->device_node, "mdio");
+ mdiobus = of_get_child_by_name(dev->of_node, "mdio");
if (mdiobus)
- macb->miibus.dev.device_node = mdiobus;
+ macb->miibus.dev.of_node = mdiobus;
macb->phy_addr = -1;
pclk_name = "pclk";
@@ -877,7 +889,7 @@ static int macb_probe(struct device_d *dev)
clk_enable(macb->rxclk);
if (config) {
- int ret = config->txclk_init(dev, &macb->txclk);
+ ret = config->txclk_init(dev, &macb->txclk);
if (ret)
return ret;
}
@@ -891,13 +903,15 @@ static int macb_probe(struct device_d *dev)
macb_init_rx_buffer_size(macb, PKTSIZE);
macb->rx_buffer = dma_alloc(macb->rx_buffer_size * macb->rx_ring_size);
- macb->rx_ring = dma_alloc_coherent(RX_RING_BYTES(macb), DMA_ADDRESS_BROKEN);
- macb->tx_ring = dma_alloc_coherent(TX_RING_BYTES, DMA_ADDRESS_BROKEN);
+ macb->rx_ring = dma_alloc_coherent(RX_RING_BYTES(macb), &macb->rx_ring_phys);
+ macb->tx_ring = dma_alloc_coherent(TX_RING_BYTES, &macb->tx_ring_phys);
if (macb->is_gem)
macb->gem_q1_descs = dma_alloc_coherent(GEM_Q1_DESC_BYTES,
DMA_ADDRESS_BROKEN);
+ macb->rx_packet_buf = xmalloc(PKTSIZE);
+
macb_reset_hw(macb);
ncfgr = macb_mdc_clk_div(macb);
ncfgr |= MACB_BIT(PAE); /* PAuse Enable */
@@ -905,7 +919,9 @@ static int macb_probe(struct device_d *dev)
ncfgr |= macb_dbw(macb);
macb_writel(macb, NCFGR, ncfgr);
- macb_init(macb);
+ ret = macb_init(macb);
+ if (ret)
+ return ret;
mdiobus_register(&macb->miibus);
eth_register(edev);
@@ -916,11 +932,13 @@ static int macb_probe(struct device_d *dev)
return 0;
}
-static void macb_remove(struct device_d *dev)
+static void macb_remove(struct device *dev)
{
struct macb_device *macb = dev->priv;
macb_halt(&macb->netdev);
+
+ free(macb->rx_packet_buf);
}
static const struct macb_config fu540_c000_config = {
@@ -931,13 +949,15 @@ static const struct of_device_id macb_dt_ids[] = {
{ .compatible = "cdns,at91sam9260-macb",},
{ .compatible = "atmel,sama5d2-gem",},
{ .compatible = "atmel,sama5d3-gem",},
- { .compatible = "cdns,zynq-gem",},
- { .compatible = "cdns,zynqmp-gem",},
+ { .compatible = "atmel,sama5d4-gem",},
+ { .compatible = "xlnx,zynq-gem",},
+ { .compatible = "xlnx,zynqmp-gem",},
{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
{ /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, macb_dt_ids);
-static struct driver_d macb_driver = {
+static struct driver macb_driver = {
.name = "macb",
.probe = macb_probe,
.remove = macb_remove,