diff options
Diffstat (limited to 'drivers/net/macb.c')
-rw-r--r-- | drivers/net/macb.c | 170 |
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, |