X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Farm%2Fam79c961a.c;h=ddd12d44ff22dab8d7ab7b3ec44e323311af46a7;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=8bd25b970903c09717de737cfcdfe728dae70fe4;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 8bd25b970..ddd12d44f 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -15,25 +15,22 @@ */ #include #include -#include #include #include -#include #include #include #include #include #include -#include #include #include #include +#include +#include -#include -#include -#include +#include #include -#include +#include #define TX_BUFFERS 15 #define RX_BUFFERS 25 @@ -41,7 +38,7 @@ #include "am79c961a.h" static irqreturn_t -am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs); +am79c961_interrupt (int irq, void *dev_id); static unsigned int net_debug = NET_DEBUG; @@ -53,25 +50,31 @@ static const char version[] = #ifdef __arm__ static void write_rreg(u_long base, u_int reg, u_int val) { - __asm__("str%?h %1, [%2] @ NET_RAP - str%?h %0, [%2, #-4] @ NET_RDP - " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); + __asm__( + "str%?h %1, [%2] @ NET_RAP\n\t" + "str%?h %0, [%2, #-4] @ NET_RDP" + : + : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); } static inline unsigned short read_rreg(u_long base_addr, u_int reg) { unsigned short v; - __asm__("str%?h %1, [%2] @ NET_RAP - ldr%?h %0, [%2, #-4] @ NET_RDP - " : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464)); + __asm__( + "str%?h %1, [%2] @ NET_RAP\n\t" + "ldr%?h %0, [%2, #-4] @ NET_RDP" + : "=r" (v) + : "r" (reg), "r" (ISAIO_BASE + 0x0464)); return v; } static inline void write_ireg(u_long base, u_int reg, u_int val) { - __asm__("str%?h %1, [%2] @ NET_RAP - str%?h %0, [%2, #8] @ NET_IDP - " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); + __asm__( + "str%?h %1, [%2] @ NET_RAP\n\t" + "str%?h %0, [%2, #8] @ NET_IDP" + : + : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); } static inline unsigned short read_ireg(u_long base_addr, u_int reg) @@ -79,7 +82,7 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg) u_short v; __asm__( "str%?h %1, [%2] @ NAT_RAP\n\t" - "str%?h %0, [%2, #8] @ NET_IDP\n\t" + "ldr%?h %0, [%2, #8] @ NET_IDP\n\t" : "=r" (v) : "r" (reg), "r" (ISAIO_BASE + 0x0464)); return v; @@ -101,16 +104,16 @@ am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigne } while (length > 8) { unsigned int tmp, tmp2; - __asm__ __volatile__(" - ldm%?ia %1!, {%2, %3} - str%?h %2, [%0], #4 - mov%? %2, %2, lsr #16 - str%?h %2, [%0], #4 - str%?h %3, [%0], #4 - mov%? %3, %3, lsr #16 - str%?h %3, [%0], #4 - " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2) - : "0" (offset), "1" (buf)); + __asm__ __volatile__( + "ldm%?ia %1!, {%2, %3}\n\t" + "str%?h %2, [%0], #4\n\t" + "mov%? %2, %2, lsr #16\n\t" + "str%?h %2, [%0], #4\n\t" + "str%?h %3, [%0], #4\n\t" + "mov%? %3, %3, lsr #16\n\t" + "str%?h %3, [%0], #4" + : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2) + : "0" (offset), "1" (buf)); length -= 8; } while (length > 0) { @@ -128,36 +131,36 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned length = (length + 1) & ~1; if ((int)buf & 2) { unsigned int tmp; - __asm__ __volatile__(" - ldr%?h %2, [%0], #4 - str%?b %2, [%1], #1 - mov%? %2, %2, lsr #8 - str%?b %2, [%1], #1 - " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf)); + __asm__ __volatile__( + "ldr%?h %2, [%0], #4\n\t" + "str%?b %2, [%1], #1\n\t" + "mov%? %2, %2, lsr #8\n\t" + "str%?b %2, [%1], #1" + : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf)); length -= 2; } while (length > 8) { unsigned int tmp, tmp2, tmp3; - __asm__ __volatile__(" - ldr%?h %2, [%0], #4 - ldr%?h %3, [%0], #4 - orr%? %2, %2, %3, lsl #16 - ldr%?h %3, [%0], #4 - ldr%?h %4, [%0], #4 - orr%? %3, %3, %4, lsl #16 - stm%?ia %1!, {%2, %3} - " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3) - : "0" (offset), "1" (buf)); + __asm__ __volatile__( + "ldr%?h %2, [%0], #4\n\t" + "ldr%?h %3, [%0], #4\n\t" + "orr%? %2, %2, %3, lsl #16\n\t" + "ldr%?h %3, [%0], #4\n\t" + "ldr%?h %4, [%0], #4\n\t" + "orr%? %3, %3, %4, lsl #16\n\t" + "stm%?ia %1!, {%2, %3}" + : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3) + : "0" (offset), "1" (buf)); length -= 8; } while (length > 0) { unsigned int tmp; - __asm__ __volatile__(" - ldr%?h %2, [%0], #4 - str%?b %2, [%1], #1 - mov%? %2, %2, lsr #8 - str%?b %2, [%1], #1 - " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf)); + __asm__ __volatile__( + "ldr%?h %2, [%0], #4\n\t" + "str%?b %2, [%1], #1\n\t" + "mov%? %2, %2, lsr #8\n\t" + "str%?b %2, [%1], #1" + : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf)); length -= 2; } } @@ -277,12 +280,15 @@ static void am79c961_timer(unsigned long data) lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST; carrier = netif_carrier_ok(dev); - if (lnkstat && !carrier) + if (lnkstat && !carrier) { netif_carrier_on(dev); - else if (!lnkstat && carrier) + printk("%s: link up\n", dev->name); + } else if (!lnkstat && carrier) { netif_carrier_off(dev); + printk("%s: link down\n", dev->name); + } - mod_timer(&priv->timer, jiffies + 5*HZ); + mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500)); } /* @@ -590,7 +596,7 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv) } static irqreturn_t -am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs) +am79c961_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; struct dev_priv *priv = netdev_priv(dev); @@ -618,11 +624,22 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (status & CSR0_CERR) { handled = 1; mod_timer(&priv->timer, jiffies); + } } while (--n && status & (CSR0_RINT | CSR0_TINT)); return IRQ_RETVAL(handled); } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void am79c961_poll_controller(struct net_device *dev) +{ + unsigned long flags; + local_irq_save(flags); + am79c961_interrupt(dev->irq, dev, NULL); + local_irq_restore(flags); +} +#endif + /* * Initialise the chip. Note that we always expect * to be entered with interrupts enabled. @@ -651,17 +668,24 @@ static void __init am79c961_banner(void) printk(KERN_INFO "%s", version); } -static int __init am79c961_init(void) +static int __init am79c961_probe(struct platform_device *pdev) { + struct resource *res; struct net_device *dev; struct dev_priv *priv; int i, ret; + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!res) + return -ENODEV; + dev = alloc_etherdev(sizeof(struct dev_priv)); ret = -ENOMEM; if (!dev) goto out; + SET_NETDEV_DEV(dev, &pdev->dev); + priv = netdev_priv(dev); /* @@ -669,10 +693,12 @@ static int __init am79c961_init(void) * The PNP initialisation should have been * done by the ether bootp loader. */ - dev->base_addr = 0x220; - dev->irq = IRQ_EBSA110_ETHERNET; + dev->base_addr = res->start; + dev->irq = platform_get_irq(pdev, 0); - ret = -ENODEV; + ret = -ENODEV; + if (dev->irq < 0) + goto nodev; if (!request_region(dev->base_addr, 0x18, dev->name)) goto nodev; @@ -691,14 +717,10 @@ static int __init am79c961_init(void) inb(dev->base_addr + 4) != 0x2b) goto release; - am79c961_banner(); - printk(KERN_INFO "%s: ether address ", dev->name); - - /* Retrive and print the ethernet address. */ - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff; - printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); - } + + am79c961_banner(); spin_lock_init(&priv->chip_lock); init_timer(&priv->timer); @@ -714,10 +736,20 @@ static int __init am79c961_init(void) dev->get_stats = am79c961_getstats; dev->set_multicast_list = am79c961_setmulticastlist; dev->tx_timeout = am79c961_timeout; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = am79c961_poll_controller; +#endif ret = register_netdev(dev); - if (ret == 0) + if (ret == 0) { + printk(KERN_INFO "%s: ether address ", dev->name); + + /* Retrive and print the ethernet address. */ + for (i = 0; i < 6; i++) + printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); + return 0; + } release: release_region(dev->base_addr, 0x18); @@ -727,4 +759,16 @@ out: return ret; } +static struct platform_driver am79c961_driver = { + .probe = am79c961_probe, + .driver = { + .name = "am79c961", + }, +}; + +static int __init am79c961_init(void) +{ + return platform_driver_register(&am79c961_driver); +} + __initcall(am79c961_init);