diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 11:04:01 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-01-07 11:04:01 +1100 |
commit | 790feac51c573fe5fa8a2561f8df8c7611d1cc2c (patch) | |
tree | 45d64d8b6d4a6a7d6cd5a8ac7107c90c0ca9d215 /drivers | |
parent | f0274dfb7324b6b9e3b1b88292a2b580eae7b274 (diff) | |
parent | 7aa60c93e5d831d6ac2ff5b8b36fd02caba485b8 (diff) |
Merge remote branch 'mips/mips-for-linux-next'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ide/au1xxx-ide.c | 21 | ||||
-rw-r--r-- | drivers/mmc/host/au1xmmc.c | 8 | ||||
-rw-r--r-- | drivers/mtd/maps/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mtd/maps/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/maps/alchemy-flash.c | 166 | ||||
-rw-r--r-- | drivers/mtd/nand/au1550nd.c | 4 | ||||
-rw-r--r-- | drivers/net/au1000_eth.c | 449 | ||||
-rw-r--r-- | drivers/net/au1000_eth.h | 9 | ||||
-rw-r--r-- | drivers/net/irda/au1k_ir.c | 14 | ||||
-rw-r--r-- | drivers/pcmcia/Kconfig | 21 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 12 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_db1x00.c | 305 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_generic.h | 12 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_pb1x00.c | 119 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_xxs1500.c | 188 | ||||
-rw-r--r-- | drivers/pcmcia/db1xxx_ss.c | 630 | ||||
-rw-r--r-- | drivers/pcmcia/xxs1500_ss.c | 357 | ||||
-rw-r--r-- | drivers/serial/8250.c | 15 | ||||
-rw-r--r-- | drivers/spi/au1550_spi.c | 6 | ||||
-rw-r--r-- | drivers/video/tdfxfb.c | 4 |
20 files changed, 1284 insertions, 1063 deletions
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c index 87cef0c440ad..349a67bf1a36 100644 --- a/drivers/ide/au1xxx-ide.c +++ b/drivers/ide/au1xxx-ide.c @@ -56,8 +56,8 @@ static inline void auide_insw(unsigned long port, void *addr, u32 count) chan_tab_t *ctp; au1x_ddma_desc_t *dp; - if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, - DDMA_FLAGS_NOIE)) { + if (!au1xxx_dbdma_put_dest(ahwif->rx_chan, virt_to_phys(addr), + count << 1, DDMA_FLAGS_NOIE)) { printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); return; } @@ -74,8 +74,8 @@ static inline void auide_outsw(unsigned long port, void *addr, u32 count) chan_tab_t *ctp; au1x_ddma_desc_t *dp; - if(!put_source_flags(ahwif->tx_chan, (void*)addr, - count << 1, DDMA_FLAGS_NOIE)) { + if (!au1xxx_dbdma_put_source(ahwif->tx_chan, virt_to_phys(addr), + count << 1, DDMA_FLAGS_NOIE)) { printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); return; } @@ -246,17 +246,14 @@ static int auide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) flags = DDMA_FLAGS_NOIE; if (iswrite) { - if(!put_source_flags(ahwif->tx_chan, - (void*) sg_virt(sg), - tc, flags)) { + if (!au1xxx_dbdma_put_source(ahwif->tx_chan, + sg_phys(sg), tc, flags)) { printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); } - } else - { - if(!put_dest_flags(ahwif->rx_chan, - (void*) sg_virt(sg), - tc, flags)) { + } else { + if (!au1xxx_dbdma_put_dest(ahwif->rx_chan, + sg_phys(sg), tc, flags)) { printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); } diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index d3f55615c099..c8649dfb2d0c 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -650,11 +650,11 @@ static int au1xmmc_prepare_data(struct au1xmmc_host *host, flags = DDMA_FLAGS_IE; if (host->flags & HOST_F_XMIT) { - ret = au1xxx_dbdma_put_source_flags(channel, - (void *)sg_virt(sg), len, flags); + ret = au1xxx_dbdma_put_source(channel, + sg_phys(sg), len, flags); } else { - ret = au1xxx_dbdma_put_dest_flags(channel, - (void *)sg_virt(sg), len, flags); + ret = au1xxx_dbdma_put_dest(channel, + sg_phys(sg), len, flags); } if (!ret) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 4c364d44ad59..179618b212e2 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -251,12 +251,6 @@ config MTD_NETtel help Support for flash chips on NETtel/SecureEdge/SnapGear boards. -config MTD_ALCHEMY - tristate "AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support" - depends on SOC_AU1X00 && MTD_PARTITIONS && MTD_CFI - help - Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards - config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index ce315214ff2b..a44919f3f3d2 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o obj-$(CONFIG_MTD_PCI) += pci.o -obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o obj-$(CONFIG_MTD_EDB7312) += edb7312.o obj-$(CONFIG_MTD_IMPA7) += impa7.o diff --git a/drivers/mtd/maps/alchemy-flash.c b/drivers/mtd/maps/alchemy-flash.c deleted file mode 100644 index 845ad4f2a542..000000000000 --- a/drivers/mtd/maps/alchemy-flash.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Flash memory access on AMD Alchemy evaluation boards - * - * (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com> - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -#include <asm/io.h> - -#ifdef CONFIG_MIPS_PB1000 -#define BOARD_MAP_NAME "Pb1000 Flash" -#define BOARD_FLASH_SIZE 0x00800000 /* 8MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_PB1500 -#define BOARD_MAP_NAME "Pb1500 Flash" -#define BOARD_FLASH_SIZE 0x04000000 /* 64MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_PB1100 -#define BOARD_MAP_NAME "Pb1100 Flash" -#define BOARD_FLASH_SIZE 0x04000000 /* 64MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_PB1550 -#define BOARD_MAP_NAME "Pb1550 Flash" -#define BOARD_FLASH_SIZE 0x08000000 /* 128MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_PB1200 -#define BOARD_MAP_NAME "Pb1200 Flash" -#define BOARD_FLASH_SIZE 0x08000000 /* 128MB */ -#define BOARD_FLASH_WIDTH 2 /* 16-bits */ -#endif - -#ifdef CONFIG_MIPS_DB1000 -#define BOARD_MAP_NAME "Db1000 Flash" -#define BOARD_FLASH_SIZE 0x02000000 /* 32MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_DB1500 -#define BOARD_MAP_NAME "Db1500 Flash" -#define BOARD_FLASH_SIZE 0x02000000 /* 32MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_DB1100 -#define BOARD_MAP_NAME "Db1100 Flash" -#define BOARD_FLASH_SIZE 0x02000000 /* 32MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_DB1550 -#define BOARD_MAP_NAME "Db1550 Flash" -#define BOARD_FLASH_SIZE 0x08000000 /* 128MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#endif - -#ifdef CONFIG_MIPS_DB1200 -#define BOARD_MAP_NAME "Db1200 Flash" -#define BOARD_FLASH_SIZE 0x04000000 /* 64MB */ -#define BOARD_FLASH_WIDTH 2 /* 16-bits */ -#endif - -#ifdef CONFIG_MIPS_BOSPORUS -#define BOARD_MAP_NAME "Bosporus Flash" -#define BOARD_FLASH_SIZE 0x01000000 /* 16MB */ -#define BOARD_FLASH_WIDTH 2 /* 16-bits */ -#endif - -#ifdef CONFIG_MIPS_MIRAGE -#define BOARD_MAP_NAME "Mirage Flash" -#define BOARD_FLASH_SIZE 0x04000000 /* 64MB */ -#define BOARD_FLASH_WIDTH 4 /* 32-bits */ -#define USE_LOCAL_ACCESSORS /* why? */ -#endif - -static struct map_info alchemy_map = { - .name = BOARD_MAP_NAME, -}; - -static struct mtd_partition alchemy_partitions[] = { - { - .name = "User FS", - .size = BOARD_FLASH_SIZE - 0x00400000, - .offset = 0x0000000 - },{ - .name = "YAMON", - .size = 0x0100000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE - },{ - .name = "raw kernel", - .size = (0x300000 - 0x40000), /* last 256KB is yamon env */ - .offset = MTDPART_OFS_APPEND, - } -}; - -static struct mtd_info *mymtd; - -static int __init alchemy_mtd_init(void) -{ - struct mtd_partition *parts; - int nb_parts = 0; - unsigned long window_addr; - unsigned long window_size; - - /* Default flash buswidth */ - alchemy_map.bankwidth = BOARD_FLASH_WIDTH; - - window_addr = 0x20000000 - BOARD_FLASH_SIZE; - window_size = BOARD_FLASH_SIZE; - - /* - * Static partition definition selection - */ - parts = alchemy_partitions; - nb_parts = ARRAY_SIZE(alchemy_partitions); - alchemy_map.size = window_size; - - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ - printk(KERN_NOTICE BOARD_MAP_NAME ": probing %d-bit flash bus\n", - alchemy_map.bankwidth*8); - alchemy_map.virt = ioremap(window_addr, window_size); - mymtd = do_map_probe("cfi_probe", &alchemy_map); - if (!mymtd) { - iounmap(alchemy_map.virt); - return -ENXIO; - } - mymtd->owner = THIS_MODULE; - - add_mtd_partitions(mymtd, parts, nb_parts); - return 0; -} - -static void __exit alchemy_mtd_cleanup(void) -{ - if (mymtd) { - del_mtd_partitions(mymtd); - map_destroy(mymtd); - iounmap(alchemy_map.virt); - } -} - -module_init(alchemy_mtd_init); -module_exit(alchemy_mtd_cleanup); - -MODULE_AUTHOR("Embedded Alley Solutions, Inc"); -MODULE_DESCRIPTION(BOARD_MAP_NAME " MTD driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 92c334ff4508..43d46e424040 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -19,6 +19,7 @@ #include <asm/io.h> #include <asm/mach-au1x00/au1xxx.h> +#include <asm/mach-db1x00/bcsr.h> /* * MTD structure for NAND controller @@ -475,7 +476,8 @@ static int __init au1xxx_nand_init(void) /* set gpio206 high */ au_writel(au_readl(GPIO2_DIR) & ~(1 << 6), GPIO2_DIR); - boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr->status >> 6) & 0x1); + boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr_read(BCSR_STATUS) >> 6) & 0x1); + switch (boot_swapboot) { case 0: case 2: diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 6bac04603a88..1acf2c1d1389 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -55,6 +55,7 @@ #include <linux/delay.h> #include <linux/crc32.h> #include <linux/phy.h> +#include <linux/platform_device.h> #include <asm/cpu.h> #include <asm/mipsregs.h> @@ -63,6 +64,7 @@ #include <asm/processor.h> #include <au1000.h> +#include <au1xxx_eth.h> #include <prom.h> #include "au1000_eth.h" @@ -112,15 +114,15 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; * * PHY detection algorithm * - * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is + * If phy_static_config is undefined, the PHY setup is * autodetected: * * mii_probe() first searches the current MAC's MII bus for a PHY, - * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is + * selecting the first (or last, if phy_search_highest_addr is * defined) PHY address not already claimed by another netdev. * * If nothing was found that way when searching for the 2nd ethernet - * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then + * controller's PHY and phy1_search_mac0 is defined, then * the first MII bus is searched as well for an unclaimed PHY; this is * needed in case of a dual-PHY accessible only through the MAC0's MII * bus. @@ -129,9 +131,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; * controller is not registered to the network subsystem. */ -/* autodetection defaults */ -#undef AU1XXX_PHY_SEARCH_HIGHEST_ADDR -#define AU1XXX_PHY1_SEARCH_ON_MAC0 +/* autodetection defaults: phy1_search_mac0 */ /* static PHY setup * @@ -148,29 +148,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; * specific irq-map */ -#if defined(CONFIG_MIPS_BOSPORUS) -/* - * Micrel/Kendin 5 port switch attached to MAC0, - * MAC0 is associated with PHY address 5 (== WAN port) - * MAC1 is not associated with any PHY, since it's connected directly - * to the switch. - * no interrupts are used - */ -# define AU1XXX_PHY_STATIC_CONFIG - -# define AU1XXX_PHY0_ADDR 5 -# define AU1XXX_PHY0_BUSID 0 -# undef AU1XXX_PHY0_IRQ - -# undef AU1XXX_PHY1_ADDR -# undef AU1XXX_PHY1_BUSID -# undef AU1XXX_PHY1_IRQ -#endif - -#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0) -# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet -#endif - static void enable_mac(struct net_device *dev, int force_reset) { unsigned long flags; @@ -390,67 +367,54 @@ static int mii_probe (struct net_device *dev) struct au1000_private *const aup = netdev_priv(dev); struct phy_device *phydev = NULL; -#if defined(AU1XXX_PHY_STATIC_CONFIG) - BUG_ON(aup->mac_id < 0 || aup->mac_id > 1); + if (aup->phy_static_config) { + BUG_ON(aup->mac_id < 0 || aup->mac_id > 1); - if(aup->mac_id == 0) { /* get PHY0 */ -# if defined(AU1XXX_PHY0_ADDR) - phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus->phy_map[AU1XXX_PHY0_ADDR]; -# else - printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", - dev->name); - return 0; -# endif /* defined(AU1XXX_PHY0_ADDR) */ - } else if (aup->mac_id == 1) { /* get PHY1 */ -# if defined(AU1XXX_PHY1_ADDR) - phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus->phy_map[AU1XXX_PHY1_ADDR]; -# else - printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", - dev->name); + if (aup->phy_addr) + phydev = aup->mii_bus->phy_map[aup->phy_addr]; + else + printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", + dev->name); return 0; -# endif /* defined(AU1XXX_PHY1_ADDR) */ - } - -#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */ - int phy_addr; - - /* find the first (lowest address) PHY on the current MAC's MII bus */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) - if (aup->mii_bus->phy_map[phy_addr]) { - phydev = aup->mii_bus->phy_map[phy_addr]; -# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR) - break; /* break out with first one found */ -# endif - } - -# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0) - /* try harder to find a PHY */ - if (!phydev && (aup->mac_id == 1)) { - /* no PHY found, maybe we have a dual PHY? */ - printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, " - "let's see if it's attached to MAC0...\n"); - - BUG_ON(!au_macs[0]); - - /* find the first (lowest address) non-attached PHY on - * the MAC0 MII bus */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - struct phy_device *const tmp_phydev = - au_macs[0]->mii_bus->phy_map[phy_addr]; - - if (!tmp_phydev) - continue; /* no PHY here... */ - - if (tmp_phydev->attached_dev) - continue; /* already claimed by MAC0 */ + } else { + int phy_addr; + + /* find the first (lowest address) PHY on the current MAC's MII bus */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) + if (aup->mii_bus->phy_map[phy_addr]) { + phydev = aup->mii_bus->phy_map[phy_addr]; + if (!aup->phy_search_highest_addr) + break; /* break out with first one found */ + } - phydev = tmp_phydev; - break; /* found it */ + if (aup->phy1_search_mac0) { + /* try harder to find a PHY */ + if (!phydev && (aup->mac_id == 1)) { + /* no PHY found, maybe we have a dual PHY? */ + printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, " + "let's see if it's attached to MAC0...\n"); + + /* find the first (lowest address) non-attached PHY on + * the MAC0 MII bus */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + if (aup->mac_id == 1) + break; + struct phy_device *const tmp_phydev = + aup->mii_bus->phy_map[phy_addr]; + + if (!tmp_phydev) + continue; /* no PHY here... */ + + if (tmp_phydev->attached_dev) + continue; /* already claimed by MAC0 */ + + phydev = tmp_phydev; + break; /* found it */ + } + } } } -# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */ -#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */ if (!phydev) { printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name); return -1; @@ -578,31 +542,6 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base) } } -static struct { - u32 base_addr; - u32 macen_addr; - int irq; - struct net_device *dev; -} iflist[2] = { -#ifdef CONFIG_SOC_AU1000 - {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT}, - {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1100 - {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1500 - {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT}, - {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1550 - {AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT}, - {AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT} -#endif -}; - -static int num_ifs; - /* * ethtool operations */ @@ -1058,53 +997,59 @@ static const struct net_device_ops au1000_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static struct net_device * au1000_probe(int port_num) +static int __devinit au1000_probe(struct platform_device *pdev) { static unsigned version_printed = 0; struct au1000_private *aup = NULL; + struct au1000_eth_platform_data *pd; struct net_device *dev = NULL; db_dest_t *pDB, *pDBfree; - char ethaddr[6]; - int irq, i, err; - u32 base, macen; + int irq, i, err = 0; + struct resource *base, *macen; + DECLARE_MAC_BUF(ethaddr); + + base = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!base) { + printk(KERN_ERR DRV_NAME ": failed to retrieve base register\n"); + err = -ENODEV; + goto out; + } - if (port_num >= NUM_ETH_INTERFACES) - return NULL; + macen = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!macen) { + printk(KERN_ERR DRV_NAME ": failed to retrieve MAC Enable register\n"); + err = -ENODEV; + goto out; + } - base = CPHYSADDR(iflist[port_num].base_addr ); - macen = CPHYSADDR(iflist[port_num].macen_addr); - irq = iflist[port_num].irq; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + printk(KERN_ERR DRV_NAME ": failed to retrieve IRQ\n"); + err = -ENODEV; + goto out; + } - if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") || - !request_mem_region(macen, 4, "Au1x00 ENET")) - return NULL; + if (!request_mem_region(base->start, resource_size(base), pdev->name)) { + printk(KERN_ERR DRV_NAME ": failed to request memory region for base registers\n"); + err = -ENXIO; + goto out; + } - if (version_printed++ == 0) - printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); + if (!request_mem_region(macen->start, resource_size(macen), pdev->name)) { + printk(KERN_ERR DRV_NAME ": failed to request memory region for MAC enable register\n"); + err = -ENXIO; + goto err_request; + } dev = alloc_etherdev(sizeof(struct au1000_private)); if (!dev) { printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); - return NULL; - } - - dev->base_addr = base; - dev->irq = irq; - dev->netdev_ops = &au1000_netdev_ops; - SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops); - dev->watchdog_timeo = ETH_TX_TIMEOUT; - - err = register_netdev(dev); - if (err != 0) { - printk(KERN_ERR "%s: Cannot register net device, error %d\n", - DRV_NAME, err); - free_netdev(dev); - return NULL; + err = -ENOMEM; + goto err_alloc; } - printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n", - dev->name, base, irq); - + SET_NETDEV_DEV(dev, &pdev->dev); + platform_set_drvdata(pdev, dev); aup = netdev_priv(dev); spin_lock_init(&aup->lock); @@ -1115,21 +1060,29 @@ static struct net_device * au1000_probe(int port_num) (NUM_TX_BUFFS + NUM_RX_BUFFS), &aup->dma_addr, 0); if (!aup->vaddr) { - free_netdev(dev); - release_mem_region( base, MAC_IOSIZE); - release_mem_region(macen, 4); - return NULL; + printk(KERN_ERR DRV_NAME ": failed to allocate data buffers\n"); + err = -ENOMEM; + goto err_vaddr; } /* aup->mac is the base address of the MAC's registers */ - aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr; + aup->mac = (volatile mac_reg_t *)ioremap_nocache(base->start, resource_size(base)); + if (!aup->mac) { + printk(KERN_ERR DRV_NAME ": failed to ioremap MAC registers\n"); + err = -ENXIO; + goto err_remap1; + } - /* Setup some variables for quick register address access */ - aup->enable = (volatile u32 *)iflist[port_num].macen_addr; - aup->mac_id = port_num; - au_macs[port_num] = aup; + /* Setup some variables for quick register address access */ + aup->enable = (volatile u32 *)ioremap_nocache(macen->start, resource_size(macen)); + if (!aup->enable) { + printk(KERN_ERR DRV_NAME ": failed to ioremap MAC enable register\n"); + err = -ENXIO; + goto err_remap2; + } + aup->mac_id = pdev->id; - if (port_num == 0) { + if (pdev->id == 0) { if (prom_get_ethernet_addr(ethaddr) == 0) memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); else { @@ -1139,7 +1092,7 @@ static struct net_device * au1000_probe(int port_num) } setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); - } else if (port_num == 1) + } else if (pdev->id == 1) setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); /* @@ -1147,14 +1100,37 @@ static struct net_device * au1000_probe(int port_num) * to match those that are printed on their stickers */ memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); - dev->dev_addr[5] += port_num; + dev->dev_addr[5] += pdev->id; *aup->enable = 0; aup->mac_enabled = 0; + pd = pdev->dev.platform_data; + if (!pd) { + printk(KERN_INFO DRV_NAME ": no platform_data passed, PHY search on MAC0\n"); + aup->phy1_search_mac0 = 1; + } else { + aup->phy_static_config = pd->phy_static_config; + aup->phy_search_highest_addr = pd->phy_search_highest_addr; + aup->phy1_search_mac0 = pd->phy1_search_mac0; + aup->phy_addr = pd->phy_addr; + aup->phy_busid = pd->phy_busid; + aup->phy_irq = pd->phy_irq; + } + + if (aup->phy_busid && aup->phy_busid > 0) { + printk(KERN_ERR DRV_NAME ": MAC0-associated PHY attached 2nd MACs MII" + "bus not supported yet\n"); + err = -ENODEV; + goto err_mdiobus_alloc; + } + aup->mii_bus = mdiobus_alloc(); - if (aup->mii_bus == NULL) - goto err_out; + if (aup->mii_bus == NULL) { + printk(KERN_ERR DRV_NAME ": failed to allocate mdiobus structure\n"); + err = -ENOMEM; + goto err_mdiobus_alloc; + } aup->mii_bus->priv = dev; aup->mii_bus->read = au1000_mdiobus_read; @@ -1168,23 +1144,19 @@ static struct net_device * au1000_probe(int port_num) for(i = 0; i < PHY_MAX_ADDR; ++i) aup->mii_bus->irq[i] = PHY_POLL; - /* if known, set corresponding PHY IRQs */ -#if defined(AU1XXX_PHY_STATIC_CONFIG) -# if defined(AU1XXX_PHY0_IRQ) - if (AU1XXX_PHY0_BUSID == aup->mac_id) - aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ; -# endif -# if defined(AU1XXX_PHY1_IRQ) - if (AU1XXX_PHY1_BUSID == aup->mac_id) - aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ; -# endif -#endif - mdiobus_register(aup->mii_bus); + if (aup->phy_static_config) + if (aup->phy_irq && aup->phy_busid == aup->mac_id) + aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq; + + err = mdiobus_register(aup->mii_bus); + if (err) { + printk(KERN_ERR DRV_NAME " failed to register MDIO bus\n"); + goto err_mdiobus_reg; + } - if (mii_probe(dev) != 0) { + if (mii_probe(dev) != 0) goto err_out; - } pDBfree = NULL; /* setup the data buffer descriptors and attach a buffer to each one */ @@ -1216,19 +1188,35 @@ static struct net_device * au1000_probe(int port_num) aup->tx_db_inuse[i] = pDB; } + dev->base_addr = base->start; + dev->irq = irq; + dev->netdev_ops = &au1000_netdev_ops; + SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops); + dev->watchdog_timeo = ETH_TX_TIMEOUT; + /* * The boot code uses the ethernet controller, so reset it to start * fresh. au1000_init() expects that the device is in reset state. */ reset_mac(dev); - return dev; + err = register_netdev(dev); + if (err) { + printk(KERN_ERR DRV_NAME "%s: Cannot register net device, aborting.\n", + dev->name); + goto err_out; + } + + printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n", + dev->name, base->start, irq); + if (version_printed++ == 0) + printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); + + return 0; err_out: - if (aup->mii_bus != NULL) { + if (aup->mii_bus != NULL) mdiobus_unregister(aup->mii_bus); - mdiobus_free(aup->mii_bus); - } /* here we should have a valid dev plus aup-> register addresses * so we can reset the mac properly.*/ @@ -1242,67 +1230,84 @@ err_out: if (aup->tx_db_inuse[i]) ReleaseDB(aup, aup->tx_db_inuse[i]); } +err_mdiobus_reg: + mdiobus_free(aup->mii_bus); +err_mdiobus_alloc: + iounmap(aup->enable); +err_remap2: + iounmap(aup->mac); +err_remap1: dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), (void *)aup->vaddr, aup->dma_addr); - unregister_netdev(dev); +err_vaddr: free_netdev(dev); - release_mem_region( base, MAC_IOSIZE); - release_mem_region(macen, 4); - return NULL; +err_alloc: + release_mem_region(macen->start, resource_size(macen)); +err_request: + release_mem_region(base->start, resource_size(base)); +out: + return err; } -/* - * Setup the base address and interrupt of the Au1xxx ethernet macs - * based on cpu type and whether the interface is enabled in sys_pinfunc - * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0. - */ -static int __init au1000_init_module(void) +static int __devexit au1000_remove(struct platform_device *pdev) { - int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4); - struct net_device *dev; - int i, found_one = 0; + struct net_device *dev = platform_get_drvdata(pdev); + struct au1000_private *aup = netdev_priv(dev); + int i; + struct resource *base, *macen; - num_ifs = NUM_ETH_INTERFACES - ni; + platform_set_drvdata(pdev, NULL); + + unregister_netdev(dev); + mdiobus_unregister(aup->mii_bus); + mdiobus_free(aup->mii_bus); + + for (i = 0; i < NUM_RX_DMA; i++) + if (aup->rx_db_inuse[i]) + ReleaseDB(aup, aup->rx_db_inuse[i]); + + for (i = 0; i < NUM_TX_DMA; i++) + if (aup->tx_db_inuse[i]) + ReleaseDB(aup, aup->tx_db_inuse[i]); + + dma_free_noncoherent(NULL, MAX_BUF_SIZE * + (NUM_TX_BUFFS + NUM_RX_BUFFS), + (void *)aup->vaddr, aup->dma_addr); + + iounmap(aup->mac); + iounmap(aup->enable); + + base = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(base->start, resource_size(base)); + + macen = platform_get_resource(pdev, IORESOURCE_MEM, 1); + release_mem_region(macen->start, resource_size(macen)); + + free_netdev(dev); - for(i = 0; i < num_ifs; i++) { - dev = au1000_probe(i); - iflist[i].dev = dev; - if (dev) - found_one++; - } - if (!found_one) - return -ENODEV; return 0; } -static void __exit au1000_cleanup_module(void) +static struct platform_driver au1000_eth_driver = { + .probe = au1000_probe, + .remove = __devexit_p(au1000_remove), + .driver = { + .name = "au1000-eth", + .owner = THIS_MODULE, + }, +}; +MODULE_ALIAS("platform:au1000-eth"); + + +static int __init au1000_init_module(void) { - int i, j; - struct net_device *dev; - struct au1000_private *aup; - - for (i = 0; i < num_ifs; i++) { - dev = iflist[i].dev; - if (dev) { - aup = netdev_priv(dev); - unregister_netdev(dev); - mdiobus_unregister(aup->mii_bus); - mdiobus_free(aup->mii_bus); - for (j = 0; j < NUM_RX_DMA; j++) - if (aup->rx_db_inuse[j]) - ReleaseDB(aup, aup->rx_db_inuse[j]); - for (j = 0; j < NUM_TX_DMA; j++) - if (aup->tx_db_inuse[j]) - ReleaseDB(aup, aup->tx_db_inuse[j]); - dma_free_noncoherent(NULL, MAX_BUF_SIZE * - (NUM_TX_BUFFS + NUM_RX_BUFFS), - (void *)aup->vaddr, aup->dma_addr); - release_mem_region(dev->base_addr, MAC_IOSIZE); - release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4); - free_netdev(dev); - } - } + return platform_driver_register(&au1000_eth_driver); +} + +static void __exit au1000_exit_module(void) +{ + platform_driver_unregister(&au1000_eth_driver); } module_init(au1000_init_module); -module_exit(au1000_cleanup_module); +module_exit(au1000_exit_module); diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h index 824ecd5ff3a8..f9d29a29b8fd 100644 --- a/drivers/net/au1000_eth.h +++ b/drivers/net/au1000_eth.h @@ -108,6 +108,15 @@ struct au1000_private { struct phy_device *phy_dev; struct mii_bus *mii_bus; + /* PHY configuration */ + int phy_static_config; + int phy_search_highest_addr; + int phy1_search_mac0; + + int phy_addr; + int phy_busid; + int phy_irq; + /* These variables are just for quick access to certain regs addresses. */ volatile mac_reg_t *mac; /* mac registers */ volatile u32 *enable; /* address of MAC Enable Register */ diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 9b2eebdbb25b..b5cbd39d0685 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -36,6 +36,7 @@ #include <asm/pb1000.h> #elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) #include <asm/db1x00.h> +#include <asm/mach-db1x00/bcsr.h> #else #error au1k_ir: unsupported board #endif @@ -66,10 +67,6 @@ static char version[] __devinitdata = #define RUN_AT(x) (jiffies + (x)) -#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) -static BCSR * const bcsr = (BCSR *)0xAE000000; -#endif - static DEFINE_SPINLOCK(ir_lock); /* @@ -282,9 +279,8 @@ static int au1k_irda_net_init(struct net_device *dev) #if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) /* power on */ - bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK; - bcsr->resets |= BCSR_RESETS_IRDA_MODE_FULL; - au_sync(); + bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK, + BCSR_RESETS_IRDA_MODE_FULL); #endif return 0; @@ -720,14 +716,14 @@ au1k_irda_set_speed(struct net_device *dev, int speed) if (speed == 4000000) { #if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) - bcsr->resets |= BCSR_RESETS_FIR_SEL; + bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_FIR_SEL); #else /* Pb1000 and Pb1100 */ writel(1<<13, CPLD_AUX1); #endif } else { #if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) - bcsr->resets &= ~BCSR_RESETS_FIR_SEL; + bcsr_mod(BCSR_RESETS, BCSR_RESETS_FIR_SEL, 0); #else /* Pb1000 and Pb1100 */ writel(readl(CPLD_AUX1) & ~(1<<13), CPLD_AUX1); #endif diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 9f3adbd9f700..1e01578a0a77 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -174,6 +174,27 @@ config PCMCIA_AU1X00 tristate "Au1x00 pcmcia support" depends on SOC_AU1X00 && PCMCIA +config PCMCIA_ALCHEMY_DEVBOARD + tristate "Alchemy Db/Pb1xxx PCMCIA socket services" + depends on SOC_AU1X00 && PCMCIA + select 64BIT_PHYS_ADDR + help + Enable this driver of you want PCMCIA support on your Alchemy + Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200 board. + NOT suitable for the PB1000! + + This driver is also available as a module called db1xxx_ss.ko + +config PCMCIA_XXS1500 + tristate "MyCable XXS1500 PCMCIA socket support" + depends on PCMCIA && MIPS_XXS1500 + select 64BIT_PHYS_ADDR + help + Support for the PCMCIA/CF socket interface on MyCable XXS1500 + systems. + + This driver is also available as a module called xxs1500_ss.ko + config PCMCIA_BCM63XX tristate "bcm63xx pcmcia support" depends on BCM63XX && PCMCIA diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 83ff802de544..21ee96448b1e 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -35,18 +35,10 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o obj-$(CONFIG_BFIN_CFPCMCIA) += bfin_cf_pcmcia.o obj-$(CONFIG_AT91_CF) += at91_cf.o obj-$(CONFIG_ELECTRA_CF) += electra_cf.o +obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o au1x00_ss-y += au1000_generic.o au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o -au1x00_ss-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o -au1x00_ss-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o -au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o -au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o -au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o -au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o -au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o -au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o -au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o sa1111_cs-y += sa1111_generic.o sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o @@ -76,3 +68,5 @@ pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) + +obj-$(CONFIG_PCMCIA_XXS1500) += xxs1500_ss.o diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c deleted file mode 100644 index c78d77fd7e3b..000000000000 --- a/drivers/pcmcia/au1000_db1x00.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * - * Alchemy Semi Db1x00 boards specific pcmcia routines. - * - * Copyright 2002 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * Copyright 2004 Pete Popov, updated the driver to 2.6. - * Followed the sa11xx API and largely copied many of the hardware - * independent functions. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/init.h> - -#include <asm/irq.h> -#include <asm/signal.h> -#include <asm/mach-au1x00/au1000.h> - -#if defined(CONFIG_MIPS_DB1200) - #include <db1200.h> -#elif defined(CONFIG_MIPS_PB1200) - #include <pb1200.h> -#else - #include <asm/mach-db1x00/db1x00.h> - static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; -#endif - -#include "au1000_generic.h" - -#if 0 -#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args) -#else -#define debug(x,args...) -#endif - - -struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS]; -extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int); - -static int db1x00_pcmcia_hw_init(struct au1000_pcmcia_socket *skt) -{ -#ifdef CONFIG_MIPS_DB1550 - skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3; -#elif defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) - skt->irq = skt->nr ? BOARD_PC1_INT : BOARD_PC0_INT; -#else - skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2; -#endif - return 0; -} - -static void db1x00_pcmcia_shutdown(struct au1000_pcmcia_socket *skt) -{ - bcsr->pcmcia = 0; /* turn off power */ - au_sync_delay(2); -} - -static void -db1x00_pcmcia_socket_state(struct au1000_pcmcia_socket *skt, struct pcmcia_state *state) -{ - u32 inserted; - unsigned char vs; - - state->ready = 0; - state->vs_Xv = 0; - state->vs_3v = 0; - state->detect = 0; - - switch (skt->nr) { - case 0: - vs = bcsr->status & 0x3; -#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) - inserted = BOARD_CARD_INSERTED(0); -#else - inserted = !(bcsr->status & (1<<4)); -#endif - break; - case 1: - vs = (bcsr->status & 0xC)>>2; -#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) - inserted = BOARD_CARD_INSERTED(1); -#else - inserted = !(bcsr->status & (1<<5)); -#endif - break; - default:/* should never happen */ - return; - } - - if (inserted) - debug("db1x00 socket %d: inserted %d, vs %d pcmcia %x\n", - skt->nr, inserted, vs, bcsr->pcmcia); - - if (inserted) { - switch (vs) { - case 0: - case 2: - state->vs_3v=1; - break; - case 3: /* 5V */ - break; - default: - /* return without setting 'detect' */ - printk(KERN_ERR "db1x00 bad VS (%d)\n", - vs); - } - state->detect = 1; - state->ready = 1; - } - else { - /* if the card was previously inserted and then ejected, - * we should turn off power to it - */ - if ((skt->nr == 0) && (bcsr->pcmcia & BCSR_PCMCIA_PC0RST)) { - bcsr->pcmcia &= ~(BCSR_PCMCIA_PC0RST | - BCSR_PCMCIA_PC0DRVEN | - BCSR_PCMCIA_PC0VPP | - BCSR_PCMCIA_PC0VCC); - au_sync_delay(10); - } - else if ((skt->nr == 1) && bcsr->pcmcia & BCSR_PCMCIA_PC1RST) { - bcsr->pcmcia &= ~(BCSR_PCMCIA_PC1RST | - BCSR_PCMCIA_PC1DRVEN | - BCSR_PCMCIA_PC1VPP | - BCSR_PCMCIA_PC1VCC); - au_sync_delay(10); - } - } - - state->bvd1=1; - state->bvd2=1; - state->wrprot=0; -} - -static int -db1x00_pcmcia_configure_socket(struct au1000_pcmcia_socket *skt, struct socket_state_t *state) -{ - u16 pwr; - int sock = skt->nr; - - debug("config_skt %d Vcc %dV Vpp %dV, reset %d\n", - sock, state->Vcc, state->Vpp, - state->flags & SS_RESET); - - /* pcmcia reg was set to zero at init time. Be careful when - * initializing a socket not to wipe out the settings of the - * other socket. - */ - pwr = bcsr->pcmcia; - pwr &= ~(0xf << sock*8); /* clear voltage settings */ - - state->Vpp = 0; - switch(state->Vcc){ - case 0: /* Vcc 0 */ - pwr |= SET_VCC_VPP(0,0,sock); - break; - case 50: /* Vcc 5V */ - switch(state->Vpp) { - case 0: - pwr |= SET_VCC_VPP(2,0,sock); - break; - case 50: - pwr |= SET_VCC_VPP(2,1,sock); - break; - case 12: - pwr |= SET_VCC_VPP(2,2,sock); - break; - case 33: - default: - pwr |= SET_VCC_VPP(0,0,sock); - printk("%s: bad Vcc/Vpp (%d:%d)\n", - __func__, - state->Vcc, - state->Vpp); - break; - } - break; - case 33: /* Vcc 3.3V */ - switch(state->Vpp) { - case 0: - pwr |= SET_VCC_VPP(1,0,sock); - break; - case 12: - pwr |= SET_VCC_VPP(1,2,sock); - break; - case 33: - pwr |= SET_VCC_VPP(1,1,sock); - break; - case 50: - default: - pwr |= SET_VCC_VPP(0,0,sock); - printk("%s: bad Vcc/Vpp (%d:%d)\n", - __func__, - state->Vcc, - state->Vpp); - break; - } - break; - default: /* what's this ? */ - pwr |= SET_VCC_VPP(0,0,sock); - printk(KERN_ERR "%s: bad Vcc %d\n", - __func__, state->Vcc); - break; - } - - bcsr->pcmcia = pwr; - au_sync_delay(300); - - if (sock == 0) { - if (!(state->flags & SS_RESET)) { - pwr |= BCSR_PCMCIA_PC0DRVEN; - bcsr->pcmcia = pwr; - au_sync_delay(300); - pwr |= BCSR_PCMCIA_PC0RST; - bcsr->pcmcia = pwr; - au_sync_delay(100); - } - else { - pwr &= ~(BCSR_PCMCIA_PC0RST | BCSR_PCMCIA_PC0DRVEN); - bcsr->pcmcia = pwr; - au_sync_delay(100); - } - } - else { - if (!(state->flags & SS_RESET)) { - pwr |= BCSR_PCMCIA_PC1DRVEN; - bcsr->pcmcia = pwr; - au_sync_delay(300); - pwr |= BCSR_PCMCIA_PC1RST; - bcsr->pcmcia = pwr; - au_sync_delay(100); - } - else { - pwr &= ~(BCSR_PCMCIA_PC1RST | BCSR_PCMCIA_PC1DRVEN); - bcsr->pcmcia = pwr; - au_sync_delay(100); - } - } - return 0; -} - -/* - * Enable card status IRQs on (re-)initialisation. This can - * be called at initialisation, power management event, or - * pcmcia event. - */ -void db1x00_socket_init(struct au1000_pcmcia_socket *skt) -{ - /* nothing to do for now */ -} - -/* - * Disable card status IRQs and PCMCIA bus on suspend. - */ -void db1x00_socket_suspend(struct au1000_pcmcia_socket *skt) -{ - /* nothing to do for now */ -} - -struct pcmcia_low_level db1x00_pcmcia_ops = { - .owner = THIS_MODULE, - - .hw_init = db1x00_pcmcia_hw_init, - .hw_shutdown = db1x00_pcmcia_shutdown, - - .socket_state = db1x00_pcmcia_socket_state, - .configure_socket = db1x00_pcmcia_configure_socket, - - .socket_init = db1x00_socket_init, - .socket_suspend = db1x00_socket_suspend -}; - -int au1x_board_init(struct device *dev) -{ - int ret = -ENODEV; - bcsr->pcmcia = 0; /* turn off power, if it's not already off */ - au_sync_delay(2); - ret = au1x00_pcmcia_socket_probe(dev, &db1x00_pcmcia_ops, 0, 2); - return ret; -} diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h index 13a4fbc58711..aa743f6875bd 100644 --- a/drivers/pcmcia/au1000_generic.h +++ b/drivers/pcmcia/au1000_generic.h @@ -44,22 +44,12 @@ /* pcmcia socket 1 needs external glue logic so the memory map * differs from board to board. */ -#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || \ - defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) || \ - defined(CONFIG_MIPS_PB1200) +#if defined(CONFIG_MIPS_PB1000) #define AU1X_SOCK1_IO 0xF08000000ULL #define AU1X_SOCK1_PHYS_ATTR 0xF48000000ULL #define AU1X_SOCK1_PHYS_MEM 0xF88000000ULL #define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4800000 #define AU1X_SOCK1_PSEUDO_PHYS_MEM 0xF8800000 -#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || \ - defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) || \ - defined(CONFIG_MIPS_DB1200) -#define AU1X_SOCK1_IO 0xF04000000ULL -#define AU1X_SOCK1_PHYS_ATTR 0xF44000000ULL -#define AU1X_SOCK1_PHYS_MEM 0xF84000000ULL -#define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4400000 -#define AU1X_SOCK1_PSEUDO_PHYS_MEM 0xF8400000 #endif struct pcmcia_state { diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index b1984ed72d1d..5a979cb8f3e6 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c @@ -1,6 +1,6 @@ /* * - * Alchemy Semi Pb1x00 boards specific pcmcia routines. + * Alchemy Semi Pb1000 boards specific pcmcia routines. * * Copyright 2002 MontaVista Software Inc. * Author: MontaVista Software, Inc. @@ -46,20 +46,11 @@ #define debug(fmt, arg...) do { } while (0) -#ifdef CONFIG_MIPS_PB1000 #include <asm/pb1000.h> #define PCMCIA_IRQ AU1000_GPIO_15 -#elif defined (CONFIG_MIPS_PB1500) -#include <asm/pb1500.h> -#define PCMCIA_IRQ AU1500_GPIO_203 -#elif defined (CONFIG_MIPS_PB1100) -#include <asm/pb1100.h> -#define PCMCIA_IRQ AU1000_GPIO_11 -#endif static int pb1x00_pcmcia_init(struct pcmcia_init *init) { -#ifdef CONFIG_MIPS_PB1000 u16 pcr; pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST; @@ -74,21 +65,10 @@ static int pb1x00_pcmcia_init(struct pcmcia_init *init) au_sync_delay(20); return PCMCIA_NUM_SOCKS; - -#else /* fixme -- take care of the Pb1500 at some point */ - - u16 pcr; - pcr = au_readw(PCMCIA_BOARD_REG) & ~0xf; /* turn off power */ - pcr &= ~(PC_DEASSERT_RST | PC_DRV_EN); - au_writew(pcr, PCMCIA_BOARD_REG); - au_sync_delay(500); - return PCMCIA_NUM_SOCKS; -#endif } static int pb1x00_pcmcia_shutdown(void) { -#ifdef CONFIG_MIPS_PB1000 u16 pcr; pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST; pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0); @@ -96,14 +76,6 @@ static int pb1x00_pcmcia_shutdown(void) au_writel(pcr, PB1000_PCR); au_sync_delay(20); return 0; -#else - u16 pcr; - pcr = au_readw(PCMCIA_BOARD_REG) & ~0xf; /* turn off power */ - pcr &= ~(PC_DEASSERT_RST | PC_DRV_EN); - au_writew(pcr, PCMCIA_BOARD_REG); - au_sync_delay(2); - return 0; -#endif } static int @@ -112,21 +84,11 @@ pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state) u32 inserted0, inserted1; u16 vs0, vs1; -#ifdef CONFIG_MIPS_PB1000 vs0 = vs1 = (u16)au_readl(PB1000_ACR1); inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2)); inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2)); vs0 = (vs0 >> 4) & 0x3; vs1 = (vs1 >> 12) & 0x3; -#else - vs0 = (au_readw(BOARD_STATUS_REG) >> 4) & 0x3; -#ifdef CONFIG_MIPS_PB1500 - inserted0 = !((au_readl(GPIO2_PINSTATE) >> 1) & 0x1); /* gpio 201 */ -#else /* Pb1100 */ - inserted0 = !((au_readl(SYS_PINSTATERD) >> 9) & 0x1); /* gpio 9 */ -#endif - inserted1 = 0; -#endif state->ready = 0; state->vs_Xv = 0; @@ -203,7 +165,6 @@ pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure) if(configure->sock > PCMCIA_MAX_SOCK) return -1; -#ifdef CONFIG_MIPS_PB1000 pcr = au_readl(PB1000_PCR); if (configure->sock == 0) { @@ -323,84 +284,6 @@ pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure) au_writel(pcr, PB1000_PCR); au_sync_delay(300); -#else - - pcr = au_readw(PCMCIA_BOARD_REG) & ~0xf; - - debug("Vcc %dV Vpp %dV, pcr %x, reset %d\n", - configure->vcc, configure->vpp, pcr, configure->reset); - - - switch(configure->vcc){ - case 0: /* Vcc 0 */ - pcr |= SET_VCC_VPP(0,0); - break; - case 50: /* Vcc 5V */ - switch(configure->vpp) { - case 0: - pcr |= SET_VCC_VPP(2,0); - break; - case 50: - pcr |= SET_VCC_VPP(2,1); - break; - case 12: - pcr |= SET_VCC_VPP(2,2); - break; - case 33: - default: - pcr |= SET_VCC_VPP(0,0); - printk("%s: bad Vcc/Vpp (%d:%d)\n", - __func__, - configure->vcc, - configure->vpp); - break; - } - break; - case 33: /* Vcc 3.3V */ - switch(configure->vpp) { - case 0: - pcr |= SET_VCC_VPP(1,0); - break; - case 12: - pcr |= SET_VCC_VPP(1,2); - break; - case 33: - pcr |= SET_VCC_VPP(1,1); - break; - case 50: - default: - pcr |= SET_VCC_VPP(0,0); - printk("%s: bad Vcc/Vpp (%d:%d)\n", - __func__, - configure->vcc, - configure->vpp); - break; - } - break; - default: /* what's this ? */ - pcr |= SET_VCC_VPP(0,0); - printk(KERN_ERR "%s: bad Vcc %d\n", - __func__, configure->vcc); - break; - } - - au_writew(pcr, PCMCIA_BOARD_REG); - au_sync_delay(300); - - if (!configure->reset) { - pcr |= PC_DRV_EN; - au_writew(pcr, PCMCIA_BOARD_REG); - au_sync_delay(100); - pcr |= PC_DEASSERT_RST; - au_writew(pcr, PCMCIA_BOARD_REG); - au_sync_delay(100); - } - else { - pcr &= ~(PC_DEASSERT_RST | PC_DRV_EN); - au_writew(pcr, PCMCIA_BOARD_REG); - au_sync_delay(100); - } -#endif return 0; } diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c deleted file mode 100644 index b43d47b50819..000000000000 --- a/drivers/pcmcia/au1000_xxs1500.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * - * MyCable board specific pcmcia routines. - * - * Copyright 2003 MontaVista Software Inc. - * Author: Pete Popov, MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * - */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/proc_fs.h> -#include <linux/types.h> - -#include <pcmcia/cs_types.h> -#include <pcmcia/cs.h> -#include <pcmcia/ss.h> -#include <pcmcia/cistpl.h> -#include <pcmcia/bus_ops.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/system.h> - -#include <asm/au1000.h> -#include <asm/au1000_pcmcia.h> - -#define PCMCIA_MAX_SOCK 0 -#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK + 1) -#define PCMCIA_IRQ AU1000_GPIO_4 - -#if 0 -#define DEBUG(x, args...) printk(__func__ ": " x, ##args) -#else -#define DEBUG(x,args...) -#endif - -static int xxs1500_pcmcia_init(struct pcmcia_init *init) -{ - return PCMCIA_NUM_SOCKS; -} - -static int xxs1500_pcmcia_shutdown(void) -{ - /* turn off power */ - au_writel(au_readl(GPIO2_PINSTATE) | (1<<14)|(1<<30), - GPIO2_OUTPUT); - au_sync_delay(100); - - /* assert reset */ - au_writel(au_readl(GPIO2_PINSTATE) | (1<<4)|(1<<20), - GPIO2_OUTPUT); - au_sync_delay(100); - return 0; -} - - -static int -xxs1500_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state) -{ - u32 inserted; u32 vs; - unsigned long gpio, gpio2; - - if(sock > PCMCIA_MAX_SOCK) return -1; - - gpio = au_readl(SYS_PINSTATERD); - gpio2 = au_readl(GPIO2_PINSTATE); - - vs = gpio2 & ((1<<8) | (1<<9)); - inserted = (!(gpio & 0x1) && !(gpio & 0x2)); - - state->ready = 0; - state->vs_Xv = 0; - state->vs_3v = 0; - state->detect = 0; - - if (inserted) { - switch (vs) { - case 0: - case 1: - case 2: - state->vs_3v=1; - break; - case 3: /* 5V */ - default: - /* return without setting 'detect' */ - printk(KERN_ERR "au1x00_cs: unsupported VS\n", - vs); - return; - } - state->detect = 1; - } - - if (state->detect) { - state->ready = 1; - } - - state->bvd1= gpio2 & (1<<10); - state->bvd2 = gpio2 & (1<<11); - state->wrprot=0; - return 1; -} - - -static int xxs1500_pcmcia_get_irq_info(struct pcmcia_irq_info *info) -{ - - if(info->sock > PCMCIA_MAX_SOCK) return -1; - info->irq = PCMCIA_IRQ; - return 0; -} - - -static int -xxs1500_pcmcia_configure_socket(const struct pcmcia_configure *configure) -{ - - if(configure->sock > PCMCIA_MAX_SOCK) return -1; - - DEBUG("Vcc %dV Vpp %dV, reset %d\n", - configure->vcc, configure->vpp, configure->reset); - - switch(configure->vcc){ - case 33: /* Vcc 3.3V */ - /* turn on power */ - DEBUG("turn on power\n"); - au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<14))|(1<<30), - GPIO2_OUTPUT); - au_sync_delay(100); - break; - case 50: /* Vcc 5V */ - default: /* what's this ? */ - printk(KERN_ERR "au1x00_cs: unsupported VCC\n"); - case 0: /* Vcc 0 */ - /* turn off power */ - au_sync_delay(100); - au_writel(au_readl(GPIO2_PINSTATE) | (1<<14)|(1<<30), - GPIO2_OUTPUT); - break; - } - - if (!configure->reset) { - DEBUG("deassert reset\n"); - au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<4))|(1<<20), - GPIO2_OUTPUT); - au_sync_delay(100); - au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<5))|(1<<21), - GPIO2_OUTPUT); - } - else { - DEBUG("assert reset\n"); - au_writel(au_readl(GPIO2_PINSTATE) | (1<<4)|(1<<20), - GPIO2_OUTPUT); - } - au_sync_delay(100); - return 0; -} - -struct pcmcia_low_level xxs1500_pcmcia_ops = { - xxs1500_pcmcia_init, - xxs1500_pcmcia_shutdown, - xxs1500_pcmcia_socket_state, - xxs1500_pcmcia_get_irq_info, - xxs1500_pcmcia_configure_socket -}; diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c new file mode 100644 index 000000000000..b35b72b0d5b5 --- /dev/null +++ b/drivers/pcmcia/db1xxx_ss.c @@ -0,0 +1,630 @@ +/* + * PCMCIA socket code for the Alchemy Db1xxx/Pb1xxx boards. + * + * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com> + * + */ + +/* This is a fairly generic PCMCIA socket driver suitable for the + * following Alchemy Development boards: + * Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200. + * + * The Db1000 is used as a reference: Per-socket card-, carddetect- and + * statuschange IRQs connected to SoC GPIOs, control and status register + * bits arranged in per-socket groups in an external PLD. All boards + * listed here use this layout, including bit positions and meanings. + * Of course there are exceptions in later boards: + * + * - Pb1100/Pb1500: single socket only; voltage key bits VS are + * at STATUS[5:4] (instead of STATUS[1:0]). + * - Au1200-based: additional card-eject irqs, irqs not gpios! + */ + +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/pm.h> +#include <linux/platform_device.h> +#include <linux/resource.h> +#include <linux/spinlock.h> + +#include <pcmcia/cs_types.h> +#include <pcmcia/ss.h> + +#include <asm/mach-au1x00/au1000.h> +#include <asm/mach-db1x00/bcsr.h> + +#define MEM_MAP_SIZE 0x400000 +#define IO_MAP_SIZE 0x1000 + +struct db1x_pcmcia_sock { + struct pcmcia_socket socket; + int nr; /* socket number */ + void *virt_io; + + /* the "pseudo" addresses of the PCMCIA space. */ + unsigned long phys_io; + unsigned long phys_attr; + unsigned long phys_mem; + + /* previous flags for set_socket() */ + unsigned int old_flags; + + /* interrupt sources: linux irq numbers! */ + int insert_irq; /* default carddetect irq */ + int stschg_irq; /* card-status-change irq */ + int card_irq; /* card irq */ + int eject_irq; /* db1200/pb1200 have these */ + +#define BOARD_TYPE_DEFAULT 0 /* most boards */ +#define BOARD_TYPE_DB1200 1 /* IRQs aren't gpios */ +#define BOARD_TYPE_PB1100 2 /* VS bits slightly different */ + int board_type; +}; + +#define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket) + +/* DB/PB1200: check CPLD SIGSTATUS register bit 10/12 */ +static int db1200_card_inserted(struct db1x_pcmcia_sock *sock) +{ + unsigned short sigstat; + + sigstat = bcsr_read(BCSR_SIGSTAT); + return sigstat & 1 << (8 + 2 * sock->nr); +} + +/* carddetect gpio: low-active */ +static int db1000_card_inserted(struct db1x_pcmcia_sock *sock) +{ + return !gpio_get_value(irq_to_gpio(sock->insert_irq)); +} + +static int db1x_card_inserted(struct db1x_pcmcia_sock *sock) +{ + switch (sock->board_type) { + case BOARD_TYPE_DB1200: + return db1200_card_inserted(sock); + default: + return db1000_card_inserted(sock); + } +} + +/* STSCHG tends to bounce heavily when cards are inserted/ejected. + * To avoid this, the interrupt is normally disabled and only enabled + * after reset to a card has been de-asserted. + */ +static inline void set_stschg(struct db1x_pcmcia_sock *sock, int en) +{ + if (sock->stschg_irq != -1) { + if (en) + enable_irq(sock->stschg_irq); + else + disable_irq(sock->stschg_irq); + } +} + +static irqreturn_t db1000_pcmcia_cdirq(int irq, void *data) +{ + struct db1x_pcmcia_sock *sock = data; + + pcmcia_parse_events(&sock->socket, SS_DETECT); + + return IRQ_HANDLED; +} + +static irqreturn_t db1000_pcmcia_stschgirq(int irq, void *data) +{ + struct db1x_pcmcia_sock *sock = data; + + pcmcia_parse_events(&sock->socket, SS_STSCHG); + + return IRQ_HANDLED; +} + +static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data) +{ + struct db1x_pcmcia_sock *sock = data; + + /* Db/Pb1200 have separate per-socket insertion and ejection + * interrupts which stay asserted as long as the card is + * inserted/missing. The one which caused us to be called + * needs to be disabled and the other one enabled. + */ + if (irq == sock->insert_irq) { + disable_irq_nosync(sock->insert_irq); + enable_irq(sock->eject_irq); + } else { + disable_irq_nosync(sock->eject_irq); + enable_irq(sock->insert_irq); + } + + pcmcia_parse_events(&sock->socket, SS_DETECT); + + return IRQ_HANDLED; +} + +static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) +{ + int ret; + unsigned long flags; + + if (sock->stschg_irq != -1) { + ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq, + 0, "pcmcia_stschg", sock); + if (ret) + return ret; + } + + /* Db/Pb1200 have separate per-socket insertion and ejection + * interrupts, which should show edge behaviour but don't. + * So interrupts are disabled until both insertion and + * ejection handler have been registered and the currently + * active one disabled. + */ + if (sock->board_type == BOARD_TYPE_DB1200) { + local_irq_save(flags); + + ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq, + IRQF_DISABLED, "pcmcia_insert", sock); + if (ret) + goto out1; + + ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq, + IRQF_DISABLED, "pcmcia_eject", sock); + if (ret) { + free_irq(sock->insert_irq, sock); + local_irq_restore(flags); + goto out1; + } + + /* disable the currently active one */ + if (db1200_card_inserted(sock)) + disable_irq_nosync(sock->insert_irq); + else + disable_irq_nosync(sock->eject_irq); + + local_irq_restore(flags); + } else { + /* all other (older) Db1x00 boards use a GPIO to show + * card detection status: use both-edge triggers. + */ + set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH); + ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq, + 0, "pcmcia_carddetect", sock); + + if (ret) + goto out1; + } + + return 0; /* all done */ + +out1: + if (sock->stschg_irq != -1) + free_irq(sock->stschg_irq, sock); + + return ret; +} + +static void db1x_pcmcia_free_irqs(struct db1x_pcmcia_sock *sock) +{ + if (sock->stschg_irq != -1) + free_irq(sock->stschg_irq, sock); + + free_irq(sock->insert_irq, sock); + if (sock->eject_irq != -1) + free_irq(sock->eject_irq, sock); +} + +/* + * configure a PCMCIA socket on the Db1x00 series of boards (and + * compatibles). + * + * 2 external registers are involved: + * pcmcia_status (offset 0x04): bits [0:1/2:3]: read card voltage id + * pcmcia_control(offset 0x10): + * bits[0:1] set vcc for card + * bits[2:3] set vpp for card + * bit 4: enable data buffers + * bit 7: reset# for card + * add 8 for second socket. + */ +static int db1x_pcmcia_configure(struct pcmcia_socket *skt, + struct socket_state_t *state) +{ + struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); + unsigned short cr_clr, cr_set; + unsigned int changed; + int v, p, ret; + + /* card voltage setup */ + cr_clr = (0xf << (sock->nr * 8)); /* clear voltage settings */ + cr_set = 0; + v = p = ret = 0; + + switch (state->Vcc) { + case 50: + ++v; + case 33: + ++v; + case 0: + break; + default: + printk(KERN_INFO "pcmcia%d unsupported Vcc %d\n", + sock->nr, state->Vcc); + } + + switch (state->Vpp) { + case 12: + ++p; + case 33: + case 50: + ++p; + case 0: + break; + default: + printk(KERN_INFO "pcmcia%d unsupported Vpp %d\n", + sock->nr, state->Vpp); + } + + /* sanity check: Vpp must be 0, 12, or Vcc */ + if (((state->Vcc == 33) && (state->Vpp == 50)) || + ((state->Vcc == 50) && (state->Vpp == 33))) { + printk(KERN_INFO "pcmcia%d bad Vcc/Vpp combo (%d %d)\n", + sock->nr, state->Vcc, state->Vpp); + v = p = 0; + ret = -EINVAL; + } + + /* create new voltage code */ + cr_set |= ((v << 2) | p) << (sock->nr * 8); + + changed = state->flags ^ sock->old_flags; + + if (changed & SS_RESET) { + if (state->flags & SS_RESET) { + set_stschg(sock, 0); + /* assert reset, disable io buffers */ + cr_clr |= (1 << (7 + (sock->nr * 8))); + cr_clr |= (1 << (4 + (sock->nr * 8))); + } else { + /* de-assert reset, enable io buffers */ + cr_set |= 1 << (7 + (sock->nr * 8)); + cr_set |= 1 << (4 + (sock->nr * 8)); + } + } + + /* update PCMCIA configuration */ + bcsr_mod(BCSR_PCMCIA, cr_clr, cr_set); + + sock->old_flags = state->flags; + + /* reset was taken away: give card time to initialize properly */ + if ((changed & SS_RESET) && !(state->flags & SS_RESET)) { + msleep(500); + set_stschg(sock, 1); + } + + return ret; +} + +/* VCC bits at [3:2]/[11:10] */ +#define GET_VCC(cr, socknr) \ + ((((cr) >> 2) >> ((socknr) * 8)) & 3) + +/* VS bits at [0:1]/[3:2] */ +#define GET_VS(sr, socknr) \ + (((sr) >> (2 * (socknr))) & 3) + +/* reset bits at [7]/[15] */ +#define GET_RESET(cr, socknr) \ + ((cr) & (1 << (7 + (8 * (socknr))))) + +static int db1x_pcmcia_get_status(struct pcmcia_socket *skt, + unsigned int *value) +{ + struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); + unsigned short cr, sr; + unsigned int status; + + status = db1x_card_inserted(sock) ? SS_DETECT : 0; + + cr = bcsr_read(BCSR_PCMCIA); + sr = bcsr_read(BCSR_STATUS); + + /* PB1100/PB1500: voltage key bits are at [5:4] */ + if (sock->board_type == BOARD_TYPE_PB1100) + sr >>= 4; + + /* determine card type */ + switch (GET_VS(sr, sock->nr)) { + case 0: + case 2: + status |= SS_3VCARD; /* 3V card */ + case 3: + break; /* 5V card: set nothing */ + default: + status |= SS_XVCARD; /* treated as unsupported in core */ + } + + /* if Vcc is not zero, we have applied power to a card */ + status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0; + + /* reset de-asserted? then we're ready */ + status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET; + + *value = status; + + return 0; +} + +static int db1x_pcmcia_sock_init(struct pcmcia_socket *skt) +{ + return 0; +} + +static int db1x_pcmcia_sock_suspend(struct pcmcia_socket *skt) +{ + return 0; +} + +static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt, + struct pccard_io_map *map) +{ + struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); + + map->start = (u32)sock->virt_io; + map->stop = map->start + IO_MAP_SIZE; + + return 0; +} + +static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt, + struct pccard_mem_map *map) +{ + struct db1x_pcmcia_sock *sock = to_db1x_socket(skt); + + if (map->flags & MAP_ATTRIB) + map->static_start = sock->phys_attr + map->card_start; + else + map->static_start = sock->phys_mem + map->card_start; + + return 0; +} + +static struct pccard_operations db1x_pcmcia_operations = { + .init = db1x_pcmcia_sock_init, + .suspend = db1x_pcmcia_sock_suspend, + .get_status = db1x_pcmcia_get_status, + .set_socket = db1x_pcmcia_configure, + .set_io_map = au1x00_pcmcia_set_io_map, + .set_mem_map = au1x00_pcmcia_set_mem_map, +}; + +static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev) +{ + struct db1x_pcmcia_sock *sock; + struct resource *r; + phys_t physio; + int ret, bid; + + sock = kzalloc(sizeof(struct db1x_pcmcia_sock), GFP_KERNEL); + if (!sock) + return -ENOMEM; + + sock->nr = pdev->id; + + bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)); + switch (bid) { + case BCSR_WHOAMI_PB1500: + case BCSR_WHOAMI_PB1500R2: + case BCSR_WHOAMI_PB1100: + sock->board_type = BOARD_TYPE_PB1100; + break; + case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR: + sock->board_type = BOARD_TYPE_DEFAULT; + break; + case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200: + sock->board_type = BOARD_TYPE_DB1200; + break; + default: + printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid); + ret = -ENODEV; + goto out0; + }; + + /* + * gather resources necessary and optional nice-to-haves to + * operate a socket: + * This includes IRQs for Carddetection/ejection, the card + * itself and optional status change detection. + * Also, the memory areas covered by a socket. For these + * we require the 32bit "pseudo" addresses (see the au1000.h + * header for more information). + */ + + /* card: irq assigned to the card itself. */ + r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card"); + sock->card_irq = r ? r->start : 0; + + /* insert: irq which triggers on card insertion/ejection */ + r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "insert"); + sock->insert_irq = r ? r->start : -1; + + /* stschg: irq which trigger on card status change (optional) */ + r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg"); + sock->stschg_irq = r ? r->start : -1; + + /* eject: irq which triggers on ejection (DB1200/PB1200 only) */ + r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eject"); + sock->eject_irq = r ? r->start : -1; + + ret = -ENODEV; + + /* + * pseudo-attr: The 32bit address of the PCMCIA attribute space + * for this socket (usually the 36bit address shifted 4 to the + * right). + */ + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pseudo-attr"); + if (!r) { + printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n", + sock->nr); + goto out0; + } + sock->phys_attr = r->start; + + /* + * pseudo-mem: The 32bit address of the PCMCIA memory space for + * this socket (usually the 36bit address shifted 4 to the right) + */ + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pseudo-mem"); + if (!r) { + printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n", + sock->nr); + goto out0; + } + sock->phys_mem = r->start; + + /* + * pseudo-io: The 32bit address of the PCMCIA IO space for this + * socket (usually the 36bit address shifted 4 to the right). + */ + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pseudo-io"); + if (!r) { + printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n", + sock->nr); + goto out0; + } + sock->phys_io = r->start; + + + /* IO: we must remap the full 36bit address (for reference see + * alchemy/common/setup.c::__fixup_bigphys_addr()) + */ + physio = ((phys_t)sock->phys_io) << 4; + + /* + * PCMCIA client drivers use the inb/outb macros to access + * the IO registers. Since mips_io_port_base is added + * to the access address of the mips implementation of + * inb/outb, we need to subtract it here because we want + * to access the I/O or MEM address directly, without + * going through this "mips_io_port_base" mechanism. + */ + sock->virt_io = (void *)(ioremap(physio, IO_MAP_SIZE) - + mips_io_port_base); + + if (!sock->virt_io) { + printk(KERN_ERR "pcmcia%d: cannot remap IO area\n", + sock->nr); + ret = -ENOMEM; + goto out0; + } + + sock->socket.ops = &db1x_pcmcia_operations; + sock->socket.owner = THIS_MODULE; + sock->socket.pci_irq = sock->card_irq; + sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD; + sock->socket.map_size = MEM_MAP_SIZE; + sock->socket.io_offset = (unsigned long)sock->virt_io; + sock->socket.dev.parent = &pdev->dev; + sock->socket.resource_ops = &pccard_static_ops; + + platform_set_drvdata(pdev, sock); + + ret = db1x_pcmcia_setup_irqs(sock); + if (ret) { + printk(KERN_ERR "pcmcia%d cannot setup interrupts\n", + sock->nr); + goto out1; + } + + set_stschg(sock, 0); + + ret = pcmcia_register_socket(&sock->socket); + if (ret) { + printk(KERN_ERR "pcmcia%d failed to register\n", sock->nr); + goto out2; + } + + printk(KERN_INFO "Alchemy Db/Pb1xxx pcmcia%d @ io/attr/mem %08lx" + "(%p) %08lx %08lx card/insert/stschg/eject irqs @ %d " + "%d %d %d\n", sock->nr, sock->phys_io, sock->virt_io, + sock->phys_attr, sock->phys_mem, sock->card_irq, + sock->insert_irq, sock->stschg_irq, sock->eject_irq); + + return 0; + +out2: + db1x_pcmcia_free_irqs(sock); +out1: + iounmap((void *)(sock->virt_io + (u32)mips_io_port_base)); +out0: + kfree(sock); + return ret; +} + +static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev) +{ + struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev); + + db1x_pcmcia_free_irqs(sock); + pcmcia_unregister_socket(&sock->socket); + iounmap((void *)(sock->virt_io + (u32)mips_io_port_base)); + kfree(sock); + + return 0; +} + +#ifdef CONFIG_PM +static int db1x_pcmcia_suspend(struct device *dev) +{ + return pcmcia_socket_dev_suspend(dev); +} + +static int db1x_pcmcia_resume(struct device *dev) +{ + return pcmcia_socket_dev_resume(dev); +} + +static struct dev_pm_ops db1x_pcmcia_pmops = { + .resume = db1x_pcmcia_resume, + .suspend = db1x_pcmcia_suspend, + .thaw = db1x_pcmcia_resume, + .freeze = db1x_pcmcia_suspend, +}; + +#define DB1XXX_SS_PMOPS &db1x_pcmcia_pmops + +#else + +#define DB1XXX_SS_PMOPS NULL + +#endif + +static struct platform_driver db1x_pcmcia_socket_driver = { + .driver = { + .name = "db1xxx_pcmcia", + .owner = THIS_MODULE, + .pm = DB1XXX_SS_PMOPS + }, + .probe = db1x_pcmcia_socket_probe, + .remove = __devexit_p(db1x_pcmcia_socket_remove), +}; + +int __init db1x_pcmcia_socket_load(void) +{ + return platform_driver_register(&db1x_pcmcia_socket_driver); +} + +void __exit db1x_pcmcia_socket_unload(void) +{ + platform_driver_unregister(&db1x_pcmcia_socket_driver); +} + +module_init(db1x_pcmcia_socket_load); +module_exit(db1x_pcmcia_socket_unload); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards"); +MODULE_AUTHOR("Manuel Lauss"); diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c new file mode 100644 index 000000000000..4e36930b51ce --- /dev/null +++ b/drivers/pcmcia/xxs1500_ss.c @@ -0,0 +1,357 @@ +/* + * PCMCIA socket code for the MyCable XXS1500 system. + * + * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com> + * + */ + +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/mm.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/resource.h> +#include <linux/spinlock.h> + +#include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/ss.h> +#include <pcmcia/cistpl.h> + +#include <asm/irq.h> +#include <asm/system.h> +#include <asm/mach-au1x00/au1000.h> + +#define MEM_MAP_SIZE 0x400000 +#define IO_MAP_SIZE 0x1000 + + +/* + * 3.3V cards only; all interfacing is done via gpios: + * + * 0/1: carddetect (00 = card present, xx = huh) + * 4: card irq + * 204: reset (high-act) + * 205: buffer enable (low-act) + * 208/209: card voltage key (00,01,10,11) + * 210: battwarn + * 211: batdead + * 214: power (low-act) + */ +#define GPIO_CDA 0 +#define GPIO_CDB 1 +#define GPIO_CARDIRQ 4 +#define GPIO_RESET 204 +#define GPIO_OUTEN 205 +#define GPIO_VSL 208 +#define GPIO_VSH 209 +#define GPIO_BATTDEAD 210 +#define GPIO_BATTWARN 211 +#define GPIO_POWER 214 + +struct xxs1500_pcmcia_sock { + struct pcmcia_socket socket; + void *virt_io; + + /* the "pseudo" addresses of the PCMCIA space. */ + unsigned long phys_io; + unsigned long phys_attr; + unsigned long phys_mem; + + /* previous flags for set_socket() */ + unsigned int old_flags; +}; + +#define to_xxs_socket(x) container_of(x, struct xxs1500_pcmcia_sock, socket) + +static irqreturn_t cdirq(int irq, void *data) +{ + struct xxs1500_pcmcia_sock *sock = data; + + pcmcia_parse_events(&sock->socket, SS_DETECT); + + return IRQ_HANDLED; +} + +static int xxs1500_pcmcia_configure(struct pcmcia_socket *skt, + struct socket_state_t *state) +{ + struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt); + unsigned int changed; + + /* power control */ + switch (state->Vcc) { + case 0: + gpio_set_value(GPIO_POWER, 1); /* power off */ + break; + case 33: + gpio_set_value(GPIO_POWER, 0); /* power on */ + break; + case 50: + default: + return -EINVAL; + } + + changed = state->flags ^ sock->old_flags; + + if (changed & SS_RESET) { + if (state->flags & SS_RESET) { + gpio_set_value(GPIO_RESET, 1); /* assert reset */ + gpio_set_value(GPIO_OUTEN, 1); /* buffers off */ + } else { + gpio_set_value(GPIO_RESET, 0); /* deassert reset */ + gpio_set_value(GPIO_OUTEN, 0); /* buffers on */ + msleep(500); + } + } + + sock->old_flags = state->flags; + + return 0; +} + +static int xxs1500_pcmcia_get_status(struct pcmcia_socket *skt, + unsigned int *value) +{ + unsigned int status; + int i; + + status = 0; + + /* check carddetects: GPIO[0:1] must both be low */ + if (!gpio_get_value(GPIO_CDA) && !gpio_get_value(GPIO_CDB)) + status |= SS_DETECT; + + /* determine card voltage: GPIO[208:209] binary value */ + i = (!!gpio_get_value(GPIO_VSL)) | ((!!gpio_get_value(GPIO_VSH)) << 1); + + switch (i) { + case 0: + case 1: + case 2: + status |= SS_3VCARD; /* 3V card */ + break; + case 3: /* 5V card, unsupported */ + default: + status |= SS_XVCARD; /* treated as unsupported in core */ + } + + /* GPIO214: low active power switch */ + status |= gpio_get_value(GPIO_POWER) ? 0 : SS_POWERON; + + /* GPIO204: high-active reset line */ + status |= gpio_get_value(GPIO_RESET) ? SS_RESET : SS_READY; + + /* other stuff */ + status |= gpio_get_value(GPIO_BATTDEAD) ? 0 : SS_BATDEAD; + status |= gpio_get_value(GPIO_BATTWARN) ? 0 : SS_BATWARN; + + *value = status; + + return 0; +} + +static int xxs1500_pcmcia_sock_init(struct pcmcia_socket *skt) +{ + gpio_direction_input(GPIO_CDA); + gpio_direction_input(GPIO_CDB); + gpio_direction_input(GPIO_VSL); + gpio_direction_input(GPIO_VSH); + gpio_direction_input(GPIO_BATTDEAD); + gpio_direction_input(GPIO_BATTWARN); + gpio_direction_output(GPIO_RESET, 1); /* assert reset */ + gpio_direction_output(GPIO_OUTEN, 1); /* disable buffers */ + gpio_direction_output(GPIO_POWER, 1); /* power off */ + + return 0; +} + +static int xxs1500_pcmcia_sock_suspend(struct pcmcia_socket *skt) +{ + return 0; +} + +static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt, + struct pccard_io_map *map) +{ + struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt); + + map->start = (u32)sock->virt_io; + map->stop = map->start + IO_MAP_SIZE; + + return 0; +} + +static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt, + struct pccard_mem_map *map) +{ + struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt); + + if (map->flags & MAP_ATTRIB) + map->static_start = sock->phys_attr + map->card_start; + else + map->static_start = sock->phys_mem + map->card_start; + + return 0; +} + +static struct pccard_operations xxs1500_pcmcia_operations = { + .init = xxs1500_pcmcia_sock_init, + .suspend = xxs1500_pcmcia_sock_suspend, + .get_status = xxs1500_pcmcia_get_status, + .set_socket = xxs1500_pcmcia_configure, + .set_io_map = au1x00_pcmcia_set_io_map, + .set_mem_map = au1x00_pcmcia_set_mem_map, +}; + +static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev) +{ + struct xxs1500_pcmcia_sock *sock; + struct resource *r; + phys_t physio; + int ret, irq; + + sock = kzalloc(sizeof(struct xxs1500_pcmcia_sock), GFP_KERNEL); + if (!sock) + return -ENOMEM; + + ret = -ENODEV; + + /* + * pseudo-attr: The 32bit address of the PCMCIA attribute space + * for this socket (usually the 36bit address shifted 4 to the + * right). + */ + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pseudo-attr"); + if (!r) { + dev_err(&pdev->dev, "missing 'pseudo-attr' resource!\n"); + goto out0; + } + sock->phys_attr = r->start; + + /* + * pseudo-mem: The 32bit address of the PCMCIA memory space for + * this socket (usually the 36bit address shifted 4 to the right) + */ + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pseudo-mem"); + if (!r) { + dev_err(&pdev->dev, "missing 'pseudo-mem' resource!\n"); + goto out0; + } + sock->phys_mem = r->start; + + /* + * pseudo-io: The 32bit address of the PCMCIA IO space for this + * socket (usually the 36bit address shifted 4 to the right). + */ + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pseudo-io"); + if (!r) { + dev_err(&pdev->dev, "missing 'pseudo-io' resource!\n"); + goto out0; + } + sock->phys_io = r->start; + + + /* for io must remap the full 36bit address (for reference see + * alchemy/common/setup.c::__fixup_bigphys_addr) + */ + physio = ((phys_t)sock->phys_io) << 4; + + /* + * PCMCIA client drivers use the inb/outb macros to access + * the IO registers. Since mips_io_port_base is added + * to the access address of the mips implementation of + * inb/outb, we need to subtract it here because we want + * to access the I/O or MEM address directly, without + * going through this "mips_io_port_base" mechanism. + */ + sock->virt_io = (void *)(ioremap(physio, IO_MAP_SIZE) - + mips_io_port_base); + + if (!sock->virt_io) { + dev_err(&pdev->dev, "cannot remap IO area\n"); + ret = -ENOMEM; + goto out0; + } + + sock->socket.ops = &xxs1500_pcmcia_operations; + sock->socket.owner = THIS_MODULE; + sock->socket.pci_irq = gpio_to_irq(GPIO_CARDIRQ); + sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD; + sock->socket.map_size = MEM_MAP_SIZE; + sock->socket.io_offset = (unsigned long)sock->virt_io; + sock->socket.dev.parent = &pdev->dev; + sock->socket.resource_ops = &pccard_static_ops; + + platform_set_drvdata(pdev, sock); + + /* setup carddetect irq: use one of the 2 GPIOs as an + * edge detector. + */ + irq = gpio_to_irq(GPIO_CDA); + set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); + ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock); + if (ret) { + dev_err(&pdev->dev, "cannot setup cd irq\n"); + goto out1; + } + + ret = pcmcia_register_socket(&sock->socket); + if (ret) { + dev_err(&pdev->dev, "failed to register\n"); + goto out2; + } + + printk(KERN_INFO "MyCable XXS1500 PCMCIA socket services\n"); + + return 0; + +out2: + free_irq(gpio_to_irq(GPIO_CDA), sock); +out1: + iounmap((void *)(sock->virt_io + (u32)mips_io_port_base)); +out0: + kfree(sock); + return ret; +} + +static int __devexit xxs1500_pcmcia_remove(struct platform_device *pdev) +{ + struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev); + + pcmcia_unregister_socket(&sock->socket); + free_irq(gpio_to_irq(GPIO_CDA), sock); + iounmap((void *)(sock->virt_io + (u32)mips_io_port_base)); + kfree(sock); + + return 0; +} + +static struct platform_driver xxs1500_pcmcia_socket_driver = { + .driver = { + .name = "xxs1500_pcmcia", + .owner = THIS_MODULE, + }, + .probe = xxs1500_pcmcia_probe, + .remove = __devexit_p(xxs1500_pcmcia_remove), +}; + +int __init xxs1500_pcmcia_socket_load(void) +{ + return platform_driver_register(&xxs1500_pcmcia_socket_driver); +} + +void __exit xxs1500_pcmcia_socket_unload(void) +{ + platform_driver_unregister(&xxs1500_pcmcia_socket_driver); +} + +module_init(xxs1500_pcmcia_socket_load); +module_exit(xxs1500_pcmcia_socket_unload); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PCMCIA Socket Services for MyCable XXS1500 systems"); +MODULE_AUTHOR("Manuel Lauss"); diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index c3e37c8e7e26..63bcbe1a46f4 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1214,12 +1214,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) } #endif -#ifdef CONFIG_SERIAL_8250_AU1X00 - /* if access method is AU, it is a 16550 with a quirk */ - if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) - up->bugs |= UART_BUG_NOMSR; -#endif - serial_outp(up, UART_LCR, save_lcr); if (up->capabilities != uart_config[up->port.type].flags) { @@ -2427,7 +2421,7 @@ serial8250_pm(struct uart_port *port, unsigned int state, static unsigned int serial8250_port_size(struct uart_8250_port *pt) { if (pt->port.iotype == UPIO_AU) - return 0x100000; + return 0x1000; #ifdef CONFIG_ARCH_OMAP if (is_omap_port(pt)) return 0x16 << pt->port.regshift; @@ -2584,6 +2578,13 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (flags & UART_CONFIG_TYPE) autoconfig(up, probeflags); + +#ifdef CONFIG_SERIAL_8250_AU1X00 + /* if access method is AU, it is a 16550 with a quirk */ + if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) + up->bugs |= UART_BUG_NOMSR; +#endif + if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) autoconfig_irq(up); diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c index cfd5ff9508fa..ba8ac4f599d3 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/au1550_spi.c @@ -412,11 +412,13 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t) } /* put buffers on the ring */ - res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, hw->rx, t->len); + res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, virt_to_phys(hw->rx), + t->len, DDMA_FLAGS_IE); if (!res) dev_err(hw->dev, "rx dma put dest error\n"); - res = au1xxx_dbdma_put_source(hw->dma_tx_ch, (void *)hw->tx, t->len); + res = au1xxx_dbdma_put_source(hw->dma_tx_ch, virt_to_phys(hw->tx), + t->len, DDMA_FLAGS_IE); if (!res) dev_err(hw->dev, "tx dma put source error\n"); diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 980548390048..3ee5e63cfa4f 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1571,8 +1571,8 @@ out_err_iobase: if (default_par->mtrr_handle >= 0) mtrr_del(default_par->mtrr_handle, info->fix.smem_start, info->fix.smem_len); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); + release_region(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); out_err_screenbase: if (info->screen_base) iounmap(info->screen_base); |