Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at b75cdf388ecdcd5ab5e66178f19c39a4c94dea26 343 lines 8.6 kB view raw
1/* 2 * jazzsonic.c 3 * 4 * (C) 2005 Finn Thain 5 * 6 * Converted to DMA API, and (from the mac68k project) introduced 7 * dhd's support for 16-bit cards. 8 * 9 * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) 10 * 11 * This driver is based on work from Andreas Busse, but most of 12 * the code is rewritten. 13 * 14 * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) 15 * 16 * A driver for the onboard Sonic ethernet controller on Mips Jazz 17 * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and 18 * perhaps others, too) 19 */ 20 21#include <linux/kernel.h> 22#include <linux/module.h> 23#include <linux/types.h> 24#include <linux/fcntl.h> 25#include <linux/interrupt.h> 26#include <linux/init.h> 27#include <linux/ioport.h> 28#include <linux/in.h> 29#include <linux/slab.h> 30#include <linux/string.h> 31#include <linux/delay.h> 32#include <linux/errno.h> 33#include <linux/netdevice.h> 34#include <linux/etherdevice.h> 35#include <linux/skbuff.h> 36#include <linux/device.h> 37#include <linux/dma-mapping.h> 38 39#include <asm/bootinfo.h> 40#include <asm/system.h> 41#include <asm/pgtable.h> 42#include <asm/io.h> 43#include <asm/dma.h> 44#include <asm/jazz.h> 45#include <asm/jazzdma.h> 46 47static char jazz_sonic_string[] = "jazzsonic"; 48static struct platform_device *jazz_sonic_device; 49 50#define SONIC_MEM_SIZE 0x100 51 52#include "sonic.h" 53 54/* 55 * Macros to access SONIC registers 56 */ 57#define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg)) 58 59#define SONIC_WRITE(reg,val) \ 60do { \ 61 *((volatile unsigned int *)dev->base_addr+(reg)) = (val); \ 62} while (0) 63 64 65/* use 0 for production, 1 for verification, >1 for debug */ 66#ifdef SONIC_DEBUG 67static unsigned int sonic_debug = SONIC_DEBUG; 68#else 69static unsigned int sonic_debug = 1; 70#endif 71 72/* 73 * Base address and interrupt of the SONIC controller on JAZZ boards 74 */ 75static struct { 76 unsigned int port; 77 unsigned int irq; 78} sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; 79 80/* 81 * We cannot use station (ethernet) address prefixes to detect the 82 * sonic controller since these are board manufacturer depended. 83 * So we check for known Silicon Revision IDs instead. 84 */ 85static unsigned short known_revisions[] = 86{ 87 0x04, /* Mips Magnum 4000 */ 88 0xffff /* end of list */ 89}; 90 91static int __init sonic_probe1(struct net_device *dev) 92{ 93 static unsigned version_printed; 94 unsigned int silicon_revision; 95 unsigned int val; 96 struct sonic_local *lp = netdev_priv(dev); 97 int err = -ENODEV; 98 int i; 99 100 if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string)) 101 return -EBUSY; 102 103 /* 104 * get the Silicon Revision ID. If this is one of the known 105 * one assume that we found a SONIC ethernet controller at 106 * the expected location. 107 */ 108 silicon_revision = SONIC_READ(SONIC_SR); 109 if (sonic_debug > 1) 110 printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); 111 112 i = 0; 113 while (known_revisions[i] != 0xffff 114 && known_revisions[i] != silicon_revision) 115 i++; 116 117 if (known_revisions[i] == 0xffff) { 118 printk("SONIC ethernet controller not found (0x%4x)\n", 119 silicon_revision); 120 goto out; 121 } 122 123 if (sonic_debug && version_printed++ == 0) 124 printk(version); 125 126 printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr); 127 128 /* 129 * Put the sonic into software reset, then 130 * retrieve and print the ethernet address. 131 */ 132 SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); 133 SONIC_WRITE(SONIC_CEP,0); 134 for (i=0; i<3; i++) { 135 val = SONIC_READ(SONIC_CAP0-i); 136 dev->dev_addr[i*2] = val; 137 dev->dev_addr[i*2+1] = val >> 8; 138 } 139 140 err = -ENOMEM; 141 142 /* Initialize the device structure. */ 143 144 lp->dma_bitmode = SONIC_BITMODE32; 145 146 /* Allocate the entire chunk of memory for the descriptors. 147 Note that this cannot cross a 64K boundary. */ 148 if ((lp->descriptors = dma_alloc_coherent(lp->device, 149 SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), 150 &lp->descriptors_laddr, GFP_KERNEL)) == NULL) { 151 printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id); 152 goto out; 153 } 154 155 /* Now set up the pointers to point to the appropriate places */ 156 lp->cda = lp->descriptors; 157 lp->tda = lp->cda + (SIZEOF_SONIC_CDA 158 * SONIC_BUS_SCALE(lp->dma_bitmode)); 159 lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS 160 * SONIC_BUS_SCALE(lp->dma_bitmode)); 161 lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS 162 * SONIC_BUS_SCALE(lp->dma_bitmode)); 163 164 lp->cda_laddr = lp->descriptors_laddr; 165 lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA 166 * SONIC_BUS_SCALE(lp->dma_bitmode)); 167 lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS 168 * SONIC_BUS_SCALE(lp->dma_bitmode)); 169 lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS 170 * SONIC_BUS_SCALE(lp->dma_bitmode)); 171 172 dev->open = sonic_open; 173 dev->stop = sonic_close; 174 dev->hard_start_xmit = sonic_send_packet; 175 dev->get_stats = sonic_get_stats; 176 dev->set_multicast_list = &sonic_multicast_list; 177 dev->tx_timeout = sonic_tx_timeout; 178 dev->watchdog_timeo = TX_TIMEOUT; 179 180 /* 181 * clear tally counter 182 */ 183 SONIC_WRITE(SONIC_CRCT,0xffff); 184 SONIC_WRITE(SONIC_FAET,0xffff); 185 SONIC_WRITE(SONIC_MPT,0xffff); 186 187 return 0; 188out: 189 release_region(dev->base_addr, SONIC_MEM_SIZE); 190 return err; 191} 192 193/* 194 * Probe for a SONIC ethernet controller on a Mips Jazz board. 195 * Actually probing is superfluous but we're paranoid. 196 */ 197static int __init jazz_sonic_probe(struct device *device) 198{ 199 struct net_device *dev; 200 struct sonic_local *lp; 201 int err = 0; 202 int i; 203 204 /* 205 * Don't probe if we're not running on a Jazz board. 206 */ 207 if (mips_machgroup != MACH_GROUP_JAZZ) 208 return -ENODEV; 209 210 dev = alloc_etherdev(sizeof(struct sonic_local)); 211 if (!dev) 212 return -ENOMEM; 213 214 lp = netdev_priv(dev); 215 lp->device = device; 216 SET_NETDEV_DEV(dev, device); 217 SET_MODULE_OWNER(dev); 218 219 netdev_boot_setup_check(dev); 220 221 if (dev->base_addr >= KSEG0) { /* Check a single specified location. */ 222 err = sonic_probe1(dev); 223 } else if (dev->base_addr != 0) { /* Don't probe at all. */ 224 err = -ENXIO; 225 } else { 226 for (i = 0; sonic_portlist[i].port; i++) { 227 dev->base_addr = sonic_portlist[i].port; 228 dev->irq = sonic_portlist[i].irq; 229 if (sonic_probe1(dev) == 0) 230 break; 231 } 232 if (!sonic_portlist[i].port) 233 err = -ENODEV; 234 } 235 if (err) 236 goto out; 237 err = register_netdev(dev); 238 if (err) 239 goto out1; 240 241 printk("%s: MAC ", dev->name); 242 for (i = 0; i < 6; i++) { 243 printk("%2.2x", dev->dev_addr[i]); 244 if (i < 5) 245 printk(":"); 246 } 247 printk(" IRQ %d\n", dev->irq); 248 249 return 0; 250 251out1: 252 release_region(dev->base_addr, SONIC_MEM_SIZE); 253out: 254 free_netdev(dev); 255 256 return err; 257} 258 259MODULE_DESCRIPTION("Jazz SONIC ethernet driver"); 260module_param(sonic_debug, int, 0); 261MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)"); 262 263#define SONIC_IRQ_FLAG SA_INTERRUPT 264 265#include "sonic.c" 266 267static int __devexit jazz_sonic_device_remove (struct device *device) 268{ 269 struct net_device *dev = device->driver_data; 270 struct sonic_local* lp = netdev_priv(dev); 271 272 unregister_netdev (dev); 273 dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), 274 lp->descriptors, lp->descriptors_laddr); 275 release_region (dev->base_addr, SONIC_MEM_SIZE); 276 free_netdev (dev); 277 278 return 0; 279} 280 281static struct device_driver jazz_sonic_driver = { 282 .name = jazz_sonic_string, 283 .bus = &platform_bus_type, 284 .probe = jazz_sonic_probe, 285 .remove = __devexit_p(jazz_sonic_device_remove), 286}; 287 288static void jazz_sonic_platform_release (struct device *device) 289{ 290 struct platform_device *pldev; 291 292 /* free device */ 293 pldev = to_platform_device (device); 294 kfree (pldev); 295} 296 297static int __init jazz_sonic_init_module(void) 298{ 299 struct platform_device *pldev; 300 int err; 301 302 if ((err = driver_register(&jazz_sonic_driver))) { 303 printk(KERN_ERR "Driver registration failed\n"); 304 return err; 305 } 306 307 jazz_sonic_device = NULL; 308 309 if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) { 310 goto out_unregister; 311 } 312 313 memset(pldev, 0, sizeof (*pldev)); 314 pldev->name = jazz_sonic_string; 315 pldev->id = 0; 316 pldev->dev.release = jazz_sonic_platform_release; 317 jazz_sonic_device = pldev; 318 319 if (platform_device_register (pldev)) { 320 kfree(pldev); 321 jazz_sonic_device = NULL; 322 } 323 324 return 0; 325 326out_unregister: 327 platform_device_unregister(pldev); 328 329 return -ENOMEM; 330} 331 332static void __exit jazz_sonic_cleanup_module(void) 333{ 334 driver_unregister(&jazz_sonic_driver); 335 336 if (jazz_sonic_device) { 337 platform_device_unregister(jazz_sonic_device); 338 jazz_sonic_device = NULL; 339 } 340} 341 342module_init(jazz_sonic_init_module); 343module_exit(jazz_sonic_cleanup_module);