Lines Matching +full:mac +full:- +full:divider
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * RDC R6040 Fast Ethernet MAC support
7 * Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
8 * Copyright (C) 2007-2012 Florian Fainelli <f.fainelli@gmail.com>
43 /* RDC MAC I/O Size */
46 /* MAX RDC MAC */
49 /* MAC registers */
57 #define MAC_RST 0x0001 /* Reset the MAC */
62 #define TM2TX 0x0001 /* Trigger MAC to transmit */
66 #define TX_FIFO_UNDR 0x0200 /* TX FIFO under-run */
118 #define TMRDIV_SHIFT 0 /* Timer divider shift */
120 #define MAC_SM 0xAC /* MAC status machine */
121 #define MAC_SM_RST 0x0002 /* MAC status machine reset */
131 #define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */
134 #define MAC_DEF_TIMEOUT 2048 /* Default MAC read/write operation timeout */
137 #define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */
152 "Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>,"
164 u16 status, len; /* 0-3 */
165 __le32 buf; /* 4-7 */
166 __le32 ndesc; /* 8-B */
167 u32 rev1; /* C-F */
168 char *vbufp; /* 10-13 */
169 struct r6040_descriptor *vndescp; /* 14-17 */
170 struct sk_buff *skb_ptr; /* 18-1B */
171 u32 rev2; /* 1C-1F */
207 while (limit--) { in r6040_phy_read()
215 return -ETIMEDOUT; in r6040_phy_read()
231 while (limit--) { in r6040_phy_write()
238 return (limit < 0) ? -ETIMEDOUT : 0; in r6040_phy_write()
243 struct net_device *dev = bus->priv; in r6040_mdiobus_read()
245 void __iomem *ioaddr = lp->base; in r6040_mdiobus_read()
253 struct net_device *dev = bus->priv; in r6040_mdiobus_write()
255 void __iomem *ioaddr = lp->base; in r6040_mdiobus_write()
266 if (lp->tx_insert_ptr->skb_ptr) { in r6040_free_txbufs()
267 dma_unmap_single(&lp->pdev->dev, in r6040_free_txbufs()
268 le32_to_cpu(lp->tx_insert_ptr->buf), in r6040_free_txbufs()
270 dev_kfree_skb(lp->tx_insert_ptr->skb_ptr); in r6040_free_txbufs()
271 lp->tx_insert_ptr->skb_ptr = NULL; in r6040_free_txbufs()
273 lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp; in r6040_free_txbufs()
283 if (lp->rx_insert_ptr->skb_ptr) { in r6040_free_rxbufs()
284 dma_unmap_single(&lp->pdev->dev, in r6040_free_rxbufs()
285 le32_to_cpu(lp->rx_insert_ptr->buf), in r6040_free_rxbufs()
287 dev_kfree_skb(lp->rx_insert_ptr->skb_ptr); in r6040_free_rxbufs()
288 lp->rx_insert_ptr->skb_ptr = NULL; in r6040_free_rxbufs()
290 lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp; in r6040_free_rxbufs()
300 while (size-- > 0) { in r6040_init_ring_desc()
302 desc->ndesc = cpu_to_le32(mapping); in r6040_init_ring_desc()
303 desc->vndescp = desc + 1; in r6040_init_ring_desc()
306 desc--; in r6040_init_ring_desc()
307 desc->ndesc = cpu_to_le32(desc_dma); in r6040_init_ring_desc()
308 desc->vndescp = desc_ring; in r6040_init_ring_desc()
315 lp->tx_free_desc = TX_DCNT; in r6040_init_txbufs()
317 lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring; in r6040_init_txbufs()
318 r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT); in r6040_init_txbufs()
328 lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring; in r6040_alloc_rxbufs()
329 r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT); in r6040_alloc_rxbufs()
332 desc = lp->rx_ring; in r6040_alloc_rxbufs()
336 rc = -ENOMEM; in r6040_alloc_rxbufs()
339 desc->skb_ptr = skb; in r6040_alloc_rxbufs()
340 desc->buf = cpu_to_le32(dma_map_single(&lp->pdev->dev, in r6040_alloc_rxbufs()
341 desc->skb_ptr->data, in r6040_alloc_rxbufs()
344 desc->status = DSC_OWNER_MAC; in r6040_alloc_rxbufs()
345 desc = desc->vndescp; in r6040_alloc_rxbufs()
346 } while (desc != lp->rx_ring); in r6040_alloc_rxbufs()
358 void __iomem *ioaddr = lp->base; in r6040_reset_mac()
364 while (limit--) { in r6040_reset_mac()
383 void __iomem *ioaddr = lp->base; in r6040_init_mac_regs()
388 /* Reset RDC MAC */ in r6040_init_mac_regs()
391 /* MAC Bus Control Register */ in r6040_init_mac_regs()
398 iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0); in r6040_init_mac_regs()
399 iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1); in r6040_init_mac_regs()
402 iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0); in r6040_init_mac_regs()
403 iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1); in r6040_init_mac_regs()
413 iowrite16(lp->mcr0 | MCR0_RCVEN, ioaddr); in r6040_init_mac_regs()
424 void __iomem *ioaddr = priv->base; in r6040_tx_timeout()
431 dev->stats.tx_errors++; in r6040_tx_timeout()
433 /* Reset MAC and re-init all registers */ in r6040_tx_timeout()
440 void __iomem *ioaddr = priv->base; in r6040_get_stats()
443 spin_lock_irqsave(&priv->lock, flags); in r6040_get_stats()
444 dev->stats.rx_crc_errors += ioread8(ioaddr + ME_CNT1); in r6040_get_stats()
445 dev->stats.multicast += ioread8(ioaddr + ME_CNT0); in r6040_get_stats()
446 spin_unlock_irqrestore(&priv->lock, flags); in r6040_get_stats()
448 return &dev->stats; in r6040_get_stats()
451 /* Stop RDC MAC and Free the allocated resource */
455 void __iomem *ioaddr = lp->base; in r6040_down()
458 /* Stop MAC */ in r6040_down()
461 /* Reset RDC MAC */ in r6040_down()
464 /* Restore MAC Address to MIDx */ in r6040_down()
465 adrp = (const u16 *) dev->dev_addr; in r6040_down()
474 struct pci_dev *pdev = lp->pdev; in r6040_close()
476 phy_stop(dev->phydev); in r6040_close()
477 napi_disable(&lp->napi); in r6040_close()
480 spin_lock_irq(&lp->lock); in r6040_close()
489 spin_unlock_irq(&lp->lock); in r6040_close()
491 free_irq(dev->irq, dev); in r6040_close()
494 if (lp->rx_ring) { in r6040_close()
495 dma_free_coherent(&pdev->dev, RX_DESC_SIZE, lp->rx_ring, in r6040_close()
496 lp->rx_ring_dma); in r6040_close()
497 lp->rx_ring = NULL; in r6040_close()
500 if (lp->tx_ring) { in r6040_close()
501 dma_free_coherent(&pdev->dev, TX_DESC_SIZE, lp->tx_ring, in r6040_close()
502 lp->tx_ring_dma); in r6040_close()
503 lp->tx_ring = NULL; in r6040_close()
512 struct r6040_descriptor *descptr = priv->rx_remove_ptr; in r6040_rx()
518 while (count < limit && !(descptr->status & DSC_OWNER_MAC)) { in r6040_rx()
520 err = descptr->status; in r6040_rx()
525 dev->stats.rx_frame_errors++; in r6040_rx()
528 dev->stats.rx_length_errors++; in r6040_rx()
531 dev->stats.rx_length_errors++; in r6040_rx()
534 dev->stats.rx_length_errors++; in r6040_rx()
537 spin_lock(&priv->lock); in r6040_rx()
538 dev->stats.rx_crc_errors++; in r6040_rx()
539 spin_unlock(&priv->lock); in r6040_rx()
547 dev->stats.rx_dropped++; in r6040_rx()
550 skb_ptr = descptr->skb_ptr; in r6040_rx()
551 skb_ptr->dev = priv->dev; in r6040_rx()
554 skb_put(skb_ptr, descptr->len - ETH_FCS_LEN); in r6040_rx()
555 dma_unmap_single(&priv->pdev->dev, le32_to_cpu(descptr->buf), in r6040_rx()
557 skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev); in r6040_rx()
561 dev->stats.rx_packets++; in r6040_rx()
562 dev->stats.rx_bytes += descptr->len - ETH_FCS_LEN; in r6040_rx()
565 descptr->skb_ptr = new_skb; in r6040_rx()
566 descptr->buf = cpu_to_le32(dma_map_single(&priv->pdev->dev, in r6040_rx()
567 descptr->skb_ptr->data, in r6040_rx()
572 /* put the descriptor back to the MAC */ in r6040_rx()
573 descptr->status = DSC_OWNER_MAC; in r6040_rx()
574 descptr = descptr->vndescp; in r6040_rx()
577 priv->rx_remove_ptr = descptr; in r6040_rx()
586 void __iomem *ioaddr = priv->base; in r6040_tx()
590 spin_lock(&priv->lock); in r6040_tx()
591 descptr = priv->tx_remove_ptr; in r6040_tx()
592 while (priv->tx_free_desc < TX_DCNT) { in r6040_tx()
597 dev->stats.tx_fifo_errors++; in r6040_tx()
599 dev->stats.tx_carrier_errors++; in r6040_tx()
601 if (descptr->status & DSC_OWNER_MAC) in r6040_tx()
603 skb_ptr = descptr->skb_ptr; in r6040_tx()
606 dev->stats.tx_packets++; in r6040_tx()
607 dev->stats.tx_bytes += skb_ptr->len; in r6040_tx()
609 dma_unmap_single(&priv->pdev->dev, le32_to_cpu(descptr->buf), in r6040_tx()
610 skb_ptr->len, DMA_TO_DEVICE); in r6040_tx()
613 descptr->skb_ptr = NULL; in r6040_tx()
615 descptr = descptr->vndescp; in r6040_tx()
616 priv->tx_free_desc++; in r6040_tx()
618 priv->tx_remove_ptr = descptr; in r6040_tx()
620 if (priv->tx_free_desc) in r6040_tx()
622 spin_unlock(&priv->lock); in r6040_tx()
629 struct net_device *dev = priv->dev; in r6040_poll()
630 void __iomem *ioaddr = priv->base; in r6040_poll()
651 void __iomem *ioaddr = lp->base; in r6040_interrupt()
656 /* Mask off RDC MAC interrupt */ in r6040_interrupt()
662 /* Restore RDC MAC interrupt */ in r6040_interrupt()
671 dev->stats.rx_dropped++; in r6040_interrupt()
672 dev->stats.rx_missed_errors++; in r6040_interrupt()
675 dev->stats.rx_fifo_errors++; in r6040_interrupt()
677 if (likely(napi_schedule_prep(&lp->napi))) { in r6040_interrupt()
680 __napi_schedule_irqoff(&lp->napi); in r6040_interrupt()
684 /* Restore RDC MAC interrupt */ in r6040_interrupt()
693 disable_irq(dev->irq); in r6040_poll_controller()
694 r6040_interrupt(dev->irq, dev); in r6040_poll_controller()
695 enable_irq(dev->irq); in r6040_poll_controller()
699 /* Init RDC MAC */
703 void __iomem *ioaddr = lp->base; in r6040_up()
720 /* Initialize all MAC registers */ in r6040_up()
723 phy_start(dev->phydev); in r6040_up()
729 /* Read/set MAC address routines */
733 void __iomem *ioaddr = lp->base; in r6040_mac_address()
736 /* Reset MAC */ in r6040_mac_address()
739 /* Restore MAC Address */ in r6040_mac_address()
740 adrp = (const u16 *) dev->dev_addr; in r6040_mac_address()
752 ret = request_irq(dev->irq, r6040_interrupt, in r6040_open()
753 IRQF_SHARED, dev->name, dev); in r6040_open()
757 /* Set MAC address */ in r6040_open()
761 lp->rx_ring = in r6040_open()
762 dma_alloc_coherent(&lp->pdev->dev, RX_DESC_SIZE, in r6040_open()
763 &lp->rx_ring_dma, GFP_KERNEL); in r6040_open()
764 if (!lp->rx_ring) { in r6040_open()
765 ret = -ENOMEM; in r6040_open()
769 lp->tx_ring = in r6040_open()
770 dma_alloc_coherent(&lp->pdev->dev, TX_DESC_SIZE, in r6040_open()
771 &lp->tx_ring_dma, GFP_KERNEL); in r6040_open()
772 if (!lp->tx_ring) { in r6040_open()
773 ret = -ENOMEM; in r6040_open()
781 napi_enable(&lp->napi); in r6040_open()
787 dma_free_coherent(&lp->pdev->dev, TX_DESC_SIZE, lp->tx_ring, in r6040_open()
788 lp->tx_ring_dma); in r6040_open()
790 dma_free_coherent(&lp->pdev->dev, RX_DESC_SIZE, lp->rx_ring, in r6040_open()
791 lp->rx_ring_dma); in r6040_open()
793 free_irq(dev->irq, dev); in r6040_open()
803 void __iomem *ioaddr = lp->base; in r6040_start_xmit()
810 spin_lock_irqsave(&lp->lock, flags); in r6040_start_xmit()
813 if (!lp->tx_free_desc) { in r6040_start_xmit()
814 spin_unlock_irqrestore(&lp->lock, flags); in r6040_start_xmit()
821 lp->tx_free_desc--; in r6040_start_xmit()
822 descptr = lp->tx_insert_ptr; in r6040_start_xmit()
823 descptr->len = skb->len; in r6040_start_xmit()
824 descptr->skb_ptr = skb; in r6040_start_xmit()
825 descptr->buf = cpu_to_le32(dma_map_single(&lp->pdev->dev, skb->data, in r6040_start_xmit()
826 skb->len, DMA_TO_DEVICE)); in r6040_start_xmit()
827 descptr->status = DSC_OWNER_MAC; in r6040_start_xmit()
831 /* Trigger the MAC to check the TX descriptor */ in r6040_start_xmit()
834 lp->tx_insert_ptr = descptr->vndescp; in r6040_start_xmit()
837 if (!lp->tx_free_desc) in r6040_start_xmit()
840 spin_unlock_irqrestore(&lp->lock, flags); in r6040_start_xmit()
848 void __iomem *ioaddr = lp->base; in r6040_multicast_list()
855 spin_lock_irqsave(&lp->lock, flags); in r6040_multicast_list()
857 /* Keep our MAC Address */ in r6040_multicast_list()
858 adrp = (const u16 *)dev->dev_addr; in r6040_multicast_list()
864 lp->mcr0 = ioread16(ioaddr + MCR0) & ~(MCR0_PROMISC | MCR0_HASH_EN); in r6040_multicast_list()
867 if (dev->flags & IFF_PROMISC) in r6040_multicast_list()
868 lp->mcr0 |= MCR0_PROMISC; in r6040_multicast_list()
872 else if (dev->flags & IFF_ALLMULTI) { in r6040_multicast_list()
873 lp->mcr0 |= MCR0_HASH_EN; in r6040_multicast_list()
889 u16 *adrp = (u16 *) ha->addr; in r6040_multicast_list()
906 lp->mcr0 |= MCR0_HASH_EN; in r6040_multicast_list()
916 u8 *addrs = ha->addr; in r6040_multicast_list()
924 iowrite16(lp->mcr0, ioaddr + MCR0); in r6040_multicast_list()
926 /* Fill the MAC hash tables with their values */ in r6040_multicast_list()
927 if (lp->mcr0 & MCR0_HASH_EN) { in r6040_multicast_list()
934 spin_unlock_irqrestore(&lp->lock, flags); in r6040_multicast_list()
942 strscpy(info->driver, DRV_NAME, sizeof(info->driver)); in netdev_get_drvinfo()
943 strscpy(info->version, DRV_VERSION, sizeof(info->version)); in netdev_get_drvinfo()
944 strscpy(info->bus_info, pci_name(rp->pdev), sizeof(info->bus_info)); in netdev_get_drvinfo()
974 struct phy_device *phydev = dev->phydev; in r6040_adjust_link()
976 void __iomem *ioaddr = lp->base; in r6040_adjust_link()
980 if (lp->old_link != phydev->link) { in r6040_adjust_link()
982 lp->old_link = phydev->link; in r6040_adjust_link()
986 if (phydev->link && (lp->old_duplex != phydev->duplex)) { in r6040_adjust_link()
987 lp->mcr0 |= (phydev->duplex == DUPLEX_FULL ? MCR0_FD : 0); in r6040_adjust_link()
988 iowrite16(lp->mcr0, ioaddr); in r6040_adjust_link()
991 lp->old_duplex = phydev->duplex; in r6040_adjust_link()
1003 phydev = phy_find_first(lp->mii_bus); in r6040_mii_probe()
1005 dev_err(&lp->pdev->dev, "no PHY found\n"); in r6040_mii_probe()
1006 return -ENODEV; in r6040_mii_probe()
1013 dev_err(&lp->pdev->dev, "could not attach to PHY\n"); in r6040_mii_probe()
1019 lp->old_link = 0; in r6040_mii_probe()
1020 lp->old_duplex = -1; in r6040_mii_probe()
1033 static int card_idx = -1; in r6040_init_one()
1044 err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); in r6040_init_one()
1046 dev_err(&pdev->dev, "32-bit PCI DMA addresses not supported by the card\n"); in r6040_init_one()
1049 err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); in r6040_init_one()
1051 dev_err(&pdev->dev, "32-bit PCI DMA addresses not supported by the card\n"); in r6040_init_one()
1057 dev_err(&pdev->dev, "Insufficient PCI resources, aborting\n"); in r6040_init_one()
1058 err = -EIO; in r6040_init_one()
1066 err = -ENOMEM; in r6040_init_one()
1069 SET_NETDEV_DEV(dev, &pdev->dev); in r6040_init_one()
1075 dev_err(&pdev->dev, "Failed to request PCI regions\n"); in r6040_init_one()
1081 dev_err(&pdev->dev, "ioremap failed for device\n"); in r6040_init_one()
1082 err = -EIO; in r6040_init_one()
1088 * - enable phy status change in r6040_init_one()
1089 * - enable all phy addresses in r6040_init_one()
1090 * - set to lowest timer divider */ in r6040_init_one()
1096 lp->base = ioaddr; in r6040_init_one()
1097 dev->irq = pdev->irq; in r6040_init_one()
1099 spin_lock_init(&lp->lock); in r6040_init_one()
1102 /* Set MAC address */ in r6040_init_one()
1111 * MAC address, warn about that */ in r6040_init_one()
1113 netdev_warn(dev, "MAC address not initialized, " in r6040_init_one()
1119 lp->pdev = pdev; in r6040_init_one()
1120 lp->dev = dev; in r6040_init_one()
1123 lp->mcr0 = MCR0_XMTEN | MCR0_RCVEN; in r6040_init_one()
1125 /* The RDC-specific entries in the device structure. */ in r6040_init_one()
1126 dev->netdev_ops = &r6040_netdev_ops; in r6040_init_one()
1127 dev->ethtool_ops = &netdev_ethtool_ops; in r6040_init_one()
1128 dev->watchdog_timeo = TX_TIMEOUT; in r6040_init_one()
1130 netif_napi_add(dev, &lp->napi, r6040_poll); in r6040_init_one()
1132 lp->mii_bus = mdiobus_alloc(); in r6040_init_one()
1133 if (!lp->mii_bus) { in r6040_init_one()
1134 dev_err(&pdev->dev, "mdiobus_alloc() failed\n"); in r6040_init_one()
1135 err = -ENOMEM; in r6040_init_one()
1139 lp->mii_bus->priv = dev; in r6040_init_one()
1140 lp->mii_bus->read = r6040_mdiobus_read; in r6040_init_one()
1141 lp->mii_bus->write = r6040_mdiobus_write; in r6040_init_one()
1142 lp->mii_bus->name = "r6040_eth_mii"; in r6040_init_one()
1143 snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", in r6040_init_one()
1144 dev_name(&pdev->dev), card_idx); in r6040_init_one()
1146 err = mdiobus_register(lp->mii_bus); in r6040_init_one()
1148 dev_err(&pdev->dev, "failed to register MII bus\n"); in r6040_init_one()
1154 dev_err(&pdev->dev, "failed to probe MII bus\n"); in r6040_init_one()
1158 /* Register net device. After this dev->name assign */ in r6040_init_one()
1161 dev_err(&pdev->dev, "Failed to register net device\n"); in r6040_init_one()
1167 phy_disconnect(dev->phydev); in r6040_init_one()
1169 mdiobus_unregister(lp->mii_bus); in r6040_init_one()
1171 mdiobus_free(lp->mii_bus); in r6040_init_one()
1173 netif_napi_del(&lp->napi); in r6040_init_one()
1191 phy_disconnect(dev->phydev); in r6040_remove_one()
1192 mdiobus_unregister(lp->mii_bus); in r6040_remove_one()
1193 mdiobus_free(lp->mii_bus); in r6040_remove_one()
1194 netif_napi_del(&lp->napi); in r6040_remove_one()
1195 pci_iounmap(pdev, lp->base); in r6040_remove_one()