--- a/drivers/net/ethernet/dec/tulip/Kconfig +++ b/drivers/net/ethernet/dec/tulip/Kconfig @@ -60,6 +60,14 @@ config TULIP_PCI To compile this driver as a module, choose M here. The module will be called tulip. +config TULIP_PLATFORM + tristate "DECchip Tulip (dc2114x) Platform support" + depends on HAS_IOMEM + select TULIP + select CRC32 + ---help--- + This driver is for the platform variant. + config TULIP_MWI bool "New bus configuration" depends on TULIP_PCI --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -204,6 +206,9 @@ struct tulip_chip_table tulip_tbl[] = { { "Conexant LANfinity", 256, 0x0001ebef, HAS_MII | HAS_ACPI, tulip_timer, tulip_media_task }, + { "Infineon ADM8668", 256, 0x0001a451, + MC_HASH_ONLY | COMET_MAC_ADDR, tulip_timer, tulip_media_task, }, + }; @@ -377,6 +382,11 @@ static void tulip_up(struct net_device * sizeof(tp->setup_frame), PCI_DMA_TODEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + mapping = dma_map_single(&tp->pldev->dev, tp->setup_frame, + sizeof(tp->setup_frame), + DMA_TO_DEVICE); +#endif tp->tx_buffers[tp->cur_tx].skb = NULL; tp->tx_buffers[tp->cur_tx].mapping = mapping; @@ -396,6 +406,7 @@ static void tulip_up(struct net_device * i = 0; if (tp->mtable == NULL) goto media_picked; + if (dev->if_port) { int looking_for = tulip_media_cap[dev->if_port] & MediaIsMII ? 11 : (dev->if_port == 12 ? 0 : dev->if_port); @@ -489,6 +500,10 @@ media_picked: iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88); dev->if_port = tp->mii_cnt ? 11 : 0; tp->csr6 = 0x00040000; + } else if (tp->chip_id == ADM8668) { + /* Enable automatic Tx underrun recovery. */ + iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88); + tp->csr6 = 0x00040000; } else if (tp->chip_id == AX88140) { tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; } else @@ -660,6 +675,10 @@ static void tulip_init_ring(struct net_d mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + mapping = dma_map_single(&tp->pldev->dev, skb->data, + PKT_BUF_SZ, DMA_FROM_DEVICE); +#endif tp->rx_buffers[i].mapping = mapping; tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */ tp->rx_ring[i].buffer1 = cpu_to_le32(mapping); @@ -696,6 +715,11 @@ tulip_start_xmit(struct sk_buff *skb, st mapping = pci_map_single(tp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + mapping = dma_map_single(&tp->pldev->dev, skb->data, + skb->len, + DMA_TO_DEVICE); +#endif tp->tx_buffers[entry].mapping = mapping; tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); @@ -752,6 +776,13 @@ static void tulip_clean_tx_ring(struct t sizeof(tp->setup_frame), PCI_DMA_TODEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + dma_unmap_single(&tp->pldev->dev, + tp->tx_buffers[entry].mapping, + sizeof(tp->setup_frame), + DMA_TO_DEVICE); +#endif + continue; } #ifdef CONFIG_TULIP_PCI @@ -759,6 +790,11 @@ static void tulip_clean_tx_ring(struct t tp->tx_buffers[entry].skb->len, PCI_DMA_TODEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + dma_unmap_single(&tp->pldev->dev, tp->tx_buffers[entry].mapping, + tp->tx_buffers[entry].skb->len, + DMA_TO_DEVICE); +#endif /* Free the original skb. */ dev_kfree_skb_irq(tp->tx_buffers[entry].skb); @@ -836,6 +872,10 @@ static void tulip_free_ring (struct net_ pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + dma_unmap_single(&tp->pldev->dev, mapping, PKT_BUF_SZ, + DMA_FROM_DEVICE); +#endif dev_kfree_skb (skb); } } @@ -848,6 +888,10 @@ static void tulip_free_ring (struct net_ pci_unmap_single(tp->pdev, tp->tx_buffers[i].mapping, skb->len, PCI_DMA_TODEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + dma_unmap_single(&tp->pldev->dev, tp->tx_buffers[i].mapping, + skb->len, DMA_TO_DEVICE); +#endif dev_kfree_skb (skb); } tp->tx_buffers[i].skb = NULL; @@ -902,6 +946,9 @@ static void tulip_get_drvinfo(struct net #ifdef CONFIG_TULIP_PCI strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info)); #endif +#ifdef CONFIG_TULIP_PLATFORM + strlcpy(info->bus_info, "platform", sizeof(info->bus_info)); +#endif } @@ -917,6 +964,9 @@ static int tulip_ethtool_set_wol(struct #ifdef CONFIG_TULIP_PCI device_set_wakeup_enable(tp->kdev, tp->wolinfo.wolopts); #endif +#ifdef CONFIG_TULIP_PLATFORM + device_set_wakeup_enable(&tp->pldev->dev, tp->wolinfo.wolopts); +#endif return 0; } @@ -1192,13 +1242,20 @@ static void set_rx_mode(struct net_devic } +#ifdef CONFIG_TULIP_PCI tp->tx_buffers[entry].skb = NULL; tp->tx_buffers[entry].mapping = -#ifdef CONFIG_TULIP_PCI pci_map_single(tp->pdev, tp->setup_frame, sizeof(tp->setup_frame), PCI_DMA_TODEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + tp->tx_buffers[entry].skb = NULL; + tp->tx_buffers[entry].mapping = + dma_map_single(&tp->pldev->dev, tp->setup_frame, + sizeof(tp->setup_frame), + DMA_TO_DEVICE); +#endif /* Put the setup frame on the Tx list. */ if (entry == TX_RING_SIZE-1) tx_flags |= DESC_RING_WRAP; /* Wrap ring. */ @@ -1218,6 +1275,9 @@ static void set_rx_mode(struct net_devic spin_unlock_irqrestore(&tp->lock, flags); } + if (tp->chip_id == ADM8668) + csr6 |= (1 << 9); /* force 100Mbps full duplex */ + iowrite32(csr6, ioaddr + CSR6); } @@ -1984,6 +2044,126 @@ static void tulip_remove_one(struct pci_ } #endif /* CONFIG_TULIP_PCI */ +#ifdef CONFIG_TULIP_PLATFORM +static int tulip_probe(struct platform_device *pdev) +{ + struct tulip_private *tp; + struct tulip_platform_data *pdata; + struct net_device *dev; + struct resource *res; + void __iomem *ioaddr; + int irq; + + if (pdev->id < 0 || pdev->id >= MAX_UNITS) + return -EINVAL; + + if (!(res = platform_get_resource(pdev, IORESOURCE_IRQ, 0))) + return -ENODEV; + irq = res->start; + if (!(res = platform_get_resource(pdev, IORESOURCE_MEM, 0))) + return -ENODEV; + if (!(ioaddr = ioremap(res->start, res->end - res->start))) + return -ENODEV; + + pdata = pdev->dev.platform_data; + if (!pdata) + return -ENODEV; + + if (!(dev = alloc_etherdev(sizeof (*tp)))) + return -ENOMEM; + + /* setup net dev */ + dev->base_addr = (unsigned long)res->start; + dev->irq = irq; + SET_NETDEV_DEV(dev, &pdev->dev); + + /* tulip private struct */ + tp = netdev_priv(dev); + tp->dev = dev; + tp->base_addr = ioaddr; + tp->csr0 = 0; + tp->pldev = pdev; + tp->kdev = &pdev->dev; + tp->irq = irq; + tp->rx_ring = dma_alloc_coherent(&pdev->dev, + sizeof(struct tulip_rx_desc) * RX_RING_SIZE + + sizeof(struct tulip_tx_desc) * TX_RING_SIZE, + &tp->rx_ring_dma, GFP_KERNEL); + if (!tp->rx_ring) + return -ENODEV; + tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); + tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; + + tp->chip_id = pdata->chip_id; + tp->flags = tulip_tbl[tp->chip_id].flags; + + spin_lock_init(&tp->lock); + spin_lock_init(&tp->mii_lock); + + init_timer(&tp->timer); + tp->timer.data = (unsigned long)dev; + tp->timer.function = tulip_tbl[tp->chip_id].media_timer; + + INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task); + + /* Stop the chip's Tx and Rx processes. */ + tulip_stop_rxtx(tp); + + /* Clear the missed-packet counter. */ + ioread32(ioaddr + CSR8); + + if (!is_valid_ether_addr(pdata->mac)) { + dev_info(&pdev->dev, "generating random ethernet MAC\n"); + random_ether_addr(dev->dev_addr); + } else + memcpy(dev->dev_addr, pdata->mac, ETH_ALEN); + + /* The Tulip-specific entries in the device structure. */ + dev->netdev_ops = &tulip_netdev_ops; + dev->watchdog_timeo = TX_TIMEOUT; + netif_napi_add(dev, &tp->napi, tulip_poll, 16); + dev->ethtool_ops = &ops; + + if (register_netdev(dev)) + goto err_out_free_ring; + + dev_info(&dev->dev, + "tulip_platform (%s) at MMIO %#lx %pM, IRQ %d\n", + tulip_tbl[tp->chip_id].chip_name, + (unsigned long)dev->base_addr, dev->dev_addr, irq); + + platform_set_drvdata(pdev, dev); + return 0; + +err_out_free_ring: + dma_free_coherent(&pdev->dev, + sizeof (struct tulip_rx_desc) * RX_RING_SIZE + + sizeof (struct tulip_tx_desc) * TX_RING_SIZE, + tp->rx_ring, tp->rx_ring_dma); + return -ENODEV; +} + +static int tulip_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata (pdev); + struct tulip_private *tp; + + if (!dev) + return -ENODEV; + + tp = netdev_priv(dev); + unregister_netdev(dev); + dma_free_coherent(&pdev->dev, + sizeof (struct tulip_rx_desc) * RX_RING_SIZE + + sizeof (struct tulip_tx_desc) * TX_RING_SIZE, + tp->rx_ring, tp->rx_ring_dma); + iounmap(tp->base_addr); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); + return 0; +} +#endif + #ifdef CONFIG_NET_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs @@ -2017,6 +2197,17 @@ static struct pci_driver tulip_pci_drive }; #endif +#ifdef CONFIG_TULIP_PLATFORM +static struct platform_driver tulip_platform_driver = { + .probe = tulip_probe, + .remove = tulip_remove, + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, +}; +#endif + static int __init tulip_init (void) { @@ -2033,6 +2224,9 @@ static int __init tulip_init (void) #ifdef CONFIG_TULIP_PCI ret = pci_register_driver(&tulip_pci_driver); #endif +#ifdef CONFIG_TULIP_PLATFORM + ret = platform_driver_register(&tulip_platform_driver); +#endif return ret; } @@ -2042,6 +2236,9 @@ static void __exit tulip_cleanup (void) #ifdef CONFIG_TULIP_PCI pci_unregister_driver (&tulip_pci_driver); #endif +#ifdef CONFIG_TULIP_PLATFORM + platform_driver_unregister (&tulip_platform_driver); +#endif } --- a/drivers/net/ethernet/dec/tulip/tulip.h +++ b/drivers/net/ethernet/dec/tulip/tulip.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -69,28 +71,6 @@ enum tbl_flag { }; -/* chip types. careful! order is VERY IMPORTANT here, as these - * are used throughout the driver as indices into arrays */ -/* Note 21142 == 21143. */ -enum chips { - DC21040 = 0, - DC21041 = 1, - DC21140 = 2, - DC21142 = 3, DC21143 = 3, - LC82C168, - MX98713, - MX98715, - MX98725, - AX88140, - PNIC2, - COMET, - COMPEX9881, - I21145, - DM910X, - CONEXANT, -}; - - enum MediaIs { MediaIsFD = 1, MediaAlwaysFD = 2, @@ -446,7 +426,12 @@ struct tulip_private { struct mediatable *mtable; int cur_index; /* Current media index. */ int saved_if_port; +#ifdef CONFIG_TULIP_PCI struct pci_dev *pdev; +#endif +#ifdef CONFIG_TULIP_PLATFORM + struct platform_device *pldev; +#endif struct device *kdev; int irq; int ttimer; --- a/drivers/net/ethernet/dec/tulip/interrupt.c +++ b/drivers/net/ethernet/dec/tulip/interrupt.c @@ -77,6 +77,10 @@ int tulip_refill_rx(struct net_device *d mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + mapping = dma_map_single(&tp->pldev->dev, skb->data, PKT_BUF_SZ, + DMA_FROM_DEVICE); +#endif if (dma_mapping_error(tp->kdev, mapping)) { dev_kfree_skb(skb); tp->rx_buffers[entry].skb = NULL; @@ -204,8 +208,7 @@ int tulip_poll(struct napi_struct *napi, dev->stats.rx_fifo_errors++; } } else { - struct sk_buff *skb; - + struct sk_buff *skb; /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak && @@ -248,6 +251,10 @@ int tulip_poll(struct napi_struct *napi, pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + dma_unmap_single(&tp->pldev->dev, tp->rx_buffers[entry].mapping, + PKT_BUF_SZ, DMA_FROM_DEVICE); +#endif tp->rx_buffers[entry].skb = NULL; tp->rx_buffers[entry].mapping = 0; @@ -641,6 +648,11 @@ irqreturn_t tulip_interrupt(int irq, voi tp->tx_buffers[entry].skb->len, PCI_DMA_TODEVICE); #endif +#ifdef CONFIG_TULIP_PLATFORM + dma_unmap_single(&tp->pldev->dev, tp->tx_buffers[entry].mapping, + tp->tx_buffers[entry].skb->len, + DMA_TO_DEVICE); +#endif /* Free the original skb. */ dev_kfree_skb_irq(tp->tx_buffers[entry].skb); --- /dev/null +++ b/include/linux/platform_data/tulip.h @@ -0,0 +1,31 @@ +#ifndef _LINUX_TULIP_PDATA_H +#define _LINUX_TULIP_PDATA_H + +/* chip types. careful! order is VERY IMPORTANT here, as these + * are used throughout the driver as indices into arrays */ +/* Note 21142 == 21143. */ +enum chips { + DC21040 = 0, + DC21041 = 1, + DC21140 = 2, + DC21142 = 3, DC21143 = 3, + LC82C168, + MX98713, + MX98715, + MX98725, + AX88140, + PNIC2, + COMET, + COMPEX9881, + I21145, + DM910X, + CONEXANT, + ADM8668, +}; + +struct tulip_platform_data { + u8 mac[6]; + enum chips chip_id; +}; + +#endif