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 f328da24c8fa..7202ca951bf3 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,20 @@ 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 | ||
| 177 | static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; | 179 | static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; |
| 178 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0}; | 180 | static 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 | ||
| 180 | static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; | 183 | static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; |
| 181 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; | 184 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; |
| 182 | #elif defined(CONFIG_MACH_QQ2440) | ||
| 183 | #include <mach/qq2440.h> | ||
| 184 | static unsigned int netcard_portlist[] __used __initdata = { QQ2440_CS8900_VIRT_BASE + 0x300, 0 }; | ||
| 185 | static unsigned int cs8900_irq_map[] = { QQ2440_CS8900_IRQ, 0, 0, 0 }; | ||
| 186 | #elif defined(CONFIG_MACH_MX31ADS) | ||
| 187 | #include <mach/board-mx31ads.h> | ||
| 188 | static unsigned int netcard_portlist[] __used __initdata = { | ||
| 189 | PBC_BASE_ADDRESS + PBC_CS8900A_IOBASE + 0x300, 0 | ||
| 190 | }; | ||
| 191 | static unsigned cs8900_irq_map[] = {EXPIO_INT_ENET_INT, 0, 0, 0}; | ||
| 192 | #else | 185 | #else |
| 186 | #ifndef CONFIG_CS89x0_PLATFORM | ||
| 193 | static unsigned int netcard_portlist[] __used __initdata = | 187 | static unsigned int netcard_portlist[] __used __initdata = |
| 194 | { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; | 188 | { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; |
| 195 | static unsigned int cs8900_irq_map[] = {10,11,12,5}; | 189 | static unsigned int cs8900_irq_map[] = {10,11,12,5}; |
| 196 | #endif | 190 | #endif |
| 191 | #endif | ||
| 197 | 192 | ||
| 198 | #if DEBUGGING | 193 | #if DEBUGGING |
| 199 | static unsigned int net_debug = DEBUGGING; | 194 | static unsigned int net_debug = DEBUGGING; |
| @@ -236,11 +231,16 @@ struct net_local { | |||
| 236 | unsigned char *end_dma_buff; /* points to the end of the buffer */ | 231 | unsigned char *end_dma_buff; /* points to the end of the buffer */ |
| 237 | unsigned char *rx_dma_ptr; /* points to the next packet */ | 232 | unsigned char *rx_dma_ptr; /* points to the next packet */ |
| 238 | #endif | 233 | #endif |
| 234 | #ifdef CONFIG_CS89x0_PLATFORM | ||
| 235 | void __iomem *virt_addr;/* Virtual address for accessing the CS89x0. */ | ||
| 236 | unsigned long phys_addr;/* Physical address for accessing the CS89x0. */ | ||
| 237 | unsigned long size; /* Length of CS89x0 memory region. */ | ||
| 238 | #endif | ||
| 239 | }; | 239 | }; |
| 240 | 240 | ||
| 241 | /* Index to functions, as function prototypes. */ | 241 | /* Index to functions, as function prototypes. */ |
| 242 | 242 | ||
| 243 | static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular); | 243 | static int cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular); |
| 244 | static int net_open(struct net_device *dev); | 244 | static int net_open(struct net_device *dev); |
| 245 | static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev); | 245 | static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev); |
| 246 | static irqreturn_t net_interrupt(int irq, void *dev_id); | 246 | static irqreturn_t net_interrupt(int irq, void *dev_id); |
| @@ -294,6 +294,7 @@ static int __init media_fn(char *str) | |||
| 294 | __setup("cs89x0_media=", media_fn); | 294 | __setup("cs89x0_media=", media_fn); |
| 295 | 295 | ||
| 296 | 296 | ||
| 297 | #ifndef CONFIG_CS89x0_PLATFORM | ||
| 297 | /* Check for a network adaptor of this type, and return '0' iff one exists. | 298 | /* Check for a network adaptor of this type, and return '0' iff one exists. |
| 298 | If dev->base_addr == 0, probe all likely locations. | 299 | If dev->base_addr == 0, probe all likely locations. |
| 299 | If dev->base_addr == 1, always return failure. | 300 | If dev->base_addr == 1, always return failure. |
| @@ -343,6 +344,7 @@ out: | |||
| 343 | return ERR_PTR(err); | 344 | return ERR_PTR(err); |
| 344 | } | 345 | } |
| 345 | #endif | 346 | #endif |
| 347 | #endif | ||
| 346 | 348 | ||
| 347 | #if defined(CONFIG_MACH_IXDP2351) | 349 | #if defined(CONFIG_MACH_IXDP2351) |
| 348 | static u16 | 350 | static u16 |
| @@ -504,7 +506,7 @@ static const struct net_device_ops net_ops = { | |||
| 504 | */ | 506 | */ |
| 505 | 507 | ||
| 506 | static int __init | 508 | static int __init |
| 507 | cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | 509 | cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular) |
| 508 | { | 510 | { |
| 509 | struct net_local *lp = netdev_priv(dev); | 511 | struct net_local *lp = netdev_priv(dev); |
| 510 | static unsigned version_printed; | 512 | static unsigned version_printed; |
| @@ -529,15 +531,12 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 529 | lp->force = g_cs89x0_media__force; | 531 | lp->force = g_cs89x0_media__force; |
| 530 | #endif | 532 | #endif |
| 531 | 533 | ||
| 532 | #if defined(CONFIG_MACH_QQ2440) | ||
| 533 | lp->force |= FORCE_RJ45 | FORCE_FULL; | ||
| 534 | #endif | ||
| 535 | } | 534 | } |
| 536 | 535 | ||
| 537 | /* Grab the region so we can find another board if autoIRQ fails. */ | 536 | /* Grab the region so we can find another board if autoIRQ fails. */ |
| 538 | /* WTF is going on here? */ | 537 | /* WTF is going on here? */ |
| 539 | if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { | 538 | if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { |
| 540 | printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n", | 539 | printk(KERN_ERR "%s: request_region(0x%lx, 0x%x) failed\n", |
| 541 | DRV_NAME, ioaddr, NETCARD_IO_EXTENT); | 540 | DRV_NAME, ioaddr, NETCARD_IO_EXTENT); |
| 542 | retval = -EBUSY; | 541 | retval = -EBUSY; |
| 543 | goto out1; | 542 | goto out1; |
| @@ -549,7 +548,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 549 | will skip the test for the ADD_PORT. */ | 548 | will skip the test for the ADD_PORT. */ |
| 550 | if (ioaddr & 1) { | 549 | if (ioaddr & 1) { |
| 551 | if (net_debug > 1) | 550 | if (net_debug > 1) |
| 552 | printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr); | 551 | printk(KERN_INFO "%s: odd ioaddr 0x%lx\n", dev->name, ioaddr); |
| 553 | if ((ioaddr & 2) != 2) | 552 | if ((ioaddr & 2) != 2) |
| 554 | if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) { | 553 | if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) { |
| 555 | printk(KERN_ERR "%s: bad signature 0x%x\n", | 554 | printk(KERN_ERR "%s: bad signature 0x%x\n", |
| @@ -560,13 +559,13 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 560 | } | 559 | } |
| 561 | 560 | ||
| 562 | ioaddr &= ~3; | 561 | ioaddr &= ~3; |
| 563 | printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", | 562 | printk(KERN_DEBUG "PP_addr at %lx[%x]: 0x%x\n", |
| 564 | ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); | 563 | ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); |
| 565 | writeword(ioaddr, ADD_PORT, PP_ChipID); | 564 | writeword(ioaddr, ADD_PORT, PP_ChipID); |
| 566 | 565 | ||
| 567 | tmp = readword(ioaddr, DATA_PORT); | 566 | tmp = readword(ioaddr, DATA_PORT); |
| 568 | if (tmp != CHIP_EISA_ID_SIG) { | 567 | if (tmp != CHIP_EISA_ID_SIG) { |
| 569 | printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!=" | 568 | printk(KERN_DEBUG "%s: incorrect signature at %lx[%x]: 0x%x!=" |
| 570 | CHIP_EISA_ID_SIG_STR "\n", | 569 | CHIP_EISA_ID_SIG_STR "\n", |
| 571 | dev->name, ioaddr, DATA_PORT, tmp); | 570 | dev->name, ioaddr, DATA_PORT, tmp); |
| 572 | retval = -ENODEV; | 571 | retval = -ENODEV; |
| @@ -736,8 +735,9 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 736 | dev->irq = i; | 735 | dev->irq = i; |
| 737 | } else { | 736 | } else { |
| 738 | i = lp->isa_config & INT_NO_MASK; | 737 | i = lp->isa_config & INT_NO_MASK; |
| 738 | #ifndef CONFIG_CS89x0_PLATFORM | ||
| 739 | if (lp->chip_type == CS8900) { | 739 | if (lp->chip_type == CS8900) { |
| 740 | #ifdef CONFIG_CS89x0_NONISA_IRQ | 740 | #ifdef CS89x0_NONISA_IRQ |
| 741 | i = cs8900_irq_map[0]; | 741 | i = cs8900_irq_map[0]; |
| 742 | #else | 742 | #else |
| 743 | /* Translate the IRQ using the IRQ mapping table. */ | 743 | /* Translate the IRQ using the IRQ mapping table. */ |
| @@ -758,6 +758,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
| 758 | } | 758 | } |
| 759 | #endif | 759 | #endif |
| 760 | } | 760 | } |
| 761 | #endif | ||
| 761 | if (!dev->irq) | 762 | if (!dev->irq) |
| 762 | dev->irq = i; | 763 | dev->irq = i; |
| 763 | } | 764 | } |
| @@ -1168,6 +1169,7 @@ write_irq(struct net_device *dev, int chip_type, int irq) | |||
| 1168 | int i; | 1169 | int i; |
| 1169 | 1170 | ||
| 1170 | if (chip_type == CS8900) { | 1171 | if (chip_type == CS8900) { |
| 1172 | #ifndef CONFIG_CS89x0_PLATFORM | ||
| 1171 | /* Search the mapping table for the corresponding IRQ pin. */ | 1173 | /* Search the mapping table for the corresponding IRQ pin. */ |
| 1172 | for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++) | 1174 | for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++) |
| 1173 | if (cs8900_irq_map[i] == irq) | 1175 | if (cs8900_irq_map[i] == irq) |
| @@ -1175,6 +1177,10 @@ write_irq(struct net_device *dev, int chip_type, int irq) | |||
| 1175 | /* Not found */ | 1177 | /* Not found */ |
| 1176 | if (i == ARRAY_SIZE(cs8900_irq_map)) | 1178 | if (i == ARRAY_SIZE(cs8900_irq_map)) |
| 1177 | i = 3; | 1179 | i = 3; |
| 1180 | #else | ||
| 1181 | /* INTRQ0 pin is used for interrupt generation. */ | ||
| 1182 | i = 0; | ||
| 1183 | #endif | ||
| 1178 | writereg(dev, PP_CS8900_ISAINT, i); | 1184 | writereg(dev, PP_CS8900_ISAINT, i); |
| 1179 | } else { | 1185 | } else { |
| 1180 | writereg(dev, PP_CS8920_ISAINT, irq); | 1186 | writereg(dev, PP_CS8920_ISAINT, irq); |
| @@ -1228,7 +1234,7 @@ net_open(struct net_device *dev) | |||
| 1228 | } | 1234 | } |
| 1229 | else | 1235 | else |
| 1230 | { | 1236 | { |
| 1231 | #ifndef CONFIG_CS89x0_NONISA_IRQ | 1237 | #if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM) |
| 1232 | if (((1 << dev->irq) & lp->irq_map) == 0) { | 1238 | 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", | 1239 | 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); | 1240 | dev->name, dev->irq, lp->irq_map); |
| @@ -1746,7 +1752,7 @@ static int set_mac_address(struct net_device *dev, void *p) | |||
| 1746 | return 0; | 1752 | return 0; |
| 1747 | } | 1753 | } |
| 1748 | 1754 | ||
| 1749 | #ifdef MODULE | 1755 | #if defined(MODULE) && !defined(CONFIG_CS89x0_PLATFORM) |
| 1750 | 1756 | ||
| 1751 | static struct net_device *dev_cs89x0; | 1757 | static struct net_device *dev_cs89x0; |
| 1752 | 1758 | ||
| @@ -1900,7 +1906,97 @@ cleanup_module(void) | |||
| 1900 | release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT); | 1906 | release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT); |
| 1901 | free_netdev(dev_cs89x0); | 1907 | free_netdev(dev_cs89x0); |
| 1902 | } | 1908 | } |
| 1903 | #endif /* MODULE */ | 1909 | #endif /* MODULE && !CONFIG_CS89x0_PLATFORM */ |
| 1910 | |||
| 1911 | #ifdef CONFIG_CS89x0_PLATFORM | ||
| 1912 | static int __init cs89x0_platform_probe(struct platform_device *pdev) | ||
| 1913 | { | ||
| 1914 | struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); | ||
| 1915 | struct net_local *lp; | ||
| 1916 | struct resource *mem_res; | ||
| 1917 | int err; | ||
| 1918 | |||
| 1919 | if (!dev) | ||
| 1920 | return -ENOMEM; | ||
| 1921 | |||
| 1922 | lp = netdev_priv(dev); | ||
| 1923 | |||
| 1924 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1925 | dev->irq = platform_get_irq(pdev, 0); | ||
| 1926 | if (mem_res == NULL || dev->irq <= 0) { | ||
| 1927 | dev_warn(&dev->dev, "memory/interrupt resource missing.\n"); | ||
| 1928 | err = -ENXIO; | ||
| 1929 | goto free; | ||
| 1930 | } | ||
| 1931 | |||
| 1932 | lp->phys_addr = mem_res->start; | ||
| 1933 | lp->size = resource_size(mem_res); | ||
| 1934 | if (!request_mem_region(lp->phys_addr, lp->size, DRV_NAME)) { | ||
| 1935 | dev_warn(&dev->dev, "request_mem_region() failed.\n"); | ||
| 1936 | err = -EBUSY; | ||
| 1937 | goto free; | ||
| 1938 | } | ||
| 1939 | |||
| 1940 | lp->virt_addr = ioremap(lp->phys_addr, lp->size); | ||
| 1941 | if (!lp->virt_addr) { | ||
| 1942 | dev_warn(&dev->dev, "ioremap() failed.\n"); | ||
| 1943 | err = -ENOMEM; | ||
| 1944 | goto release; | ||
| 1945 | } | ||
| 1946 | |||
| 1947 | err = cs89x0_probe1(dev, (unsigned long)lp->virt_addr, 0); | ||
| 1948 | if (err) { | ||
| 1949 | dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n"); | ||
| 1950 | goto unmap; | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | platform_set_drvdata(pdev, dev); | ||
| 1954 | return 0; | ||
| 1955 | |||
| 1956 | unmap: | ||
| 1957 | iounmap(lp->virt_addr); | ||
| 1958 | release: | ||
| 1959 | release_mem_region(lp->phys_addr, lp->size); | ||
| 1960 | free: | ||
| 1961 | free_netdev(dev); | ||
| 1962 | return err; | ||
| 1963 | } | ||
| 1964 | |||
| 1965 | static int cs89x0_platform_remove(struct platform_device *pdev) | ||
| 1966 | { | ||
| 1967 | struct net_device *dev = platform_get_drvdata(pdev); | ||
| 1968 | struct net_local *lp = netdev_priv(dev); | ||
| 1969 | |||
| 1970 | unregister_netdev(dev); | ||
| 1971 | iounmap(lp->virt_addr); | ||
| 1972 | release_mem_region(lp->phys_addr, lp->size); | ||
| 1973 | free_netdev(dev); | ||
| 1974 | return 0; | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | static struct platform_driver cs89x0_driver = { | ||
| 1978 | .driver = { | ||
| 1979 | .name = DRV_NAME, | ||
| 1980 | .owner = THIS_MODULE, | ||
| 1981 | }, | ||
| 1982 | .remove = cs89x0_platform_remove, | ||
| 1983 | }; | ||
| 1984 | |||
| 1985 | static int __init cs89x0_init(void) | ||
| 1986 | { | ||
| 1987 | return platform_driver_probe(&cs89x0_driver, cs89x0_platform_probe); | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | module_init(cs89x0_init); | ||
| 1991 | |||
| 1992 | static void __exit cs89x0_cleanup(void) | ||
| 1993 | { | ||
| 1994 | platform_driver_unregister(&cs89x0_driver); | ||
| 1995 | } | ||
| 1996 | |||
| 1997 | module_exit(cs89x0_cleanup); | ||
| 1998 | |||
| 1999 | #endif /* CONFIG_CS89x0_PLATFORM */ | ||
| 1904 | 2000 | ||
| 1905 | /* | 2001 | /* |
| 1906 | * Local variables: | 2002 | * Local variables: |
