jazzsonic.c revision d8865d5bb92d0d362ed6904cb248776d4da6efbb
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/init.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 36d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 37efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain#include <linux/dma-mapping.h> 385a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/bootinfo.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/jazz.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/jazzdma.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char jazz_sonic_string[] = "jazzsonic"; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SONIC_MEM_SIZE 0x100 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sonic.h" 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Macros to access SONIC registers 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 56efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain#define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg)) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SONIC_WRITE(reg,val) \ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo { \ 60efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain *((volatile unsigned int *)dev->base_addr+(reg)) = (val); \ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} while (0) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain/* use 0 for production, 1 for verification, >1 for debug */ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SONIC_DEBUG 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int sonic_debug = SONIC_DEBUG; 676aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik#else 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int sonic_debug = 1; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cannot use station (ethernet) address prefixes to detect the 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sonic controller since these are board manufacturer depended. 746aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik * So we check for known Silicon Revision IDs instead. 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short known_revisions[] = 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x04, /* Mips Magnum 4000 */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xffff /* end of list */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 82f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thainstatic int jazzsonic_open(struct net_device* dev) 83f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain{ 8462cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy int retval; 8562cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy 86d8865d5bb92d0d362ed6904cb248776d4da6efbbMichael Opdenacker retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev); 8762cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy if (retval) { 8862cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy printk(KERN_ERR "%s: unable to get IRQ %d.\n", 8962cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy dev->name, dev->irq); 9062cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy return retval; 91f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain } 9262cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy 9362cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy retval = sonic_open(dev); 9462cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy if (retval) 9562cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy free_irq(dev->irq, dev); 9662cd69a10683bd17a2454213b8c36a4399c533abKulikov Vasiliy return retval; 97f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain} 98f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain 99f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thainstatic int jazzsonic_close(struct net_device* dev) 100f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain{ 101f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain int err; 102f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain err = sonic_close(dev); 103f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain free_irq(dev->irq, dev); 104f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain return err; 105f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain} 106f4d86754f956ab5ea73aa91759a0d89a2f0e3f2aFinn Thain 107502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalovstatic const struct net_device_ops sonic_netdev_ops = { 108502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_open = jazzsonic_open, 109502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_stop = jazzsonic_close, 110502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_start_xmit = sonic_send_packet, 111502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_get_stats = sonic_get_stats, 112afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = sonic_multicast_list, 113502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_tx_timeout = sonic_tx_timeout, 114502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_change_mtu = eth_change_mtu, 115502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_validate_addr = eth_validate_addr, 116502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov .ndo_set_mac_address = eth_mac_addr, 117502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov}; 118502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov 1196980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pembertonstatic int sonic_probe1(struct net_device *dev) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static unsigned version_printed; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int silicon_revision; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val; 124efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain struct sonic_local *lp = netdev_priv(dev); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENODEV; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string)) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 130efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get the Silicon Revision ID. If this is one of the known 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one assume that we found a SONIC ethernet controller at 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the expected location. 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds silicon_revision = SONIC_READ(SONIC_SR); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sonic_debug > 1) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; 1418e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches while (known_revisions[i] != 0xffff && 1428e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches known_revisions[i] != silicon_revision) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i++; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (known_revisions[i] == 0xffff) { 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SONIC ethernet controller not found (0x%4x)\n", 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds silicon_revision); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1506aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sonic_debug && version_printed++ == 0) 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(version); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 154c23135573f37facd18edb2e8e8512c67928c54acKay Sievers printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", 155c23135573f37facd18edb2e8e8512c67928c54acKay Sievers dev_name(lp->device), dev->base_addr); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Put the sonic into software reset, then 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * retrieve and print the ethernet address. 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_CEP,0); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i<3; i++) { 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = SONIC_READ(SONIC_CAP0-i); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i*2] = val; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i*2+1] = val >> 8; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 1706aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the device structure. */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 173efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->dma_bitmode = SONIC_BITMODE32; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain /* Allocate the entire chunk of memory for the descriptors. 176efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain Note that this cannot cross a 64K boundary. */ 177d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches lp->descriptors = dma_alloc_coherent(lp->device, 178d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches SIZEOF_SONIC_DESC * 179d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches SONIC_BUS_SCALE(lp->dma_bitmode), 180d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches &lp->descriptors_laddr, 181d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches GFP_KERNEL); 182d0320f750093d012d3ed69fc1e8b385f654523d5Joe Perches if (lp->descriptors == NULL) 183efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain goto out; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 185efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain /* Now set up the pointers to point to the appropriate places */ 186efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->cda = lp->descriptors; 187efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->tda = lp->cda + (SIZEOF_SONIC_CDA 188efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 189efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS 190efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 191efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS 192efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 193efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 194efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->cda_laddr = lp->descriptors_laddr; 195efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA 196efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 197efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS 198efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 199efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS 200efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain * SONIC_BUS_SCALE(lp->dma_bitmode)); 201efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 202502a326f833927a84a8de29f5fb638aa9da15f4bAlexander Beregalov dev->netdev_ops = &sonic_netdev_ops; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->watchdog_timeo = TX_TIMEOUT; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clear tally counter 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_CRCT,0xffff); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_FAET,0xffff); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SONIC_WRITE(SONIC_MPT,0xffff); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 214c9145a2df072f75d97592ddac1624baeb7bad195Julia Lawall release_mem_region(dev->base_addr, SONIC_MEM_SIZE); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Probe for a SONIC ethernet controller on a Mips Jazz board. 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Actually probing is superfluous but we're paranoid. 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2226980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pembertonstatic int jazz_sonic_probe(struct platform_device *pdev) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sonic_local *lp; 226ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer struct resource *res; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 230ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer if (!res) 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 233efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain dev = alloc_etherdev(sizeof(struct sonic_local)); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 237efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp = netdev_priv(dev); 2383ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King lp->device = &pdev->dev; 2393ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King SET_NETDEV_DEV(dev, &pdev->dev); 2404564cba71637d3b4ea3730f5637b21a9eb3c8999Finn Thain platform_set_drvdata(pdev, dev); 241efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev_boot_setup_check(dev); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 244ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer dev->base_addr = res->start; 245ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer dev->irq = platform_get_irq(pdev, 0); 246ed9f0e0bf3ceb44334ca9b70779a50b2e79b7f97Thomas Bogendoerfer err = sonic_probe1(dev); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out1; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk("%s: MAC %pM IRQ %d\n", dev->name, dev->dev_addr, dev->irq); 254efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout1: 258c9145a2df072f75d97592ddac1624baeb7bad195Julia Lawall release_mem_region(dev->base_addr, SONIC_MEM_SIZE); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 265efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn ThainMODULE_DESCRIPTION("Jazz SONIC ethernet driver"); 266efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thainmodule_param(sonic_debug, int, 0); 267efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn ThainMODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)"); 26872abb46101fb5c47a9592914adb221b430ff26bdKay SieversMODULE_ALIAS("platform:jazzsonic"); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sonic.c" 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2726980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pembertonstatic int jazz_sonic_device_remove(struct platform_device *pdev) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2743ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct net_device *dev = platform_get_drvdata(pdev); 275efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain struct sonic_local* lp = netdev_priv(dev); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 277d74472f0b2553e59eafb7feee0ff9558136a17e0Finn Thain unregister_netdev(dev); 278efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), 279efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain lp->descriptors, lp->descriptors_laddr); 280c9145a2df072f75d97592ddac1624baeb7bad195Julia Lawall release_mem_region(dev->base_addr, SONIC_MEM_SIZE); 281d74472f0b2553e59eafb7feee0ff9558136a17e0Finn Thain free_netdev(dev); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2863ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver jazz_sonic_driver = { 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = jazz_sonic_probe, 2886980cbe4a6dbb3d7871e99a3cbc74a572d14d327Bill Pemberton .remove = jazz_sonic_device_remove, 2893ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .driver = { 2903ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .name = jazz_sonic_string, 29172abb46101fb5c47a9592914adb221b430ff26bdKay Sievers .owner = THIS_MODULE, 2923ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King }, 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 294efcce839360fb3a7b6dedeacaec80f68b0f2d052Finn Thain 295db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(jazz_sonic_driver); 296