| 1 | --- a/drivers/net/ethernet/dec/tulip/Kconfig |
| 2 | +++ b/drivers/net/ethernet/dec/tulip/Kconfig |
| 3 | @@ -60,6 +60,14 @@ config TULIP_PCI |
| 4 | To compile this driver as a module, choose M here. The module will |
| 5 | be called tulip. |
| 6 | |
| 7 | +config TULIP_PLATFORM |
| 8 | + tristate "DECchip Tulip (dc2114x) Platform support" |
| 9 | + depends on HAS_IOMEM |
| 10 | + select TULIP |
| 11 | + select CRC32 |
| 12 | + ---help--- |
| 13 | + This driver is for the platform variant. |
| 14 | + |
| 15 | config TULIP_MWI |
| 16 | bool "New bus configuration (EXPERIMENTAL)" |
| 17 | depends on TULIP_PCI && EXPERIMENTAL |
| 18 | --- a/drivers/net/ethernet/dec/tulip/tulip_core.c |
| 19 | +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c |
| 20 | @@ -27,6 +27,8 @@ |
| 21 | #include <linux/init.h> |
| 22 | #include <linux/interrupt.h> |
| 23 | #include <linux/etherdevice.h> |
| 24 | +#include <linux/platform_device.h> |
| 25 | +#include <linux/platform_data/tulip.h> |
| 26 | #include <linux/delay.h> |
| 27 | #include <linux/mii.h> |
| 28 | #include <linux/crc32.h> |
| 29 | @@ -204,6 +206,9 @@ struct tulip_chip_table tulip_tbl[] = { |
| 30 | { "Conexant LANfinity", 256, 0x0001ebef, |
| 31 | HAS_MII | HAS_ACPI, tulip_timer, tulip_media_task }, |
| 32 | |
| 33 | + { "Infineon ADM8668", 256, 0x0001a451, |
| 34 | + MC_HASH_ONLY | COMET_MAC_ADDR, tulip_timer, tulip_media_task, }, |
| 35 | + |
| 36 | }; |
| 37 | |
| 38 | #ifdef CONFIG_TULIP_PCI |
| 39 | @@ -395,6 +400,7 @@ static void tulip_up(struct net_device * |
| 40 | i = 0; |
| 41 | if (tp->mtable == NULL) |
| 42 | goto media_picked; |
| 43 | + |
| 44 | if (dev->if_port) { |
| 45 | int looking_for = tulip_media_cap[dev->if_port] & MediaIsMII ? 11 : |
| 46 | (dev->if_port == 12 ? 0 : dev->if_port); |
| 47 | @@ -488,6 +494,10 @@ media_picked: |
| 48 | iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88); |
| 49 | dev->if_port = tp->mii_cnt ? 11 : 0; |
| 50 | tp->csr6 = 0x00040000; |
| 51 | + } else if (tp->chip_id == ADM8668) { |
| 52 | + /* Enable automatic Tx underrun recovery. */ |
| 53 | + iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88); |
| 54 | + tp->csr6 = 0x00040000; |
| 55 | } else if (tp->chip_id == AX88140) { |
| 56 | tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; |
| 57 | } else |
| 58 | @@ -657,6 +667,10 @@ static void tulip_init_ring(struct net_d |
| 59 | mapping = pci_map_single(tp->pdev, skb->data, |
| 60 | PKT_BUF_SZ, PCI_DMA_FROMDEVICE); |
| 61 | #endif |
| 62 | +#ifdef CONFIG_TULIP_PLATFORM |
| 63 | + mapping = dma_map_single(&tp->pldev->dev, skb->data, |
| 64 | + PKT_BUF_SZ, DMA_FROM_DEVICE); |
| 65 | +#endif |
| 66 | tp->rx_buffers[i].mapping = mapping; |
| 67 | skb->dev = dev; /* Mark as being used by this device. */ |
| 68 | tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */ |
| 69 | @@ -694,6 +708,11 @@ tulip_start_xmit(struct sk_buff *skb, st |
| 70 | mapping = pci_map_single(tp->pdev, skb->data, |
| 71 | skb->len, PCI_DMA_TODEVICE); |
| 72 | #endif |
| 73 | +#ifdef CONFIG_TULIP_PLATFORM |
| 74 | + mapping = dma_map_single(&tp->pldev->dev, skb->data, |
| 75 | + skb->len, |
| 76 | + DMA_TO_DEVICE); |
| 77 | +#endif |
| 78 | tp->tx_buffers[entry].mapping = mapping; |
| 79 | tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); |
| 80 | |
| 81 | @@ -757,6 +776,11 @@ static void tulip_clean_tx_ring(struct t |
| 82 | tp->tx_buffers[entry].skb->len, |
| 83 | PCI_DMA_TODEVICE); |
| 84 | #endif |
| 85 | +#ifdef CONFIG_TULIP_PLATFORM |
| 86 | + dma_unmap_single(&tp->pldev->dev, tp->tx_buffers[entry].mapping, |
| 87 | + tp->tx_buffers[entry].skb->len, |
| 88 | + DMA_TO_DEVICE); |
| 89 | +#endif |
| 90 | |
| 91 | /* Free the original skb. */ |
| 92 | dev_kfree_skb_irq(tp->tx_buffers[entry].skb); |
| 93 | @@ -834,6 +858,10 @@ static void tulip_free_ring (struct net_ |
| 94 | pci_unmap_single(tp->pdev, mapping, PKT_BUF_SZ, |
| 95 | PCI_DMA_FROMDEVICE); |
| 96 | #endif |
| 97 | +#ifdef CONFIG_TULIP_PLATFORM |
| 98 | + dma_unmap_single(&tp->pldev->dev, mapping, PKT_BUF_SZ, |
| 99 | + DMA_FROM_DEVICE); |
| 100 | +#endif |
| 101 | dev_kfree_skb (skb); |
| 102 | } |
| 103 | } |
| 104 | @@ -846,6 +874,10 @@ static void tulip_free_ring (struct net_ |
| 105 | pci_unmap_single(tp->pdev, tp->tx_buffers[i].mapping, |
| 106 | skb->len, PCI_DMA_TODEVICE); |
| 107 | #endif |
| 108 | +#ifdef CONFIG_TULIP_PLATFORM |
| 109 | + dma_unmap_single(&tp->pldev->dev, tp->tx_buffers[i].mapping, |
| 110 | + skb->len, DMA_TO_DEVICE); |
| 111 | +#endif |
| 112 | dev_kfree_skb (skb); |
| 113 | } |
| 114 | tp->tx_buffers[i].skb = NULL; |
| 115 | @@ -900,6 +932,9 @@ static void tulip_get_drvinfo(struct net |
| 116 | #ifdef CONFIG_TULIP_PCI |
| 117 | strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info)); |
| 118 | #endif |
| 119 | +#ifdef CONFIG_TULIP_PLATFORM |
| 120 | + strlcpy(info->bus_info, "platform", sizeof(info->bus_info)); |
| 121 | +#endif |
| 122 | } |
| 123 | |
| 124 | |
| 125 | @@ -915,6 +950,9 @@ static int tulip_ethtool_set_wol(struct |
| 126 | #ifdef CONFIG_TULIP_PCI |
| 127 | device_set_wakeup_enable(&tp->pdev->dev, tp->wolinfo.wolopts); |
| 128 | #endif |
| 129 | +#ifdef CONFIG_TULIP_PLATFORM |
| 130 | + device_set_wakeup_enable(&tp->pldev->dev, tp->wolinfo.wolopts); |
| 131 | +#endif |
| 132 | return 0; |
| 133 | } |
| 134 | |
| 135 | @@ -1193,9 +1231,9 @@ static void set_rx_mode(struct net_devic |
| 136 | |
| 137 | } |
| 138 | |
| 139 | +#ifdef CONFIG_TULIP_PCI |
| 140 | tp->tx_buffers[entry].skb = NULL; |
| 141 | tp->tx_buffers[entry].mapping = |
| 142 | -#ifdef CONFIG_TULIP_PCI |
| 143 | pci_map_single(tp->pdev, tp->setup_frame, |
| 144 | sizeof(tp->setup_frame), |
| 145 | PCI_DMA_TODEVICE); |
| 146 | @@ -1219,6 +1257,9 @@ static void set_rx_mode(struct net_devic |
| 147 | spin_unlock_irqrestore(&tp->lock, flags); |
| 148 | } |
| 149 | |
| 150 | + if (tp->chip_id == ADM8668) |
| 151 | + csr6 |= (1 << 9); /* force 100Mbps full duplex */ |
| 152 | + |
| 153 | iowrite32(csr6, ioaddr + CSR6); |
| 154 | } |
| 155 | |
| 156 | @@ -1991,6 +2032,124 @@ static void __devexit tulip_remove_one ( |
| 157 | } |
| 158 | #endif /* CONFIG_TULIP_PCI */ |
| 159 | |
| 160 | +#ifdef CONFIG_TULIP_PLATFORM |
| 161 | +static int __devinit tulip_probe(struct platform_device *pdev) |
| 162 | +{ |
| 163 | + struct tulip_private *tp; |
| 164 | + struct tulip_platform_data *pdata; |
| 165 | + struct net_device *dev; |
| 166 | + struct resource *res; |
| 167 | + void __iomem *ioaddr; |
| 168 | + int irq; |
| 169 | + |
| 170 | + if (pdev->id < 0 || pdev->id >= MAX_UNITS) |
| 171 | + return -EINVAL; |
| 172 | + |
| 173 | + if (!(res = platform_get_resource(pdev, IORESOURCE_IRQ, 0))) |
| 174 | + return -ENODEV; |
| 175 | + irq = res->start; |
| 176 | + if (!(res = platform_get_resource(pdev, IORESOURCE_MEM, 0))) |
| 177 | + return -ENODEV; |
| 178 | + if (!(ioaddr = ioremap(res->start, res->end - res->start))) |
| 179 | + return -ENODEV; |
| 180 | + |
| 181 | + pdata = pdev->dev.platform_data; |
| 182 | + if (!pdata) |
| 183 | + return -ENODEV; |
| 184 | + |
| 185 | + if (!(dev = alloc_etherdev(sizeof (*tp)))) |
| 186 | + return -ENOMEM; |
| 187 | + |
| 188 | + /* setup net dev */ |
| 189 | + dev->base_addr = (unsigned long)res->start; |
| 190 | + dev->irq = irq; |
| 191 | + SET_NETDEV_DEV(dev, &pdev->dev); |
| 192 | + |
| 193 | + /* tulip private struct */ |
| 194 | + tp = netdev_priv(dev); |
| 195 | + tp->dev = dev; |
| 196 | + tp->base_addr = ioaddr; |
| 197 | + tp->csr0 = 0; |
| 198 | + tp->pldev = pdev; |
| 199 | + tp->rx_ring = dma_alloc_coherent(&pdev->dev, |
| 200 | + sizeof(struct tulip_rx_desc) * RX_RING_SIZE + |
| 201 | + sizeof(struct tulip_tx_desc) * TX_RING_SIZE, |
| 202 | + &tp->rx_ring_dma, GFP_KERNEL); |
| 203 | + if (!tp->rx_ring) |
| 204 | + return -ENODEV; |
| 205 | + tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); |
| 206 | + tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; |
| 207 | + |
| 208 | + tp->chip_id = pdata->chip_id; |
| 209 | + tp->flags = tulip_tbl[tp->chip_id].flags; |
| 210 | + |
| 211 | + spin_lock_init(&tp->lock); |
| 212 | + spin_lock_init(&tp->mii_lock); |
| 213 | + |
| 214 | + init_timer(&tp->timer); |
| 215 | + tp->timer.data = (unsigned long)dev; |
| 216 | + tp->timer.function = tulip_tbl[tp->chip_id].media_timer; |
| 217 | + |
| 218 | + INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task); |
| 219 | + |
| 220 | + /* Stop the chip's Tx and Rx processes. */ |
| 221 | + tulip_stop_rxtx(tp); |
| 222 | + |
| 223 | + /* Clear the missed-packet counter. */ |
| 224 | + ioread32(ioaddr + CSR8); |
| 225 | + |
| 226 | + if (!is_valid_ether_addr(pdata->mac)) { |
| 227 | + dev_info(&pdev->dev, "generating random ethernet MAC\n"); |
| 228 | + random_ether_addr(dev->dev_addr); |
| 229 | + } else |
| 230 | + memcpy(dev->dev_addr, pdata->mac, ETH_ALEN); |
| 231 | + |
| 232 | + /* The Tulip-specific entries in the device structure. */ |
| 233 | + dev->netdev_ops = &tulip_netdev_ops; |
| 234 | + dev->watchdog_timeo = TX_TIMEOUT; |
| 235 | + netif_napi_add(dev, &tp->napi, tulip_poll, 16); |
| 236 | + SET_ETHTOOL_OPS(dev, &ops); |
| 237 | + |
| 238 | + if (register_netdev(dev)) |
| 239 | + goto err_out_free_ring; |
| 240 | + |
| 241 | + dev_info(&dev->dev, |
| 242 | + "tulip_platform (%s) at MMIO %#lx %pM, IRQ %d\n", |
| 243 | + tulip_tbl[tp->chip_id].chip_name, |
| 244 | + (unsigned long)dev->base_addr, dev->dev_addr, irq); |
| 245 | + |
| 246 | + platform_set_drvdata(pdev, dev); |
| 247 | + return 0; |
| 248 | + |
| 249 | +err_out_free_ring: |
| 250 | + dma_free_coherent(&pdev->dev, |
| 251 | + sizeof (struct tulip_rx_desc) * RX_RING_SIZE + |
| 252 | + sizeof (struct tulip_tx_desc) * TX_RING_SIZE, |
| 253 | + tp->rx_ring, tp->rx_ring_dma); |
| 254 | + return -ENODEV; |
| 255 | +} |
| 256 | + |
| 257 | +static int __devexit tulip_remove(struct platform_device *pdev) |
| 258 | +{ |
| 259 | + struct net_device *dev = platform_get_drvdata (pdev); |
| 260 | + struct tulip_private *tp; |
| 261 | + |
| 262 | + if (!dev) |
| 263 | + return -ENODEV; |
| 264 | + |
| 265 | + tp = netdev_priv(dev); |
| 266 | + unregister_netdev(dev); |
| 267 | + dma_free_coherent(&pdev->dev, |
| 268 | + sizeof (struct tulip_rx_desc) * RX_RING_SIZE + |
| 269 | + sizeof (struct tulip_tx_desc) * TX_RING_SIZE, |
| 270 | + tp->rx_ring, tp->rx_ring_dma); |
| 271 | + iounmap(tp->base_addr); |
| 272 | + free_netdev(dev); |
| 273 | + platform_set_drvdata(pdev, NULL); |
| 274 | + return 0; |
| 275 | +} |
| 276 | +#endif |
| 277 | + |
| 278 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 279 | /* |
| 280 | * Polling 'interrupt' - used by things like netconsole to send skbs |
| 281 | @@ -2021,6 +2180,17 @@ static struct pci_driver tulip_pci_drive |
| 282 | }; |
| 283 | #endif |
| 284 | |
| 285 | +#ifdef CONFIG_TULIP_PLATFORM |
| 286 | +static struct platform_driver tulip_platform_driver = { |
| 287 | + .probe = tulip_probe, |
| 288 | + .remove = __devexit_p(tulip_remove), |
| 289 | + .driver = { |
| 290 | + .owner = THIS_MODULE, |
| 291 | + .name = DRV_NAME, |
| 292 | + }, |
| 293 | +}; |
| 294 | +#endif |
| 295 | + |
| 296 | |
| 297 | static int __init tulip_init (void) |
| 298 | { |
| 299 | @@ -2037,6 +2207,9 @@ static int __init tulip_init (void) |
| 300 | #ifdef CONFIG_TULIP_PCI |
| 301 | ret = pci_register_driver(&tulip_pci_driver); |
| 302 | #endif |
| 303 | +#ifdef CONFIG_TULIP_PLATFORM |
| 304 | + ret = platform_driver_register(&tulip_platform_driver); |
| 305 | +#endif |
| 306 | return ret; |
| 307 | } |
| 308 | |
| 309 | @@ -2046,6 +2219,9 @@ static void __exit tulip_cleanup (void) |
| 310 | #ifdef CONFIG_TULIP_PCI |
| 311 | pci_unregister_driver (&tulip_pci_driver); |
| 312 | #endif |
| 313 | +#ifdef CONFIG_TULIP_PLATFORM |
| 314 | + platform_driver_unregister (&tulip_platform_driver); |
| 315 | +#endif |
| 316 | } |
| 317 | |
| 318 | |
| 319 | --- a/drivers/net/ethernet/dec/tulip/tulip.h |
| 320 | +++ b/drivers/net/ethernet/dec/tulip/tulip.h |
| 321 | @@ -21,6 +21,8 @@ |
| 322 | #include <linux/timer.h> |
| 323 | #include <linux/delay.h> |
| 324 | #include <linux/pci.h> |
| 325 | +#include <linux/platform_device.h> |
| 326 | +#include <linux/platform_data/tulip.h> |
| 327 | #include <asm/io.h> |
| 328 | #include <asm/irq.h> |
| 329 | #include <asm/unaligned.h> |
| 330 | @@ -69,28 +71,6 @@ enum tbl_flag { |
| 331 | }; |
| 332 | |
| 333 | |
| 334 | -/* chip types. careful! order is VERY IMPORTANT here, as these |
| 335 | - * are used throughout the driver as indices into arrays */ |
| 336 | -/* Note 21142 == 21143. */ |
| 337 | -enum chips { |
| 338 | - DC21040 = 0, |
| 339 | - DC21041 = 1, |
| 340 | - DC21140 = 2, |
| 341 | - DC21142 = 3, DC21143 = 3, |
| 342 | - LC82C168, |
| 343 | - MX98713, |
| 344 | - MX98715, |
| 345 | - MX98725, |
| 346 | - AX88140, |
| 347 | - PNIC2, |
| 348 | - COMET, |
| 349 | - COMPEX9881, |
| 350 | - I21145, |
| 351 | - DM910X, |
| 352 | - CONEXANT, |
| 353 | -}; |
| 354 | - |
| 355 | - |
| 356 | enum MediaIs { |
| 357 | MediaIsFD = 1, |
| 358 | MediaAlwaysFD = 2, |
| 359 | @@ -446,7 +426,12 @@ struct tulip_private { |
| 360 | struct mediatable *mtable; |
| 361 | int cur_index; /* Current media index. */ |
| 362 | int saved_if_port; |
| 363 | +#ifdef CONFIG_TULIP_PCI |
| 364 | struct pci_dev *pdev; |
| 365 | +#endif |
| 366 | +#ifdef CONFIG_TULIP_PLATFORM |
| 367 | + struct platform_device *pldev; |
| 368 | +#endif |
| 369 | int ttimer; |
| 370 | int susp_rx; |
| 371 | unsigned long nir; |
| 372 | --- a/drivers/net/ethernet/dec/tulip/interrupt.c |
| 373 | +++ b/drivers/net/ethernet/dec/tulip/interrupt.c |
| 374 | @@ -76,6 +76,10 @@ int tulip_refill_rx(struct net_device *d |
| 375 | mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, |
| 376 | PCI_DMA_FROMDEVICE); |
| 377 | #endif |
| 378 | +#ifdef CONFIG_TULIP_PLATFORM |
| 379 | + mapping = dma_map_single(&tp->pldev->dev, skb->data, PKT_BUF_SZ, |
| 380 | + DMA_FROM_DEVICE); |
| 381 | +#endif |
| 382 | tp->rx_buffers[entry].mapping = mapping; |
| 383 | |
| 384 | skb->dev = dev; /* Mark as being used by this device. */ |
| 385 | @@ -198,8 +202,7 @@ int tulip_poll(struct napi_struct *napi, |
| 386 | dev->stats.rx_fifo_errors++; |
| 387 | } |
| 388 | } else { |
| 389 | - struct sk_buff *skb; |
| 390 | - |
| 391 | + struct sk_buff *skb; |
| 392 | /* Check if the packet is long enough to accept without copying |
| 393 | to a minimally-sized skbuff. */ |
| 394 | if (pkt_len < tulip_rx_copybreak && |
| 395 | @@ -242,6 +245,10 @@ int tulip_poll(struct napi_struct *napi, |
| 396 | pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, |
| 397 | PKT_BUF_SZ, PCI_DMA_FROMDEVICE); |
| 398 | #endif |
| 399 | +#ifdef CONFIG_TULIP_PLATFORM |
| 400 | + dma_unmap_single(&tp->pldev->dev, tp->rx_buffers[entry].mapping, |
| 401 | + PKT_BUF_SZ, DMA_FROM_DEVICE); |
| 402 | +#endif |
| 403 | |
| 404 | tp->rx_buffers[entry].skb = NULL; |
| 405 | tp->rx_buffers[entry].mapping = 0; |
| 406 | @@ -635,6 +642,11 @@ irqreturn_t tulip_interrupt(int irq, voi |
| 407 | tp->tx_buffers[entry].skb->len, |
| 408 | PCI_DMA_TODEVICE); |
| 409 | #endif |
| 410 | +#ifdef CONFIG_TULIP_PLATFORM |
| 411 | + dma_unmap_single(&tp->pldev->dev, tp->tx_buffers[entry].mapping, |
| 412 | + tp->tx_buffers[entry].skb->len, |
| 413 | + DMA_TO_DEVICE); |
| 414 | +#endif |
| 415 | |
| 416 | /* Free the original skb. */ |
| 417 | dev_kfree_skb_irq(tp->tx_buffers[entry].skb); |
| 418 | --- /dev/null |
| 419 | +++ b/include/linux/platform_data/tulip.h |
| 420 | @@ -0,0 +1,31 @@ |
| 421 | +#ifndef _LINUX_TULIP_PDATA_H |
| 422 | +#define _LINUX_TULIP_PDATA_H |
| 423 | + |
| 424 | +/* chip types. careful! order is VERY IMPORTANT here, as these |
| 425 | + * are used throughout the driver as indices into arrays */ |
| 426 | +/* Note 21142 == 21143. */ |
| 427 | +enum chips { |
| 428 | + DC21040 = 0, |
| 429 | + DC21041 = 1, |
| 430 | + DC21140 = 2, |
| 431 | + DC21142 = 3, DC21143 = 3, |
| 432 | + LC82C168, |
| 433 | + MX98713, |
| 434 | + MX98715, |
| 435 | + MX98725, |
| 436 | + AX88140, |
| 437 | + PNIC2, |
| 438 | + COMET, |
| 439 | + COMPEX9881, |
| 440 | + I21145, |
| 441 | + DM910X, |
| 442 | + CONEXANT, |
| 443 | + ADM8668, |
| 444 | +}; |
| 445 | + |
| 446 | +struct tulip_platform_data { |
| 447 | + u8 mac[6]; |
| 448 | + enum chips chip_id; |
| 449 | +}; |
| 450 | + |
| 451 | +#endif |
| 452 | |