diff options
Diffstat (limited to 'drivers/net/ethernet/cirrus/cs89x0.c')
| -rw-r--r-- | drivers/net/ethernet/cirrus/cs89x0.c | 148 | 
1 files changed, 122 insertions, 26 deletions
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index d5ff93653e4..30fee428c48 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -100,9 +100,6 @@  */ -/* Always include 'config.h' first in case the user wants to turn on -   or override something. */ -#include <linux/module.h>  /*   * Set this to zero to disable DMA code @@ -131,9 +128,12 @@  */ +#include <linux/module.h> +#include <linux/printk.h>  #include <linux/errno.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> +#include <linux/platform_device.h>  #include <linux/kernel.h>  #include <linux/types.h>  #include <linux/fcntl.h> @@ -151,6 +151,7 @@  #include <asm/system.h>  #include <asm/io.h>  #include <asm/irq.h> +#include <linux/atomic.h>  #if ALLOW_DMA  #include <asm/dma.h>  #endif @@ -174,26 +175,20 @@ static char version[] __initdata =     them to system IRQ numbers. This mapping is card specific and is set to     the configuration of the Cirrus Eval board for this chip. */  #if defined(CONFIG_MACH_IXDP2351) +#define CS89x0_NONISA_IRQ  static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};  static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};  #elif defined(CONFIG_ARCH_IXDP2X01) +#define CS89x0_NONISA_IRQ  static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};  static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; -#elif defined(CONFIG_MACH_QQ2440) -#include <mach/qq2440.h> -static unsigned int netcard_portlist[] __used __initdata = { QQ2440_CS8900_VIRT_BASE + 0x300, 0 }; -static unsigned int cs8900_irq_map[] = { QQ2440_CS8900_IRQ, 0, 0, 0 }; -#elif defined(CONFIG_MACH_MX31ADS) -#include <mach/board-mx31ads.h> -static unsigned int netcard_portlist[] __used __initdata = { -	PBC_BASE_ADDRESS + PBC_CS8900A_IOBASE + 0x300, 0 -}; -static unsigned cs8900_irq_map[] = {EXPIO_INT_ENET_INT, 0, 0, 0};  #else +#ifndef CONFIG_CS89x0_PLATFORM  static unsigned int netcard_portlist[] __used __initdata =     { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};  static unsigned int cs8900_irq_map[] = {10,11,12,5};  #endif +#endif  #if DEBUGGING  static unsigned int net_debug = DEBUGGING; @@ -236,11 +231,16 @@ struct net_local {  	unsigned char *end_dma_buff;	/* points to the end of the buffer */  	unsigned char *rx_dma_ptr;	/* points to the next packet  */  #endif +#ifdef CONFIG_CS89x0_PLATFORM +	void __iomem *virt_addr;/* Virtual address for accessing the CS89x0. */ +	unsigned long phys_addr;/* Physical address for accessing the CS89x0. */ +	unsigned long size;	/* Length of CS89x0 memory region. */ +#endif  };  /* Index to functions, as function prototypes. */ -static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular); +static int cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular);  static int net_open(struct net_device *dev);  static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);  static irqreturn_t net_interrupt(int irq, void *dev_id); @@ -294,6 +294,7 @@ static int __init media_fn(char *str)  __setup("cs89x0_media=", media_fn); +#ifndef CONFIG_CS89x0_PLATFORM  /* Check for a network adaptor of this type, and return '0' iff one exists.     If dev->base_addr == 0, probe all likely locations.     If dev->base_addr == 1, always return failure. @@ -343,6 +344,7 @@ out:  	return ERR_PTR(err);  }  #endif +#endif  #if defined(CONFIG_MACH_IXDP2351)  static u16 @@ -504,7 +506,7 @@ static const struct net_device_ops net_ops = {   */  static int __init -cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) +cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)  {  	struct net_local *lp = netdev_priv(dev);  	static unsigned version_printed; @@ -529,15 +531,12 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)  		lp->force = g_cs89x0_media__force;  #endif -#if defined(CONFIG_MACH_QQ2440) -		lp->force |= FORCE_RJ45 | FORCE_FULL; -#endif          }  	/* Grab the region so we can find another board if autoIRQ fails. */  	/* WTF is going on here? */  	if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { -		printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n", +		printk(KERN_ERR "%s: request_region(0x%lx, 0x%x) failed\n",  				DRV_NAME, ioaddr, NETCARD_IO_EXTENT);  		retval = -EBUSY;  		goto out1; @@ -549,7 +548,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)  	   will skip the test for the ADD_PORT. */  	if (ioaddr & 1) {  		if (net_debug > 1) -			printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr); +			printk(KERN_INFO "%s: odd ioaddr 0x%lx\n", dev->name, ioaddr);  	        if ((ioaddr & 2) != 2)  	        	if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {  				printk(KERN_ERR "%s: bad signature 0x%x\n", @@ -560,13 +559,13 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)  	}  	ioaddr &= ~3; -	printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", +	printk(KERN_DEBUG "PP_addr at %lx[%x]: 0x%x\n",  			ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));  	writeword(ioaddr, ADD_PORT, PP_ChipID);  	tmp = readword(ioaddr, DATA_PORT);  	if (tmp != CHIP_EISA_ID_SIG) { -		printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!=" +		printk(KERN_DEBUG "%s: incorrect signature at %lx[%x]: 0x%x!="  			CHIP_EISA_ID_SIG_STR "\n",  			dev->name, ioaddr, DATA_PORT, tmp);    		retval = -ENODEV; @@ -736,8 +735,9 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)  			dev->irq = i;  	} else {  		i = lp->isa_config & INT_NO_MASK; +#ifndef CONFIG_CS89x0_PLATFORM  		if (lp->chip_type == CS8900) { -#ifdef CONFIG_CS89x0_NONISA_IRQ +#ifdef CS89x0_NONISA_IRQ  		        i = cs8900_irq_map[0];  #else  			/* Translate the IRQ using the IRQ mapping table. */ @@ -758,6 +758,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)  			}  #endif  		} +#endif  		if (!dev->irq)  			dev->irq = i;  	} @@ -1168,6 +1169,7 @@ write_irq(struct net_device *dev, int chip_type, int irq)  	int i;  	if (chip_type == CS8900) { +#ifndef CONFIG_CS89x0_PLATFORM  		/* Search the mapping table for the corresponding IRQ pin. */  		for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)  			if (cs8900_irq_map[i] == irq) @@ -1175,6 +1177,10 @@ write_irq(struct net_device *dev, int chip_type, int irq)  		/* Not found */  		if (i == ARRAY_SIZE(cs8900_irq_map))  			i = 3; +#else +		/* INTRQ0 pin is used for interrupt generation. */ +		i = 0; +#endif  		writereg(dev, PP_CS8900_ISAINT, i);  	} else {  		writereg(dev, PP_CS8920_ISAINT, irq); @@ -1228,7 +1234,7 @@ net_open(struct net_device *dev)  	}  	else  	{ -#ifndef CONFIG_CS89x0_NONISA_IRQ +#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)  		if (((1 << dev->irq) & lp->irq_map) == 0) {  			printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",                                 dev->name, dev->irq, lp->irq_map); @@ -1746,7 +1752,7 @@ static int set_mac_address(struct net_device *dev, void *p)  	return 0;  } -#ifdef MODULE +#if defined(MODULE) && !defined(CONFIG_CS89x0_PLATFORM)  static struct net_device *dev_cs89x0; @@ -1900,7 +1906,97 @@ cleanup_module(void)  	release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);  	free_netdev(dev_cs89x0);  } -#endif /* MODULE */ +#endif /* MODULE && !CONFIG_CS89x0_PLATFORM */ + +#ifdef CONFIG_CS89x0_PLATFORM +static int __init cs89x0_platform_probe(struct platform_device *pdev) +{ +	struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); +	struct net_local *lp; +	struct resource *mem_res; +	int err; + +	if (!dev) +		return -ENOMEM; + +	lp = netdev_priv(dev); + +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	dev->irq = platform_get_irq(pdev, 0); +	if (mem_res == NULL || dev->irq <= 0) { +		dev_warn(&dev->dev, "memory/interrupt resource missing.\n"); +		err = -ENXIO; +		goto free; +	} + +	lp->phys_addr = mem_res->start; +	lp->size = resource_size(mem_res); +	if (!request_mem_region(lp->phys_addr, lp->size, DRV_NAME)) { +		dev_warn(&dev->dev, "request_mem_region() failed.\n"); +		err = -EBUSY; +		goto free; +	} + +	lp->virt_addr = ioremap(lp->phys_addr, lp->size); +	if (!lp->virt_addr) { +		dev_warn(&dev->dev, "ioremap() failed.\n"); +		err = -ENOMEM; +		goto release; +	} + +	err = cs89x0_probe1(dev, (unsigned long)lp->virt_addr, 0); +	if (err) { +		dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n"); +		goto unmap; +	} + +	platform_set_drvdata(pdev, dev); +	return 0; + +unmap: +	iounmap(lp->virt_addr); +release: +	release_mem_region(lp->phys_addr, lp->size); +free: +	free_netdev(dev); +	return err; +} + +static int cs89x0_platform_remove(struct platform_device *pdev) +{ +	struct net_device *dev = platform_get_drvdata(pdev); +	struct net_local *lp = netdev_priv(dev); + +	unregister_netdev(dev); +	iounmap(lp->virt_addr); +	release_mem_region(lp->phys_addr, lp->size); +	free_netdev(dev); +	return 0; +} + +static struct platform_driver cs89x0_driver = { +	.driver	= { +		.name	= DRV_NAME, +		.owner	= THIS_MODULE, +	}, +	.remove	= cs89x0_platform_remove, +}; + +static int __init cs89x0_init(void) +{ +	return platform_driver_probe(&cs89x0_driver, cs89x0_platform_probe); +} + +module_init(cs89x0_init); + +static void __exit cs89x0_cleanup(void) +{ +	platform_driver_unregister(&cs89x0_driver); +} + +module_exit(cs89x0_cleanup); + +#endif /* CONFIG_CS89x0_PLATFORM */  /*   * Local variables:  |