aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/cirrus
diff options
context:
space:
mode:
authorJaccon Bastiaansen <jaccon.bastiaansen@gmail.com>2012-01-26 15:46:15 -0500
committerSascha Hauer <s.hauer@pengutronix.de>2012-02-01 10:49:50 -0500
commite9460a9e811dddd9ea1ae9838d9b53bfaf78cd2c (patch)
tree016ab829cf8c7cf76c117d82232a78eba1b64c01 /drivers/net/ethernet/cirrus
parent62aa2b537c6f5957afd98e29f96897419ed5ebab (diff)
CS89x0 : add platform driver support
The CS89x0 ethernet controller is used on a number of evaluation boards, such as the MX31ADS. The current driver has memory address and IRQ settings for each board on which this controller is used. Driver updates are therefore required to support other boards that also use the CS89x0. To avoid these driver updates, a better mechanism (platform driver support) is added to communicate the board dependent settings to the driver. Signed-off-by: Jaccon Bastiaansen <jaccon.bastiaansen@gmail.com> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/net/ethernet/cirrus')
-rw-r--r--drivers/net/ethernet/cirrus/Kconfig19
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c137
2 files changed, 135 insertions, 21 deletions
diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig
index 1f8648f099c7..8388e36cf08f 100644
--- a/drivers/net/ethernet/cirrus/Kconfig
+++ b/drivers/net/ethernet/cirrus/Kconfig
@@ -5,8 +5,7 @@
5config NET_VENDOR_CIRRUS 5config NET_VENDOR_CIRRUS
6 bool "Cirrus devices" 6 bool "Cirrus devices"
7 default y 7 default y
8 depends on ISA || EISA || MACH_IXDP2351 || ARCH_IXDP2X01 \ 8 depends on ISA || EISA || ARM || MAC
9 || MACH_MX31ADS || MACH_QQ2440 || (ARM && ARCH_EP93XX) || MAC
10 ---help--- 9 ---help---
11 If you have a network (Ethernet) card belonging to this class, say Y 10 If you have a network (Ethernet) card belonging to this class, say Y
12 and read the Ethernet-HOWTO, available from 11 and read the Ethernet-HOWTO, available from
@@ -21,8 +20,7 @@ if NET_VENDOR_CIRRUS
21 20
22config CS89x0 21config CS89x0
23 tristate "CS89x0 support" 22 tristate "CS89x0 support"
24 depends on (ISA || EISA || MACH_IXDP2351 \ 23 depends on ISA || EISA || ARM
25 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
26 ---help--- 24 ---help---
27 Support for CS89x0 chipset based Ethernet cards. If you have a 25 Support for CS89x0 chipset based Ethernet cards. If you have a
28 network (Ethernet) card of this type, say Y and read the 26 network (Ethernet) card of this type, say Y and read the
@@ -33,10 +31,15 @@ config CS89x0
33 To compile this driver as a module, choose M here. The module 31 To compile this driver as a module, choose M here. The module
34 will be called cs89x0. 32 will be called cs89x0.
35 33
36config CS89x0_NONISA_IRQ 34config CS89x0_PLATFORM
37 def_bool y 35 bool "CS89x0 platform driver support"
38 depends on CS89x0 != n 36 depends on CS89x0
39 depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440 37 help
38 Say Y to compile the cs89x0 driver as a platform driver. This
39 makes this driver suitable for use on certain evaluation boards
40 such as the iMX21ADS.
41
42 If you are unsure, say N.
40 43
41config EP93XX_ETH 44config EP93XX_ETH
42 tristate "EP93xx Ethernet support" 45 tristate "EP93xx Ethernet support"
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index f328da24c8fa..6b3cd24eb454 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -100,9 +100,6 @@
100 100
101*/ 101*/
102 102
103/* Always include 'config.h' first in case the user wants to turn on
104 or override something. */
105#include <linux/module.h>
106 103
107/* 104/*
108 * Set this to zero to disable DMA code 105 * Set this to zero to disable DMA code
@@ -131,9 +128,12 @@
131 128
132*/ 129*/
133 130
131#include <linux/module.h>
132#include <linux/printk.h>
134#include <linux/errno.h> 133#include <linux/errno.h>
135#include <linux/netdevice.h> 134#include <linux/netdevice.h>
136#include <linux/etherdevice.h> 135#include <linux/etherdevice.h>
136#include <linux/platform_device.h>
137#include <linux/kernel.h> 137#include <linux/kernel.h>
138#include <linux/types.h> 138#include <linux/types.h>
139#include <linux/fcntl.h> 139#include <linux/fcntl.h>
@@ -151,6 +151,7 @@
151#include <asm/system.h> 151#include <asm/system.h>
152#include <asm/io.h> 152#include <asm/io.h>
153#include <asm/irq.h> 153#include <asm/irq.h>
154#include <linux/atomic.h>
154#if ALLOW_DMA 155#if ALLOW_DMA
155#include <asm/dma.h> 156#include <asm/dma.h>
156#endif 157#endif
@@ -174,26 +175,32 @@ static char version[] __initdata =
174 them to system IRQ numbers. This mapping is card specific and is set to 175 them to system IRQ numbers. This mapping is card specific and is set to
175 the configuration of the Cirrus Eval board for this chip. */ 176 the configuration of the Cirrus Eval board for this chip. */
176#if defined(CONFIG_MACH_IXDP2351) 177#if defined(CONFIG_MACH_IXDP2351)
178#define CS89x0_NONISA_IRQ
177static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; 179static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
178static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0}; 180static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
179#elif defined(CONFIG_ARCH_IXDP2X01) 181#elif defined(CONFIG_ARCH_IXDP2X01)
182#define CS89x0_NONISA_IRQ
180static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; 183static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
181static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; 184static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
182#elif defined(CONFIG_MACH_QQ2440) 185#elif defined(CONFIG_MACH_QQ2440)
186#define CS89x0_NONISA_IRQ
183#include <mach/qq2440.h> 187#include <mach/qq2440.h>
184static unsigned int netcard_portlist[] __used __initdata = { QQ2440_CS8900_VIRT_BASE + 0x300, 0 }; 188static unsigned int netcard_portlist[] __used __initdata = { QQ2440_CS8900_VIRT_BASE + 0x300, 0 };
185static unsigned int cs8900_irq_map[] = { QQ2440_CS8900_IRQ, 0, 0, 0 }; 189static unsigned int cs8900_irq_map[] = { QQ2440_CS8900_IRQ, 0, 0, 0 };
186#elif defined(CONFIG_MACH_MX31ADS) 190#elif defined(CONFIG_MACH_MX31ADS)
191#define CS89x0_NONISA_IRQ
187#include <mach/board-mx31ads.h> 192#include <mach/board-mx31ads.h>
188static unsigned int netcard_portlist[] __used __initdata = { 193static unsigned int netcard_portlist[] __used __initdata = {
189 PBC_BASE_ADDRESS + PBC_CS8900A_IOBASE + 0x300, 0 194 PBC_BASE_ADDRESS + PBC_CS8900A_IOBASE + 0x300, 0
190}; 195};
191static unsigned cs8900_irq_map[] = {EXPIO_INT_ENET_INT, 0, 0, 0}; 196static unsigned cs8900_irq_map[] = {EXPIO_INT_ENET_INT, 0, 0, 0};
192#else 197#else
198#ifndef CONFIG_CS89x0_PLATFORM
193static unsigned int netcard_portlist[] __used __initdata = 199static unsigned int netcard_portlist[] __used __initdata =
194 { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; 200 { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
195static unsigned int cs8900_irq_map[] = {10,11,12,5}; 201static unsigned int cs8900_irq_map[] = {10,11,12,5};
196#endif 202#endif
203#endif
197 204
198#if DEBUGGING 205#if DEBUGGING
199static unsigned int net_debug = DEBUGGING; 206static unsigned int net_debug = DEBUGGING;
@@ -236,11 +243,16 @@ struct net_local {
236 unsigned char *end_dma_buff; /* points to the end of the buffer */ 243 unsigned char *end_dma_buff; /* points to the end of the buffer */
237 unsigned char *rx_dma_ptr; /* points to the next packet */ 244 unsigned char *rx_dma_ptr; /* points to the next packet */
238#endif 245#endif
246#ifdef CONFIG_CS89x0_PLATFORM
247 void __iomem *virt_addr;/* Virtual address for accessing the CS89x0. */
248 unsigned long phys_addr;/* Physical address for accessing the CS89x0. */
249 unsigned long size; /* Length of CS89x0 memory region. */
250#endif
239}; 251};
240 252
241/* Index to functions, as function prototypes. */ 253/* Index to functions, as function prototypes. */
242 254
243static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular); 255static int cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular);
244static int net_open(struct net_device *dev); 256static int net_open(struct net_device *dev);
245static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev); 257static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
246static irqreturn_t net_interrupt(int irq, void *dev_id); 258static irqreturn_t net_interrupt(int irq, void *dev_id);
@@ -294,6 +306,7 @@ static int __init media_fn(char *str)
294__setup("cs89x0_media=", media_fn); 306__setup("cs89x0_media=", media_fn);
295 307
296 308
309#ifndef CONFIG_CS89x0_PLATFORM
297/* Check for a network adaptor of this type, and return '0' iff one exists. 310/* Check for a network adaptor of this type, and return '0' iff one exists.
298 If dev->base_addr == 0, probe all likely locations. 311 If dev->base_addr == 0, probe all likely locations.
299 If dev->base_addr == 1, always return failure. 312 If dev->base_addr == 1, always return failure.
@@ -343,6 +356,7 @@ out:
343 return ERR_PTR(err); 356 return ERR_PTR(err);
344} 357}
345#endif 358#endif
359#endif
346 360
347#if defined(CONFIG_MACH_IXDP2351) 361#if defined(CONFIG_MACH_IXDP2351)
348static u16 362static u16
@@ -504,7 +518,7 @@ static const struct net_device_ops net_ops = {
504 */ 518 */
505 519
506static int __init 520static int __init
507cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) 521cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
508{ 522{
509 struct net_local *lp = netdev_priv(dev); 523 struct net_local *lp = netdev_priv(dev);
510 static unsigned version_printed; 524 static unsigned version_printed;
@@ -537,7 +551,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
537 /* Grab the region so we can find another board if autoIRQ fails. */ 551 /* Grab the region so we can find another board if autoIRQ fails. */
538 /* WTF is going on here? */ 552 /* WTF is going on here? */
539 if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { 553 if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
540 printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n", 554 printk(KERN_ERR "%s: request_region(0x%lx, 0x%x) failed\n",
541 DRV_NAME, ioaddr, NETCARD_IO_EXTENT); 555 DRV_NAME, ioaddr, NETCARD_IO_EXTENT);
542 retval = -EBUSY; 556 retval = -EBUSY;
543 goto out1; 557 goto out1;
@@ -549,7 +563,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
549 will skip the test for the ADD_PORT. */ 563 will skip the test for the ADD_PORT. */
550 if (ioaddr & 1) { 564 if (ioaddr & 1) {
551 if (net_debug > 1) 565 if (net_debug > 1)
552 printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr); 566 printk(KERN_INFO "%s: odd ioaddr 0x%lx\n", dev->name, ioaddr);
553 if ((ioaddr & 2) != 2) 567 if ((ioaddr & 2) != 2)
554 if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) { 568 if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
555 printk(KERN_ERR "%s: bad signature 0x%x\n", 569 printk(KERN_ERR "%s: bad signature 0x%x\n",
@@ -560,13 +574,13 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
560 } 574 }
561 575
562 ioaddr &= ~3; 576 ioaddr &= ~3;
563 printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", 577 printk(KERN_DEBUG "PP_addr at %lx[%x]: 0x%x\n",
564 ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); 578 ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
565 writeword(ioaddr, ADD_PORT, PP_ChipID); 579 writeword(ioaddr, ADD_PORT, PP_ChipID);
566 580
567 tmp = readword(ioaddr, DATA_PORT); 581 tmp = readword(ioaddr, DATA_PORT);
568 if (tmp != CHIP_EISA_ID_SIG) { 582 if (tmp != CHIP_EISA_ID_SIG) {
569 printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!=" 583 printk(KERN_DEBUG "%s: incorrect signature at %lx[%x]: 0x%x!="
570 CHIP_EISA_ID_SIG_STR "\n", 584 CHIP_EISA_ID_SIG_STR "\n",
571 dev->name, ioaddr, DATA_PORT, tmp); 585 dev->name, ioaddr, DATA_PORT, tmp);
572 retval = -ENODEV; 586 retval = -ENODEV;
@@ -736,8 +750,9 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
736 dev->irq = i; 750 dev->irq = i;
737 } else { 751 } else {
738 i = lp->isa_config & INT_NO_MASK; 752 i = lp->isa_config & INT_NO_MASK;
753#ifndef CONFIG_CS89x0_PLATFORM
739 if (lp->chip_type == CS8900) { 754 if (lp->chip_type == CS8900) {
740#ifdef CONFIG_CS89x0_NONISA_IRQ 755#ifdef CS89x0_NONISA_IRQ
741 i = cs8900_irq_map[0]; 756 i = cs8900_irq_map[0];
742#else 757#else
743 /* Translate the IRQ using the IRQ mapping table. */ 758 /* Translate the IRQ using the IRQ mapping table. */
@@ -758,6 +773,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
758 } 773 }
759#endif 774#endif
760 } 775 }
776#endif
761 if (!dev->irq) 777 if (!dev->irq)
762 dev->irq = i; 778 dev->irq = i;
763 } 779 }
@@ -1168,6 +1184,7 @@ write_irq(struct net_device *dev, int chip_type, int irq)
1168 int i; 1184 int i;
1169 1185
1170 if (chip_type == CS8900) { 1186 if (chip_type == CS8900) {
1187#ifndef CONFIG_CS89x0_PLATFORM
1171 /* Search the mapping table for the corresponding IRQ pin. */ 1188 /* Search the mapping table for the corresponding IRQ pin. */
1172 for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++) 1189 for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
1173 if (cs8900_irq_map[i] == irq) 1190 if (cs8900_irq_map[i] == irq)
@@ -1175,6 +1192,10 @@ write_irq(struct net_device *dev, int chip_type, int irq)
1175 /* Not found */ 1192 /* Not found */
1176 if (i == ARRAY_SIZE(cs8900_irq_map)) 1193 if (i == ARRAY_SIZE(cs8900_irq_map))
1177 i = 3; 1194 i = 3;
1195#else
1196 /* INTRQ0 pin is used for interrupt generation. */
1197 i = 0;
1198#endif
1178 writereg(dev, PP_CS8900_ISAINT, i); 1199 writereg(dev, PP_CS8900_ISAINT, i);
1179 } else { 1200 } else {
1180 writereg(dev, PP_CS8920_ISAINT, irq); 1201 writereg(dev, PP_CS8920_ISAINT, irq);
@@ -1228,7 +1249,7 @@ net_open(struct net_device *dev)
1228 } 1249 }
1229 else 1250 else
1230 { 1251 {
1231#ifndef CONFIG_CS89x0_NONISA_IRQ 1252#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)
1232 if (((1 << dev->irq) & lp->irq_map) == 0) { 1253 if (((1 << dev->irq) & lp->irq_map) == 0) {
1233 printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", 1254 printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
1234 dev->name, dev->irq, lp->irq_map); 1255 dev->name, dev->irq, lp->irq_map);
@@ -1746,7 +1767,7 @@ static int set_mac_address(struct net_device *dev, void *p)
1746 return 0; 1767 return 0;
1747} 1768}
1748 1769
1749#ifdef MODULE 1770#if defined(MODULE) && !defined(CONFIG_CS89x0_PLATFORM)
1750 1771
1751static struct net_device *dev_cs89x0; 1772static struct net_device *dev_cs89x0;
1752 1773
@@ -1900,7 +1921,97 @@ cleanup_module(void)
1900 release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT); 1921 release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
1901 free_netdev(dev_cs89x0); 1922 free_netdev(dev_cs89x0);
1902} 1923}
1903#endif /* MODULE */ 1924#endif /* MODULE && !CONFIG_CS89x0_PLATFORM */
1925
1926#ifdef CONFIG_CS89x0_PLATFORM
1927static int __init cs89x0_platform_probe(struct platform_device *pdev)
1928{
1929 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
1930 struct net_local *lp;
1931 struct resource *mem_res;
1932 int err;
1933
1934 if (!dev)
1935 return -ENOMEM;
1936
1937 lp = netdev_priv(dev);
1938
1939 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1940 dev->irq = platform_get_irq(pdev, 0);
1941 if (mem_res == NULL || dev->irq <= 0) {
1942 dev_warn(&dev->dev, "memory/interrupt resource missing.\n");
1943 err = -ENXIO;
1944 goto free;
1945 }
1946
1947 lp->phys_addr = mem_res->start;
1948 lp->size = resource_size(mem_res);
1949 if (!request_mem_region(lp->phys_addr, lp->size, DRV_NAME)) {
1950 dev_warn(&dev->dev, "request_mem_region() failed.\n");
1951 err = -EBUSY;
1952 goto free;
1953 }
1954
1955 lp->virt_addr = ioremap(lp->phys_addr, lp->size);
1956 if (!lp->virt_addr) {
1957 dev_warn(&dev->dev, "ioremap() failed.\n");
1958 err = -ENOMEM;
1959 goto release;
1960 }
1961
1962 err = cs89x0_probe1(dev, (unsigned long)lp->virt_addr, 0);
1963 if (err) {
1964 dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n");
1965 goto unmap;
1966 }
1967
1968 platform_set_drvdata(pdev, dev);
1969 return 0;
1970
1971unmap:
1972 iounmap(lp->virt_addr);
1973release:
1974 release_mem_region(lp->phys_addr, lp->size);
1975free:
1976 free_netdev(dev);
1977 return err;
1978}
1979
1980static int cs89x0_platform_remove(struct platform_device *pdev)
1981{
1982 struct net_device *dev = platform_get_drvdata(pdev);
1983 struct net_local *lp = netdev_priv(dev);
1984
1985 unregister_netdev(dev);
1986 iounmap(lp->virt_addr);
1987 release_mem_region(lp->phys_addr, lp->size);
1988 free_netdev(dev);
1989 return 0;
1990}
1991
1992static struct platform_driver cs89x0_driver = {
1993 .driver = {
1994 .name = DRV_NAME,
1995 .owner = THIS_MODULE,
1996 },
1997 .remove = cs89x0_platform_remove,
1998};
1999
2000static int __init cs89x0_init(void)
2001{
2002 return platform_driver_probe(&cs89x0_driver, cs89x0_platform_probe);
2003}
2004
2005module_init(cs89x0_init);
2006
2007static void __exit cs89x0_cleanup(void)
2008{
2009 platform_driver_unregister(&cs89x0_driver);
2010}
2011
2012module_exit(cs89x0_cleanup);
2013
2014#endif /* CONFIG_CS89x0_PLATFORM */
1904 2015
1905/* 2016/*
1906 * Local variables: 2017 * Local variables: