Merge branch 'features/cs89x0' of git://git.pengutronix.de/git/imx/linux-2.6 into next/drivers

* 'features/cs89x0' of git://git.pengutronix.de/git/imx/linux-2.6:
  CS89x0 : add CS89x0 platform device to the iMX31ADS board
  CS89x0 : remove QQ2440 board support from the CS89x0 driver
  CS89x0 : add CS89x0 platform device to the iMX21ADS board
  CS89x0 : add platform driver support
This commit is contained in:
Arnd Bergmann 2012-02-27 12:52:05 +00:00
commit afde962608
8 changed files with 186 additions and 73 deletions

View File

@ -78,6 +78,8 @@ CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_AT25=y
CONFIG_NETDEVICES=y
CONFIG_CS89x0=y
CONFIG_CS89x0_PLATFORM=y
CONFIG_DM9000=y
CONFIG_SMC91X=y
CONFIG_SMC911X=y

View File

@ -26,7 +26,6 @@ CONFIG_MACH_ARMADILLO5X0=y
CONFIG_MACH_KZM_ARM11_01=y
CONFIG_MACH_PCM043=y
CONFIG_MACH_MX35_3DS=y
CONFIG_MACH_EUKREA_CPUIMX35=y
CONFIG_MACH_VPR200=y
CONFIG_MACH_IMX51_DT=y
CONFIG_MACH_MX51_3DS=y
@ -82,8 +81,9 @@ CONFIG_PATA_IMX=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
CONFIG_CS89x0=y
CONFIG_CS89x0_PLATFORM=y
# CONFIG_NET_VENDOR_FARADAY is not set
CONFIG_FEC=y
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set

View File

@ -37,8 +37,8 @@
#define MX21ADS_REG_ADDR(offset) (void __force __iomem *) \
(MX21ADS_MMIO_BASE_ADDR + (offset))
#define MX21ADS_CS8900A_MMIO_SIZE 0x200000
#define MX21ADS_CS8900A_IRQ IRQ_GPIOE(11)
#define MX21ADS_CS8900A_IOBASE_REG MX21ADS_REG_ADDR(0x000000)
#define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000)
#define MX21ADS_VERSION_REG MX21ADS_REG_ADDR(0x400000)
#define MX21ADS_IO_REG MX21ADS_REG_ADDR(0x800000)
@ -159,6 +159,18 @@ static struct platform_device mx21ads_nor_mtd_device = {
.resource = &mx21ads_flash_resource,
};
static const struct resource mx21ads_cs8900_resources[] __initconst = {
DEFINE_RES_MEM(MX21_CS1_BASE_ADDR, MX21ADS_CS8900A_MMIO_SIZE),
DEFINE_RES_IRQ(MX21ADS_CS8900A_IRQ),
};
static const struct platform_device_info mx21ads_cs8900_devinfo __initconst = {
.name = "cs89x0",
.id = 0,
.res = mx21ads_cs8900_resources,
.num_res = ARRAY_SIZE(mx21ads_cs8900_resources),
};
static const struct imxuart_platform_data uart_pdata_rts __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@ -292,6 +304,8 @@ static void __init mx21ads_board_init(void)
imx21_add_mxc_nand(&mx21ads_nand_board_info);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
platform_device_register_full(
(struct platform_device_info *)&mx21ads_cs8900_devinfo);
}
static void __init mx21ads_timer_init(void)

View File

@ -28,7 +28,6 @@
#include <asm/memory.h>
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/board-mx31ads.h>
#include <mach/iomux-mx3.h>
#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
@ -39,6 +38,9 @@
#include "devices-imx31.h"
/* Base address of PBC controller */
#define PBC_BASE_ADDRESS MX31_CS4_BASE_ADDR_VIRT
/* PBC Board interrupt status register */
#define PBC_INTSTATUS 0x000016
@ -62,6 +64,7 @@
#define PBC_INTMASK_CLEAR_REG (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS)
#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_4)
#define MXC_EXP_IO_BASE MXC_BOARD_IRQ_START
#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE)
#define EXPIO_INT_XUART_INTA (MXC_EXP_IO_BASE + 10)
@ -69,6 +72,10 @@
#define MXC_MAX_EXP_IO_LINES 16
/* CS8900 */
#define EXPIO_INT_ENET_INT (MXC_EXP_IO_BASE + 8)
#define CS4_CS8900_MMIO_START 0x20000
/*
* The serial port definition structure.
*/
@ -101,11 +108,29 @@ static struct platform_device serial_device = {
},
};
static const struct resource mx31ads_cs8900_resources[] __initconst = {
DEFINE_RES_MEM(MX31_CS4_BASE_ADDR + CS4_CS8900_MMIO_START, SZ_64K),
DEFINE_RES_IRQ(EXPIO_INT_ENET_INT),
};
static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = {
.name = "cs89x0",
.id = 0,
.res = mx31ads_cs8900_resources,
.num_res = ARRAY_SIZE(mx31ads_cs8900_resources),
};
static int __init mxc_init_extuart(void)
{
return platform_device_register(&serial_device);
}
static void __init mxc_init_ext_ethernet(void)
{
platform_device_register_full(
(struct platform_device_info *)&mx31ads_cs8900_devinfo);
}
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@ -492,12 +517,15 @@ static void __init mxc_init_audio(void)
mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
}
/* static mappings */
/*
* Static mappings, starting from the CS4 start address up to the start address
* of the CS8900.
*/
static struct map_desc mx31ads_io_desc[] __initdata = {
{
.virtual = MX31_CS4_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(MX31_CS4_BASE_ADDR),
.length = MX31_CS4_SIZE / 2,
.length = CS4_CS8900_MMIO_START,
.type = MT_DEVICE
},
};
@ -522,6 +550,7 @@ static void __init mx31ads_init(void)
mxc_init_imx_uart();
mxc_init_i2c();
mxc_init_audio();
mxc_init_ext_ethernet();
}
static void __init mx31ads_timer_init(void)

View File

@ -1,33 +0,0 @@
/*
* Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
#define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
#include <mach/hardware.h>
/*
* These symbols are used by drivers/net/cs89x0.c.
* This is ugly as hell, but we have to provide them until
* someone fixed the driver.
*/
/* Base address of PBC controller */
#define PBC_BASE_ADDRESS MX31_CS4_BASE_ADDR_VIRT
/* Offsets for the PBC Controller register */
/* Ethernet Controller IO base address */
#define PBC_CS8900A_IOBASE 0x020000
#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START)
#define EXPIO_INT_ENET_INT (MXC_EXP_IO_BASE + 8)
#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */

View File

@ -190,8 +190,10 @@ static struct devprobe2 isa_probes[] __initdata = {
{seeq8005_probe, 0},
#endif
#ifdef CONFIG_CS89x0
#ifndef CONFIG_CS89x0_PLATFORM
{cs89x0_probe, 0},
#endif
#endif
#ifdef CONFIG_AT1700
{at1700_probe, 0},
#endif

View File

@ -5,8 +5,7 @@
config NET_VENDOR_CIRRUS
bool "Cirrus devices"
default y
depends on ISA || EISA || MACH_IXDP2351 || ARCH_IXDP2X01 \
|| MACH_MX31ADS || MACH_QQ2440 || (ARM && ARCH_EP93XX) || MAC
depends on ISA || EISA || ARM || MAC
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@ -21,8 +20,7 @@ if NET_VENDOR_CIRRUS
config CS89x0
tristate "CS89x0 support"
depends on (ISA || EISA || MACH_IXDP2351 \
|| ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
depends on ISA || EISA || ARM
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
@ -33,10 +31,15 @@ config CS89x0
To compile this driver as a module, choose M here. The module
will be called cs89x0.
config CS89x0_NONISA_IRQ
def_bool y
depends on CS89x0 != n
depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
config CS89x0_PLATFORM
bool "CS89x0 platform driver support"
depends on CS89x0
help
Say Y to compile the cs89x0 driver as a platform driver. This
makes this driver suitable for use on certain evaluation boards
such as the iMX21ADS.
If you are unsure, say N.
config EP93XX_ETH
tristate "EP93xx Ethernet support"

View File

@ -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: