diff options
Diffstat (limited to 'drivers/pcmcia')
34 files changed, 401 insertions, 872 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index f9e3fb3..bba3ab2 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -183,10 +183,14 @@ config PCMCIA_BCM63XX config PCMCIA_SOC_COMMON tristate +config PCMCIA_SA11XX_BASE + tristate + config PCMCIA_SA1100 tristate "SA1100 support" depends on ARM && ARCH_SA1100 && PCMCIA select PCMCIA_SOC_COMMON + select PCMCIA_SA11XX_BASE help Say Y here to include support for SA11x0-based PCMCIA or CF sockets, found on HP iPAQs, Yopy, and other StrongARM(R)/ @@ -196,8 +200,9 @@ config PCMCIA_SA1100 config PCMCIA_SA1111 tristate "SA1111 support" - depends on ARM && ARCH_SA1100 && SA1111 && PCMCIA + depends on ARM && SA1111 && PCMCIA select PCMCIA_SOC_COMMON + select PCMCIA_SA11XX_BASE if ARCH_SA1100 help Say Y here to include support for SA1111-based PCMCIA or CF sockets, found on the Jornada 720, Graphicsmaster and other @@ -213,6 +218,7 @@ config PCMCIA_PXA2XX || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \ || MACH_COLIBRI320) + select PCMCIA_SA1111 if ARCH_LUBBOCK && SA1111 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 ec543a4..47525de 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -25,8 +25,9 @@ obj-$(CONFIG_I82092) += i82092.o obj-$(CONFIG_TCIC) += tcic.o obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o obj-$(CONFIG_PCMCIA_SOC_COMMON) += soc_common.o -obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_base.o sa1100_cs.o -obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_base.o sa1111_cs.o +obj-$(CONFIG_PCMCIA_SA11XX_BASE) += sa11xx_base.o +obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o +obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o obj-$(CONFIG_M32R_PCC) += m32r_pcc.o obj-$(CONFIG_M32R_CFC) += m32r_cfc.o obj-$(CONFIG_PCMCIA_BCM63XX) += bcm63xx_pcmcia.o @@ -39,9 +40,10 @@ obj-$(CONFIG_ELECTRA_CF) += electra_cf.o obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o sa1111_cs-y += sa1111_generic.o -sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o -sa1111_cs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o -sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o +sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1111_neponset.o +sa1111_cs-$(CONFIG_SA1100_BADGE4) += sa1111_badge4.o +sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1111_jornada720.o +sa1111_cs-$(CONFIG_ARCH_LUBBOCK) += sa1111_lubbock.o sa1100_cs-y += sa1100_generic.o sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o @@ -52,9 +54,7 @@ sa1100_cs-$(CONFIG_SA1100_NANOENGINE) += sa1100_nanoengine.o sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o -pxa2xx_lubbock_cs-y += pxa2xx_lubbock.o sa1111_generic.o pxa2xx_cm_x2xx_cs-y += pxa2xx_cm_x2xx.o pxa2xx_cm_x255.o pxa2xx_cm_x270.o -pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.o diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 4902206..1dd68f5 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -26,6 +26,7 @@ #include <mach/board.h> #include <mach/at91rm9200_mc.h> +#include <mach/at91_ramc.h> /* @@ -156,7 +157,7 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) /* * Use 16 bit accesses unless/until we need 8-bit i/o space. */ - csr = at91_sys_read(AT91_SMC_CSR(cf->board->chipselect)) & ~AT91_SMC_DBW; + csr = at91_ramc_read(0, AT91_SMC_CSR(cf->board->chipselect)) & ~AT91_SMC_DBW; /* * NOTE: this CF controller ignores IOIS16, so we can't really do @@ -175,7 +176,7 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) csr |= AT91_SMC_DBW_16; pr_debug("%s: 16bit i/o bus\n", driver_name); } - at91_sys_write(AT91_SMC_CSR(cf->board->chipselect), csr); + at91_ramc_write(0, AT91_SMC_CSR(cf->board->chipselect), csr); io->start = cf->socket.io_offset; io->stop = io->start + SZ_2K - 1; diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 9a58862..6e75153 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -108,5 +108,5 @@ void cb_free(struct pcmcia_socket *s) struct pci_dev *bridge = s->cb_dev; if (bridge) - pci_remove_behind_bridge(bridge); + pci_stop_and_remove_behind_bridge(bridge); } diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c index 22a75e6..2ef576c 100644 --- a/drivers/pcmcia/pxa2xx_balloon3.c +++ b/drivers/pcmcia/pxa2xx_balloon3.c @@ -29,15 +29,6 @@ #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; @@ -49,12 +40,12 @@ static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ver); skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ; - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} + skt->stat[SOC_STAT_CD].gpio = BALLOON3_GPIO_S0_CD; + skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; + skt->stat[SOC_STAT_BVD1].irq = BALLOON3_BP_NSTSCHG_IRQ; + skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG"; -static void balloon3_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); + return 0; } static unsigned long balloon3_pcmcia_status[2] = { @@ -85,13 +76,11 @@ static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 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, @@ -106,7 +95,6 @@ static int balloon3_pcmcia_configure_socket(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, .first = 0, diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 85ac095..490bb82 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -317,10 +317,7 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev) skt->nr = ops->first + i; skt->clk = clk; - skt->ops = ops; - skt->socket.owner = ops->owner; - skt->socket.dev.parent = &dev->dev; - skt->socket.pci_irq = NO_IRQ; + soc_pcmcia_init_one(skt, ops, &dev->dev); ret = pxa2xx_drv_pcmcia_add_one(skt); if (ret) diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c index 31ab6ddf..da40908 100644 --- a/drivers/pcmcia/pxa2xx_cm_x255.c +++ b/drivers/pcmcia/pxa2xx_cm_x255.c @@ -25,17 +25,6 @@ #define GPIO_PCMCIA_S1_RDYINT (8) #define GPIO_PCMCIA_RESET (9) -#define PCMCIA_S0_CD_VALID gpio_to_irq(GPIO_PCMCIA_S0_CD_VALID) -#define PCMCIA_S1_CD_VALID gpio_to_irq(GPIO_PCMCIA_S1_CD_VALID) -#define PCMCIA_S0_RDYINT gpio_to_irq(GPIO_PCMCIA_S0_RDYINT) -#define PCMCIA_S1_RDYINT gpio_to_irq(GPIO_PCMCIA_S1_RDYINT) - - -static struct pcmcia_irqs irqs[] = { - { .sock = 0, .str = "PCMCIA0 CD" }, - { .sock = 1, .str = "PCMCIA1 CD" }, -}; - static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset"); @@ -43,19 +32,23 @@ static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt) return ret; gpio_direction_output(GPIO_PCMCIA_RESET, 0); - skt->socket.pci_irq = skt->nr == 0 ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT; - irqs[0].irq = PCMCIA_S0_CD_VALID; - irqs[1].irq = PCMCIA_S1_CD_VALID; - ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); - if (!ret) - gpio_free(GPIO_PCMCIA_RESET); + if (skt->nr == 0) { + skt->stat[SOC_STAT_CD].gpio = GPIO_PCMCIA_S0_CD_VALID; + skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; + skt->stat[SOC_STAT_RDY].gpio = GPIO_PCMCIA_S0_RDYINT; + skt->stat[SOC_STAT_RDY].name = "PCMCIA0 RDY"; + } else { + skt->stat[SOC_STAT_CD].gpio = GPIO_PCMCIA_S1_CD_VALID; + skt->stat[SOC_STAT_CD].name = "PCMCIA1 CD"; + skt->stat[SOC_STAT_RDY].gpio = GPIO_PCMCIA_S1_RDYINT; + skt->stat[SOC_STAT_RDY].name = "PCMCIA1 RDY"; + } - return ret; + return 0; } static void cmx255_pcmcia_shutdown(struct soc_pcmcia_socket *skt) { - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); gpio_free(GPIO_PCMCIA_RESET); } @@ -63,16 +56,8 @@ static void cmx255_pcmcia_shutdown(struct soc_pcmcia_socket *skt) static void cmx255_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - int cd = skt->nr ? GPIO_PCMCIA_S1_CD_VALID : GPIO_PCMCIA_S0_CD_VALID; - int rdy = skt->nr ? GPIO_PCMCIA_S1_RDYINT : GPIO_PCMCIA_S0_RDYINT; - - state->detect = !gpio_get_value(cd); - state->ready = !!gpio_get_value(rdy); - state->bvd1 = 1; - state->bvd2 = 1; state->vs_3v = 0; state->vs_Xv = 0; - state->wrprot = 0; /* not available */ } diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c index 3dc7621..f59223f 100644 --- a/drivers/pcmcia/pxa2xx_cm_x270.c +++ b/drivers/pcmcia/pxa2xx_cm_x270.c @@ -22,14 +22,6 @@ #define GPIO_PCMCIA_S0_RDYINT (82) #define GPIO_PCMCIA_RESET (53) -#define PCMCIA_S0_CD_VALID gpio_to_irq(GPIO_PCMCIA_S0_CD_VALID) -#define PCMCIA_S0_RDYINT gpio_to_irq(GPIO_PCMCIA_S0_RDYINT) - - -static struct pcmcia_irqs irqs[] = { - { .sock = 0, .str = "PCMCIA0 CD" }, -}; - static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset"); @@ -37,18 +29,16 @@ static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) return ret; gpio_direction_output(GPIO_PCMCIA_RESET, 0); - skt->socket.pci_irq = PCMCIA_S0_RDYINT; - irqs[0].irq = PCMCIA_S0_CD_VALID; - ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); - if (!ret) - gpio_free(GPIO_PCMCIA_RESET); + skt->stat[SOC_STAT_CD].gpio = GPIO_PCMCIA_S0_CD_VALID; + skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; + skt->stat[SOC_STAT_RDY].gpio = GPIO_PCMCIA_S0_RDYINT; + skt->stat[SOC_STAT_RDY].name = "PCMCIA0 RDY"; return ret; } static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt) { - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); gpio_free(GPIO_PCMCIA_RESET); } @@ -56,13 +46,8 @@ static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt) static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - state->detect = (gpio_get_value(GPIO_PCMCIA_S0_CD_VALID) == 0) ? 1 : 0; - state->ready = (gpio_get_value(GPIO_PCMCIA_S0_RDYINT) == 0) ? 0 : 1; - state->bvd1 = 1; - state->bvd2 = 1; state->vs_3v = 0; state->vs_Xv = 0; - state->wrprot = 0; /* not available */ } diff --git a/drivers/pcmcia/pxa2xx_colibri.c b/drivers/pcmcia/pxa2xx_colibri.c index c6dec57..4dee7b2 100644 --- a/drivers/pcmcia/pxa2xx_colibri.c +++ b/drivers/pcmcia/pxa2xx_colibri.c @@ -53,13 +53,6 @@ static struct gpio colibri_pcmcia_gpios[] = { { 0, GPIOF_INIT_HIGH,"PCMCIA Reset" }, }; -static struct pcmcia_irqs colibri_irqs[] = { - { - .sock = 0, - .str = "PCMCIA CD" - }, -}; - static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; @@ -69,19 +62,10 @@ static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt) if (ret) goto err1; - colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpios[DETECT].gpio); skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpios[READY].gpio); + skt->stat[SOC_STAT_CD].irq = gpio_to_irq(colibri_pcmcia_gpios[DETECT].gpio); + skt->stat[SOC_STAT_CD].name = "PCMCIA CD"; - ret = soc_pcmcia_request_irqs(skt, colibri_irqs, - ARRAY_SIZE(colibri_irqs)); - if (ret) - goto err2; - - return ret; - -err2: - gpio_free_array(colibri_pcmcia_gpios, - ARRAY_SIZE(colibri_pcmcia_gpios)); err1: return ret; } @@ -100,7 +84,6 @@ static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt, state->ready = !!gpio_get_value(colibri_pcmcia_gpios[READY].gpio); state->bvd1 = !!gpio_get_value(colibri_pcmcia_gpios[BVD1].gpio); state->bvd2 = !!gpio_get_value(colibri_pcmcia_gpios[BVD2].gpio); - state->wrprot = 0; state->vs_3v = 1; state->vs_Xv = 0; } diff --git a/drivers/pcmcia/pxa2xx_e740.c b/drivers/pcmcia/pxa2xx_e740.c index 17cd2ce..8751a32 100644 --- a/drivers/pcmcia/pxa2xx_e740.c +++ b/drivers/pcmcia/pxa2xx_e740.c @@ -23,53 +23,27 @@ #include "soc_common.h" -static struct pcmcia_irqs cd_irqs[] = { - { - .sock = 0, - .str = "CF card detect" - }, - { - .sock = 1, - .str = "Wifi switch" - }, -}; - static int e740_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - if (skt->nr == 0) - skt->socket.pci_irq = gpio_to_irq(GPIO_E740_PCMCIA_RDY0); - else - skt->socket.pci_irq = gpio_to_irq(GPIO_E740_PCMCIA_RDY1); - - cd_irqs[0].irq = gpio_to_irq(GPIO_E740_PCMCIA_CD0); - cd_irqs[1].irq = gpio_to_irq(GPIO_E740_PCMCIA_CD1); - - return soc_pcmcia_request_irqs(skt, &cd_irqs[skt->nr], 1); -} + if (skt->nr == 0) { + skt->stat[SOC_STAT_CD].gpio = GPIO_E740_PCMCIA_CD0; + skt->stat[SOC_STAT_CD].name = "CF card detect"; + skt->stat[SOC_STAT_RDY].gpio = GPIO_E740_PCMCIA_RDY0; + skt->stat[SOC_STAT_RDY].name = "CF ready"; + } else { + skt->stat[SOC_STAT_CD].gpio = GPIO_E740_PCMCIA_CD1; + skt->stat[SOC_STAT_CD].name = "Wifi switch"; + skt->stat[SOC_STAT_RDY].gpio = GPIO_E740_PCMCIA_RDY1; + skt->stat[SOC_STAT_RDY].name = "Wifi ready"; + } -/* - * Release all resources. - */ -static void e740_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, &cd_irqs[skt->nr], 1); + return 0; } static void e740_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - if (skt->nr == 0) { - state->detect = gpio_get_value(GPIO_E740_PCMCIA_CD0) ? 0 : 1; - state->ready = gpio_get_value(GPIO_E740_PCMCIA_RDY0) ? 1 : 0; - } else { - state->detect = gpio_get_value(GPIO_E740_PCMCIA_CD1) ? 0 : 1; - state->ready = gpio_get_value(GPIO_E740_PCMCIA_RDY1) ? 1 : 0; - } - state->vs_3v = 1; - state->bvd1 = 1; - state->bvd2 = 1; - state->wrprot = 0; state->vs_Xv = 0; } @@ -109,32 +83,11 @@ static int e740_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, return 0; } -/* - * Enable card status IRQs on (re-)initialisation. This can - * be called at initialisation, power management event, or - * pcmcia event. - */ -static void e740_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_enable_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs)); -} - -/* - * Disable card status IRQs on suspend. - */ -static void e740_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_disable_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs)); -} - static struct pcmcia_low_level e740_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = e740_pcmcia_hw_init, - .hw_shutdown = e740_pcmcia_hw_shutdown, .socket_state = e740_pcmcia_socket_state, .configure_socket = e740_pcmcia_configure_socket, - .socket_init = e740_pcmcia_socket_init, - .socket_suspend = e740_pcmcia_socket_suspend, .nr = 2, }; diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index aded706c..7e32e25 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c @@ -30,27 +30,26 @@ #include "soc_common.h" -static struct pcmcia_irqs irqs[] = { - { 0, MAINSTONE_S0_CD_IRQ, "PCMCIA0 CD" }, - { 1, MAINSTONE_S1_CD_IRQ, "PCMCIA1 CD" }, - { 0, MAINSTONE_S0_STSCHG_IRQ, "PCMCIA0 STSCHG" }, - { 1, MAINSTONE_S1_STSCHG_IRQ, "PCMCIA1 STSCHG" }, -}; - static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { /* * Setup default state of GPIO outputs * before we enable them as outputs. */ - - skt->socket.pci_irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ; - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void mst_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); + if (skt->nr == 0) { + skt->socket.pci_irq = MAINSTONE_S0_IRQ; + skt->stat[SOC_STAT_CD].irq = MAINSTONE_S0_CD_IRQ; + skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; + skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S0_STSCHG_IRQ; + skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG"; + } else { + skt->socket.pci_irq = MAINSTONE_S1_IRQ; + skt->stat[SOC_STAT_CD].irq = MAINSTONE_S1_CD_IRQ; + skt->stat[SOC_STAT_CD].name = "PCMCIA1 CD"; + skt->stat[SOC_STAT_BVD1].irq = MAINSTONE_S1_STSCHG_IRQ; + skt->stat[SOC_STAT_BVD1].name = "PCMCIA1 STSCHG"; + } + return 0; } static unsigned long mst_pcmcia_status[2]; @@ -84,7 +83,6 @@ static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt, state->bvd2 = (status & MST_PCMCIA_nSPKR_BVD2) ? 1 : 0; state->vs_3v = (status & MST_PCMCIA_nVS1) ? 0 : 1; state->vs_Xv = (status & MST_PCMCIA_nVS2) ? 0 : 1; - state->wrprot = 0; /* not available */ } static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, @@ -131,7 +129,6 @@ static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, static struct pcmcia_low_level mst_pcmcia_ops __initdata = { .owner = THIS_MODULE, .hw_init = mst_pcmcia_hw_init, - .hw_shutdown = mst_pcmcia_hw_shutdown, .socket_state = mst_pcmcia_socket_state, .configure_socket = mst_pcmcia_configure_socket, .nr = 2, diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c index 6a8e011..ed7d4db 100644 --- a/drivers/pcmcia/pxa2xx_palmld.c +++ b/drivers/pcmcia/pxa2xx_palmld.c @@ -23,7 +23,6 @@ static struct gpio palmld_pcmcia_gpios[] = { { GPIO_NR_PALMLD_PCMCIA_POWER, GPIOF_INIT_LOW, "PCMCIA Power" }, { GPIO_NR_PALMLD_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, - { GPIO_NR_PALMLD_PCMCIA_READY, GPIOF_IN, "PCMCIA Ready" }, }; static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt) @@ -33,7 +32,8 @@ static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(palmld_pcmcia_gpios, ARRAY_SIZE(palmld_pcmcia_gpios)); - skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMLD_PCMCIA_READY); + skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMLD_PCMCIA_READY; + skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; return ret; } @@ -47,10 +47,6 @@ static void palmld_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { state->detect = 1; /* always inserted */ - state->ready = !!gpio_get_value(GPIO_NR_PALMLD_PCMCIA_READY); - state->bvd1 = 1; - state->bvd2 = 1; - state->wrprot = 0; state->vs_3v = 1; state->vs_Xv = 0; } diff --git a/drivers/pcmcia/pxa2xx_palmtc.c b/drivers/pcmcia/pxa2xx_palmtc.c index 9e38de7..81225a7 100644 --- a/drivers/pcmcia/pxa2xx_palmtc.c +++ b/drivers/pcmcia/pxa2xx_palmtc.c @@ -26,7 +26,6 @@ static struct gpio palmtc_pcmcia_gpios[] = { { GPIO_NR_PALMTC_PCMCIA_POWER2, GPIOF_INIT_LOW, "PCMCIA Power 2" }, { GPIO_NR_PALMTC_PCMCIA_POWER3, GPIOF_INIT_LOW, "PCMCIA Power 3" }, { GPIO_NR_PALMTC_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, - { GPIO_NR_PALMTC_PCMCIA_READY, GPIOF_IN, "PCMCIA Ready" }, { GPIO_NR_PALMTC_PCMCIA_PWRREADY, GPIOF_IN, "PCMCIA Power Ready" }, }; @@ -37,7 +36,8 @@ static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios)); - skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTC_PCMCIA_READY); + skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMTC_PCMCIA_READY; + skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; return ret; } @@ -51,10 +51,6 @@ static void palmtc_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { state->detect = 1; /* always inserted */ - state->ready = !!gpio_get_value(GPIO_NR_PALMTC_PCMCIA_READY); - state->bvd1 = 1; - state->bvd2 = 1; - state->wrprot = 0; state->vs_3v = 1; state->vs_Xv = 0; } diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c index 80645a6..069b6bb 100644 --- a/drivers/pcmcia/pxa2xx_palmtx.c +++ b/drivers/pcmcia/pxa2xx_palmtx.c @@ -23,7 +23,6 @@ static struct gpio palmtx_pcmcia_gpios[] = { { GPIO_NR_PALMTX_PCMCIA_POWER1, GPIOF_INIT_LOW, "PCMCIA Power 1" }, { GPIO_NR_PALMTX_PCMCIA_POWER2, GPIOF_INIT_LOW, "PCMCIA Power 2" }, { GPIO_NR_PALMTX_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, - { GPIO_NR_PALMTX_PCMCIA_READY, GPIOF_IN, "PCMCIA Ready" }, }; static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt) @@ -33,7 +32,8 @@ static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(palmtx_pcmcia_gpios, ARRAY_SIZE(palmtx_pcmcia_gpios)); - skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY); + skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMTX_PCMCIA_READY; + skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; return ret; } @@ -47,10 +47,6 @@ static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { state->detect = 1; /* always inserted */ - state->ready = !!gpio_get_value(GPIO_NR_PALMTX_PCMCIA_READY); - state->bvd1 = 1; - state->bvd2 = 1; - state->wrprot = 0; state->vs_3v = 1; state->vs_Xv = 0; } diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index 69ae2fd..b066273 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -46,21 +46,9 @@ static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt) static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - int ret; - - /* Register interrupts */ if (SCOOP_DEV[skt->nr].cd_irq >= 0) { - struct pcmcia_irqs cd_irq; - - cd_irq.sock = skt->nr; - cd_irq.irq = SCOOP_DEV[skt->nr].cd_irq; - cd_irq.str = SCOOP_DEV[skt->nr].cd_irq_str; - ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1); - - if (ret) { - printk(KERN_ERR "Request for Compact Flash IRQ failed\n"); - return ret; - } + skt->stat[SOC_STAT_CD].irq = SCOOP_DEV[skt->nr].cd_irq; + skt->stat[SOC_STAT_CD].name = SCOOP_DEV[skt->nr].cd_irq_str; } skt->socket.pci_irq = SCOOP_DEV[skt->nr].irq; @@ -68,19 +56,6 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) return 0; } -static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - if (SCOOP_DEV[skt->nr].cd_irq >= 0) { - struct pcmcia_irqs cd_irq; - - cd_irq.sock = skt->nr; - cd_irq.irq = SCOOP_DEV[skt->nr].cd_irq; - cd_irq.str = SCOOP_DEV[skt->nr].cd_irq_str; - soc_pcmcia_free_irqs(skt, &cd_irq, 1); - } -} - - static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { @@ -222,7 +197,6 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { .owner = THIS_MODULE, .hw_init = sharpsl_pcmcia_hw_init, - .hw_shutdown = sharpsl_pcmcia_hw_shutdown, .socket_state = sharpsl_pcmcia_socket_state, .configure_socket = sharpsl_pcmcia_configure_socket, .socket_init = sharpsl_pcmcia_socket_init, diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c index 6c2366b..1d73c44 100644 --- a/drivers/pcmcia/pxa2xx_stargate2.c +++ b/drivers/pcmcia/pxa2xx_stargate2.c @@ -33,10 +33,6 @@ #define SG2_S0_GPIO_DETECT 53 #define SG2_S0_GPIO_READY 81 -static struct pcmcia_irqs irqs[] = { - {.sock = 0, .str = "PCMCIA0 CD" }, -}; - static struct gpio sg2_pcmcia_gpios[] = { { SG2_S0_GPIO_RESET, GPIOF_OUT_INIT_HIGH, "PCMCIA Reset" }, { SG2_S0_POWER_CTL, GPIOF_OUT_INIT_HIGH, "PCMCIA Power Ctrl" }, @@ -44,27 +40,20 @@ static struct gpio sg2_pcmcia_gpios[] = { static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->socket.pci_irq = gpio_to_irq(SG2_S0_GPIO_READY); - irqs[0].irq = gpio_to_irq(SG2_S0_GPIO_DETECT); - - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void sg2_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); + skt->stat[SOC_STAT_CD].gpio = SG2_S0_GPIO_DETECT; + skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; + skt->stat[SOC_STAT_RDY].gpio = SG2_S0_GPIO_READY; + skt->stat[SOC_STAT_RDY].name = "PCMCIA0 RDY"; + return 0; } static void sg2_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - state->detect = !gpio_get_value(SG2_S0_GPIO_DETECT); - state->ready = !!gpio_get_value(SG2_S0_GPIO_READY); state->bvd1 = 0; /* not available - battery detect on card */ state->bvd2 = 0; /* not available */ state->vs_3v = 1; /* not available - voltage detect for card */ state->vs_Xv = 0; /* not available */ - state->wrprot = 0; /* not available - write protect */ } static int sg2_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, @@ -94,24 +83,11 @@ static int sg2_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, return 0; } -static void sg2_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void sg2_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - static struct pcmcia_low_level sg2_pcmcia_ops __initdata = { .owner = THIS_MODULE, .hw_init = sg2_pcmcia_hw_init, - .hw_shutdown = sg2_pcmcia_hw_shutdown, .socket_state = sg2_pcmcia_socket_state, .configure_socket = sg2_pcmcia_configure_socket, - .socket_init = sg2_pcmcia_socket_init, - .socket_suspend = sg2_pcmcia_socket_suspend, .nr = 1, }; diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c index 7c33f89..d326ba1 100644 --- a/drivers/pcmcia/pxa2xx_trizeps4.c +++ b/drivers/pcmcia/pxa2xx_trizeps4.c @@ -29,32 +29,17 @@ extern void board_pcmcia_power(int power); -static struct pcmcia_irqs irqs[] = { - { .sock = 0, .str = "cs0_cd" } - /* on other baseboards we can have more inputs */ -}; - static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - int ret, i; /* we dont have voltage/card/ready detection * so we dont need interrupts for it */ switch (skt->nr) { case 0: - if (gpio_request(GPIO_PRDY, "cf_irq") < 0) { - pr_err("%s: sock %d unable to request gpio %d\n", __func__, - skt->nr, GPIO_PRDY); - return -EBUSY; - } - if (gpio_direction_input(GPIO_PRDY) < 0) { - pr_err("%s: sock %d unable to set input gpio %d\n", __func__, - skt->nr, GPIO_PRDY); - gpio_free(GPIO_PRDY); - return -EINVAL; - } - skt->socket.pci_irq = gpio_to_irq(GPIO_PRDY); - irqs[0].irq = gpio_to_irq(GPIO_PCD); + skt->stat[SOC_STAT_CD].gpio = GPIO_PCD; + skt->stat[SOC_STAT_CD].name = "cs0_cd"; + skt->stat[SOC_STAT_RDY].gpio = GPIO_PRDY; + skt->stat[SOC_STAT_RDY].name = "cs0_rdy"; break; default: break; @@ -62,39 +47,7 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt) /* release the reset of this card */ pr_debug("%s: sock %d irq %d\n", __func__, skt->nr, skt->socket.pci_irq); - /* supplementory irqs for the socket */ - for (i = 0; i < ARRAY_SIZE(irqs); i++) { - if (irqs[i].sock != skt->nr) - continue; - if (gpio_request(irq_to_gpio(irqs[i].irq), irqs[i].str) < 0) { - pr_err("%s: sock %d unable to request gpio %d\n", - __func__, skt->nr, irq_to_gpio(irqs[i].irq)); - ret = -EBUSY; - goto error; - } - if (gpio_direction_input(irq_to_gpio(irqs[i].irq)) < 0) { - pr_err("%s: sock %d unable to set input gpio %d\n", - __func__, skt->nr, irq_to_gpio(irqs[i].irq)); - ret = -EINVAL; - goto error; - } - } - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); - -error: - for (; i >= 0; i--) { - gpio_free(irq_to_gpio(irqs[i].irq)); - } - return (ret); -} - -static void trizeps_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - int i; - /* free allocated gpio's */ - gpio_free(GPIO_PRDY); - for (i = 0; i < ARRAY_SIZE(irqs); i++) - gpio_free(irq_to_gpio(irqs[i].irq)); + return 0; } static unsigned long trizeps_pcmcia_status[2]; @@ -118,13 +71,10 @@ static void trizeps_pcmcia_socket_state(struct soc_pcmcia_socket *skt, switch (skt->nr) { case 0: /* just fill in fix states */ - state->detect = gpio_get_value(GPIO_PCD) ? 0 : 1; - state->ready = gpio_get_value(GPIO_PRDY) ? 1 : 0; state->bvd1 = (status & ConXS_CFSR_BVD1) ? 1 : 0; state->bvd2 = (status & ConXS_CFSR_BVD2) ? 1 : 0; state->vs_3v = (status & ConXS_CFSR_VS1) ? 0 : 1; state->vs_Xv = (status & ConXS_CFSR_VS2) ? 0 : 1; - state->wrprot = 0; /* not available */ break; #ifndef CONFIG_MACH_TRIZEPS_CONXS @@ -136,7 +86,6 @@ static void trizeps_pcmcia_socket_state(struct soc_pcmcia_socket *skt, state->bvd2 = 0; state->vs_3v = 0; state->vs_Xv = 0; - state->wrprot = 0; break; #endif @@ -204,7 +153,6 @@ static void trizeps_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) static struct pcmcia_low_level trizeps_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = trizeps_pcmcia_hw_init, - .hw_shutdown = trizeps_pcmcia_hw_shutdown, .socket_state = trizeps_pcmcia_socket_state, .configure_socket = trizeps_pcmcia_configure_socket, .socket_init = trizeps_pcmcia_socket_init, diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c index 1064b1c..adfae49 100644 --- a/drivers/pcmcia/pxa2xx_viper.c +++ b/drivers/pcmcia/pxa2xx_viper.c @@ -32,13 +32,6 @@ static struct platform_device *arcom_pcmcia_dev; -static struct pcmcia_irqs irqs[] = { - { - .sock = 0, - .str = "PCMCIA_CD", - }, -}; - static inline struct arcom_pcmcia_pdata *viper_get_pdata(void) { return arcom_pcmcia_dev->dev.platform_data; @@ -49,38 +42,28 @@ static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt) struct arcom_pcmcia_pdata *pdata = viper_get_pdata(); unsigned long flags; - skt->socket.pci_irq = gpio_to_irq(pdata->rdy_gpio); - irqs[0].irq = gpio_to_irq(pdata->cd_gpio); - - if (gpio_request(pdata->cd_gpio, "CF detect")) - goto err_request_cd; - - if (gpio_request(pdata->rdy_gpio, "CF ready")) - goto err_request_rdy; + skt->stat[SOC_STAT_CD].gpio = pdata->cd_gpio; + skt->stat[SOC_STAT_CD].name = "PCMCIA_CD"; + skt->stat[SOC_STAT_RDY].gpio = pdata->rdy_gpio; + skt->stat[SOC_STAT_RDY].name = "CF ready"; if (gpio_request(pdata->pwr_gpio, "CF power")) goto err_request_pwr; local_irq_save(flags); - if (gpio_direction_output(pdata->pwr_gpio, 0) || - gpio_direction_input(pdata->cd_gpio) || - gpio_direction_input(pdata->rdy_gpio)) { + if (gpio_direction_output(pdata->pwr_gpio, 0)) { local_irq_restore(flags); goto err_dir; } local_irq_restore(flags); - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); + return 0; err_dir: gpio_free(pdata->pwr_gpio); err_request_pwr: - gpio_free(pdata->rdy_gpio); -err_request_rdy: - gpio_free(pdata->cd_gpio); -err_request_cd: dev_err(&arcom_pcmcia_dev->dev, "Failed to setup PCMCIA GPIOs\n"); return -1; } @@ -92,22 +75,12 @@ static void viper_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { struct arcom_pcmcia_pdata *pdata = viper_get_pdata(); - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); gpio_free(pdata->pwr_gpio); - gpio_free(pdata->rdy_gpio); - gpio_free(pdata->cd_gpio); } static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - struct arcom_pcmcia_pdata *pdata = viper_get_pdata(); - - state->detect = !gpio_get_value(pdata->cd_gpio); - state->ready = !!gpio_get_value(pdata->rdy_gpio); - state->bvd1 = 1; - state->bvd2 = 1; - state->wrprot = 0; state->vs_3v = 1; /* Can only apply 3.3V */ state->vs_Xv = 0; } diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c index 61b17d2..a47dcd2 100644 --- a/drivers/pcmcia/pxa2xx_vpac270.c +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -23,29 +23,14 @@ #include "soc_common.h" static struct gpio vpac270_pcmcia_gpios[] = { - { GPIO84_VPAC270_PCMCIA_CD, GPIOF_IN, "PCMCIA Card Detect" }, - { GPIO35_VPAC270_PCMCIA_RDY, GPIOF_IN, "PCMCIA Ready" }, { GPIO107_VPAC270_PCMCIA_PPEN, GPIOF_INIT_LOW, "PCMCIA PPEN" }, { GPIO11_VPAC270_PCMCIA_RESET, GPIOF_INIT_LOW, "PCMCIA Reset" }, }; static struct gpio vpac270_cf_gpios[] = { - { GPIO17_VPAC270_CF_CD, GPIOF_IN, "CF Card Detect" }, - { GPIO12_VPAC270_CF_RDY, GPIOF_IN, "CF Ready" }, { GPIO16_VPAC270_CF_RESET, GPIOF_INIT_LOW, "CF Reset" }, }; -static struct pcmcia_irqs cd_irqs[] = { - { - .sock = 0, - .str = "PCMCIA CD" - }, - { - .sock = 1, - .str = "CF CD" - }, -}; - static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; @@ -54,20 +39,18 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(vpac270_pcmcia_gpios, ARRAY_SIZE(vpac270_pcmcia_gpios)); - skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY); - cd_irqs[0].irq = gpio_to_irq(GPIO84_VPAC270_PCMCIA_CD); - - if (!ret) - ret = soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); + skt->stat[SOC_STAT_CD].gpio = GPIO84_VPAC270_PCMCIA_CD; + skt->stat[SOC_STAT_CD].name = "PCMCIA CD"; + skt->stat[SOC_STAT_RDY].gpio = GPIO35_VPAC270_PCMCIA_RDY; + skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; } else { ret = gpio_request_array(vpac270_cf_gpios, ARRAY_SIZE(vpac270_cf_gpios)); - skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY); - cd_irqs[1].irq = gpio_to_irq(GPIO17_VPAC270_CF_CD); - - if (!ret) - ret = soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); + skt->stat[SOC_STAT_CD].gpio = GPIO17_VPAC270_CF_CD; + skt->stat[SOC_STAT_CD].name = "CF CD"; + skt->stat[SOC_STAT_RDY].gpio = GPIO12_VPAC270_CF_RDY; + skt->stat[SOC_STAT_RDY].name = "CF Ready"; } return ret; @@ -86,16 +69,6 @@ static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - if (skt->nr == 0) { - state->detect = !gpio_get_value(GPIO84_VPAC270_PCMCIA_CD); - state->ready = !!gpio_get_value(GPIO35_VPAC270_PCMCIA_RDY); - } else { - state->detect = !gpio_get_value(GPIO17_VPAC270_CF_CD); - state->ready = !!gpio_get_value(GPIO12_VPAC270_CF_RDY); - } - state->bvd1 = 1; - state->bvd2 = 1; - state->wrprot = 0; state->vs_3v = 1; state->vs_Xv = 0; } @@ -117,14 +90,6 @@ vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, return 0; } -static void vpac270_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ -} - -static void vpac270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ -} - static struct pcmcia_low_level vpac270_pcmcia_ops = { .owner = THIS_MODULE, @@ -136,9 +101,6 @@ static struct pcmcia_low_level vpac270_pcmcia_ops = { .socket_state = vpac270_pcmcia_socket_state, .configure_socket = vpac270_pcmcia_configure_socket, - - .socket_init = vpac270_pcmcia_socket_init, - .socket_suspend = vpac270_pcmcia_socket_suspend, }; static struct platform_device *vpac270_pcmcia_device; diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c index f1e8822..ba8557e 100644 --- a/drivers/pcmcia/sa1100_assabet.c +++ b/drivers/pcmcia/sa1100_assabet.c @@ -10,46 +10,30 @@ #include <linux/interrupt.h> #include <linux/device.h> #include <linux/init.h> +#include <linux/gpio.h> -#include <mach/hardware.h> #include <asm/mach-types.h> -#include <asm/irq.h> -#include <asm/signal.h> #include <mach/assabet.h> #include "sa1100_generic.h" -static struct pcmcia_irqs irqs[] = { - { 1, ASSABET_IRQ_GPIO_CF_CD, "CF CD" }, - { 1, ASSABET_IRQ_GPIO_CF_BVD2, "CF BVD2" }, - { 1, ASSABET_IRQ_GPIO_CF_BVD1, "CF BVD1" }, -}; - static int assabet_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->socket.pci_irq = ASSABET_IRQ_GPIO_CF_IRQ; - - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} + skt->stat[SOC_STAT_CD].gpio = ASSABET_GPIO_CF_CD; + skt->stat[SOC_STAT_CD].name = "CF CD"; + skt->stat[SOC_STAT_BVD1].gpio = ASSABET_GPIO_CF_BVD1; + skt->stat[SOC_STAT_BVD1].name = "CF BVD1"; + skt->stat[SOC_STAT_BVD2].gpio = ASSABET_GPIO_CF_BVD2; + skt->stat[SOC_STAT_BVD2].name = "CF BVD2"; + skt->stat[SOC_STAT_RDY].gpio = ASSABET_GPIO_CF_IRQ; + skt->stat[SOC_STAT_RDY].name = "CF RDY"; -/* - * Release all resources. - */ -static void assabet_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); + return 0; } static void assabet_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - unsigned long levels = GPLR; - - state->detect = (levels & ASSABET_GPIO_CF_CD) ? 0 : 1; - state->ready = (levels & ASSABET_GPIO_CF_IRQ) ? 1 : 0; - state->bvd1 = (levels & ASSABET_GPIO_CF_BVD1) ? 1 : 0; - state->bvd2 = (levels & ASSABET_GPIO_CF_BVD2) ? 1 : 0; - state->wrprot = 0; /* Not available on Assabet. */ state->vs_3v = 1; /* Can only apply 3.3V on Assabet. */ state->vs_Xv = 0; } @@ -78,38 +62,24 @@ assabet_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_stat return -1; } - /* Silently ignore Vpp, output enable, speaker enable. */ + /* Silently ignore Vpp, speaker enable. */ if (state->flags & SS_RESET) mask |= ASSABET_BCR_CF_RST; + if (!(state->flags & SS_OUTPUT_ENA)) + mask |= ASSABET_BCR_CF_BUS_OFF; - ASSABET_BCR_frob(ASSABET_BCR_CF_RST | ASSABET_BCR_CF_PWR, mask); + ASSABET_BCR_frob(ASSABET_BCR_CF_RST | ASSABET_BCR_CF_PWR | + ASSABET_BCR_CF_BUS_OFF, mask); return 0; } /* - * Enable card status IRQs on (re-)initialisation. This can - * be called at initialisation, power management event, or - * pcmcia event. - */ -static void assabet_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - /* - * Enable CF bus - */ - ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF); - - soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -/* * Disable card status IRQs on suspend. */ static void assabet_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { - soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); - /* * Tristate the CF bus signals. Also assert CF * reset as per user guide page 4-11. @@ -119,14 +89,9 @@ static void assabet_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) static struct pcmcia_low_level assabet_pcmcia_ops = { .owner = THIS_MODULE, - .hw_init = assabet_pcmcia_hw_init, - .hw_shutdown = assabet_pcmcia_hw_shutdown, - .socket_state = assabet_pcmcia_socket_state, .configure_socket = assabet_pcmcia_configure_socket, - - .socket_init = assabet_pcmcia_socket_init, .socket_suspend = assabet_pcmcia_socket_suspend, }; diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c index 30560df..c59c449 100644 --- a/drivers/pcmcia/sa1100_cerf.c +++ b/drivers/pcmcia/sa1100_cerf.c @@ -10,6 +10,7 @@ #include <linux/device.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/gpio.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -19,34 +20,34 @@ #define CERF_SOCKET 1 -static struct pcmcia_irqs irqs[] = { - { CERF_SOCKET, CERF_IRQ_GPIO_CF_CD, "CF_CD" }, - { CERF_SOCKET, CERF_IRQ_GPIO_CF_BVD2, "CF_BVD2" }, - { CERF_SOCKET, CERF_IRQ_GPIO_CF_BVD1, "CF_BVD1" } -}; - static int cerf_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->socket.pci_irq = CERF_IRQ_GPIO_CF_IRQ; + int ret; + + ret = gpio_request_one(CERF_GPIO_CF_RESET, GPIOF_OUT_INIT_LOW, "CF_RESET"); + if (ret) + return ret; + + skt->stat[SOC_STAT_CD].gpio = CERF_GPIO_CF_CD; + skt->stat[SOC_STAT_CD].name = "CF_CD"; + skt->stat[SOC_STAT_BVD1].gpio = CERF_GPIO_CF_BVD1; + skt->stat[SOC_STAT_BVD1].name = "CF_BVD1"; + skt->stat[SOC_STAT_BVD2].gpio = CERF_GPIO_CF_BVD2; + skt->stat[SOC_STAT_BVD2].name = "CF_BVD2"; + skt->stat[SOC_STAT_RDY].gpio = CERF_GPIO_CF_IRQ; + skt->stat[SOC_STAT_RDY].name = "CF_IRQ"; - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); + return 0; } static void cerf_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); + gpio_free(CERF_GPIO_CF_RESET); } static void cerf_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - unsigned long levels = GPLR; - - state->detect = (levels & CERF_GPIO_CF_CD) ?0:1; - state->ready = (levels & CERF_GPIO_CF_IRQ) ?1:0; - state->bvd1 = (levels & CERF_GPIO_CF_BVD1)?1:0; - state->bvd2 = (levels & CERF_GPIO_CF_BVD2)?1:0; - state->wrprot = 0; state->vs_3v = 1; state->vs_Xv = 0; } @@ -67,34 +68,17 @@ cerf_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, return -1; } - if (state->flags & SS_RESET) { - GPSR = CERF_GPIO_CF_RESET; - } else { - GPCR = CERF_GPIO_CF_RESET; - } + gpio_set_value(CERF_GPIO_CF_RESET, !!(state->flags & SS_RESET)); return 0; } -static void cerf_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void cerf_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - static struct pcmcia_low_level cerf_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = cerf_pcmcia_hw_init, .hw_shutdown = cerf_pcmcia_hw_shutdown, .socket_state = cerf_pcmcia_socket_state, .configure_socket = cerf_pcmcia_configure_socket, - - .socket_init = cerf_pcmcia_socket_init, - .socket_suspend = cerf_pcmcia_socket_suspend, }; int __devinit pcmcia_cerf_init(struct device *dev) diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c index edf8f00..d9c7337 100644 --- a/drivers/pcmcia/sa1100_h3600.c +++ b/drivers/pcmcia/sa1100_h3600.c @@ -19,36 +19,20 @@ #include "sa1100_generic.h" -static struct pcmcia_irqs irqs[] = { - { .sock = 0, .str = "PCMCIA CD0" }, /* .irq will be filled later */ - { .sock = 1, .str = "PCMCIA CD1" } -}; - static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int err; switch (skt->nr) { case 0: - err = gpio_request(H3XXX_GPIO_PCMCIA_IRQ0, "PCMCIA IRQ0"); - if (err) - goto err00; - err = gpio_direction_input(H3XXX_GPIO_PCMCIA_IRQ0); - if (err) - goto err01; - skt->socket.pci_irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_IRQ0); - - err = gpio_request(H3XXX_GPIO_PCMCIA_CD0, "PCMCIA CD0"); - if (err) - goto err01; - err = gpio_direction_input(H3XXX_GPIO_PCMCIA_CD0); - if (err) - goto err02; - irqs[0].irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_CD0); + skt->stat[SOC_STAT_CD].gpio = H3XXX_GPIO_PCMCIA_CD0; + skt->stat[SOC_STAT_CD].name = "PCMCIA CD0"; + skt->stat[SOC_STAT_RDY].gpio = H3XXX_GPIO_PCMCIA_IRQ0; + skt->stat[SOC_STAT_RDY].name = "PCMCIA IRQ0"; err = gpio_request(H3XXX_EGPIO_OPT_NVRAM_ON, "OPT NVRAM ON"); if (err) - goto err02; + goto err01; err = gpio_direction_output(H3XXX_EGPIO_OPT_NVRAM_ON, 0); if (err) goto err03; @@ -70,30 +54,12 @@ static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt) err = gpio_direction_output(H3XXX_EGPIO_CARD_RESET, 0); if (err) goto err06; - err = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); - if (err) - goto err06; break; case 1: - err = gpio_request(H3XXX_GPIO_PCMCIA_IRQ1, "PCMCIA IRQ1"); - if (err) - goto err10; - err = gpio_direction_input(H3XXX_GPIO_PCMCIA_IRQ1); - if (err) - goto err11; - skt->socket.pci_irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_IRQ1); - - err = gpio_request(H3XXX_GPIO_PCMCIA_CD1, "PCMCIA CD1"); - if (err) - goto err11; - err = gpio_direction_input(H3XXX_GPIO_PCMCIA_CD1); - if (err) - goto err12; - irqs[1].irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_CD1); - - err = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); - if (err) - goto err12; + skt->stat[SOC_STAT_CD].gpio = H3XXX_GPIO_PCMCIA_CD1; + skt->stat[SOC_STAT_CD].name = "PCMCIA CD1"; + skt->stat[SOC_STAT_RDY].gpio = H3XXX_GPIO_PCMCIA_IRQ1; + skt->stat[SOC_STAT_RDY].name = "PCMCIA IRQ1"; break; } return 0; @@ -102,19 +68,12 @@ err06: gpio_free(H3XXX_EGPIO_CARD_RESET); err05: gpio_free(H3XXX_EGPIO_OPT_RESET); err04: gpio_free(H3XXX_EGPIO_OPT_ON); err03: gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); -err02: gpio_free(H3XXX_GPIO_PCMCIA_CD0); err01: gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); -err00: return err; - -err12: gpio_free(H3XXX_GPIO_PCMCIA_CD0); -err11: gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); -err10: return err; + return err; } static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); - switch (skt->nr) { case 0: /* Disable CF bus: */ @@ -126,12 +85,8 @@ static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) gpio_free(H3XXX_EGPIO_OPT_RESET); gpio_free(H3XXX_EGPIO_OPT_ON); gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); - gpio_free(H3XXX_GPIO_PCMCIA_CD0); - gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); break; case 1: - gpio_free(H3XXX_GPIO_PCMCIA_CD1); - gpio_free(H3XXX_GPIO_PCMCIA_IRQ1); break; } } @@ -139,27 +94,10 @@ static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) static void h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - switch (skt->nr) { - case 0: - state->detect = !gpio_get_value(H3XXX_GPIO_PCMCIA_CD0); - state->ready = !!gpio_get_value(H3XXX_GPIO_PCMCIA_IRQ0); - state->bvd1 = 0; - state->bvd2 = 0; - state->wrprot = 0; /* Not available on H3600. */ - state->vs_3v = 0; - state->vs_Xv = 0; - break; - - case 1: - state->detect = !gpio_get_value(H3XXX_GPIO_PCMCIA_CD1); - state->ready = !!gpio_get_value(H3XXX_GPIO_PCMCIA_IRQ1); - state->bvd1 = 0; - state->bvd2 = 0; - state->wrprot = 0; /* Not available on H3600. */ - state->vs_3v = 0; - state->vs_Xv = 0; - break; - } + state->bvd1 = 0; + state->bvd2 = 0; + state->vs_3v = 0; + state->vs_Xv = 0; } static int @@ -186,14 +124,10 @@ static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt) gpio_set_value(H3XXX_EGPIO_OPT_RESET, 0); msleep(10); - - soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); } static void h3600_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { - soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); - /* * FIXME: This doesn't fit well. We don't have the mechanism in * the generic PCMCIA layer to deal with the idea of two sockets diff --git a/drivers/pcmcia/sa1100_nanoengine.c b/drivers/pcmcia/sa1100_nanoengine.c index 93b9c9b..35c30ff 100644 --- a/drivers/pcmcia/sa1100_nanoengine.c +++ b/drivers/pcmcia/sa1100_nanoengine.c @@ -19,6 +19,7 @@ */ #include <linux/device.h> #include <linux/errno.h> +#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/init.h> @@ -34,43 +35,23 @@ #include "sa1100_generic.h" -static struct pcmcia_irqs irqs_skt0[] = { - /* socket, IRQ, name */ - { 0, NANOENGINE_IRQ_GPIO_PC_CD0, "PC CD0" }, -}; - -static struct pcmcia_irqs irqs_skt1[] = { - /* socket, IRQ, name */ - { 1, NANOENGINE_IRQ_GPIO_PC_CD1, "PC CD1" }, -}; - struct nanoengine_pins { - unsigned input_pins; unsigned output_pins; unsigned clear_outputs; - unsigned transition_pins; - unsigned pci_irq; - struct pcmcia_irqs *pcmcia_irqs; - unsigned pcmcia_irqs_size; + int gpio_rst; + int gpio_cd; + int gpio_rdy; }; static struct nanoengine_pins nano_skts[] = { { - .input_pins = GPIO_PC_READY0 | GPIO_PC_CD0, - .output_pins = GPIO_PC_RESET0, - .clear_outputs = GPIO_PC_RESET0, - .transition_pins = NANOENGINE_IRQ_GPIO_PC_CD0, - .pci_irq = NANOENGINE_IRQ_GPIO_PC_READY0, - .pcmcia_irqs = irqs_skt0, - .pcmcia_irqs_size = ARRAY_SIZE(irqs_skt0) + .gpio_rst = GPIO_PC_RESET0, + .gpio_cd = GPIO_PC_CD0, + .gpio_rdy = GPIO_PC_READY0, }, { - .input_pins = GPIO_PC_READY1 | GPIO_PC_CD1, - .output_pins = GPIO_PC_RESET1, - .clear_outputs = GPIO_PC_RESET1, - .transition_pins = NANOENGINE_IRQ_GPIO_PC_CD1, - .pci_irq = NANOENGINE_IRQ_GPIO_PC_READY1, - .pcmcia_irqs = irqs_skt1, - .pcmcia_irqs_size = ARRAY_SIZE(irqs_skt1) + .gpio_rst = GPIO_PC_RESET1, + .gpio_cd = GPIO_PC_CD1, + .gpio_rdy = GPIO_PC_READY1, } }; @@ -79,58 +60,38 @@ unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts); static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { unsigned i = skt->nr; + int ret; if (i >= num_nano_pcmcia_sockets) return -ENXIO; - GPDR &= ~nano_skts[i].input_pins; - GPDR |= nano_skts[i].output_pins; - GPCR = nano_skts[i].clear_outputs; - irq_set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH); - skt->socket.pci_irq = nano_skts[i].pci_irq; + ret = gpio_request_one(nano_skts[i].gpio_rst, GPIOF_OUT_INIT_LOW, + i ? "PC RST1" : "PC RST0"); + if (ret) + return ret; + + skt->stat[SOC_STAT_CD].gpio = nano_skts[i].gpio_cd; + skt->stat[SOC_STAT_CD].name = i ? "PC CD1" : "PC CD0"; + skt->stat[SOC_STAT_RDY].gpio = nano_skts[i].gpio_rdy; + skt->stat[SOC_STAT_RDY].name = i ? "PC RDY1" : "PC RDY0"; - return soc_pcmcia_request_irqs(skt, - nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size); + return 0; } -/* - * Release all resources. - */ static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - unsigned i = skt->nr; - - if (i >= num_nano_pcmcia_sockets) - return; - - soc_pcmcia_free_irqs(skt, - nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size); + gpio_free(nano_skts[skt->nr].gpio_rst); } static int nanoengine_pcmcia_configure_socket( struct soc_pcmcia_socket *skt, const socket_state_t *state) { - unsigned reset; unsigned i = skt->nr; if (i >= num_nano_pcmcia_sockets) return -ENXIO; - switch (i) { - case 0: - reset = GPIO_PC_RESET0; - break; - case 1: - reset = GPIO_PC_RESET1; - break; - default: - return -ENXIO; - } - - if (state->flags & SS_RESET) - GPSR = reset; - else - GPCR = reset; + gpio_set_value(nano_skts[skt->nr].gpio_rst, !!(state->flags & SS_RESET)); return 0; } @@ -138,62 +99,17 @@ static int nanoengine_pcmcia_configure_socket( static void nanoengine_pcmcia_socket_state( struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - unsigned long levels = GPLR; unsigned i = skt->nr; if (i >= num_nano_pcmcia_sockets) return; - memset(state, 0, sizeof(struct pcmcia_state)); - switch (i) { - case 0: - state->ready = (levels & GPIO_PC_READY0) ? 1 : 0; - state->detect = !(levels & GPIO_PC_CD0) ? 1 : 0; - break; - case 1: - state->ready = (levels & GPIO_PC_READY1) ? 1 : 0; - state->detect = !(levels & GPIO_PC_CD1) ? 1 : 0; - break; - default: - return; - } state->bvd1 = 1; state->bvd2 = 1; - state->wrprot = 0; /* Not available */ state->vs_3v = 1; /* Can only apply 3.3V */ state->vs_Xv = 0; } -/* - * Enable card status IRQs on (re-)initialisation. This can - * be called at initialisation, power management event, or - * pcmcia event. - */ -static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - unsigned i = skt->nr; - - if (i >= num_nano_pcmcia_sockets) - return; - - soc_pcmcia_enable_irqs(skt, - nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size); -} - -/* - * Disable card status IRQs on suspend. - */ -static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ - unsigned i = skt->nr; - - if (i >= num_nano_pcmcia_sockets) - return; - - soc_pcmcia_disable_irqs(skt, - nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size); -} - static struct pcmcia_low_level nanoengine_pcmcia_ops = { .owner = THIS_MODULE, @@ -202,8 +118,6 @@ static struct pcmcia_low_level nanoengine_pcmcia_ops = { .configure_socket = nanoengine_pcmcia_configure_socket, .socket_state = nanoengine_pcmcia_socket_state, - .socket_init = nanoengine_pcmcia_socket_init, - .socket_suspend = nanoengine_pcmcia_socket_suspend, }; int pcmcia_nanoengine_init(struct device *dev) diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c index 7ff1b43..decb347 100644 --- a/drivers/pcmcia/sa1100_shannon.c +++ b/drivers/pcmcia/sa1100_shannon.c @@ -15,40 +15,35 @@ #include <asm/irq.h> #include "sa1100_generic.h" -static struct pcmcia_irqs irqs[] = { - { 0, SHANNON_IRQ_GPIO_EJECT_0, "PCMCIA_CD_0" }, - { 1, SHANNON_IRQ_GPIO_EJECT_1, "PCMCIA_CD_1" }, -}; - static int shannon_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { /* All those are inputs */ - GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 | - SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1); - GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 | - SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1); - - skt->socket.pci_irq = skt->nr ? SHANNON_IRQ_GPIO_RDY_1 : SHANNON_IRQ_GPIO_RDY_0; - - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} + GAFR &= ~(GPIO_GPIO(SHANNON_GPIO_EJECT_0) | + GPIO_GPIO(SHANNON_GPIO_EJECT_1) | + GPIO_GPIO(SHANNON_GPIO_RDY_0) | + GPIO_GPIO(SHANNON_GPIO_RDY_1)); + + if (skt->nr == 0) { + skt->stat[SOC_STAT_CD].gpio = SHANNON_GPIO_EJECT_0; + skt->stat[SOC_STAT_CD].name = "PCMCIA_CD_0"; + skt->stat[SOC_STAT_RDY].gpio = SHANNON_GPIO_RDY_0; + skt->stat[SOC_STAT_RDY].name = "PCMCIA_RDY_0"; + } else { + skt->stat[SOC_STAT_CD].gpio = SHANNON_GPIO_EJECT_1; + skt->stat[SOC_STAT_CD].name = "PCMCIA_CD_1"; + skt->stat[SOC_STAT_RDY].gpio = SHANNON_GPIO_RDY_1; + skt->stat[SOC_STAT_RDY].name = "PCMCIA_RDY_1"; + } -static void shannon_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); + return 0; } static void shannon_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - unsigned long levels = GPLR; - switch (skt->nr) { case 0: - state->detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1; - state->ready = (levels & SHANNON_GPIO_RDY_0) ? 1 : 0; - state->wrprot = 0; /* Not available on Shannon. */ state->bvd1 = 1; state->bvd2 = 1; state->vs_3v = 1; /* FIXME Can only apply 3.3V on Shannon. */ @@ -56,9 +51,6 @@ shannon_pcmcia_socket_state(struct soc_pcmcia_socket *skt, break; case 1: - state->detect = (levels & SHANNON_GPIO_EJECT_1) ? 0 : 1; - state->ready = (levels & SHANNON_GPIO_RDY_1) ? 1 : 0; - state->wrprot = 0; /* Not available on Shannon. */ state->bvd1 = 1; state->bvd2 = 1; state->vs_3v = 1; /* FIXME Can only apply 3.3V on Shannon. */ @@ -92,25 +84,11 @@ shannon_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, return 0; } -static void shannon_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void shannon_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - static struct pcmcia_low_level shannon_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = shannon_pcmcia_hw_init, - .hw_shutdown = shannon_pcmcia_hw_shutdown, .socket_state = shannon_pcmcia_socket_state, .configure_socket = shannon_pcmcia_configure_socket, - - .socket_init = shannon_pcmcia_socket_init, - .socket_suspend = shannon_pcmcia_socket_suspend, }; int __devinit pcmcia_shannon_init(struct device *dev) diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c index 0fac965..8647b17 100644 --- a/drivers/pcmcia/sa1100_simpad.c +++ b/drivers/pcmcia/sa1100_simpad.c @@ -15,24 +15,21 @@ #include <mach/simpad.h> #include "sa1100_generic.h" -static struct pcmcia_irqs irqs[] = { - { 1, IRQ_GPIO_CF_CD, "CF_CD" }, -}; - static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); - skt->socket.pci_irq = IRQ_GPIO_CF_IRQ; + skt->stat[SOC_STAT_CD].gpio = GPIO_CF_CD; + skt->stat[SOC_STAT_CD].name = "CF_CD"; + skt->stat[SOC_STAT_RDY].gpio = GPIO_CF_IRQ; + skt->stat[SOC_STAT_RDY].name = "CF_RDY"; - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); + return 0; } static void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); - /* Disable CF bus: */ /*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/ simpad_clear_cs3_bit(PCMCIA_RESET); @@ -42,14 +39,13 @@ static void simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - unsigned long levels = GPLR; long cs3reg = simpad_get_cs3_ro(); - state->detect=((levels & GPIO_CF_CD)==0)?1:0; - state->ready=(levels & GPIO_CF_IRQ)?1:0; + /* the detect signal is inverted - fix that up here */ + state->detect = !state->detect; + state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */ state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */ - state->wrprot=0; /* Not available on Simpad. */ if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) == (PCMCIA_VS1|PCMCIA_VS2)) { @@ -99,14 +95,8 @@ simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, return 0; } -static void simpad_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - static void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { - soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); simpad_set_cs3_bit(PCMCIA_RESET); } @@ -116,7 +106,6 @@ static struct pcmcia_low_level simpad_pcmcia_ops = { .hw_shutdown = simpad_pcmcia_hw_shutdown, .socket_state = simpad_pcmcia_socket_state, .configure_socket = simpad_pcmcia_configure_socket, - .socket_init = simpad_pcmcia_socket_init, .socket_suspend = simpad_pcmcia_socket_suspend, }; diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1111_badge4.c index 1ce53f4..4d206f4 100644 --- a/drivers/pcmcia/sa1100_badge4.c +++ b/drivers/pcmcia/sa1111_badge4.c @@ -122,13 +122,12 @@ badge4_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state local_irq_restore(flags); } - return 0; + return ret; } static struct pcmcia_low_level badge4_pcmcia_ops = { .owner = THIS_MODULE, .configure_socket = badge4_pcmcia_configure_socket, - .socket_init = sa1111_pcmcia_socket_init, .first = 0, .nr = 2, }; diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 27f2fe3..70f728c 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -22,6 +22,40 @@ #include "sa1111_generic.h" +/* + * These are offsets from the above base. + */ +#define PCCR 0x0000 +#define PCSSR 0x0004 +#define PCSR 0x0008 + +#define PCSR_S0_READY (1<<0) +#define PCSR_S1_READY (1<<1) +#define PCSR_S0_DETECT (1<<2) +#define PCSR_S1_DETECT (1<<3) +#define PCSR_S0_VS1 (1<<4) +#define PCSR_S0_VS2 (1<<5) +#define PCSR_S1_VS1 (1<<6) +#define PCSR_S1_VS2 (1<<7) +#define PCSR_S0_WP (1<<8) +#define PCSR_S1_WP (1<<9) +#define PCSR_S0_BVD1 (1<<10) +#define PCSR_S0_BVD2 (1<<11) +#define PCSR_S1_BVD1 (1<<12) +#define PCSR_S1_BVD2 (1<<13) + +#define PCCR_S0_RST (1<<0) +#define PCCR_S1_RST (1<<1) +#define PCCR_S0_FLT (1<<2) +#define PCCR_S1_FLT (1<<3) +#define PCCR_S0_PWAITEN (1<<4) +#define PCCR_S1_PWAITEN (1<<5) +#define PCCR_S0_PSE (1<<6) +#define PCCR_S1_PSE (1<<7) + +#define PCSSR_S0_SLEEP (1<<0) +#define PCSSR_S1_SLEEP (1<<1) + #define IDX_IRQ_S0_READY_NINT (0) #define IDX_IRQ_S0_CD_VALID (1) #define IDX_IRQ_S0_BVD1_STSCHG (2) @@ -29,27 +63,10 @@ #define IDX_IRQ_S1_CD_VALID (4) #define IDX_IRQ_S1_BVD1_STSCHG (5) -static struct pcmcia_irqs irqs[] = { - { 0, NO_IRQ, "SA1111 PCMCIA card detect" }, - { 0, NO_IRQ, "SA1111 PCMCIA BVD1" }, - { 1, NO_IRQ, "SA1111 CF card detect" }, - { 1, NO_IRQ, "SA1111 CF BVD1" }, -}; - -static int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt) -{ - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { struct sa1111_pcmcia_socket *s = to_skt(skt); - unsigned long status = sa1111_readl(s->dev->mapbase + SA1111_PCSR); + unsigned long status = sa1111_readl(s->dev->mapbase + PCSR); switch (skt->nr) { case 0: @@ -105,35 +122,22 @@ int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT; local_irq_save(flags); - val = sa1111_readl(s->dev->mapbase + SA1111_PCCR); + val = sa1111_readl(s->dev->mapbase + PCCR); val &= ~pccr_skt_mask; val |= pccr_set_mask & pccr_skt_mask; - sa1111_writel(val, s->dev->mapbase + SA1111_PCCR); + sa1111_writel(val, s->dev->mapbase + PCCR); local_irq_restore(flags); return 0; } -void sa1111_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, int (*add)(struct soc_pcmcia_socket *)) { struct sa1111_pcmcia_socket *s; int i, ret = 0; - ops->hw_init = sa1111_pcmcia_hw_init; - ops->hw_shutdown = sa1111_pcmcia_hw_shutdown; ops->socket_state = sa1111_pcmcia_socket_state; - ops->socket_suspend = sa1111_pcmcia_socket_suspend; for (i = 0; i < ops->nr; i++) { s = kzalloc(sizeof(*s), GFP_KERNEL); @@ -141,13 +145,21 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, return -ENOMEM; s->soc.nr = ops->first + i; - s->soc.ops = ops; - s->soc.socket.owner = ops->owner; - s->soc.socket.dev.parent = &dev->dev; - s->soc.socket.pci_irq = s->soc.nr ? - dev->irq[IDX_IRQ_S0_READY_NINT] : - dev->irq[IDX_IRQ_S1_READY_NINT]; + soc_pcmcia_init_one(&s->soc, ops, &dev->dev); s->dev = dev; + if (s->soc.nr) { + s->soc.socket.pci_irq = dev->irq[IDX_IRQ_S1_READY_NINT]; + s->soc.stat[SOC_STAT_CD].irq = dev->irq[IDX_IRQ_S1_CD_VALID]; + s->soc.stat[SOC_STAT_CD].name = "SA1111 CF card detect"; + s->soc.stat[SOC_STAT_BVD1].irq = dev->irq[IDX_IRQ_S1_BVD1_STSCHG]; + s->soc.stat[SOC_STAT_BVD1].name = "SA1111 CF BVD1"; + } else { + s->soc.socket.pci_irq = dev->irq[IDX_IRQ_S0_READY_NINT]; + s->soc.stat[SOC_STAT_CD].irq = dev->irq[IDX_IRQ_S0_CD_VALID]; + s->soc.stat[SOC_STAT_CD].name = "SA1111 PCMCIA card detect"; + s->soc.stat[SOC_STAT_BVD1].irq = dev->irq[IDX_IRQ_S0_BVD1_STSCHG]; + s->soc.stat[SOC_STAT_BVD1].name = "SA1111 PCMCIA BVD1"; + } ret = add(&s->soc); if (ret == 0) { @@ -163,26 +175,26 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, static int pcmcia_probe(struct sa1111_dev *dev) { void __iomem *base; + int ret; + + ret = sa1111_enable_device(dev); + if (ret) + return ret; dev_set_drvdata(&dev->dev, NULL); - if (!request_mem_region(dev->res.start, 512, - SA1111_DRIVER_NAME(dev))) + if (!request_mem_region(dev->res.start, 512, SA1111_DRIVER_NAME(dev))) { + sa1111_disable_device(dev); return -EBUSY; + } base = dev->mapbase; - /* Initialize PCMCIA IRQs */ - irqs[0].irq = dev->irq[IDX_IRQ_S0_CD_VALID]; - irqs[1].irq = dev->irq[IDX_IRQ_S0_BVD1_STSCHG]; - irqs[2].irq = dev->irq[IDX_IRQ_S1_CD_VALID]; - irqs[3].irq = dev->irq[IDX_IRQ_S1_BVD1_STSCHG]; - /* * Initialise the suspend state. */ - sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + SA1111_PCSSR); - sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR); + sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + PCSSR); + sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + PCCR); #ifdef CONFIG_SA1100_BADGE4 pcmcia_badge4_init(&dev->dev); @@ -212,6 +224,7 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev) } release_mem_region(dev->res.start, 512); + sa1111_disable_device(dev); return 0; } diff --git a/drivers/pcmcia/sa1111_generic.h b/drivers/pcmcia/sa1111_generic.h index 02dc857..f6376e3 100644 --- a/drivers/pcmcia/sa1111_generic.h +++ b/drivers/pcmcia/sa1111_generic.h @@ -17,7 +17,6 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, extern void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *, struct pcmcia_state *); extern int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *, const socket_state_t *); -extern void sa1111_pcmcia_socket_init(struct soc_pcmcia_socket *); extern int pcmcia_badge4_init(struct device *); extern int pcmcia_jornada720_init(struct device *); diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1111_jornada720.c index 6bcabee..69428d1 100644 --- a/drivers/pcmcia/sa1100_jornada720.c +++ b/drivers/pcmcia/sa1111_jornada720.c @@ -78,13 +78,8 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s } ret = sa1111_pcmcia_configure_socket(skt, state); - if (ret == 0) { - unsigned long flags; - - local_irq_save(flags); + if (ret == 0) sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); - local_irq_restore(flags); - } return ret; } @@ -92,7 +87,6 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s static struct pcmcia_low_level jornada720_pcmcia_ops = { .owner = THIS_MODULE, .configure_socket = jornada720_pcmcia_configure_socket, - .socket_init = sa1111_pcmcia_socket_init, .first = 0, .nr = 2, }; diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/sa1111_lubbock.c index c21888e..c5caf57 100644 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ b/drivers/pcmcia/sa1111_lubbock.c @@ -202,7 +202,6 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, static struct pcmcia_low_level lubbock_pcmcia_ops = { .owner = THIS_MODULE, .configure_socket = lubbock_pcmcia_configure_socket, - .socket_init = sa1111_pcmcia_socket_init, .first = 0, .nr = 2, }; diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1111_neponset.c index c95639b..1d78739 100644 --- a/drivers/pcmcia/sa1100_neponset.c +++ b/drivers/pcmcia/sa1111_neponset.c @@ -94,30 +94,16 @@ neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_sta ret = sa1111_pcmcia_configure_socket(skt, state); if (ret == 0) { - unsigned long flags; - - local_irq_save(flags); - NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set; - - local_irq_restore(flags); + neponset_ncr_frob(ncr_mask, ncr_set); sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set); } - return 0; -} - -static void neponset_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ - if (skt->nr == 0) - NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP); - - sa1111_pcmcia_socket_init(skt); + return ret; } static struct pcmcia_low_level neponset_pcmcia_ops = { .owner = THIS_MODULE, .configure_socket = neponset_pcmcia_configure_socket, - .socket_init = neponset_pcmcia_socket_init, .first = 0, .nr = 2, }; diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index 79ecc23..6eecd7c 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c @@ -235,10 +235,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, skt = &sinfo->skt[i]; skt->nr = first + i; - skt->ops = ops; - skt->socket.owner = ops->owner; - skt->socket.dev.parent = dev; - skt->socket.pci_irq = NO_IRQ; + soc_pcmcia_init_one(skt, ops, dev); ret = sa11xx_drv_pcmcia_add_one(skt); if (ret) diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 5d22c6a..a2bc6ee 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -32,6 +32,7 @@ #include <linux/cpufreq.h> +#include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -48,6 +49,8 @@ #include "soc_common.h" +static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev); + #ifdef CONFIG_PCMCIA_DEBUG static int pc_debug; @@ -103,6 +106,93 @@ void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, } EXPORT_SYMBOL(soc_common_pcmcia_get_timing); +static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt, + unsigned int nr) +{ + unsigned int i; + + for (i = 0; i < nr; i++) { + if (skt->stat[i].irq) + free_irq(skt->stat[i].irq, skt); + if (gpio_is_valid(skt->stat[i].gpio)) + gpio_free(skt->stat[i].gpio); + } + + if (skt->ops->hw_shutdown) + skt->ops->hw_shutdown(skt); +} + +static void soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) +{ + __soc_pcmcia_hw_shutdown(skt, ARRAY_SIZE(skt->stat)); +} + +static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + int ret = 0, i; + + if (skt->ops->hw_init) { + ret = skt->ops->hw_init(skt); + if (ret) + return ret; + } + + for (i = 0; i < ARRAY_SIZE(skt->stat); i++) { + if (gpio_is_valid(skt->stat[i].gpio)) { + int irq; + + ret = gpio_request_one(skt->stat[i].gpio, GPIOF_IN, + skt->stat[i].name); + if (ret) { + __soc_pcmcia_hw_shutdown(skt, i); + return ret; + } + + irq = gpio_to_irq(skt->stat[i].gpio); + + if (i == SOC_STAT_RDY) + skt->socket.pci_irq = irq; + else + skt->stat[i].irq = irq; + } + + if (skt->stat[i].irq) { + ret = request_irq(skt->stat[i].irq, + soc_common_pcmcia_interrupt, + IRQF_TRIGGER_NONE, + skt->stat[i].name, skt); + if (ret) { + if (gpio_is_valid(skt->stat[i].gpio)) + gpio_free(skt->stat[i].gpio); + __soc_pcmcia_hw_shutdown(skt, i); + return ret; + } + } + } + + return ret; +} + +static void soc_pcmcia_hw_enable(struct soc_pcmcia_socket *skt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(skt->stat); i++) + if (skt->stat[i].irq) { + irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_RISING); + irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_BOTH); + } +} + +static void soc_pcmcia_hw_disable(struct soc_pcmcia_socket *skt) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(skt->stat); i++) + if (skt->stat[i].irq) + irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_NONE); +} + static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt) { struct pcmcia_state state; @@ -110,6 +200,22 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt) memset(&state, 0, sizeof(struct pcmcia_state)); + /* Make battery voltage state report 'good' */ + state.bvd1 = 1; + state.bvd2 = 1; + + /* CD is active low by default */ + if (gpio_is_valid(skt->stat[SOC_STAT_CD].gpio)) + state.detect = !gpio_get_value(skt->stat[SOC_STAT_CD].gpio); + + /* RDY and BVD are active high by default */ + if (gpio_is_valid(skt->stat[SOC_STAT_RDY].gpio)) + state.ready = !!gpio_get_value(skt->stat[SOC_STAT_RDY].gpio); + if (gpio_is_valid(skt->stat[SOC_STAT_BVD1].gpio)) + state.bvd1 = !!gpio_get_value(skt->stat[SOC_STAT_BVD1].gpio); + if (gpio_is_valid(skt->stat[SOC_STAT_BVD2].gpio)) + state.bvd2 = !!gpio_get_value(skt->stat[SOC_STAT_BVD2].gpio); + skt->ops->socket_state(skt, &state); stat = state.detect ? SS_DETECT : 0; @@ -187,6 +293,7 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock) debug(skt, 2, "initializing socket\n"); if (skt->ops->socket_init) skt->ops->socket_init(skt); + soc_pcmcia_hw_enable(skt); return 0; } @@ -206,6 +313,7 @@ static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock) debug(skt, 2, "suspending socket\n"); + soc_pcmcia_hw_disable(skt); if (skt->ops->socket_suspend) skt->ops->socket_suspend(skt); @@ -525,69 +633,6 @@ static struct pccard_operations soc_common_pcmcia_operations = { }; -int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i, res = 0; - - for (i = 0; i < nr; i++) { - if (irqs[i].sock != skt->nr) - continue; - res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt, - IRQF_DISABLED, irqs[i].str, skt); - if (res) - break; - irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE); - } - - if (res) { - printk(KERN_ERR "PCMCIA: request for IRQ%d failed (%d)\n", - irqs[i].irq, res); - - while (i--) - if (irqs[i].sock == skt->nr) - free_irq(irqs[i].irq, skt); - } - return res; -} -EXPORT_SYMBOL(soc_pcmcia_request_irqs); - -void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i; - - for (i = 0; i < nr; i++) - if (irqs[i].sock == skt->nr) - free_irq(irqs[i].irq, skt); -} -EXPORT_SYMBOL(soc_pcmcia_free_irqs); - -void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i; - - for (i = 0; i < nr; i++) - if (irqs[i].sock == skt->nr) - irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE); -} -EXPORT_SYMBOL(soc_pcmcia_disable_irqs); - -void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i; - - for (i = 0; i < nr; i++) - if (irqs[i].sock == skt->nr) { - irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING); - irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH); - } -} -EXPORT_SYMBOL(soc_pcmcia_enable_irqs); - - static LIST_HEAD(soc_pcmcia_sockets); static DEFINE_MUTEX(soc_pcmcia_sockets_lock); @@ -634,6 +679,21 @@ module_exit(soc_pcmcia_cpufreq_unregister); #endif +void soc_pcmcia_init_one(struct soc_pcmcia_socket *skt, + struct pcmcia_low_level *ops, struct device *dev) +{ + int i; + + skt->ops = ops; + skt->socket.owner = ops->owner; + skt->socket.dev.parent = dev; + skt->socket.pci_irq = NO_IRQ; + + for (i = 0; i < ARRAY_SIZE(skt->stat); i++) + skt->stat[i].gpio = -EINVAL; +} +EXPORT_SYMBOL(soc_pcmcia_init_one); + void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt) { mutex_lock(&soc_pcmcia_sockets_lock); @@ -641,8 +701,9 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt) pcmcia_unregister_socket(&skt->socket); - skt->ops->hw_shutdown(skt); + soc_pcmcia_hw_shutdown(skt); + /* should not be required; violates some lowlevel drivers */ soc_common_pcmcia_config_skt(skt, &dead_socket); list_del(&skt->node); @@ -699,7 +760,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt) */ skt->ops->set_timing(skt); - ret = skt->ops->hw_init(skt); + ret = soc_pcmcia_hw_init(skt); if (ret) goto out_err_6; @@ -732,7 +793,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt) pcmcia_unregister_socket(&skt->socket); out_err_7: - skt->ops->hw_shutdown(skt); + soc_pcmcia_hw_shutdown(skt); out_err_6: list_del(&skt->node); mutex_unlock(&soc_pcmcia_sockets_lock); diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h index 9daa736..e6fcbea 100644 --- a/drivers/pcmcia/soc_common.h +++ b/drivers/pcmcia/soc_common.h @@ -50,6 +50,16 @@ struct soc_pcmcia_socket { struct resource res_attr; void __iomem *virt_io; + struct { + int gpio; + unsigned int irq; + const char *name; + } stat[4]; +#define SOC_STAT_CD 0 /* Card detect */ +#define SOC_STAT_BVD1 1 /* BATDEAD / IOSTSCHG */ +#define SOC_STAT_BVD2 2 /* BATWARN / IOSPKR */ +#define SOC_STAT_RDY 3 /* Ready / Interrupt */ + unsigned int irq_state; struct timer_list poll_timer; @@ -115,25 +125,16 @@ struct pcmcia_low_level { }; -struct pcmcia_irqs { - int sock; - int irq; - const char *str; -}; - struct soc_pcmcia_timing { unsigned short io; unsigned short mem; unsigned short attr; }; -extern int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); -extern void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); -extern void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); -extern void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); extern void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *, struct soc_pcmcia_timing *); - +void soc_pcmcia_init_one(struct soc_pcmcia_socket *skt, + struct pcmcia_low_level *ops, struct device *dev); void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt); int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt); |