From a9c0629cdefd9c26746ece510fcc88357869685e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 27 Jul 2010 21:48:10 +0200 Subject: [ARM] pxa/balloon3: PCMCIA Support This driver adds support for the on-board CF socket. Signed-off-by: Marek Vasut --- drivers/pcmcia/Kconfig | 2 +- drivers/pcmcia/Makefile | 1 + drivers/pcmcia/pxa2xx_balloon3.c | 158 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 drivers/pcmcia/pxa2xx_balloon3.c (limited to 'drivers/pcmcia') diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d0f5ad306078..ef2f659ca161 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -215,7 +215,7 @@ config PCMCIA_PXA2XX depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ - || MACH_VPAC270) + || MACH_VPAC270 || MACH_BALLOON3) select PCMCIA_SOC_COMMON help Say Y here to include support for the PXA2xx PCMCIA controller diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index d006e8beab9c..6a6077325527 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -70,6 +70,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o +pxa2xx-obj-$(CONFIG_MACH_BALLOON3) += pxa2xx_balloon3.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c new file mode 100644 index 000000000000..dbbdd0063202 --- /dev/null +++ b/drivers/pcmcia/pxa2xx_balloon3.c @@ -0,0 +1,158 @@ +/* + * linux/drivers/pcmcia/pxa2xx_balloon3.c + * + * Balloon3 PCMCIA specific routines. + * + * Author: Nick Bane + * Created: June, 2006 + * Copyright: Toby Churchill Ltd + * Derived from pxa2xx_mainstone.c, by Nico Pitre + * + * Various modification by Marek Vasut + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "soc_common.h" + +/* + * These are a list of interrupt sources that provokes a polled + * check of status + */ +static struct pcmcia_irqs irqs[] = { + { 0, BALLOON3_S0_CD_IRQ, "PCMCIA0 CD" }, + { 0, BALLOON3_BP_NSTSCHG_IRQ, "PCMCIA0 STSCHG" }, +}; + +static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + uint16_t ver; + int ret; + static void __iomem *fpga_ver; + + ver = __raw_readw(BALLOON3_FPGA_VER); + if (ver > 0x0201) + pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. " + "PCMCIA/CF support might be broken in this version!", + ver); + + skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ; + return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); +} + +static void balloon3_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) +{ + soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); +} + +static unsigned long balloon3_pcmcia_status[2] = { + BALLOON3_CF_nSTSCHG_BVD1, + BALLOON3_CF_nSTSCHG_BVD1 +}; + +static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt, + struct pcmcia_state *state) +{ + uint16_t status; + int flip; + + /* This actually reads the STATUS register */ + status = __raw_readw(BALLOON3_CF_STATUS_REG); + flip = (status ^ balloon3_pcmcia_status[skt->nr]) + & BALLOON3_CF_nSTSCHG_BVD1; + /* + * Workaround for STSCHG which can't be deasserted: + * We therefore disable/enable corresponding IRQs + * as needed to avoid IRQ locks. + */ + if (flip) { + balloon3_pcmcia_status[skt->nr] = status; + if (status & BALLOON3_CF_nSTSCHG_BVD1) + enable_irq(BALLOON3_BP_NSTSCHG_IRQ); + else + disable_irq(BALLOON3_BP_NSTSCHG_IRQ); + } + + state->detect = !gpio_get_value(BALLOON3_GPIO_S0_CD); + state->ready = !!(status & BALLOON3_CF_nIRQ); + state->bvd1 = !!(status & BALLOON3_CF_nSTSCHG_BVD1); + state->bvd2 = 0; /* not available */ + state->vs_3v = 1; /* Always true its a CF card */ + state->vs_Xv = 0; /* not available */ + state->wrprot = 0; /* not available */ +} + +static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, + const socket_state_t *state) +{ + __raw_writew((state->flags & SS_RESET) ? BALLOON3_CF_RESET : 0, + BALLOON3_CF_CONTROL_REG); + return 0; +} + +static void balloon3_pcmcia_socket_init(struct soc_pcmcia_socket *skt) +{ +} + +static void balloon3_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) +{ +} + +static struct pcmcia_low_level balloon3_pcmcia_ops = { + .owner = THIS_MODULE, + .hw_init = balloon3_pcmcia_hw_init, + .hw_shutdown = balloon3_pcmcia_hw_shutdown, + .socket_state = balloon3_pcmcia_socket_state, + .configure_socket = balloon3_pcmcia_configure_socket, + .socket_init = balloon3_pcmcia_socket_init, + .socket_suspend = balloon3_pcmcia_socket_suspend, + .first = 0, + .nr = 1, +}; + +static struct platform_device *balloon3_pcmcia_device; + +static int __init balloon3_pcmcia_init(void) +{ + int ret; + + balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); + if (!balloon3_pcmcia_device) + return -ENOMEM; + + ret = platform_device_add_data(balloon3_pcmcia_device, + &balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops)); + + if (!ret) + ret = platform_device_add(balloon3_pcmcia_device); + + if (ret) + platform_device_put(balloon3_pcmcia_device); + + return ret; +} + +static void __exit balloon3_pcmcia_exit(void) +{ + platform_device_unregister(balloon3_pcmcia_device); +} + +module_init(balloon3_pcmcia_init); +module_exit(balloon3_pcmcia_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nick Bane "); +MODULE_ALIAS("platform:pxa2xx-pcmcia"); +MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver"); -- cgit v1.2.1