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

AX88796 network driver

Support for the Asix AX88796 network controller, an
NE2000 compatible 10/100 ethernet device with internal
PHY.

The driver supports PHY settings via either ioctl() or
the ethtool driver ops.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

authored by

Ben Dooks and committed by
Jeff Garzik
825a2ff1 f49343a5

+999
+11
drivers/net/8390.h
··· 73 73 u32 *reg_offset; /* Register mapping table */ 74 74 spinlock_t page_lock; /* Page register locks */ 75 75 unsigned long priv; /* Private field to store bus IDs etc. */ 76 + #ifdef AX88796_PLATFORM 77 + unsigned char rxcr_base; /* default value for RXCR */ 78 + #endif 76 79 }; 77 80 78 81 /* The maximum number of 8390 interrupt service routines called per IRQ. */ ··· 89 86 /* Some generic ethernet register configurations. */ 90 87 #define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ 91 88 #define E8390_RX_IRQ_MASK 0x5 89 + 90 + #ifdef AX88796_PLATFORM 91 + #define E8390_RXCONFIG (ei_status.rxcr_base | 0x04) 92 + #define E8390_RXOFF (ei_status.rxcr_base | 0x20) 93 + #else 92 94 #define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ 93 95 #define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ 96 + #endif 97 + 94 98 #define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ 95 99 #define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ 100 + 96 101 97 102 /* Register accessed at EN_CMD, the 8390 base addr. */ 98 103 #define E8390_STOP 0x01 /* Stop and reset the chip */
+8
drivers/net/Kconfig
··· 197 197 198 198 source "drivers/net/arm/Kconfig" 199 199 200 + config AX88796 201 + tristate "ASIX AX88796 NE2000 clone support" 202 + select CRC32 203 + select MII 204 + help 205 + AX88796 driver, using platform bus to provide 206 + chip detection and resources 207 + 200 208 config MACE 201 209 tristate "MACE (Power Mac ethernet) support" 202 210 depends on PPC_PMAC && PPC32
+1
drivers/net/Makefile
··· 107 107 obj-$(CONFIG_B44) += b44.o 108 108 obj-$(CONFIG_FORCEDETH) += forcedeth.o 109 109 obj-$(CONFIG_NE_H8300) += ne-h8300.o 110 + obj-$(CONFIG_AX88796) += ax88796.o 110 111 111 112 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o 112 113 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+952
drivers/net/ax88796.c
··· 1 + /* drivers/net/ax88796.c 2 + * 3 + * Copyright 2005,2007 Simtec Electronics 4 + * Ben Dooks <ben@simtec.co.uk> 5 + * 6 + * Asix AX88796 10/100 Ethernet controller support 7 + * Based on ne.c, by Donald Becker, et-al. 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/kernel.h> 16 + #include <linux/errno.h> 17 + #include <linux/isapnp.h> 18 + #include <linux/init.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/delay.h> 22 + #include <linux/timer.h> 23 + #include <linux/netdevice.h> 24 + #include <linux/etherdevice.h> 25 + #include <linux/ethtool.h> 26 + #include <linux/mii.h> 27 + 28 + #include <net/ax88796.h> 29 + 30 + #include <asm/system.h> 31 + #include <asm/io.h> 32 + 33 + static int phy_debug = 0; 34 + 35 + /* Rename the lib8390.c functions to show that they are in this driver */ 36 + #define __ei_open ax_ei_open 37 + #define __ei_close ax_ei_close 38 + #define __ei_poll ax_ei_poll 39 + #define __ei_tx_timeout ax_ei_tx_timeout 40 + #define __ei_interrupt ax_ei_interrupt 41 + #define ____alloc_ei_netdev ax__alloc_ei_netdev 42 + #define __NS8390_init ax_NS8390_init 43 + 44 + /* force unsigned long back to 'void __iomem *' */ 45 + #define ax_convert_addr(_a) ((void __force __iomem *)(_a)) 46 + 47 + #define ei_inb(_a) readb(ax_convert_addr(_a)) 48 + #define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a)) 49 + 50 + #define ei_inb_p(_a) ei_inb(_a) 51 + #define ei_outb_p(_v, _a) ei_outb(_v, _a) 52 + 53 + /* define EI_SHIFT() to take into account our register offsets */ 54 + #define EI_SHIFT(x) (ei_local->reg_offset[(x)]) 55 + 56 + /* Ensure we have our RCR base value */ 57 + #define AX88796_PLATFORM 58 + 59 + static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n"; 60 + 61 + #include "lib8390.c" 62 + 63 + #define DRV_NAME "ax88796" 64 + #define DRV_VERSION "1.00" 65 + 66 + /* from ne.c */ 67 + #define NE_CMD EI_SHIFT(0x00) 68 + #define NE_RESET EI_SHIFT(0x1f) 69 + #define NE_DATAPORT EI_SHIFT(0x10) 70 + 71 + #define NE1SM_START_PG 0x20 /* First page of TX buffer */ 72 + #define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ 73 + #define NESM_START_PG 0x40 /* First page of TX buffer */ 74 + #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ 75 + 76 + /* device private data */ 77 + 78 + struct ax_device { 79 + struct timer_list mii_timer; 80 + spinlock_t mii_lock; 81 + struct mii_if_info mii; 82 + 83 + u32 msg_enable; 84 + void __iomem *map2; 85 + struct platform_device *dev; 86 + struct resource *mem; 87 + struct resource *mem2; 88 + struct ax_plat_data *plat; 89 + 90 + unsigned char running; 91 + unsigned char resume_open; 92 + 93 + u32 reg_offsets[0x20]; 94 + }; 95 + 96 + static inline struct ax_device *to_ax_dev(struct net_device *dev) 97 + { 98 + struct ei_device *ei_local = netdev_priv(dev); 99 + return (struct ax_device *)(ei_local+1); 100 + } 101 + 102 + /* ax_initial_check 103 + * 104 + * do an initial probe for the card to check wether it exists 105 + * and is functional 106 + */ 107 + 108 + static int ax_initial_check(struct net_device *dev) 109 + { 110 + struct ei_device *ei_local = netdev_priv(dev); 111 + void __iomem *ioaddr = ei_local->mem; 112 + int reg0; 113 + int regd; 114 + 115 + reg0 = ei_inb(ioaddr); 116 + if (reg0 == 0xFF) 117 + return -ENODEV; 118 + 119 + ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD); 120 + regd = ei_inb(ioaddr + 0x0d); 121 + ei_outb(0xff, ioaddr + 0x0d); 122 + ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD); 123 + ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */ 124 + if (ei_inb(ioaddr + EN0_COUNTER0) != 0) { 125 + ei_outb(reg0, ioaddr); 126 + ei_outb(regd, ioaddr + 0x0d); /* Restore the old values. */ 127 + return -ENODEV; 128 + } 129 + 130 + return 0; 131 + } 132 + 133 + /* Hard reset the card. This used to pause for the same period that a 134 + 8390 reset command required, but that shouldn't be necessary. */ 135 + 136 + static void ax_reset_8390(struct net_device *dev) 137 + { 138 + struct ei_device *ei_local = netdev_priv(dev); 139 + unsigned long reset_start_time = jiffies; 140 + void __iomem *addr = (void __iomem *)dev->base_addr; 141 + 142 + if (ei_debug > 1) 143 + printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies); 144 + 145 + ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET); 146 + 147 + ei_status.txing = 0; 148 + ei_status.dmaing = 0; 149 + 150 + /* This check _should_not_ be necessary, omit eventually. */ 151 + while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) { 152 + if (jiffies - reset_start_time > 2*HZ/100) { 153 + printk(KERN_WARNING "%s: %s did not complete.\n", 154 + __FUNCTION__, dev->name); 155 + break; 156 + } 157 + } 158 + 159 + ei_outb(ENISR_RESET, addr + EN0_ISR); /* Ack intr. */ 160 + } 161 + 162 + 163 + static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, 164 + int ring_page) 165 + { 166 + struct ei_device *ei_local = netdev_priv(dev); 167 + void __iomem *nic_base = ei_local->mem; 168 + 169 + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 170 + if (ei_status.dmaing) { 171 + printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n", 172 + dev->name, __FUNCTION__, 173 + ei_status.dmaing, ei_status.irqlock); 174 + return; 175 + } 176 + 177 + ei_status.dmaing |= 0x01; 178 + ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); 179 + ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); 180 + ei_outb(0, nic_base + EN0_RCNTHI); 181 + ei_outb(0, nic_base + EN0_RSARLO); /* On page boundary */ 182 + ei_outb(ring_page, nic_base + EN0_RSARHI); 183 + ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); 184 + 185 + if (ei_status.word16) 186 + readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); 187 + else 188 + readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)); 189 + 190 + ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ 191 + ei_status.dmaing &= ~0x01; 192 + 193 + le16_to_cpus(&hdr->count); 194 + } 195 + 196 + 197 + /* Block input and output, similar to the Crynwr packet driver. If you 198 + are porting to a new ethercard, look at the packet driver source for hints. 199 + The NEx000 doesn't share the on-board packet memory -- you have to put 200 + the packet out through the "remote DMA" dataport using ei_outb. */ 201 + 202 + static void ax_block_input(struct net_device *dev, int count, 203 + struct sk_buff *skb, int ring_offset) 204 + { 205 + struct ei_device *ei_local = netdev_priv(dev); 206 + void __iomem *nic_base = ei_local->mem; 207 + char *buf = skb->data; 208 + 209 + if (ei_status.dmaing) { 210 + printk(KERN_EMERG "%s: DMAing conflict in ax_block_input " 211 + "[DMAstat:%d][irqlock:%d].\n", 212 + dev->name, ei_status.dmaing, ei_status.irqlock); 213 + return; 214 + } 215 + 216 + ei_status.dmaing |= 0x01; 217 + 218 + ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); 219 + ei_outb(count & 0xff, nic_base + EN0_RCNTLO); 220 + ei_outb(count >> 8, nic_base + EN0_RCNTHI); 221 + ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO); 222 + ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI); 223 + ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); 224 + 225 + if (ei_status.word16) { 226 + readsw(nic_base + NE_DATAPORT, buf, count >> 1); 227 + if (count & 0x01) 228 + buf[count-1] = ei_inb(nic_base + NE_DATAPORT); 229 + 230 + } else { 231 + readsb(nic_base + NE_DATAPORT, buf, count); 232 + } 233 + 234 + ei_status.dmaing &= ~1; 235 + } 236 + 237 + static void ax_block_output(struct net_device *dev, int count, 238 + const unsigned char *buf, const int start_page) 239 + { 240 + struct ei_device *ei_local = netdev_priv(dev); 241 + void __iomem *nic_base = ei_local->mem; 242 + unsigned long dma_start; 243 + 244 + /* Round the count up for word writes. Do we need to do this? 245 + What effect will an odd byte count have on the 8390? 246 + I should check someday. */ 247 + 248 + if (ei_status.word16 && (count & 0x01)) 249 + count++; 250 + 251 + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 252 + if (ei_status.dmaing) { 253 + printk(KERN_EMERG "%s: DMAing conflict in %s." 254 + "[DMAstat:%d][irqlock:%d]\n", 255 + dev->name, __FUNCTION__, 256 + ei_status.dmaing, ei_status.irqlock); 257 + return; 258 + } 259 + 260 + ei_status.dmaing |= 0x01; 261 + /* We should already be in page 0, but to be safe... */ 262 + ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); 263 + 264 + ei_outb(ENISR_RDC, nic_base + EN0_ISR); 265 + 266 + /* Now the normal output. */ 267 + ei_outb(count & 0xff, nic_base + EN0_RCNTLO); 268 + ei_outb(count >> 8, nic_base + EN0_RCNTHI); 269 + ei_outb(0x00, nic_base + EN0_RSARLO); 270 + ei_outb(start_page, nic_base + EN0_RSARHI); 271 + 272 + ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); 273 + if (ei_status.word16) { 274 + writesw(nic_base + NE_DATAPORT, buf, count>>1); 275 + } else { 276 + writesb(nic_base + NE_DATAPORT, buf, count); 277 + } 278 + 279 + dma_start = jiffies; 280 + 281 + while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) { 282 + if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ 283 + printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); 284 + ax_reset_8390(dev); 285 + ax_NS8390_init(dev,1); 286 + break; 287 + } 288 + } 289 + 290 + ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ 291 + ei_status.dmaing &= ~0x01; 292 + return; 293 + } 294 + 295 + /* definitions for accessing MII/EEPROM interface */ 296 + 297 + #define AX_MEMR EI_SHIFT(0x14) 298 + #define AX_MEMR_MDC (1<<0) 299 + #define AX_MEMR_MDIR (1<<1) 300 + #define AX_MEMR_MDI (1<<2) 301 + #define AX_MEMR_MDO (1<<3) 302 + #define AX_MEMR_EECS (1<<4) 303 + #define AX_MEMR_EEI (1<<5) 304 + #define AX_MEMR_EEO (1<<6) 305 + #define AX_MEMR_EECLK (1<<7) 306 + 307 + /* ax_mii_ei_outbits 308 + * 309 + * write the specified set of bits to the phy 310 + */ 311 + 312 + static void 313 + ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len) 314 + { 315 + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); 316 + void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; 317 + unsigned int memr; 318 + 319 + /* clock low, data to output mode */ 320 + memr = ei_inb(memr_addr); 321 + memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR); 322 + ei_outb(memr, memr_addr); 323 + 324 + for (len--; len >= 0; len--) { 325 + if (bits & (1 << len)) 326 + memr |= AX_MEMR_MDO; 327 + else 328 + memr &= ~AX_MEMR_MDO; 329 + 330 + ei_outb(memr, memr_addr); 331 + 332 + /* clock high */ 333 + 334 + ei_outb(memr | AX_MEMR_MDC, memr_addr); 335 + udelay(1); 336 + 337 + /* clock low */ 338 + ei_outb(memr, memr_addr); 339 + } 340 + 341 + /* leaves the clock line low, mdir input */ 342 + memr |= AX_MEMR_MDIR; 343 + ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR); 344 + } 345 + 346 + /* ax_phy_ei_inbits 347 + * 348 + * read a specified number of bits from the phy 349 + */ 350 + 351 + static unsigned int 352 + ax_phy_ei_inbits(struct net_device *dev, int no) 353 + { 354 + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); 355 + void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; 356 + unsigned int memr; 357 + unsigned int result = 0; 358 + 359 + /* clock low, data to input mode */ 360 + memr = ei_inb(memr_addr); 361 + memr &= ~AX_MEMR_MDC; 362 + memr |= AX_MEMR_MDIR; 363 + ei_outb(memr, memr_addr); 364 + 365 + for (no--; no >= 0; no--) { 366 + ei_outb(memr | AX_MEMR_MDC, memr_addr); 367 + 368 + udelay(1); 369 + 370 + if (ei_inb(memr_addr) & AX_MEMR_MDI) 371 + result |= (1<<no); 372 + 373 + ei_outb(memr, memr_addr); 374 + } 375 + 376 + return result; 377 + } 378 + 379 + /* ax_phy_issueaddr 380 + * 381 + * use the low level bit shifting routines to send the address 382 + * and command to the specified phy 383 + */ 384 + 385 + static void 386 + ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc) 387 + { 388 + if (phy_debug) 389 + pr_debug("%s: dev %p, %04x, %04x, %d\n", 390 + __FUNCTION__, dev, phy_addr, reg, opc); 391 + 392 + ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */ 393 + ax_mii_ei_outbits(dev, 1, 2); /* frame-start */ 394 + ax_mii_ei_outbits(dev, opc, 2); /* op code */ 395 + ax_mii_ei_outbits(dev, phy_addr, 5); /* phy address */ 396 + ax_mii_ei_outbits(dev, reg, 5); /* reg address */ 397 + } 398 + 399 + static int 400 + ax_phy_read(struct net_device *dev, int phy_addr, int reg) 401 + { 402 + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); 403 + unsigned long flags; 404 + unsigned int result; 405 + 406 + spin_lock_irqsave(&ei_local->page_lock, flags); 407 + 408 + ax_phy_issueaddr(dev, phy_addr, reg, 2); 409 + 410 + result = ax_phy_ei_inbits(dev, 17); 411 + result &= ~(3<<16); 412 + 413 + spin_unlock_irqrestore(&ei_local->page_lock, flags); 414 + 415 + if (phy_debug) 416 + pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__, 417 + phy_addr, reg, result); 418 + 419 + return result; 420 + } 421 + 422 + static void 423 + ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value) 424 + { 425 + struct ei_device *ei = (struct ei_device *) netdev_priv(dev); 426 + unsigned long flags; 427 + 428 + printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n", 429 + __FUNCTION__, dev, phy_addr, reg, value); 430 + 431 + spin_lock_irqsave(&ei->page_lock, flags); 432 + 433 + ax_phy_issueaddr(dev, phy_addr, reg, 1); 434 + ax_mii_ei_outbits(dev, 2, 2); /* send TA */ 435 + ax_mii_ei_outbits(dev, value, 16); 436 + 437 + spin_unlock_irqrestore(&ei->page_lock, flags); 438 + } 439 + 440 + static void ax_mii_expiry(unsigned long data) 441 + { 442 + struct net_device *dev = (struct net_device *)data; 443 + struct ax_device *ax = to_ax_dev(dev); 444 + unsigned long flags; 445 + 446 + spin_lock_irqsave(&ax->mii_lock, flags); 447 + mii_check_media(&ax->mii, netif_msg_link(ax), 0); 448 + spin_unlock_irqrestore(&ax->mii_lock, flags); 449 + 450 + if (ax->running) { 451 + ax->mii_timer.expires = jiffies + HZ*2; 452 + add_timer(&ax->mii_timer); 453 + } 454 + } 455 + 456 + static int ax_open(struct net_device *dev) 457 + { 458 + struct ax_device *ax = to_ax_dev(dev); 459 + struct ei_device *ei_local = netdev_priv(dev); 460 + int ret; 461 + 462 + dev_dbg(ax->dev, "%s: open\n", dev->name); 463 + 464 + ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev); 465 + if (ret) 466 + return ret; 467 + 468 + ret = ax_ei_open(dev); 469 + if (ret) 470 + return ret; 471 + 472 + /* turn the phy on (if turned off) */ 473 + 474 + ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17)); 475 + ax->running = 1; 476 + 477 + /* start the MII timer */ 478 + 479 + init_timer(&ax->mii_timer); 480 + 481 + ax->mii_timer.expires = jiffies+1; 482 + ax->mii_timer.data = (unsigned long) dev; 483 + ax->mii_timer.function = ax_mii_expiry; 484 + 485 + add_timer(&ax->mii_timer); 486 + 487 + return 0; 488 + } 489 + 490 + static int ax_close(struct net_device *dev) 491 + { 492 + struct ax_device *ax = to_ax_dev(dev); 493 + struct ei_device *ei_local = netdev_priv(dev); 494 + 495 + dev_dbg(ax->dev, "%s: close\n", dev->name); 496 + 497 + /* turn the phy off */ 498 + 499 + ei_outb(ax->plat->gpoc_val | (1<<6), 500 + ei_local->mem + EI_SHIFT(0x17)); 501 + 502 + ax->running = 0; 503 + wmb(); 504 + 505 + del_timer_sync(&ax->mii_timer); 506 + ax_ei_close(dev); 507 + 508 + free_irq(dev->irq, dev); 509 + return 0; 510 + } 511 + 512 + static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd) 513 + { 514 + struct ax_device *ax = to_ax_dev(dev); 515 + unsigned long flags; 516 + int rc; 517 + 518 + if (!netif_running(dev)) 519 + return -EINVAL; 520 + 521 + spin_lock_irqsave(&ax->mii_lock, flags); 522 + rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL); 523 + spin_unlock_irqrestore(&ax->mii_lock, flags); 524 + 525 + return rc; 526 + } 527 + 528 + /* ethtool ops */ 529 + 530 + static void ax_get_drvinfo(struct net_device *dev, 531 + struct ethtool_drvinfo *info) 532 + { 533 + struct ax_device *ax = to_ax_dev(dev); 534 + 535 + strcpy(info->driver, DRV_NAME); 536 + strcpy(info->version, DRV_VERSION); 537 + strcpy(info->bus_info, ax->dev->name); 538 + } 539 + 540 + static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 541 + { 542 + struct ax_device *ax = to_ax_dev(dev); 543 + unsigned long flags; 544 + 545 + spin_lock_irqsave(&ax->mii_lock, flags); 546 + mii_ethtool_gset(&ax->mii, cmd); 547 + spin_lock_irqsave(&ax->mii_lock, flags); 548 + 549 + return 0; 550 + } 551 + 552 + static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 553 + { 554 + struct ax_device *ax = to_ax_dev(dev); 555 + unsigned long flags; 556 + int rc; 557 + 558 + spin_lock_irqsave(&ax->mii_lock, flags); 559 + rc = mii_ethtool_sset(&ax->mii, cmd); 560 + spin_lock_irqsave(&ax->mii_lock, flags); 561 + 562 + return rc; 563 + } 564 + 565 + static int ax_nway_reset(struct net_device *dev) 566 + { 567 + struct ax_device *ax = to_ax_dev(dev); 568 + return mii_nway_restart(&ax->mii); 569 + } 570 + 571 + static u32 ax_get_link(struct net_device *dev) 572 + { 573 + struct ax_device *ax = to_ax_dev(dev); 574 + return mii_link_ok(&ax->mii); 575 + } 576 + 577 + static const struct ethtool_ops ax_ethtool_ops = { 578 + .get_drvinfo = ax_get_drvinfo, 579 + .get_settings = ax_get_settings, 580 + .set_settings = ax_set_settings, 581 + .nway_reset = ax_nway_reset, 582 + .get_link = ax_get_link, 583 + .get_perm_addr = ethtool_op_get_perm_addr, 584 + }; 585 + 586 + /* setup code */ 587 + 588 + static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) 589 + { 590 + void __iomem *ioaddr = ei_local->mem; 591 + struct ax_device *ax = to_ax_dev(dev); 592 + 593 + /* Select page 0*/ 594 + ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD); 595 + 596 + /* set to byte access */ 597 + ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG); 598 + ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17)); 599 + } 600 + 601 + /* ax_init_dev 602 + * 603 + * initialise the specified device, taking care to note the MAC 604 + * address it may already have (if configured), ensure 605 + * the device is ready to be used by lib8390.c and registerd with 606 + * the network layer. 607 + */ 608 + 609 + static int ax_init_dev(struct net_device *dev, int first_init) 610 + { 611 + struct ei_device *ei_local = netdev_priv(dev); 612 + struct ax_device *ax = to_ax_dev(dev); 613 + void __iomem *ioaddr = ei_local->mem; 614 + unsigned int start_page; 615 + unsigned int stop_page; 616 + int ret; 617 + int i; 618 + 619 + ret = ax_initial_check(dev); 620 + if (ret) 621 + goto err_out; 622 + 623 + /* setup goes here */ 624 + 625 + ax_initial_setup(dev, ei_local); 626 + 627 + /* read the mac from the card prom if we need it */ 628 + 629 + if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) { 630 + unsigned char SA_prom[32]; 631 + 632 + for(i = 0; i < sizeof(SA_prom); i+=2) { 633 + SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT); 634 + SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT); 635 + } 636 + 637 + if (ax->plat->wordlength == 2) 638 + for (i = 0; i < 16; i++) 639 + SA_prom[i] = SA_prom[i+i]; 640 + 641 + memcpy(dev->dev_addr, SA_prom, 6); 642 + } 643 + 644 + if (ax->plat->wordlength == 2) { 645 + /* We must set the 8390 for word mode. */ 646 + ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG); 647 + start_page = NESM_START_PG; 648 + stop_page = NESM_STOP_PG; 649 + } else { 650 + start_page = NE1SM_START_PG; 651 + stop_page = NE1SM_STOP_PG; 652 + } 653 + 654 + /* load the mac-address from the device if this is the 655 + * first time we've initialised */ 656 + 657 + if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) { 658 + ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, 659 + ei_local->mem + E8390_CMD); /* 0x61 */ 660 + 661 + for (i = 0 ; i < ETHER_ADDR_LEN ; i++) 662 + dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i)); 663 + } 664 + 665 + ax_reset_8390(dev); 666 + 667 + ei_status.name = "AX88796"; 668 + ei_status.tx_start_page = start_page; 669 + ei_status.stop_page = stop_page; 670 + ei_status.word16 = (ax->plat->wordlength == 2); 671 + ei_status.rx_start_page = start_page + TX_PAGES; 672 + 673 + #ifdef PACKETBUF_MEMSIZE 674 + /* Allow the packet buffer size to be overridden by know-it-alls. */ 675 + ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; 676 + #endif 677 + 678 + ei_status.reset_8390 = &ax_reset_8390; 679 + ei_status.block_input = &ax_block_input; 680 + ei_status.block_output = &ax_block_output; 681 + ei_status.get_8390_hdr = &ax_get_8390_hdr; 682 + ei_status.priv = 0; 683 + 684 + dev->open = ax_open; 685 + dev->stop = ax_close; 686 + dev->do_ioctl = ax_ioctl; 687 + dev->ethtool_ops = &ax_ethtool_ops; 688 + 689 + ax->msg_enable = NETIF_MSG_LINK; 690 + ax->mii.phy_id_mask = 0x1f; 691 + ax->mii.reg_num_mask = 0x1f; 692 + ax->mii.phy_id = 0x10; /* onboard phy */ 693 + ax->mii.force_media = 0; 694 + ax->mii.full_duplex = 0; 695 + ax->mii.mdio_read = ax_phy_read; 696 + ax->mii.mdio_write = ax_phy_write; 697 + ax->mii.dev = dev; 698 + 699 + #ifdef CONFIG_NET_POLL_CONTROLLER 700 + dev->poll_controller = ax_ei_poll; 701 + #endif 702 + ax_NS8390_init(dev, 0); 703 + 704 + if (first_init) { 705 + printk("AX88796: %dbit, irq %d, %lx, MAC: ", 706 + ei_status.word16 ? 16:8, dev->irq, dev->base_addr); 707 + 708 + for (i = 0; i < ETHER_ADDR_LEN; i++) 709 + printk("%2.2x%c", dev->dev_addr[i], 710 + (i < (ETHER_ADDR_LEN-1) ? ':' : ' ')); 711 + 712 + printk("\n"); 713 + } 714 + 715 + ret = register_netdev(dev); 716 + if (ret) 717 + goto out_irq; 718 + 719 + return 0; 720 + 721 + out_irq: 722 + /* cleanup irq */ 723 + free_irq(dev->irq, dev); 724 + err_out: 725 + return ret; 726 + } 727 + 728 + static int ax_remove(struct platform_device *_dev) 729 + { 730 + struct net_device *dev = platform_get_drvdata(_dev); 731 + struct ax_device *ax; 732 + 733 + ax = to_ax_dev(dev); 734 + 735 + unregister_netdev(dev); 736 + free_irq(dev->irq, dev); 737 + 738 + iounmap(ei_status.mem); 739 + release_resource(ax->mem); 740 + kfree(ax->mem); 741 + 742 + if (ax->map2) { 743 + iounmap(ax->map2); 744 + release_resource(ax->mem2); 745 + kfree(ax->mem2); 746 + } 747 + 748 + free_netdev(dev); 749 + 750 + return 0; 751 + } 752 + 753 + /* ax_probe 754 + * 755 + * This is the entry point when the platform device system uses to 756 + * notify us of a new device to attach to. Allocate memory, find 757 + * the resources and information passed, and map the necessary registers. 758 + */ 759 + 760 + static int ax_probe(struct platform_device *pdev) 761 + { 762 + struct net_device *dev; 763 + struct ax_device *ax; 764 + struct resource *res; 765 + size_t size; 766 + int ret; 767 + 768 + dev = ax__alloc_ei_netdev(sizeof(struct ax_device)); 769 + if (dev == NULL) 770 + return -ENOMEM; 771 + 772 + /* ok, let's setup our device */ 773 + ax = to_ax_dev(dev); 774 + 775 + memset(ax, 0, sizeof(struct ax_device)); 776 + 777 + spin_lock_init(&ax->mii_lock); 778 + 779 + ax->dev = pdev; 780 + ax->plat = pdev->dev.platform_data; 781 + platform_set_drvdata(pdev, dev); 782 + 783 + ei_status.rxcr_base = ax->plat->rcr_val; 784 + 785 + /* find the platform resources */ 786 + 787 + dev->irq = platform_get_irq(pdev, 0); 788 + if (dev->irq < 0) { 789 + dev_err(&pdev->dev, "no IRQ specified\n"); 790 + ret = -ENXIO; 791 + goto exit_mem; 792 + } 793 + 794 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 795 + if (res == NULL) { 796 + dev_err(&pdev->dev, "no MEM specified\n"); 797 + ret = -ENXIO; 798 + goto exit_mem; 799 + } 800 + 801 + size = (res->end - res->start) + 1; 802 + 803 + /* setup the register offsets from either the platform data 804 + * or by using the size of the resource provided */ 805 + 806 + if (ax->plat->reg_offsets) 807 + ei_status.reg_offset = ax->plat->reg_offsets; 808 + else { 809 + ei_status.reg_offset = ax->reg_offsets; 810 + for (ret = 0; ret < 0x18; ret++) 811 + ax->reg_offsets[ret] = (size / 0x18) * ret; 812 + } 813 + 814 + ax->mem = request_mem_region(res->start, size, pdev->name); 815 + if (ax->mem == NULL) { 816 + dev_err(&pdev->dev, "cannot reserve registers\n"); 817 + ret = -ENXIO; 818 + goto exit_mem; 819 + } 820 + 821 + ei_status.mem = ioremap(res->start, size); 822 + dev->base_addr = (long)ei_status.mem; 823 + 824 + if (ei_status.mem == NULL) { 825 + dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n", 826 + res->start, res->end); 827 + 828 + ret = -ENXIO; 829 + goto exit_req; 830 + } 831 + 832 + /* look for reset area */ 833 + 834 + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 835 + if (res == NULL) { 836 + if (!ax->plat->reg_offsets) { 837 + for (ret = 0; ret < 0x20; ret++) 838 + ax->reg_offsets[ret] = (size / 0x20) * ret; 839 + } 840 + 841 + ax->map2 = NULL; 842 + } else { 843 + size = (res->end - res->start) + 1; 844 + 845 + ax->mem2 = request_mem_region(res->start, size, pdev->name); 846 + if (ax->mem == NULL) { 847 + dev_err(&pdev->dev, "cannot reserve registers\n"); 848 + ret = -ENXIO; 849 + goto exit_mem1; 850 + } 851 + 852 + ax->map2 = ioremap(res->start, size); 853 + if (ax->map2 == NULL) { 854 + dev_err(&pdev->dev, "cannot map reset register"); 855 + ret = -ENXIO; 856 + goto exit_mem2; 857 + } 858 + 859 + ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem; 860 + } 861 + 862 + /* got resources, now initialise and register device */ 863 + 864 + ret = ax_init_dev(dev, 1); 865 + if (!ret) 866 + return 0; 867 + 868 + if (ax->map2 == NULL) 869 + goto exit_mem1; 870 + 871 + iounmap(ax->map2); 872 + 873 + exit_mem2: 874 + release_resource(ax->mem2); 875 + kfree(ax->mem2); 876 + 877 + exit_mem1: 878 + iounmap(ei_status.mem); 879 + 880 + exit_req: 881 + release_resource(ax->mem); 882 + kfree(ax->mem); 883 + 884 + exit_mem: 885 + free_netdev(dev); 886 + 887 + return ret; 888 + } 889 + 890 + /* suspend and resume */ 891 + 892 + #ifdef CONFIG_PM 893 + static int ax_suspend(struct platform_device *dev, pm_message_t state) 894 + { 895 + struct net_device *ndev = platform_get_drvdata(dev); 896 + struct ax_device *ax = to_ax_dev(ndev); 897 + 898 + ax->resume_open = ax->running; 899 + 900 + netif_device_detach(ndev); 901 + ax_close(ndev); 902 + 903 + return 0; 904 + } 905 + 906 + static int ax_resume(struct platform_device *pdev) 907 + { 908 + struct net_device *ndev = platform_get_drvdata(pdev); 909 + struct ax_device *ax = to_ax_dev(ndev); 910 + 911 + ax_initial_setup(ndev, netdev_priv(ndev)); 912 + ax_NS8390_init(ndev, ax->resume_open); 913 + netif_device_attach(ndev); 914 + 915 + if (ax->resume_open) 916 + ax_open(ndev); 917 + 918 + return 0; 919 + } 920 + 921 + #else 922 + #define ax_suspend NULL 923 + #define ax_resume NULL 924 + #endif 925 + 926 + static struct platform_driver axdrv = { 927 + .driver = { 928 + .name = "ax88796", 929 + .owner = THIS_MODULE, 930 + }, 931 + .probe = ax_probe, 932 + .remove = ax_remove, 933 + .suspend = ax_suspend, 934 + .resume = ax_resume, 935 + }; 936 + 937 + static int __init axdrv_init(void) 938 + { 939 + return platform_driver_register(&axdrv); 940 + } 941 + 942 + static void __exit axdrv_exit(void) 943 + { 944 + platform_driver_unregister(&axdrv); 945 + } 946 + 947 + module_init(axdrv_init); 948 + module_exit(axdrv_exit); 949 + 950 + MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver"); 951 + MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 952 + MODULE_LICENSE("GPL v2");
+27
include/net/ax88796.h
··· 1 + /* include/net/ax88796.h 2 + * 3 + * Copyright 2005 Simtec Electronics 4 + * Ben Dooks <ben@simtec.co.uk> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + * 10 + */ 11 + 12 + #ifndef __NET_AX88796_PLAT_H 13 + #define __NET_AX88796_PLAT_H 14 + 15 + #define AXFLG_HAS_EEPROM (1<<0) 16 + #define AXFLG_MAC_FROMDEV (1<<1) /* device already has MAC */ 17 + 18 + struct ax_plat_data { 19 + unsigned int flags; 20 + unsigned char wordlength; /* 1 or 2 */ 21 + unsigned char dcr_val; /* default value for DCR */ 22 + unsigned char rcr_val; /* default value for RCR */ 23 + unsigned char gpoc_val; /* default value for GPOC */ 24 + u32 *reg_offsets; /* register offsets */ 25 + }; 26 + 27 + #endif /* __NET_AX88796_PLAT_H */