Lines Matching +full:mac +full:- +full:clk +full:- +full:rx
4 * Copyright (C) 2007-2008 Avionic Design Development GmbH
5 * Copyright (C) 2008-2009 Avionic Design GmbH
11 * Written by Thierry Reding <thierry.reding@avionic-design.de>
14 #include <linux/dma-mapping.h>
16 #include <linux/clk.h>
67 #define MODER_NBO (1 << 8) /* no back-off */
155 /* RX buffer descriptor */
157 #define RX_BD_CRC (1 << 1) /* RX CRC error */
180 * struct ethoc - driver-private device structure
219 struct clk *clk; member
227 * struct ethoc_bd - buffer descriptor
238 if (dev->big_endian) in ethoc_read()
239 return ioread32be(dev->iobase + offset); in ethoc_read()
241 return ioread32(dev->iobase + offset); in ethoc_read()
246 if (dev->big_endian) in ethoc_write()
247 iowrite32be(data, dev->iobase + offset); in ethoc_write()
249 iowrite32(data, dev->iobase + offset); in ethoc_write()
256 bd->stat = ethoc_read(dev, offset + 0); in ethoc_read_bd()
257 bd->addr = ethoc_read(dev, offset + 4); in ethoc_read_bd()
264 ethoc_write(dev, offset + 0, bd->stat); in ethoc_write_bd()
265 ethoc_write(dev, offset + 4, bd->addr); in ethoc_write_bd()
307 dev->cur_tx = 0; in ethoc_init_ring()
308 dev->dty_tx = 0; in ethoc_init_ring()
309 dev->cur_rx = 0; in ethoc_init_ring()
311 ethoc_write(dev, TX_BD_NUM, dev->num_tx); in ethoc_init_ring()
316 vma = dev->membase; in ethoc_init_ring()
318 for (i = 0; i < dev->num_tx; i++) { in ethoc_init_ring()
319 if (i == dev->num_tx - 1) in ethoc_init_ring()
325 dev->vma[i] = vma; in ethoc_init_ring()
331 for (i = 0; i < dev->num_rx; i++) { in ethoc_init_ring()
332 if (i == dev->num_rx - 1) in ethoc_init_ring()
335 ethoc_write_bd(dev, dev->num_tx + i, &bd); in ethoc_init_ring()
338 dev->vma[dev->num_tx + i] = vma; in ethoc_init_ring()
360 /* set full-duplex mode */ in ethoc_reset()
375 struct net_device *netdev = dev->netdev; in ethoc_update_rx_stats()
378 if (bd->stat & RX_BD_TL) { in ethoc_update_rx_stats()
379 dev_err(&netdev->dev, "RX: frame too long\n"); in ethoc_update_rx_stats()
380 netdev->stats.rx_length_errors++; in ethoc_update_rx_stats()
384 if (bd->stat & RX_BD_SF) { in ethoc_update_rx_stats()
385 dev_err(&netdev->dev, "RX: frame too short\n"); in ethoc_update_rx_stats()
386 netdev->stats.rx_length_errors++; in ethoc_update_rx_stats()
390 if (bd->stat & RX_BD_DN) { in ethoc_update_rx_stats()
391 dev_err(&netdev->dev, "RX: dribble nibble\n"); in ethoc_update_rx_stats()
392 netdev->stats.rx_frame_errors++; in ethoc_update_rx_stats()
395 if (bd->stat & RX_BD_CRC) { in ethoc_update_rx_stats()
396 dev_err(&netdev->dev, "RX: wrong CRC\n"); in ethoc_update_rx_stats()
397 netdev->stats.rx_crc_errors++; in ethoc_update_rx_stats()
401 if (bd->stat & RX_BD_OR) { in ethoc_update_rx_stats()
402 dev_err(&netdev->dev, "RX: overrun\n"); in ethoc_update_rx_stats()
403 netdev->stats.rx_over_errors++; in ethoc_update_rx_stats()
407 if (bd->stat & RX_BD_MISS) in ethoc_update_rx_stats()
408 netdev->stats.rx_missed_errors++; in ethoc_update_rx_stats()
410 if (bd->stat & RX_BD_LC) { in ethoc_update_rx_stats()
411 dev_err(&netdev->dev, "RX: late collision\n"); in ethoc_update_rx_stats()
412 netdev->stats.collisions++; in ethoc_update_rx_stats()
428 entry = priv->num_tx + priv->cur_rx; in ethoc_rx()
434 * risk missing the packet as the RX interrupt won't in ethoc_rx()
448 size -= 4; /* strip the CRC */ in ethoc_rx()
452 void *src = priv->vma[entry]; in ethoc_rx()
454 skb->protocol = eth_type_trans(skb, dev); in ethoc_rx()
455 dev->stats.rx_packets++; in ethoc_rx()
456 dev->stats.rx_bytes += size; in ethoc_rx()
460 dev_warn(&dev->dev, in ethoc_rx()
461 "low on memory - packet dropped\n"); in ethoc_rx()
463 dev->stats.rx_dropped++; in ethoc_rx()
472 if (++priv->cur_rx == priv->num_rx) in ethoc_rx()
473 priv->cur_rx = 0; in ethoc_rx()
481 struct net_device *netdev = dev->netdev; in ethoc_update_tx_stats()
483 if (bd->stat & TX_BD_LC) { in ethoc_update_tx_stats()
484 dev_err(&netdev->dev, "TX: late collision\n"); in ethoc_update_tx_stats()
485 netdev->stats.tx_window_errors++; in ethoc_update_tx_stats()
488 if (bd->stat & TX_BD_RL) { in ethoc_update_tx_stats()
489 dev_err(&netdev->dev, "TX: retransmit limit\n"); in ethoc_update_tx_stats()
490 netdev->stats.tx_aborted_errors++; in ethoc_update_tx_stats()
493 if (bd->stat & TX_BD_UR) { in ethoc_update_tx_stats()
494 dev_err(&netdev->dev, "TX: underrun\n"); in ethoc_update_tx_stats()
495 netdev->stats.tx_fifo_errors++; in ethoc_update_tx_stats()
498 if (bd->stat & TX_BD_CS) { in ethoc_update_tx_stats()
499 dev_err(&netdev->dev, "TX: carrier sense lost\n"); in ethoc_update_tx_stats()
500 netdev->stats.tx_carrier_errors++; in ethoc_update_tx_stats()
503 if (bd->stat & TX_BD_STATS) in ethoc_update_tx_stats()
504 netdev->stats.tx_errors++; in ethoc_update_tx_stats()
506 netdev->stats.collisions += (bd->stat >> 4) & 0xf; in ethoc_update_tx_stats()
507 netdev->stats.tx_bytes += bd->stat >> 16; in ethoc_update_tx_stats()
508 netdev->stats.tx_packets++; in ethoc_update_tx_stats()
520 entry = priv->dty_tx & (priv->num_tx-1); in ethoc_tx()
524 if (bd.stat & TX_BD_READY || (priv->dty_tx == priv->cur_tx)) { in ethoc_tx()
535 (priv->dty_tx == priv->cur_tx)) in ethoc_tx()
540 priv->dty_tx++; in ethoc_tx()
543 if ((priv->cur_tx - priv->dty_tx) <= (priv->num_tx / 2)) in ethoc_tx()
575 dev_dbg(&dev->dev, "packet dropped\n"); in ethoc_interrupt()
576 dev->stats.rx_dropped++; in ethoc_interrupt()
582 napi_schedule(&priv->napi); in ethoc_interrupt()
591 u8 *mac = (u8 *)addr; in ethoc_get_mac_address() local
595 mac[2] = (reg >> 24) & 0xff; in ethoc_get_mac_address()
596 mac[3] = (reg >> 16) & 0xff; in ethoc_get_mac_address()
597 mac[4] = (reg >> 8) & 0xff; in ethoc_get_mac_address()
598 mac[5] = (reg >> 0) & 0xff; in ethoc_get_mac_address()
601 mac[0] = (reg >> 8) & 0xff; in ethoc_get_mac_address()
602 mac[1] = (reg >> 0) & 0xff; in ethoc_get_mac_address()
613 rx_work_done = ethoc_rx(priv->netdev, budget); in ethoc_poll()
614 tx_work_done = ethoc_tx(priv->netdev, budget); in ethoc_poll()
626 struct ethoc *priv = bus->priv; in ethoc_mdio_read()
643 return -EBUSY; in ethoc_mdio_read()
648 struct ethoc *priv = bus->priv; in ethoc_mdio_write()
665 return -EBUSY; in ethoc_mdio_write()
671 struct phy_device *phydev = dev->phydev; in ethoc_mdio_poll()
675 if (priv->old_link != phydev->link) { in ethoc_mdio_poll()
677 priv->old_link = phydev->link; in ethoc_mdio_poll()
680 if (priv->old_duplex != phydev->duplex) { in ethoc_mdio_poll()
682 priv->old_duplex = phydev->duplex; in ethoc_mdio_poll()
689 if (phydev->duplex == DUPLEX_FULL) in ethoc_mdio_poll()
704 if (priv->phy_id != -1) in ethoc_mdio_probe()
705 phy = mdiobus_get_phy(priv->mdio, priv->phy_id); in ethoc_mdio_probe()
707 phy = phy_find_first(priv->mdio); in ethoc_mdio_probe()
710 dev_err(&dev->dev, "no PHY found\n"); in ethoc_mdio_probe()
711 return -ENXIO; in ethoc_mdio_probe()
714 priv->old_duplex = -1; in ethoc_mdio_probe()
715 priv->old_link = -1; in ethoc_mdio_probe()
720 dev_err(&dev->dev, "could not attach to PHY\n"); in ethoc_mdio_probe()
724 phy->advertising &= ~(ADVERTISED_1000baseT_Full | in ethoc_mdio_probe()
726 phy->supported &= ~(SUPPORTED_1000baseT_Full | in ethoc_mdio_probe()
737 ret = request_irq(dev->irq, ethoc_interrupt, IRQF_SHARED, in ethoc_open()
738 dev->name, dev); in ethoc_open()
742 napi_enable(&priv->napi); in ethoc_open()
744 ethoc_init_ring(priv, dev->mem_start); in ethoc_open()
748 dev_dbg(&dev->dev, " resuming queue\n"); in ethoc_open()
751 dev_dbg(&dev->dev, " starting queue\n"); in ethoc_open()
755 priv->old_link = -1; in ethoc_open()
756 priv->old_duplex = -1; in ethoc_open()
758 phy_start(dev->phydev); in ethoc_open()
761 dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", in ethoc_open()
762 dev->base_addr, dev->mem_start, dev->mem_end); in ethoc_open()
772 napi_disable(&priv->napi); in ethoc_stop()
774 if (dev->phydev) in ethoc_stop()
775 phy_stop(dev->phydev); in ethoc_stop()
778 free_irq(dev->irq, dev); in ethoc_stop()
793 return -EINVAL; in ethoc_ioctl()
796 if (mdio->phy_id >= PHY_MAX_ADDR) in ethoc_ioctl()
797 return -ERANGE; in ethoc_ioctl()
799 phy = mdiobus_get_phy(priv->mdio, mdio->phy_id); in ethoc_ioctl()
801 return -ENODEV; in ethoc_ioctl()
803 phy = dev->phydev; in ethoc_ioctl()
812 unsigned char *mac = dev->dev_addr; in ethoc_do_set_mac_address() local
814 ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) | in ethoc_do_set_mac_address()
815 (mac[4] << 8) | (mac[5] << 0)); in ethoc_do_set_mac_address()
816 ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0)); in ethoc_do_set_mac_address()
823 if (!is_valid_ether_addr(addr->sa_data)) in ethoc_set_mac_address()
824 return -EADDRNOTAVAIL; in ethoc_set_mac_address()
825 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); in ethoc_set_mac_address()
838 if (dev->flags & IFF_LOOPBACK) in ethoc_set_multicast_list()
844 if (dev->flags & IFF_BROADCAST) in ethoc_set_multicast_list()
850 if (dev->flags & IFF_PROMISC) in ethoc_set_multicast_list()
858 if (dev->flags & IFF_ALLMULTI) { in ethoc_set_multicast_list()
863 u32 crc = ether_crc(ETH_ALEN, ha->addr); in ethoc_set_multicast_list()
875 return -ENOSYS; in ethoc_change_mtu()
883 ethoc_interrupt(dev->irq, dev); in ethoc_tx_timeout()
894 dev->stats.tx_errors++; in ethoc_start_xmit()
898 if (unlikely(skb->len > ETHOC_BUFSIZ)) { in ethoc_start_xmit()
899 dev->stats.tx_errors++; in ethoc_start_xmit()
903 entry = priv->cur_tx % priv->num_tx; in ethoc_start_xmit()
904 spin_lock_irq(&priv->lock); in ethoc_start_xmit()
905 priv->cur_tx++; in ethoc_start_xmit()
908 if (unlikely(skb->len < ETHOC_ZLEN)) in ethoc_start_xmit()
913 dest = priv->vma[entry]; in ethoc_start_xmit()
914 memcpy_toio(dest, skb->data, skb->len); in ethoc_start_xmit()
917 bd.stat |= TX_BD_LEN(skb->len); in ethoc_start_xmit()
923 if (priv->cur_tx == (priv->dty_tx + priv->num_tx)) { in ethoc_start_xmit()
924 dev_dbg(&dev->dev, "stopping queue\n"); in ethoc_start_xmit()
928 spin_unlock_irq(&priv->lock); in ethoc_start_xmit()
948 regs->version = 0; in ethoc_get_regs()
958 ring->rx_max_pending = priv->num_bd - 1; in ethoc_get_ringparam()
959 ring->rx_mini_max_pending = 0; in ethoc_get_ringparam()
960 ring->rx_jumbo_max_pending = 0; in ethoc_get_ringparam()
961 ring->tx_max_pending = priv->num_bd - 1; in ethoc_get_ringparam()
963 ring->rx_pending = priv->num_rx; in ethoc_get_ringparam()
964 ring->rx_mini_pending = 0; in ethoc_get_ringparam()
965 ring->rx_jumbo_pending = 0; in ethoc_get_ringparam()
966 ring->tx_pending = priv->num_tx; in ethoc_get_ringparam()
974 if (ring->tx_pending < 1 || ring->rx_pending < 1 || in ethoc_set_ringparam()
975 ring->tx_pending + ring->rx_pending > priv->num_bd) in ethoc_set_ringparam()
976 return -EINVAL; in ethoc_set_ringparam()
977 if (ring->rx_mini_pending || ring->rx_jumbo_pending) in ethoc_set_ringparam()
978 return -EINVAL; in ethoc_set_ringparam()
984 synchronize_irq(dev->irq); in ethoc_set_ringparam()
987 priv->num_tx = rounddown_pow_of_two(ring->tx_pending); in ethoc_set_ringparam()
988 priv->num_rx = ring->rx_pending; in ethoc_set_ringparam()
989 ethoc_init_ring(priv, dev->mem_start); in ethoc_set_ringparam()
1023 * ethoc_probe - initialize OpenCores ethernet MAC
1035 struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev); in ethoc_probe()
1036 u32 eth_clkfreq = pdata ? pdata->eth_clkfreq : 0; in ethoc_probe()
1041 ret = -ENOMEM; in ethoc_probe()
1045 SET_NETDEV_DEV(netdev, &pdev->dev); in ethoc_probe()
1051 dev_err(&pdev->dev, "cannot obtain I/O memory space\n"); in ethoc_probe()
1052 ret = -ENXIO; in ethoc_probe()
1056 mmio = devm_request_mem_region(&pdev->dev, res->start, in ethoc_probe()
1057 resource_size(res), res->name); in ethoc_probe()
1059 dev_err(&pdev->dev, "cannot request I/O memory space\n"); in ethoc_probe()
1060 ret = -ENXIO; in ethoc_probe()
1064 netdev->base_addr = mmio->start; in ethoc_probe()
1069 mem = devm_request_mem_region(&pdev->dev, res->start, in ethoc_probe()
1070 resource_size(res), res->name); in ethoc_probe()
1072 dev_err(&pdev->dev, "cannot request memory space\n"); in ethoc_probe()
1073 ret = -ENXIO; in ethoc_probe()
1077 netdev->mem_start = mem->start; in ethoc_probe()
1078 netdev->mem_end = mem->end; in ethoc_probe()
1085 dev_err(&pdev->dev, "cannot obtain IRQ\n"); in ethoc_probe()
1086 ret = -ENXIO; in ethoc_probe()
1090 netdev->irq = res->start; in ethoc_probe()
1092 /* setup driver-private data */ in ethoc_probe()
1094 priv->netdev = netdev; in ethoc_probe()
1096 priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, in ethoc_probe()
1098 if (!priv->iobase) { in ethoc_probe()
1099 dev_err(&pdev->dev, "cannot remap I/O memory space\n"); in ethoc_probe()
1100 ret = -ENXIO; in ethoc_probe()
1104 if (netdev->mem_end) { in ethoc_probe()
1105 priv->membase = devm_ioremap_nocache(&pdev->dev, in ethoc_probe()
1106 netdev->mem_start, resource_size(mem)); in ethoc_probe()
1107 if (!priv->membase) { in ethoc_probe()
1108 dev_err(&pdev->dev, "cannot remap memory space\n"); in ethoc_probe()
1109 ret = -ENXIO; in ethoc_probe()
1114 priv->membase = dmam_alloc_coherent(&pdev->dev, in ethoc_probe()
1115 buffer_size, (void *)&netdev->mem_start, in ethoc_probe()
1117 if (!priv->membase) { in ethoc_probe()
1118 dev_err(&pdev->dev, "cannot allocate %dB buffer\n", in ethoc_probe()
1120 ret = -ENOMEM; in ethoc_probe()
1123 netdev->mem_end = netdev->mem_start + buffer_size; in ethoc_probe()
1126 priv->big_endian = pdata ? pdata->big_endian : in ethoc_probe()
1127 of_device_is_big_endian(pdev->dev.of_node); in ethoc_probe()
1129 /* calculate the number of TX/RX buffers, maximum 128 supported */ in ethoc_probe()
1131 128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ); in ethoc_probe()
1133 ret = -ENODEV; in ethoc_probe()
1136 priv->num_bd = num_bd; in ethoc_probe()
1138 priv->num_tx = rounddown_pow_of_two(num_bd >> 1); in ethoc_probe()
1139 priv->num_rx = num_bd - priv->num_tx; in ethoc_probe()
1141 dev_dbg(&pdev->dev, "ethoc: num_tx: %d num_rx: %d\n", in ethoc_probe()
1142 priv->num_tx, priv->num_rx); in ethoc_probe()
1144 priv->vma = devm_kcalloc(&pdev->dev, num_bd, sizeof(void *), in ethoc_probe()
1146 if (!priv->vma) { in ethoc_probe()
1147 ret = -ENOMEM; in ethoc_probe()
1151 /* Allow the platform setup code to pass in a MAC address. */ in ethoc_probe()
1153 ether_addr_copy(netdev->dev_addr, pdata->hwaddr); in ethoc_probe()
1154 priv->phy_id = pdata->phy_id; in ethoc_probe()
1156 const void *mac; in ethoc_probe() local
1158 mac = of_get_mac_address(pdev->dev.of_node); in ethoc_probe()
1159 if (mac) in ethoc_probe()
1160 ether_addr_copy(netdev->dev_addr, mac); in ethoc_probe()
1161 priv->phy_id = -1; in ethoc_probe()
1164 /* Check that the given MAC address is valid. If it isn't, read the in ethoc_probe()
1165 * current MAC from the controller. in ethoc_probe()
1167 if (!is_valid_ether_addr(netdev->dev_addr)) in ethoc_probe()
1168 ethoc_get_mac_address(netdev, netdev->dev_addr); in ethoc_probe()
1170 /* Check the MAC again for validity, if it still isn't choose and in ethoc_probe()
1173 if (!is_valid_ether_addr(netdev->dev_addr)) in ethoc_probe()
1180 struct clk *clk = devm_clk_get(&pdev->dev, NULL); in ethoc_probe() local
1182 if (!IS_ERR(clk)) { in ethoc_probe()
1183 priv->clk = clk; in ethoc_probe()
1184 clk_prepare_enable(clk); in ethoc_probe()
1185 eth_clkfreq = clk_get_rate(clk); in ethoc_probe()
1193 dev_dbg(&pdev->dev, "setting MII clkdiv to %u\n", clkdiv); in ethoc_probe()
1200 priv->mdio = mdiobus_alloc(); in ethoc_probe()
1201 if (!priv->mdio) { in ethoc_probe()
1202 ret = -ENOMEM; in ethoc_probe()
1206 priv->mdio->name = "ethoc-mdio"; in ethoc_probe()
1207 snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "%s-%d", in ethoc_probe()
1208 priv->mdio->name, pdev->id); in ethoc_probe()
1209 priv->mdio->read = ethoc_mdio_read; in ethoc_probe()
1210 priv->mdio->write = ethoc_mdio_write; in ethoc_probe()
1211 priv->mdio->priv = priv; in ethoc_probe()
1213 ret = mdiobus_register(priv->mdio); in ethoc_probe()
1215 dev_err(&netdev->dev, "failed to register MDIO bus\n"); in ethoc_probe()
1221 dev_err(&netdev->dev, "failed to probe MDIO bus\n"); in ethoc_probe()
1226 netdev->netdev_ops = ðoc_netdev_ops; in ethoc_probe()
1227 netdev->watchdog_timeo = ETHOC_TIMEOUT; in ethoc_probe()
1228 netdev->features |= 0; in ethoc_probe()
1229 netdev->ethtool_ops = ðoc_ethtool_ops; in ethoc_probe()
1232 netif_napi_add(netdev, &priv->napi, ethoc_poll, 64); in ethoc_probe()
1234 spin_lock_init(&priv->lock); in ethoc_probe()
1238 dev_err(&netdev->dev, "failed to register interface\n"); in ethoc_probe()
1245 netif_napi_del(&priv->napi); in ethoc_probe()
1247 mdiobus_unregister(priv->mdio); in ethoc_probe()
1248 mdiobus_free(priv->mdio); in ethoc_probe()
1250 clk_disable_unprepare(priv->clk); in ethoc_probe()
1258 * ethoc_remove - shutdown OpenCores ethernet MAC
1267 netif_napi_del(&priv->napi); in ethoc_remove()
1268 phy_disconnect(netdev->phydev); in ethoc_remove()
1270 if (priv->mdio) { in ethoc_remove()
1271 mdiobus_unregister(priv->mdio); in ethoc_remove()
1272 mdiobus_free(priv->mdio); in ethoc_remove()
1274 clk_disable_unprepare(priv->clk); in ethoc_remove()
1285 return -ENOSYS; in ethoc_suspend()
1290 return -ENOSYS; in ethoc_resume()
1316 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
1317 MODULE_DESCRIPTION("OpenCores Ethernet MAC driver");