11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * jazzsonic.c 3efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * 4efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * (C) 2005 Finn Thain 5efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * 6efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * Converted to DMA API, and (from the mac68k project) introduced 7efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * dhd's support for 16-bit cards. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) 106aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver is based on work from Andreas Busse, but most of 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the code is rewritten. 136aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A driver for the onboard Sonic ethernet controller on Mips Jazz 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * perhaps others, too) 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h> 255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 35d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 36efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain#include <linux/dma-mapping.h> 375a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/bootinfo.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/jazz.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/jazzdma.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char jazz_sonic_string[] = "jazzsonic"; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SONIC_MEM_SIZE 0x100 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sonic.h" 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Macros to access SONIC registers 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 55efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain#define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg)) 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SONIC_WRITE(reg,val) \ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo { \ 59efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain *((volatile unsigned int *)dev->base_addr+(reg)) = (val); \ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} while (0) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 63efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain/* use 0 for production, 1 for verification, >1 for debug */ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SONIC_DEBUG 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int sonic_debug = SONIC_DEBUG; 666aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik#else 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int sonic_debug = 1; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cannot use station (ethernet) address prefixes to detect the 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sonic controller since these are board manufacturer depended. 736aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik * So we check for known Silicon Revision IDs instead. 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short known_revisions[] = 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x04, /* Mips Magnum 4000 */ 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xffff /* end of list */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thainstatic int jazzsonic_open(struct net_device* dev) 82f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain{ 8362cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy int retval; 8462cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy 85d8865d5bb92d0d362ed6904cb248776d4da6efbbMichael Opdenacker retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev); 8662cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy if (retval) { 8762cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy printk(KERN_ERR "%s: unable to get IRQ %d.\n", 8862cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy dev->name, dev->irq); 8962cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy return retval; 90f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain } 9162cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy 9262cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy retval = sonic_open(dev); 9362cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy if (retval) 9462cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy free_irq(dev->irq, dev); 9562cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy return retval; 96f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain} 97f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain 98f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thainstatic int jazzsonic_close(struct net_device* dev) 99f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain{ 100f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain int err; 101f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain err = sonic_close(dev); 102f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain free_irq(dev->irq, dev); 103f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain return err; 104f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain} 105f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain 106502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalovstatic const struct net_device_ops sonic_netdev_ops = { 107502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_open = jazzsonic_open, 108502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_stop = jazzsonic_close, 109502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_start_xmit = sonic_send_packet, 110502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_get_stats = sonic_get_stats, 111afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = sonic_multicast_list, 112502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_tx_timeout = sonic_tx_timeout, 113502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_change_mtu = eth_change_mtu, 114502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_validate_addr = eth_validate_addr, 115502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_set_mac_address = eth_mac_addr, 116502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov}; 117502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov 1186980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pembertonstatic int sonic_probe1(struct net_device *dev) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static unsigned version_printed; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int silicon_revision; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val; 123efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain struct sonic_local *lp = netdev_priv(dev); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENODEV; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string)) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 129efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get the Silicon Revision ID. If this is one of the known 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one assume that we found a SONIC ethernet controller at 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the expected location. 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds silicon_revision = SONIC_READ(SONIC_SR); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sonic_debug > 1) 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; 1408e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches while (known_revisions[i] != 0xffff && 1418e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches known_revisions[i] != silicon_revision) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i++; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (known_revisions[i] == 0xffff) { 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SONIC ethernet controller not found (0x%4x)\n", 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds silicon_revision); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1496aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sonic_debug && version_printed++ == 0) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(version); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 153c23135573f37facd18edb2e8e8512c67928c54acKay Sievers printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", 154c23135573f37facd18edb2e8e8512c67928c54acKay Sievers dev_name(lp->device), dev->base_addr); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Put the sonic into software reset, then 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * retrieve and print the ethernet address. 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_CEP,0); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i<3; i++) { 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = SONIC_READ(SONIC_CAP0-i); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i*2] = val; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i*2+1] = val >> 8; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 1696aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the device structure. */ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 172efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->dma_bitmode = SONIC_BITMODE32; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 174efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain /* Allocate the entire chunk of memory for the descriptors. 175efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain Note that this cannot cross a 64K boundary. */ 176d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches lp->descriptors = dma_alloc_coherent(lp->device, 177d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches SIZEOF_SONIC_DESC * 178d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches SONIC_BUS_SCALE(lp->dma_bitmode), 179d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches &lp->descriptors_laddr, 180d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches GFP_KERNEL); 181d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches if (lp->descriptors == NULL) 182efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain goto out; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 184efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain /* Now set up the pointers to point to the appropriate places */ 185efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->cda = lp->descriptors; 186efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->tda = lp->cda + (SIZEOF_SONIC_CDA 187efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 188efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS 189efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 190efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS 191efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 192efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 193efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->cda_laddr = lp->descriptors_laddr; 194efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA 195efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 196efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS 197efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 198efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS 199efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 200efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 201502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov dev->netdev_ops = &sonic_netdev_ops; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->watchdog_timeo = TX_TIMEOUT; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clear tally counter 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_CRCT,0xffff); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_FAET,0xffff); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_MPT,0xffff); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 213c9145a2df072f75d97592ddac1624baeb7bad195Julia Lawall release_mem_region(dev->base_addr, SONIC_MEM_SIZE); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Probe for a SONIC ethernet controller on a Mips Jazz board. 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Actually probing is superfluous but we're paranoid. 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2216980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pembertonstatic int jazz_sonic_probe(struct platform_device *pdev) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sonic_local *lp; 225ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer struct resource *res; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 228ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 229ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer if (!res) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 232efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain dev = alloc_etherdev(sizeof(struct sonic_local)); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 236efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp = netdev_priv(dev); 2373ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King lp->device = &pdev->dev; 2383ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King SET_NETDEV_DEV(dev, &pdev->dev); 2394564cba71637d3b4ea3730f5637b21a9eb3c8999Finn Thain platform_set_drvdata(pdev, dev); 240efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev_boot_setup_check(dev); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 243ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer dev->base_addr = res->start; 244ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer dev->irq = platform_get_irq(pdev, 0); 245ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer err = sonic_probe1(dev); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out1; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 252e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk("%s: MAC %pM IRQ %d\n", dev->name, dev->dev_addr, dev->irq); 253efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout1: 257c9145a2df072f75d97592ddac1624baeb7bad195Julia Lawall release_mem_region(dev->base_addr, SONIC_MEM_SIZE); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 264efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn ThainMODULE_DESCRIPTION("Jazz SONIC ethernet driver"); 265efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thainmodule_param(sonic_debug, int, 0); 266efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn ThainMODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)"); 26772abb46101fb5c47a9592914adb221b430ff26bdKay SieversMODULE_ALIAS("platform:jazzsonic"); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sonic.c" 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2716980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pembertonstatic int jazz_sonic_device_remove(struct platform_device *pdev) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2733ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct net_device *dev = platform_get_drvdata(pdev); 274efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain struct sonic_local* lp = netdev_priv(dev); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 276d74472f0b2553e59eafb7feee0ff9558136a17e0Finn Thain unregister_netdev(dev); 277efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), 278efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->descriptors, lp->descriptors_laddr); 279c9145a2df072f75d97592ddac1624baeb7bad195Julia Lawall release_mem_region(dev->base_addr, SONIC_MEM_SIZE); 280d74472f0b2553e59eafb7feee0ff9558136a17e0Finn Thain free_netdev(dev); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2853ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver jazz_sonic_driver = { 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = jazz_sonic_probe, 2876980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pemberton .remove = jazz_sonic_device_remove, 2883ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .driver = { 2893ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .name = jazz_sonic_string, 29072abb46101fb5c47a9592914adb221b430ff26bdKay Sievers .owner = THIS_MODULE, 2913ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King }, 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 293efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 294db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(jazz_sonic_driver); 295