Lines Matching +full:mac +full:- +full:clk +full:- +full:tx
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2007-2008 Avionic Design Development GmbH
6 * Copyright (C) 2008-2009 Avionic Design GmbH
8 * Written by Thierry Reding <thierry.reding@avionic-design.de>
11 #include <linux/dma-mapping.h>
13 #include <linux/clk.h>
64 #define MODER_NBO (1 << 8) /* no back-off */
133 /* TX buffer descriptor */
141 #define TX_BD_CRC (1 << 11) /* TX CRC enable */
145 #define TX_BD_READY (1 << 15) /* TX buffer ready */
177 * struct ethoc - driver-private device structure
193 * @clk: clock
220 struct clk *clk; member
228 * struct ethoc_bd - buffer descriptor
239 if (dev->big_endian) in ethoc_read()
240 return ioread32be(dev->iobase + offset); in ethoc_read()
242 return ioread32(dev->iobase + offset); in ethoc_read()
247 if (dev->big_endian) in ethoc_write()
248 iowrite32be(data, dev->iobase + offset); in ethoc_write()
250 iowrite32(data, dev->iobase + offset); in ethoc_write()
257 bd->stat = ethoc_read(dev, offset + 0); in ethoc_read_bd()
258 bd->addr = ethoc_read(dev, offset + 4); in ethoc_read_bd()
265 ethoc_write(dev, offset + 0, bd->stat); in ethoc_write_bd()
266 ethoc_write(dev, offset + 4, bd->addr); in ethoc_write_bd()
308 dev->cur_tx = 0; in ethoc_init_ring()
309 dev->dty_tx = 0; in ethoc_init_ring()
310 dev->cur_rx = 0; in ethoc_init_ring()
312 ethoc_write(dev, TX_BD_NUM, dev->num_tx); in ethoc_init_ring()
317 vma = dev->membase; in ethoc_init_ring()
319 for (i = 0; i < dev->num_tx; i++) { in ethoc_init_ring()
320 if (i == dev->num_tx - 1) in ethoc_init_ring()
326 dev->vma[i] = vma; in ethoc_init_ring()
332 for (i = 0; i < dev->num_rx; i++) { in ethoc_init_ring()
333 if (i == dev->num_rx - 1) in ethoc_init_ring()
336 ethoc_write_bd(dev, dev->num_tx + i, &bd); in ethoc_init_ring()
339 dev->vma[dev->num_tx + i] = vma; in ethoc_init_ring()
361 /* set full-duplex mode */ in ethoc_reset()
376 struct net_device *netdev = dev->netdev; in ethoc_update_rx_stats()
379 if (bd->stat & RX_BD_TL) { in ethoc_update_rx_stats()
380 dev_err(&netdev->dev, "RX: frame too long\n"); in ethoc_update_rx_stats()
381 netdev->stats.rx_length_errors++; in ethoc_update_rx_stats()
385 if (bd->stat & RX_BD_SF) { in ethoc_update_rx_stats()
386 dev_err(&netdev->dev, "RX: frame too short\n"); in ethoc_update_rx_stats()
387 netdev->stats.rx_length_errors++; in ethoc_update_rx_stats()
391 if (bd->stat & RX_BD_DN) { in ethoc_update_rx_stats()
392 dev_err(&netdev->dev, "RX: dribble nibble\n"); in ethoc_update_rx_stats()
393 netdev->stats.rx_frame_errors++; in ethoc_update_rx_stats()
396 if (bd->stat & RX_BD_CRC) { in ethoc_update_rx_stats()
397 dev_err(&netdev->dev, "RX: wrong CRC\n"); in ethoc_update_rx_stats()
398 netdev->stats.rx_crc_errors++; in ethoc_update_rx_stats()
402 if (bd->stat & RX_BD_OR) { in ethoc_update_rx_stats()
403 dev_err(&netdev->dev, "RX: overrun\n"); in ethoc_update_rx_stats()
404 netdev->stats.rx_over_errors++; in ethoc_update_rx_stats()
408 if (bd->stat & RX_BD_MISS) in ethoc_update_rx_stats()
409 netdev->stats.rx_missed_errors++; in ethoc_update_rx_stats()
411 if (bd->stat & RX_BD_LC) { in ethoc_update_rx_stats()
412 dev_err(&netdev->dev, "RX: late collision\n"); in ethoc_update_rx_stats()
413 netdev->stats.collisions++; in ethoc_update_rx_stats()
429 entry = priv->num_tx + priv->cur_rx; in ethoc_rx()
449 size -= 4; /* strip the CRC */ in ethoc_rx()
453 void *src = priv->vma[entry]; in ethoc_rx()
455 skb->protocol = eth_type_trans(skb, dev); in ethoc_rx()
456 dev->stats.rx_packets++; in ethoc_rx()
457 dev->stats.rx_bytes += size; in ethoc_rx()
461 dev_warn(&dev->dev, in ethoc_rx()
462 "low on memory - packet dropped\n"); in ethoc_rx()
464 dev->stats.rx_dropped++; in ethoc_rx()
473 if (++priv->cur_rx == priv->num_rx) in ethoc_rx()
474 priv->cur_rx = 0; in ethoc_rx()
482 struct net_device *netdev = dev->netdev; in ethoc_update_tx_stats()
484 if (bd->stat & TX_BD_LC) { in ethoc_update_tx_stats()
485 dev_err(&netdev->dev, "TX: late collision\n"); in ethoc_update_tx_stats()
486 netdev->stats.tx_window_errors++; in ethoc_update_tx_stats()
489 if (bd->stat & TX_BD_RL) { in ethoc_update_tx_stats()
490 dev_err(&netdev->dev, "TX: retransmit limit\n"); in ethoc_update_tx_stats()
491 netdev->stats.tx_aborted_errors++; in ethoc_update_tx_stats()
494 if (bd->stat & TX_BD_UR) { in ethoc_update_tx_stats()
495 dev_err(&netdev->dev, "TX: underrun\n"); in ethoc_update_tx_stats()
496 netdev->stats.tx_fifo_errors++; in ethoc_update_tx_stats()
499 if (bd->stat & TX_BD_CS) { in ethoc_update_tx_stats()
500 dev_err(&netdev->dev, "TX: carrier sense lost\n"); in ethoc_update_tx_stats()
501 netdev->stats.tx_carrier_errors++; in ethoc_update_tx_stats()
504 if (bd->stat & TX_BD_STATS) in ethoc_update_tx_stats()
505 netdev->stats.tx_errors++; in ethoc_update_tx_stats()
507 netdev->stats.collisions += (bd->stat >> 4) & 0xf; in ethoc_update_tx_stats()
508 netdev->stats.tx_bytes += bd->stat >> 16; in ethoc_update_tx_stats()
509 netdev->stats.tx_packets++; in ethoc_update_tx_stats()
521 entry = priv->dty_tx & (priv->num_tx-1); in ethoc_tx()
525 if (bd.stat & TX_BD_READY || (priv->dty_tx == priv->cur_tx)) { in ethoc_tx()
529 * missing the event as the TX interrupt won't trigger in ethoc_tx()
536 (priv->dty_tx == priv->cur_tx)) in ethoc_tx()
541 priv->dty_tx++; in ethoc_tx()
544 if ((priv->cur_tx - priv->dty_tx) <= (priv->num_tx / 2)) in ethoc_tx()
576 dev_dbg(&dev->dev, "packet dropped\n"); in ethoc_interrupt()
577 dev->stats.rx_dropped++; in ethoc_interrupt()
583 napi_schedule(&priv->napi); in ethoc_interrupt()
592 u8 *mac = (u8 *)addr; in ethoc_get_mac_address() local
596 mac[2] = (reg >> 24) & 0xff; in ethoc_get_mac_address()
597 mac[3] = (reg >> 16) & 0xff; in ethoc_get_mac_address()
598 mac[4] = (reg >> 8) & 0xff; in ethoc_get_mac_address()
599 mac[5] = (reg >> 0) & 0xff; in ethoc_get_mac_address()
602 mac[0] = (reg >> 8) & 0xff; in ethoc_get_mac_address()
603 mac[1] = (reg >> 0) & 0xff; in ethoc_get_mac_address()
614 rx_work_done = ethoc_rx(priv->netdev, budget); in ethoc_poll()
615 tx_work_done = ethoc_tx(priv->netdev, budget); in ethoc_poll()
627 struct ethoc *priv = bus->priv; in ethoc_mdio_read()
644 return -EBUSY; in ethoc_mdio_read()
649 struct ethoc *priv = bus->priv; in ethoc_mdio_write()
666 return -EBUSY; in ethoc_mdio_write()
672 struct phy_device *phydev = dev->phydev; in ethoc_mdio_poll()
676 if (priv->old_link != phydev->link) { in ethoc_mdio_poll()
678 priv->old_link = phydev->link; in ethoc_mdio_poll()
681 if (priv->old_duplex != phydev->duplex) { in ethoc_mdio_poll()
683 priv->old_duplex = phydev->duplex; in ethoc_mdio_poll()
690 if (phydev->duplex == DUPLEX_FULL) in ethoc_mdio_poll()
705 if (priv->phy_id != -1) in ethoc_mdio_probe()
706 phy = mdiobus_get_phy(priv->mdio, priv->phy_id); in ethoc_mdio_probe()
708 phy = phy_find_first(priv->mdio); in ethoc_mdio_probe()
711 dev_err(&dev->dev, "no PHY found\n"); in ethoc_mdio_probe()
712 return -ENXIO; in ethoc_mdio_probe()
715 priv->old_duplex = -1; in ethoc_mdio_probe()
716 priv->old_link = -1; in ethoc_mdio_probe()
721 dev_err(&dev->dev, "could not attach to PHY\n"); in ethoc_mdio_probe()
735 ret = request_irq(dev->irq, ethoc_interrupt, IRQF_SHARED, in ethoc_open()
736 dev->name, dev); in ethoc_open()
740 napi_enable(&priv->napi); in ethoc_open()
742 ethoc_init_ring(priv, dev->mem_start); in ethoc_open()
746 dev_dbg(&dev->dev, " resuming queue\n"); in ethoc_open()
749 dev_dbg(&dev->dev, " starting queue\n"); in ethoc_open()
753 priv->old_link = -1; in ethoc_open()
754 priv->old_duplex = -1; in ethoc_open()
756 phy_start(dev->phydev); in ethoc_open()
759 dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", in ethoc_open()
760 dev->base_addr, dev->mem_start, dev->mem_end); in ethoc_open()
770 napi_disable(&priv->napi); in ethoc_stop()
772 if (dev->phydev) in ethoc_stop()
773 phy_stop(dev->phydev); in ethoc_stop()
776 free_irq(dev->irq, dev); in ethoc_stop()
791 return -EINVAL; in ethoc_ioctl()
794 if (mdio->phy_id >= PHY_MAX_ADDR) in ethoc_ioctl()
795 return -ERANGE; in ethoc_ioctl()
797 phy = mdiobus_get_phy(priv->mdio, mdio->phy_id); in ethoc_ioctl()
799 return -ENODEV; in ethoc_ioctl()
801 phy = dev->phydev; in ethoc_ioctl()
810 unsigned char *mac = dev->dev_addr; in ethoc_do_set_mac_address() local
812 ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) | in ethoc_do_set_mac_address()
813 (mac[4] << 8) | (mac[5] << 0)); in ethoc_do_set_mac_address()
814 ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0)); in ethoc_do_set_mac_address()
821 if (!is_valid_ether_addr(addr->sa_data)) in ethoc_set_mac_address()
822 return -EADDRNOTAVAIL; in ethoc_set_mac_address()
823 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); in ethoc_set_mac_address()
836 if (dev->flags & IFF_LOOPBACK) in ethoc_set_multicast_list()
842 if (dev->flags & IFF_BROADCAST) in ethoc_set_multicast_list()
848 if (dev->flags & IFF_PROMISC) in ethoc_set_multicast_list()
856 if (dev->flags & IFF_ALLMULTI) { in ethoc_set_multicast_list()
861 u32 crc = ether_crc(ETH_ALEN, ha->addr); in ethoc_set_multicast_list()
873 return -ENOSYS; in ethoc_change_mtu()
881 ethoc_interrupt(dev->irq, dev); in ethoc_tx_timeout()
892 dev->stats.tx_errors++; in ethoc_start_xmit()
896 if (unlikely(skb->len > ETHOC_BUFSIZ)) { in ethoc_start_xmit()
897 dev->stats.tx_errors++; in ethoc_start_xmit()
901 entry = priv->cur_tx % priv->num_tx; in ethoc_start_xmit()
902 spin_lock_irq(&priv->lock); in ethoc_start_xmit()
903 priv->cur_tx++; in ethoc_start_xmit()
906 if (unlikely(skb->len < ETHOC_ZLEN)) in ethoc_start_xmit()
911 dest = priv->vma[entry]; in ethoc_start_xmit()
912 memcpy_toio(dest, skb->data, skb->len); in ethoc_start_xmit()
915 bd.stat |= TX_BD_LEN(skb->len); in ethoc_start_xmit()
921 if (priv->cur_tx == (priv->dty_tx + priv->num_tx)) { in ethoc_start_xmit()
922 dev_dbg(&dev->dev, "stopping queue\n"); in ethoc_start_xmit()
926 spin_unlock_irq(&priv->lock); in ethoc_start_xmit()
946 regs->version = 0; in ethoc_get_regs()
956 ring->rx_max_pending = priv->num_bd - 1; in ethoc_get_ringparam()
957 ring->rx_mini_max_pending = 0; in ethoc_get_ringparam()
958 ring->rx_jumbo_max_pending = 0; in ethoc_get_ringparam()
959 ring->tx_max_pending = priv->num_bd - 1; in ethoc_get_ringparam()
961 ring->rx_pending = priv->num_rx; in ethoc_get_ringparam()
962 ring->rx_mini_pending = 0; in ethoc_get_ringparam()
963 ring->rx_jumbo_pending = 0; in ethoc_get_ringparam()
964 ring->tx_pending = priv->num_tx; in ethoc_get_ringparam()
972 if (ring->tx_pending < 1 || ring->rx_pending < 1 || in ethoc_set_ringparam()
973 ring->tx_pending + ring->rx_pending > priv->num_bd) in ethoc_set_ringparam()
974 return -EINVAL; in ethoc_set_ringparam()
975 if (ring->rx_mini_pending || ring->rx_jumbo_pending) in ethoc_set_ringparam()
976 return -EINVAL; in ethoc_set_ringparam()
982 synchronize_irq(dev->irq); in ethoc_set_ringparam()
985 priv->num_tx = rounddown_pow_of_two(ring->tx_pending); in ethoc_set_ringparam()
986 priv->num_rx = ring->rx_pending; in ethoc_set_ringparam()
987 ethoc_init_ring(priv, dev->mem_start); in ethoc_set_ringparam()
1021 * ethoc_probe - initialize OpenCores ethernet MAC
1033 struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev); in ethoc_probe()
1034 u32 eth_clkfreq = pdata ? pdata->eth_clkfreq : 0; in ethoc_probe()
1039 ret = -ENOMEM; in ethoc_probe()
1043 SET_NETDEV_DEV(netdev, &pdev->dev); in ethoc_probe()
1049 dev_err(&pdev->dev, "cannot obtain I/O memory space\n"); in ethoc_probe()
1050 ret = -ENXIO; in ethoc_probe()
1054 mmio = devm_request_mem_region(&pdev->dev, res->start, in ethoc_probe()
1055 resource_size(res), res->name); in ethoc_probe()
1057 dev_err(&pdev->dev, "cannot request I/O memory space\n"); in ethoc_probe()
1058 ret = -ENXIO; in ethoc_probe()
1062 netdev->base_addr = mmio->start; in ethoc_probe()
1067 mem = devm_request_mem_region(&pdev->dev, res->start, in ethoc_probe()
1068 resource_size(res), res->name); in ethoc_probe()
1070 dev_err(&pdev->dev, "cannot request memory space\n"); in ethoc_probe()
1071 ret = -ENXIO; in ethoc_probe()
1075 netdev->mem_start = mem->start; in ethoc_probe()
1076 netdev->mem_end = mem->end; in ethoc_probe()
1083 dev_err(&pdev->dev, "cannot obtain IRQ\n"); in ethoc_probe()
1084 ret = -ENXIO; in ethoc_probe()
1088 netdev->irq = res->start; in ethoc_probe()
1090 /* setup driver-private data */ in ethoc_probe()
1092 priv->netdev = netdev; in ethoc_probe()
1094 priv->iobase = devm_ioremap(&pdev->dev, netdev->base_addr, in ethoc_probe()
1096 if (!priv->iobase) { in ethoc_probe()
1097 dev_err(&pdev->dev, "cannot remap I/O memory space\n"); in ethoc_probe()
1098 ret = -ENXIO; in ethoc_probe()
1102 if (netdev->mem_end) { in ethoc_probe()
1103 priv->membase = devm_ioremap(&pdev->dev, in ethoc_probe()
1104 netdev->mem_start, resource_size(mem)); in ethoc_probe()
1105 if (!priv->membase) { in ethoc_probe()
1106 dev_err(&pdev->dev, "cannot remap memory space\n"); in ethoc_probe()
1107 ret = -ENXIO; in ethoc_probe()
1112 priv->membase = dmam_alloc_coherent(&pdev->dev, in ethoc_probe()
1113 buffer_size, (void *)&netdev->mem_start, in ethoc_probe()
1115 if (!priv->membase) { in ethoc_probe()
1116 dev_err(&pdev->dev, "cannot allocate %dB buffer\n", in ethoc_probe()
1118 ret = -ENOMEM; in ethoc_probe()
1121 netdev->mem_end = netdev->mem_start + buffer_size; in ethoc_probe()
1124 priv->big_endian = pdata ? pdata->big_endian : in ethoc_probe()
1125 of_device_is_big_endian(pdev->dev.of_node); in ethoc_probe()
1127 /* calculate the number of TX/RX buffers, maximum 128 supported */ in ethoc_probe()
1129 128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ); in ethoc_probe()
1131 ret = -ENODEV; in ethoc_probe()
1134 priv->num_bd = num_bd; in ethoc_probe()
1136 priv->num_tx = rounddown_pow_of_two(num_bd >> 1); in ethoc_probe()
1137 priv->num_rx = num_bd - priv->num_tx; in ethoc_probe()
1139 dev_dbg(&pdev->dev, "ethoc: num_tx: %d num_rx: %d\n", in ethoc_probe()
1140 priv->num_tx, priv->num_rx); in ethoc_probe()
1142 priv->vma = devm_kcalloc(&pdev->dev, num_bd, sizeof(void *), in ethoc_probe()
1144 if (!priv->vma) { in ethoc_probe()
1145 ret = -ENOMEM; in ethoc_probe()
1149 /* Allow the platform setup code to pass in a MAC address. */ in ethoc_probe()
1151 ether_addr_copy(netdev->dev_addr, pdata->hwaddr); in ethoc_probe()
1152 priv->phy_id = pdata->phy_id; in ethoc_probe()
1154 const void *mac; in ethoc_probe() local
1156 mac = of_get_mac_address(pdev->dev.of_node); in ethoc_probe()
1157 if (!IS_ERR(mac)) in ethoc_probe()
1158 ether_addr_copy(netdev->dev_addr, mac); in ethoc_probe()
1159 priv->phy_id = -1; in ethoc_probe()
1162 /* Check that the given MAC address is valid. If it isn't, read the in ethoc_probe()
1163 * current MAC from the controller. in ethoc_probe()
1165 if (!is_valid_ether_addr(netdev->dev_addr)) in ethoc_probe()
1166 ethoc_get_mac_address(netdev, netdev->dev_addr); in ethoc_probe()
1168 /* Check the MAC again for validity, if it still isn't choose and in ethoc_probe()
1171 if (!is_valid_ether_addr(netdev->dev_addr)) in ethoc_probe()
1178 struct clk *clk = devm_clk_get(&pdev->dev, NULL); in ethoc_probe() local
1180 if (!IS_ERR(clk)) { in ethoc_probe()
1181 priv->clk = clk; in ethoc_probe()
1182 clk_prepare_enable(clk); in ethoc_probe()
1183 eth_clkfreq = clk_get_rate(clk); in ethoc_probe()
1191 dev_dbg(&pdev->dev, "setting MII clkdiv to %u\n", clkdiv); in ethoc_probe()
1198 priv->mdio = mdiobus_alloc(); in ethoc_probe()
1199 if (!priv->mdio) { in ethoc_probe()
1200 ret = -ENOMEM; in ethoc_probe()
1204 priv->mdio->name = "ethoc-mdio"; in ethoc_probe()
1205 snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "%s-%d", in ethoc_probe()
1206 priv->mdio->name, pdev->id); in ethoc_probe()
1207 priv->mdio->read = ethoc_mdio_read; in ethoc_probe()
1208 priv->mdio->write = ethoc_mdio_write; in ethoc_probe()
1209 priv->mdio->priv = priv; in ethoc_probe()
1211 ret = mdiobus_register(priv->mdio); in ethoc_probe()
1213 dev_err(&netdev->dev, "failed to register MDIO bus\n"); in ethoc_probe()
1219 dev_err(&netdev->dev, "failed to probe MDIO bus\n"); in ethoc_probe()
1224 netdev->netdev_ops = ðoc_netdev_ops; in ethoc_probe()
1225 netdev->watchdog_timeo = ETHOC_TIMEOUT; in ethoc_probe()
1226 netdev->features |= 0; in ethoc_probe()
1227 netdev->ethtool_ops = ðoc_ethtool_ops; in ethoc_probe()
1230 netif_napi_add(netdev, &priv->napi, ethoc_poll, 64); in ethoc_probe()
1232 spin_lock_init(&priv->lock); in ethoc_probe()
1236 dev_err(&netdev->dev, "failed to register interface\n"); in ethoc_probe()
1243 netif_napi_del(&priv->napi); in ethoc_probe()
1245 mdiobus_unregister(priv->mdio); in ethoc_probe()
1246 mdiobus_free(priv->mdio); in ethoc_probe()
1248 clk_disable_unprepare(priv->clk); in ethoc_probe()
1256 * ethoc_remove - shutdown OpenCores ethernet MAC
1265 netif_napi_del(&priv->napi); in ethoc_remove()
1266 phy_disconnect(netdev->phydev); in ethoc_remove()
1268 if (priv->mdio) { in ethoc_remove()
1269 mdiobus_unregister(priv->mdio); in ethoc_remove()
1270 mdiobus_free(priv->mdio); in ethoc_remove()
1272 clk_disable_unprepare(priv->clk); in ethoc_remove()
1283 return -ENOSYS; in ethoc_suspend()
1288 return -ENOSYS; in ethoc_resume()
1314 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
1315 MODULE_DESCRIPTION("OpenCores Ethernet MAC driver");