#define BALLOON3_AUX_NIRQ PXA_GPIO_TO_IRQ(BALLOON3_GPIO_AUX_NIRQ)
#define BALLOON3_CODEC_IRQ PXA_GPIO_TO_IRQ(BALLOON3_GPIO_CODEC_IRQ)
-#define BALLOON3_S0_CD_IRQ PXA_GPIO_TO_IRQ(BALLOON3_GPIO_S0_CD)
#define BALLOON3_NR_IRQS (IRQ_BOARD_START + 16)
#define ASSABET_BSR_RAD_RI (1 << 31)
-/* GPIOs for which the generic definition doesn't say much */
+/* GPIOs (bitmasks) for which the generic definition doesn't say much */
#define ASSABET_GPIO_RADIO_IRQ GPIO_GPIO (14) /* Radio interrupt request */
#define ASSABET_GPIO_PS_MODE_SYNC GPIO_GPIO (16) /* Power supply mode/sync */
#define ASSABET_GPIO_STEREO_64FS_CLK GPIO_GPIO (19) /* SSP UDA1341 clock input */
-#define ASSABET_GPIO_CF_IRQ GPIO_GPIO (21) /* CF IRQ */
-#define ASSABET_GPIO_CF_CD GPIO_GPIO (22) /* CF CD */
-#define ASSABET_GPIO_CF_BVD2 GPIO_GPIO (24) /* CF BVD */
#define ASSABET_GPIO_GFX_IRQ GPIO_GPIO (24) /* Graphics IRQ */
-#define ASSABET_GPIO_CF_BVD1 GPIO_GPIO (25) /* CF BVD */
#define ASSABET_GPIO_BATT_LOW GPIO_GPIO (26) /* Low battery */
#define ASSABET_GPIO_RCLK GPIO_GPIO (26) /* CCLK/2 */
-#define ASSABET_IRQ_GPIO_CF_IRQ IRQ_GPIO21
-#define ASSABET_IRQ_GPIO_CF_CD IRQ_GPIO22
-#define ASSABET_IRQ_GPIO_CF_BVD2 IRQ_GPIO24
-#define ASSABET_IRQ_GPIO_CF_BVD1 IRQ_GPIO25
+/* These are gpiolib GPIO numbers, not bitmasks */
+#define ASSABET_GPIO_CF_IRQ 21 /* CF IRQ */
+#define ASSABET_GPIO_CF_CD 22 /* CF CD */
+#define ASSABET_GPIO_CF_BVD2 24 /* CF BVD / IOSPKR */
+#define ASSABET_GPIO_CF_BVD1 25 /* CF BVD / IOSTSCHG */
#endif
#define CERF_ETH_IO 0xf0000000
#define CERF_ETH_IRQ IRQ_GPIO26
-#define CERF_GPIO_CF_BVD2 GPIO_GPIO (19)
-#define CERF_GPIO_CF_BVD1 GPIO_GPIO (20)
-#define CERF_GPIO_CF_RESET GPIO_GPIO (21)
-#define CERF_GPIO_CF_IRQ GPIO_GPIO (22)
-#define CERF_GPIO_CF_CD GPIO_GPIO (23)
-
-#define CERF_IRQ_GPIO_CF_BVD2 IRQ_GPIO19
-#define CERF_IRQ_GPIO_CF_BVD1 IRQ_GPIO20
-#define CERF_IRQ_GPIO_CF_IRQ IRQ_GPIO22
-#define CERF_IRQ_GPIO_CF_CD IRQ_GPIO23
+#define CERF_GPIO_CF_BVD2 19
+#define CERF_GPIO_CF_BVD1 20
+#define CERF_GPIO_CF_RESET 21
+#define CERF_GPIO_CF_IRQ 22
+#define CERF_GPIO_CF_CD 23
#endif // _INCLUDE_CERF_H_
#include <mach/irqs.h>
-#define GPIO_PC_READY0 GPIO_GPIO(11) /* ready for socket 0 (active high)*/
-#define GPIO_PC_READY1 GPIO_GPIO(12) /* ready for socket 1 (active high) */
-#define GPIO_PC_CD0 GPIO_GPIO(13) /* detect for socket 0 (active low) */
-#define GPIO_PC_CD1 GPIO_GPIO(14) /* detect for socket 1 (active low) */
-#define GPIO_PC_RESET0 GPIO_GPIO(15) /* reset socket 0 */
-#define GPIO_PC_RESET1 GPIO_GPIO(16) /* reset socket 1 */
+#define GPIO_PC_READY0 11 /* ready for socket 0 (active high)*/
+#define GPIO_PC_READY1 12 /* ready for socket 1 (active high) */
+#define GPIO_PC_CD0 13 /* detect for socket 0 (active low) */
+#define GPIO_PC_CD1 14 /* detect for socket 1 (active low) */
+#define GPIO_PC_RESET0 15 /* reset socket 0 */
+#define GPIO_PC_RESET1 16 /* reset socket 1 */
#define NANOENGINE_IRQ_GPIO_PCI IRQ_GPIO0
#define NANOENGINE_IRQ_GPIO_PC_READY0 IRQ_GPIO11
#define SHANNON_GPIO_SENSE_12V GPIO_GPIO (21) /* Input, 12v flash unprotect detected */
#define SHANNON_GPIO_DISP_EN GPIO_GPIO (22) /* out */
/* XXX GPIO 23 unaccounted for */
-#define SHANNON_GPIO_EJECT_0 GPIO_GPIO (24) /* in */
-#define SHANNON_IRQ_GPIO_EJECT_0 IRQ_GPIO24
-#define SHANNON_GPIO_EJECT_1 GPIO_GPIO (25) /* in */
-#define SHANNON_IRQ_GPIO_EJECT_1 IRQ_GPIO25
-#define SHANNON_GPIO_RDY_0 GPIO_GPIO (26) /* in */
-#define SHANNON_IRQ_GPIO_RDY_0 IRQ_GPIO26
-#define SHANNON_GPIO_RDY_1 GPIO_GPIO (27) /* in */
-#define SHANNON_IRQ_GPIO_RDY_1 IRQ_GPIO27
+#define SHANNON_GPIO_EJECT_0 24 /* in */
+#define SHANNON_GPIO_EJECT_1 25 /* in */
+#define SHANNON_GPIO_RDY_0 26 /* in */
+#define SHANNON_GPIO_RDY_1 27 /* in */
/* MCP UCB codec GPIO pins... */
/*--- PCMCIA ---*/
-#define GPIO_CF_CD GPIO_GPIO24
-#define GPIO_CF_IRQ GPIO_GPIO1
-#define IRQ_GPIO_CF_IRQ IRQ_GPIO1
-#define IRQ_GPIO_CF_CD IRQ_GPIO24
+#define GPIO_CF_CD 24
+#define GPIO_CF_IRQ 1
/*--- SmartCard ---*/
#define GPIO_SMART_CARD GPIO_GPIO10
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)/
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
|| 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
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
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
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
#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;
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] = {
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,
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,
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)
#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");
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);
}
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 */
}
#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");
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);
}
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 */
}
{ 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;
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;
}
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;
}
#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;
}
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,
};
+++ /dev/null
-/*
- * linux/drivers/pcmcia/pxa2xx_lubbock.c
- *
- * Author: George Davis
- * Created: Jan 10, 2002
- * Copyright: MontaVista Software Inc.
- *
- * 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.
- *
- * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
- *
- * Lubbock PCMCIA specific routines.
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <mach/hardware.h>
-#include <asm/hardware/sa1111.h>
-#include <asm/mach-types.h>
-#include <mach/lubbock.h>
-
-#include "sa1111_generic.h"
-
-static int
-lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
- const socket_state_t *state)
-{
- struct sa1111_pcmcia_socket *s = to_skt(skt);
- unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set;
- int ret = 0;
-
- pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0;
-
- /* Lubbock uses the Maxim MAX1602, with the following connections:
- *
- * Socket 0 (PCMCIA):
- * MAX1602 Lubbock Register
- * Pin Signal
- * ----- ------- ----------------------
- * A0VPP S0_PWR0 SA-1111 GPIO A<0>
- * A1VPP S0_PWR1 SA-1111 GPIO A<1>
- * A0VCC S0_PWR2 SA-1111 GPIO A<2>
- * A1VCC S0_PWR3 SA-1111 GPIO A<3>
- * VX VCC
- * VY +3.3V
- * 12IN +12V
- * CODE +3.3V Cirrus Code, CODE = High (VY)
- *
- * Socket 1 (CF):
- * MAX1602 Lubbock Register
- * Pin Signal
- * ----- ------- ----------------------
- * A0VPP GND VPP is not connected
- * A1VPP GND VPP is not connected
- * A0VCC S1_PWR0 MISC_WR<14>
- * A1VCC S1_PWR1 MISC_WR<15>
- * VX VCC
- * VY +3.3V
- * 12IN GND VPP is not connected
- * CODE +3.3V Cirrus Code, CODE = High (VY)
- *
- */
-
- again:
- switch (skt->nr) {
- case 0:
- pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
-
- switch (state->Vcc) {
- case 0: /* Hi-Z */
- break;
-
- case 33: /* VY */
- pa_dwr_set |= GPIO_A3;
- break;
-
- case 50: /* VX */
- pa_dwr_set |= GPIO_A2;
- break;
-
- default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
- __func__, state->Vcc);
- ret = -1;
- }
-
- switch (state->Vpp) {
- case 0: /* Hi-Z */
- break;
-
- case 120: /* 12IN */
- pa_dwr_set |= GPIO_A1;
- break;
-
- default: /* VCC */
- if (state->Vpp == state->Vcc)
- pa_dwr_set |= GPIO_A0;
- else {
- printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
- __func__, state->Vpp);
- ret = -1;
- break;
- }
- }
- break;
-
- case 1:
- misc_mask = (1 << 15) | (1 << 14);
-
- switch (state->Vcc) {
- case 0: /* Hi-Z */
- break;
-
- case 33: /* VY */
- misc_set |= 1 << 15;
- break;
-
- case 50: /* VX */
- misc_set |= 1 << 14;
- break;
-
- default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
- __func__, state->Vcc);
- ret = -1;
- break;
- }
-
- if (state->Vpp != state->Vcc && state->Vpp != 0) {
- printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
- __func__, state->Vpp);
- ret = -1;
- break;
- }
- break;
-
- default:
- ret = -1;
- }
-
- if (ret == 0)
- ret = sa1111_pcmcia_configure_socket(skt, state);
-
- if (ret == 0) {
- lubbock_set_misc_wr(misc_mask, misc_set);
- sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
- }
-
-#if 1
- if (ret == 0 && state->Vcc == 33) {
- struct pcmcia_state new_state;
-
- /*
- * HACK ALERT:
- * We can't sense the voltage properly on Lubbock before
- * actually applying some power to the socket (catch 22).
- * Resense the socket Voltage Sense pins after applying
- * socket power.
- *
- * Note: It takes about 2.5ms for the MAX1602 VCC output
- * to rise.
- */
- mdelay(3);
-
- sa1111_pcmcia_socket_state(skt, &new_state);
-
- if (!new_state.vs_3v && !new_state.vs_Xv) {
- /*
- * Switch to 5V, Configure socket with 5V voltage
- */
- lubbock_set_misc_wr(misc_mask, 0);
- sa1111_set_io(s->dev, pa_dwr_mask, 0);
-
- /*
- * It takes about 100ms to turn off Vcc.
- */
- mdelay(100);
-
- /*
- * We need to hack around the const qualifier as
- * well to keep this ugly workaround localized and
- * not force it to the rest of the code. Barf bags
- * available in the seat pocket in front of you!
- */
- ((socket_state_t *)state)->Vcc = 50;
- ((socket_state_t *)state)->Vpp = 50;
- goto again;
- }
- }
-#endif
-
- return ret;
-}
-
-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,
-};
-
-#include "pxa2xx_base.h"
-
-int pcmcia_lubbock_init(struct sa1111_dev *sadev)
-{
- int ret = -ENODEV;
-
- if (machine_is_lubbock()) {
- /*
- * Set GPIO_A<3:0> to be outputs for the MAX1600,
- * and switch to standby mode.
- */
- sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
- sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
- sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
-
- /* Set CF Socket 1 power to standby mode. */
- lubbock_set_misc_wr((1 << 15) | (1 << 14), 0);
-
- pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops);
- pxa2xx_configure_sockets(&sadev->dev);
- ret = sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops,
- pxa2xx_drv_pcmcia_add_one);
- }
-
- return ret;
-}
-
-MODULE_LICENSE("GPL");
#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];
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,
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,
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)
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;
}
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;
}
{ 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" },
};
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;
}
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;
}
{ 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)
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;
}
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;
}
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;
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)
{
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,
#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" },
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,
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,
};
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;
/* 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];
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
state->bvd2 = 0;
state->vs_3v = 0;
state->vs_Xv = 0;
- state->wrprot = 0;
break;
#endif
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,
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;
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;
}
{
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;
}
#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;
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;
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;
}
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,
.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;
#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;
}
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.
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,
};
+++ /dev/null
-/*
- * linux/drivers/pcmcia/sa1100_badge4.c
- *
- * BadgePAD 4 PCMCIA specific routines
- *
- * Christopher Hoover <ch@hpl.hp.com>
- *
- * Copyright (C) 2002 Hewlett-Packard Company
- *
- * 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 <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <mach/badge4.h>
-#include <asm/hardware/sa1111.h>
-
-#include "sa1111_generic.h"
-
-/*
- * BadgePAD 4 Details
- *
- * PCM Vcc:
- *
- * PCM Vcc on BadgePAD 4 can be jumpered for 3v3 (short pins 1 and 3
- * on JP6) or 5v0 (short pins 3 and 5 on JP6).
- *
- * PCM Vpp:
- *
- * PCM Vpp on BadgePAD 4 can be jumpered for 12v0 (short pins 4 and 6
- * on JP6) or tied to PCM Vcc (short pins 2 and 4 on JP6). N.B.,
- * 12v0 operation requires that the power supply actually supply 12v0
- * via pin 7 of JP7.
- *
- * CF Vcc:
- *
- * CF Vcc on BadgePAD 4 can be jumpered either for 3v3 (short pins 1
- * and 2 on JP10) or 5v0 (short pins 2 and 3 on JP10).
- *
- * Unfortunately there's no way programmatically to determine how a
- * given board is jumpered. This code assumes a default jumpering
- * as described below.
- *
- * If the defaults aren't correct, you may override them with a pcmv
- * setup argument: pcmv=<pcm vcc>,<pcm vpp>,<cf vcc>. The units are
- * tenths of volts; e.g. pcmv=33,120,50 indicates 3v3 PCM Vcc, 12v0
- * PCM Vpp, and 5v0 CF Vcc.
- *
- */
-
-static int badge4_pcmvcc = 50; /* pins 3 and 5 jumpered on JP6 */
-static int badge4_pcmvpp = 50; /* pins 2 and 4 jumpered on JP6 */
-static int badge4_cfvcc = 33; /* pins 1 and 2 jumpered on JP10 */
-
-static void complain_about_jumpering(const char *whom,
- const char *supply,
- int given, int wanted)
-{
- printk(KERN_ERR
- "%s: %s %d.%dV wanted but board is jumpered for %s %d.%dV operation"
- "; re-jumper the board and/or use pcmv=xx,xx,xx\n",
- whom, supply,
- wanted / 10, wanted % 10,
- supply,
- given / 10, given % 10);
-}
-
-static int
-badge4_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
-{
- int ret;
-
- switch (skt->nr) {
- case 0:
- if ((state->Vcc != 0) &&
- (state->Vcc != badge4_pcmvcc)) {
- complain_about_jumpering(__func__, "pcmvcc",
- badge4_pcmvcc, state->Vcc);
- // Apply power regardless of the jumpering.
- // return -1;
- }
- if ((state->Vpp != 0) &&
- (state->Vpp != badge4_pcmvpp)) {
- complain_about_jumpering(__func__, "pcmvpp",
- badge4_pcmvpp, state->Vpp);
- return -1;
- }
- break;
-
- case 1:
- if ((state->Vcc != 0) &&
- (state->Vcc != badge4_cfvcc)) {
- complain_about_jumpering(__func__, "cfvcc",
- badge4_cfvcc, state->Vcc);
- return -1;
- }
- break;
-
- default:
- return -1;
- }
-
- ret = sa1111_pcmcia_configure_socket(skt, state);
- if (ret == 0) {
- unsigned long flags;
- int need5V;
-
- local_irq_save(flags);
-
- need5V = ((state->Vcc == 50) || (state->Vpp == 50));
-
- badge4_set_5V(BADGE4_5V_PCMCIA_SOCK(skt->nr), need5V);
-
- local_irq_restore(flags);
- }
-
- return 0;
-}
-
-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,
-};
-
-int pcmcia_badge4_init(struct device *dev)
-{
- int ret = -ENODEV;
-
- if (machine_is_badge4()) {
- printk(KERN_INFO
- "%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
- __func__,
- badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
-
- sa11xx_drv_pcmcia_ops(&badge4_pcmcia_ops);
- ret = sa1111_pcmcia_add(dev, &badge4_pcmcia_ops,
- sa11xx_drv_pcmcia_add_one);
- }
-
- return ret;
-}
-
-static int __init pcmv_setup(char *s)
-{
- int v[4];
-
- s = get_options(s, ARRAY_SIZE(v), v);
-
- if (v[0] >= 1) badge4_pcmvcc = v[1];
- if (v[0] >= 2) badge4_pcmvpp = v[2];
- if (v[0] >= 3) badge4_cfvcc = v[3];
-
- return 1;
-}
-
-__setup("pcmv=", pcmv_setup);
#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>
#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;
}
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)
#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;
if (err)
goto err05;
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;
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: */
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;
}
}
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
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
+++ /dev/null
-/*
- * drivers/pcmcia/sa1100_jornada720.c
- *
- * Jornada720 PCMCIA specific routines
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/hardware/sa1111.h>
-#include <asm/mach-types.h>
-
-#include "sa1111_generic.h"
-
-/* Does SOCKET1_3V actually do anything? */
-#define SOCKET0_POWER GPIO_GPIO0
-#define SOCKET0_3V GPIO_GPIO2
-#define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3)
-#define SOCKET1_3V GPIO_GPIO3
-
-static int
-jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
-{
- struct sa1111_pcmcia_socket *s = to_skt(skt);
- unsigned int pa_dwr_mask, pa_dwr_set;
- int ret;
-
- printk(KERN_INFO "%s(): config socket %d vcc %d vpp %d\n", __func__,
- skt->nr, state->Vcc, state->Vpp);
-
- switch (skt->nr) {
- case 0:
- pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V;
-
- switch (state->Vcc) {
- default:
- case 0:
- pa_dwr_set = 0;
- break;
- case 33:
- pa_dwr_set = SOCKET0_POWER | SOCKET0_3V;
- break;
- case 50:
- pa_dwr_set = SOCKET0_POWER;
- break;
- }
- break;
-
- case 1:
- pa_dwr_mask = SOCKET1_POWER;
-
- switch (state->Vcc) {
- default:
- case 0:
- pa_dwr_set = 0;
- break;
- case 33:
- pa_dwr_set = SOCKET1_POWER;
- break;
- case 50:
- pa_dwr_set = SOCKET1_POWER;
- break;
- }
- break;
-
- default:
- return -1;
- }
-
- if (state->Vpp != state->Vcc && state->Vpp != 0) {
- printk(KERN_ERR "%s(): slot cannot support VPP %u\n",
- __func__, state->Vpp);
- return -EPERM;
- }
-
- ret = sa1111_pcmcia_configure_socket(skt, state);
- if (ret == 0) {
- unsigned long flags;
-
- local_irq_save(flags);
- sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
- local_irq_restore(flags);
- }
-
- return ret;
-}
-
-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,
-};
-
-int __devinit pcmcia_jornada720_init(struct device *dev)
-{
- int ret = -ENODEV;
-
- if (machine_is_jornada720()) {
- unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
-
- GRER |= 0x00000002;
-
- /* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */
- sa1111_set_io_dir(dev, pin, 0, 0);
- sa1111_set_io(dev, pin, 0);
- sa1111_set_sleep_io(dev, pin, 0);
-
- sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops);
- ret = sa1111_pcmcia_add(dev, &jornada720_pcmcia_ops,
- sa11xx_drv_pcmcia_add_one);
- }
-
- return ret;
-}
*/
#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/init.h>
#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,
}
};
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;
}
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,
.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)
+++ /dev/null
-/*
- * linux/drivers/pcmcia/sa1100_neponset.c
- *
- * Neponset PCMCIA specific routines
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <mach/neponset.h>
-#include <asm/hardware/sa1111.h>
-
-#include "sa1111_generic.h"
-
-/*
- * Neponset uses the Maxim MAX1600, with the following connections:
- *
- * MAX1600 Neponset
- *
- * A0VCC SA-1111 GPIO A<1>
- * A1VCC SA-1111 GPIO A<0>
- * A0VPP CPLD NCR A0VPP
- * A1VPP CPLD NCR A1VPP
- * B0VCC SA-1111 GPIO A<2>
- * B1VCC SA-1111 GPIO A<3>
- * B0VPP ground (slot B is CF)
- * B1VPP ground (slot B is CF)
- *
- * VX VCC (5V)
- * VY VCC3_3 (3.3V)
- * 12INA 12V
- * 12INB ground (slot B is CF)
- *
- * The MAX1600 CODE pin is tied to ground, placing the device in
- * "Standard Intel code" mode. Refer to the Maxim data sheet for
- * the corresponding truth table.
- */
-
-static int
-neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
-{
- struct sa1111_pcmcia_socket *s = to_skt(skt);
- unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
- int ret;
-
- switch (skt->nr) {
- case 0:
- pa_dwr_mask = GPIO_A0 | GPIO_A1;
- ncr_mask = NCR_A0VPP | NCR_A1VPP;
-
- if (state->Vpp == 0)
- ncr_set = 0;
- else if (state->Vpp == 120)
- ncr_set = NCR_A1VPP;
- else if (state->Vpp == state->Vcc)
- ncr_set = NCR_A0VPP;
- else {
- printk(KERN_ERR "%s(): unrecognized VPP %u\n",
- __func__, state->Vpp);
- return -1;
- }
- break;
-
- case 1:
- pa_dwr_mask = GPIO_A2 | GPIO_A3;
- ncr_mask = 0;
- ncr_set = 0;
-
- if (state->Vpp != state->Vcc && state->Vpp != 0) {
- printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
- __func__, state->Vpp);
- return -1;
- }
- break;
-
- default:
- return -1;
- }
-
- /*
- * pa_dwr_set is the mask for selecting Vcc on both sockets.
- * pa_dwr_mask selects which bits (and therefore socket) we change.
- */
- switch (state->Vcc) {
- default:
- case 0: pa_dwr_set = 0; break;
- case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break;
- case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break;
- }
-
- 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);
- 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);
-}
-
-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,
-};
-
-int pcmcia_neponset_init(struct sa1111_dev *sadev)
-{
- int ret = -ENODEV;
-
- if (machine_is_assabet()) {
- /*
- * Set GPIO_A<3:0> to be outputs for the MAX1600,
- * and switch to standby mode.
- */
- sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
- sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
- sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
- sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops);
- ret = sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops,
- sa11xx_drv_pcmcia_add_one);
- }
-
- return ret;
-}
#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. */
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. */
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)
#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);
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)) {
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);
}
.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,
};
--- /dev/null
+/*
+ * linux/drivers/pcmcia/sa1100_badge4.c
+ *
+ * BadgePAD 4 PCMCIA specific routines
+ *
+ * Christopher Hoover <ch@hpl.hp.com>
+ *
+ * Copyright (C) 2002 Hewlett-Packard Company
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <mach/badge4.h>
+#include <asm/hardware/sa1111.h>
+
+#include "sa1111_generic.h"
+
+/*
+ * BadgePAD 4 Details
+ *
+ * PCM Vcc:
+ *
+ * PCM Vcc on BadgePAD 4 can be jumpered for 3v3 (short pins 1 and 3
+ * on JP6) or 5v0 (short pins 3 and 5 on JP6).
+ *
+ * PCM Vpp:
+ *
+ * PCM Vpp on BadgePAD 4 can be jumpered for 12v0 (short pins 4 and 6
+ * on JP6) or tied to PCM Vcc (short pins 2 and 4 on JP6). N.B.,
+ * 12v0 operation requires that the power supply actually supply 12v0
+ * via pin 7 of JP7.
+ *
+ * CF Vcc:
+ *
+ * CF Vcc on BadgePAD 4 can be jumpered either for 3v3 (short pins 1
+ * and 2 on JP10) or 5v0 (short pins 2 and 3 on JP10).
+ *
+ * Unfortunately there's no way programmatically to determine how a
+ * given board is jumpered. This code assumes a default jumpering
+ * as described below.
+ *
+ * If the defaults aren't correct, you may override them with a pcmv
+ * setup argument: pcmv=<pcm vcc>,<pcm vpp>,<cf vcc>. The units are
+ * tenths of volts; e.g. pcmv=33,120,50 indicates 3v3 PCM Vcc, 12v0
+ * PCM Vpp, and 5v0 CF Vcc.
+ *
+ */
+
+static int badge4_pcmvcc = 50; /* pins 3 and 5 jumpered on JP6 */
+static int badge4_pcmvpp = 50; /* pins 2 and 4 jumpered on JP6 */
+static int badge4_cfvcc = 33; /* pins 1 and 2 jumpered on JP10 */
+
+static void complain_about_jumpering(const char *whom,
+ const char *supply,
+ int given, int wanted)
+{
+ printk(KERN_ERR
+ "%s: %s %d.%dV wanted but board is jumpered for %s %d.%dV operation"
+ "; re-jumper the board and/or use pcmv=xx,xx,xx\n",
+ whom, supply,
+ wanted / 10, wanted % 10,
+ supply,
+ given / 10, given % 10);
+}
+
+static int
+badge4_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+ int ret;
+
+ switch (skt->nr) {
+ case 0:
+ if ((state->Vcc != 0) &&
+ (state->Vcc != badge4_pcmvcc)) {
+ complain_about_jumpering(__func__, "pcmvcc",
+ badge4_pcmvcc, state->Vcc);
+ // Apply power regardless of the jumpering.
+ // return -1;
+ }
+ if ((state->Vpp != 0) &&
+ (state->Vpp != badge4_pcmvpp)) {
+ complain_about_jumpering(__func__, "pcmvpp",
+ badge4_pcmvpp, state->Vpp);
+ return -1;
+ }
+ break;
+
+ case 1:
+ if ((state->Vcc != 0) &&
+ (state->Vcc != badge4_cfvcc)) {
+ complain_about_jumpering(__func__, "cfvcc",
+ badge4_cfvcc, state->Vcc);
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ ret = sa1111_pcmcia_configure_socket(skt, state);
+ if (ret == 0) {
+ unsigned long flags;
+ int need5V;
+
+ local_irq_save(flags);
+
+ need5V = ((state->Vcc == 50) || (state->Vpp == 50));
+
+ badge4_set_5V(BADGE4_5V_PCMCIA_SOCK(skt->nr), need5V);
+
+ local_irq_restore(flags);
+ }
+
+ return ret;
+}
+
+static struct pcmcia_low_level badge4_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .configure_socket = badge4_pcmcia_configure_socket,
+ .first = 0,
+ .nr = 2,
+};
+
+int pcmcia_badge4_init(struct device *dev)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_badge4()) {
+ printk(KERN_INFO
+ "%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
+ __func__,
+ badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
+
+ sa11xx_drv_pcmcia_ops(&badge4_pcmcia_ops);
+ ret = sa1111_pcmcia_add(dev, &badge4_pcmcia_ops,
+ sa11xx_drv_pcmcia_add_one);
+ }
+
+ return ret;
+}
+
+static int __init pcmv_setup(char *s)
+{
+ int v[4];
+
+ s = get_options(s, ARRAY_SIZE(v), v);
+
+ if (v[0] >= 1) badge4_pcmvcc = v[1];
+ if (v[0] >= 2) badge4_pcmvpp = v[2];
+ if (v[0] >= 3) badge4_cfvcc = v[3];
+
+ return 1;
+}
+
+__setup("pcmv=", pcmv_setup);
#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);
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);
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) {
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.
*/
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 *);
--- /dev/null
+/*
+ * drivers/pcmcia/sa1100_jornada720.c
+ *
+ * Jornada720 PCMCIA specific routines
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <asm/hardware/sa1111.h>
+#include <asm/mach-types.h>
+
+#include "sa1111_generic.h"
+
+/* Does SOCKET1_3V actually do anything? */
+#define SOCKET0_POWER GPIO_GPIO0
+#define SOCKET0_3V GPIO_GPIO2
+#define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3)
+#define SOCKET1_3V GPIO_GPIO3
+
+static int
+jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+ struct sa1111_pcmcia_socket *s = to_skt(skt);
+ unsigned int pa_dwr_mask, pa_dwr_set;
+ int ret;
+
+ printk(KERN_INFO "%s(): config socket %d vcc %d vpp %d\n", __func__,
+ skt->nr, state->Vcc, state->Vpp);
+
+ switch (skt->nr) {
+ case 0:
+ pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V;
+
+ switch (state->Vcc) {
+ default:
+ case 0:
+ pa_dwr_set = 0;
+ break;
+ case 33:
+ pa_dwr_set = SOCKET0_POWER | SOCKET0_3V;
+ break;
+ case 50:
+ pa_dwr_set = SOCKET0_POWER;
+ break;
+ }
+ break;
+
+ case 1:
+ pa_dwr_mask = SOCKET1_POWER;
+
+ switch (state->Vcc) {
+ default:
+ case 0:
+ pa_dwr_set = 0;
+ break;
+ case 33:
+ pa_dwr_set = SOCKET1_POWER;
+ break;
+ case 50:
+ pa_dwr_set = SOCKET1_POWER;
+ break;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (state->Vpp != state->Vcc && state->Vpp != 0) {
+ printk(KERN_ERR "%s(): slot cannot support VPP %u\n",
+ __func__, state->Vpp);
+ return -EPERM;
+ }
+
+ ret = sa1111_pcmcia_configure_socket(skt, state);
+ if (ret == 0)
+ sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
+
+ return ret;
+}
+
+static struct pcmcia_low_level jornada720_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .configure_socket = jornada720_pcmcia_configure_socket,
+ .first = 0,
+ .nr = 2,
+};
+
+int __devinit pcmcia_jornada720_init(struct device *dev)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_jornada720()) {
+ unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
+
+ GRER |= 0x00000002;
+
+ /* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */
+ sa1111_set_io_dir(dev, pin, 0, 0);
+ sa1111_set_io(dev, pin, 0);
+ sa1111_set_sleep_io(dev, pin, 0);
+
+ sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops);
+ ret = sa1111_pcmcia_add(dev, &jornada720_pcmcia_ops,
+ sa11xx_drv_pcmcia_add_one);
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * linux/drivers/pcmcia/pxa2xx_lubbock.c
+ *
+ * Author: George Davis
+ * Created: Jan 10, 2002
+ * Copyright: MontaVista Software Inc.
+ *
+ * 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.
+ *
+ * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
+ *
+ * Lubbock PCMCIA specific routines.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <asm/hardware/sa1111.h>
+#include <asm/mach-types.h>
+#include <mach/lubbock.h>
+
+#include "sa1111_generic.h"
+
+static int
+lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ struct sa1111_pcmcia_socket *s = to_skt(skt);
+ unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set;
+ int ret = 0;
+
+ pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0;
+
+ /* Lubbock uses the Maxim MAX1602, with the following connections:
+ *
+ * Socket 0 (PCMCIA):
+ * MAX1602 Lubbock Register
+ * Pin Signal
+ * ----- ------- ----------------------
+ * A0VPP S0_PWR0 SA-1111 GPIO A<0>
+ * A1VPP S0_PWR1 SA-1111 GPIO A<1>
+ * A0VCC S0_PWR2 SA-1111 GPIO A<2>
+ * A1VCC S0_PWR3 SA-1111 GPIO A<3>
+ * VX VCC
+ * VY +3.3V
+ * 12IN +12V
+ * CODE +3.3V Cirrus Code, CODE = High (VY)
+ *
+ * Socket 1 (CF):
+ * MAX1602 Lubbock Register
+ * Pin Signal
+ * ----- ------- ----------------------
+ * A0VPP GND VPP is not connected
+ * A1VPP GND VPP is not connected
+ * A0VCC S1_PWR0 MISC_WR<14>
+ * A1VCC S1_PWR1 MISC_WR<15>
+ * VX VCC
+ * VY +3.3V
+ * 12IN GND VPP is not connected
+ * CODE +3.3V Cirrus Code, CODE = High (VY)
+ *
+ */
+
+ again:
+ switch (skt->nr) {
+ case 0:
+ pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
+
+ switch (state->Vcc) {
+ case 0: /* Hi-Z */
+ break;
+
+ case 33: /* VY */
+ pa_dwr_set |= GPIO_A3;
+ break;
+
+ case 50: /* VX */
+ pa_dwr_set |= GPIO_A2;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
+ __func__, state->Vcc);
+ ret = -1;
+ }
+
+ switch (state->Vpp) {
+ case 0: /* Hi-Z */
+ break;
+
+ case 120: /* 12IN */
+ pa_dwr_set |= GPIO_A1;
+ break;
+
+ default: /* VCC */
+ if (state->Vpp == state->Vcc)
+ pa_dwr_set |= GPIO_A0;
+ else {
+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
+ __func__, state->Vpp);
+ ret = -1;
+ break;
+ }
+ }
+ break;
+
+ case 1:
+ misc_mask = (1 << 15) | (1 << 14);
+
+ switch (state->Vcc) {
+ case 0: /* Hi-Z */
+ break;
+
+ case 33: /* VY */
+ misc_set |= 1 << 15;
+ break;
+
+ case 50: /* VX */
+ misc_set |= 1 << 14;
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
+ __func__, state->Vcc);
+ ret = -1;
+ break;
+ }
+
+ if (state->Vpp != state->Vcc && state->Vpp != 0) {
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
+ __func__, state->Vpp);
+ ret = -1;
+ break;
+ }
+ break;
+
+ default:
+ ret = -1;
+ }
+
+ if (ret == 0)
+ ret = sa1111_pcmcia_configure_socket(skt, state);
+
+ if (ret == 0) {
+ lubbock_set_misc_wr(misc_mask, misc_set);
+ sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
+ }
+
+#if 1
+ if (ret == 0 && state->Vcc == 33) {
+ struct pcmcia_state new_state;
+
+ /*
+ * HACK ALERT:
+ * We can't sense the voltage properly on Lubbock before
+ * actually applying some power to the socket (catch 22).
+ * Resense the socket Voltage Sense pins after applying
+ * socket power.
+ *
+ * Note: It takes about 2.5ms for the MAX1602 VCC output
+ * to rise.
+ */
+ mdelay(3);
+
+ sa1111_pcmcia_socket_state(skt, &new_state);
+
+ if (!new_state.vs_3v && !new_state.vs_Xv) {
+ /*
+ * Switch to 5V, Configure socket with 5V voltage
+ */
+ lubbock_set_misc_wr(misc_mask, 0);
+ sa1111_set_io(s->dev, pa_dwr_mask, 0);
+
+ /*
+ * It takes about 100ms to turn off Vcc.
+ */
+ mdelay(100);
+
+ /*
+ * We need to hack around the const qualifier as
+ * well to keep this ugly workaround localized and
+ * not force it to the rest of the code. Barf bags
+ * available in the seat pocket in front of you!
+ */
+ ((socket_state_t *)state)->Vcc = 50;
+ ((socket_state_t *)state)->Vpp = 50;
+ goto again;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+static struct pcmcia_low_level lubbock_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .configure_socket = lubbock_pcmcia_configure_socket,
+ .first = 0,
+ .nr = 2,
+};
+
+#include "pxa2xx_base.h"
+
+int pcmcia_lubbock_init(struct sa1111_dev *sadev)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_lubbock()) {
+ /*
+ * Set GPIO_A<3:0> to be outputs for the MAX1600,
+ * and switch to standby mode.
+ */
+ sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
+ sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
+ sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
+
+ /* Set CF Socket 1 power to standby mode. */
+ lubbock_set_misc_wr((1 << 15) | (1 << 14), 0);
+
+ pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops);
+ pxa2xx_configure_sockets(&sadev->dev);
+ ret = sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops,
+ pxa2xx_drv_pcmcia_add_one);
+ }
+
+ return ret;
+}
+
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * linux/drivers/pcmcia/sa1100_neponset.c
+ *
+ * Neponset PCMCIA specific routines
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <mach/neponset.h>
+#include <asm/hardware/sa1111.h>
+
+#include "sa1111_generic.h"
+
+/*
+ * Neponset uses the Maxim MAX1600, with the following connections:
+ *
+ * MAX1600 Neponset
+ *
+ * A0VCC SA-1111 GPIO A<1>
+ * A1VCC SA-1111 GPIO A<0>
+ * A0VPP CPLD NCR A0VPP
+ * A1VPP CPLD NCR A1VPP
+ * B0VCC SA-1111 GPIO A<2>
+ * B1VCC SA-1111 GPIO A<3>
+ * B0VPP ground (slot B is CF)
+ * B1VPP ground (slot B is CF)
+ *
+ * VX VCC (5V)
+ * VY VCC3_3 (3.3V)
+ * 12INA 12V
+ * 12INB ground (slot B is CF)
+ *
+ * The MAX1600 CODE pin is tied to ground, placing the device in
+ * "Standard Intel code" mode. Refer to the Maxim data sheet for
+ * the corresponding truth table.
+ */
+
+static int
+neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+ struct sa1111_pcmcia_socket *s = to_skt(skt);
+ unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
+ int ret;
+
+ switch (skt->nr) {
+ case 0:
+ pa_dwr_mask = GPIO_A0 | GPIO_A1;
+ ncr_mask = NCR_A0VPP | NCR_A1VPP;
+
+ if (state->Vpp == 0)
+ ncr_set = 0;
+ else if (state->Vpp == 120)
+ ncr_set = NCR_A1VPP;
+ else if (state->Vpp == state->Vcc)
+ ncr_set = NCR_A0VPP;
+ else {
+ printk(KERN_ERR "%s(): unrecognized VPP %u\n",
+ __func__, state->Vpp);
+ return -1;
+ }
+ break;
+
+ case 1:
+ pa_dwr_mask = GPIO_A2 | GPIO_A3;
+ ncr_mask = 0;
+ ncr_set = 0;
+
+ if (state->Vpp != state->Vcc && state->Vpp != 0) {
+ printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
+ __func__, state->Vpp);
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ /*
+ * pa_dwr_set is the mask for selecting Vcc on both sockets.
+ * pa_dwr_mask selects which bits (and therefore socket) we change.
+ */
+ switch (state->Vcc) {
+ default:
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break;
+ case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break;
+ }
+
+ 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);
+ sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
+ }
+
+ return ret;
+}
+
+static struct pcmcia_low_level neponset_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .configure_socket = neponset_pcmcia_configure_socket,
+ .first = 0,
+ .nr = 2,
+};
+
+int pcmcia_neponset_init(struct sa1111_dev *sadev)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_assabet()) {
+ /*
+ * Set GPIO_A<3:0> to be outputs for the MAX1600,
+ * and switch to standby mode.
+ */
+ sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
+ sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
+ sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
+ sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops);
+ ret = sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops,
+ sa11xx_drv_pcmcia_add_one);
+ }
+
+ return ret;
+}
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)
#include <linux/cpufreq.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include "soc_common.h"
+static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev);
+
#ifdef CONFIG_PCMCIA_DEBUG
static int pc_debug;
}
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;
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;
debug(skt, 2, "initializing socket\n");
if (skt->ops->socket_init)
skt->ops->socket_init(skt);
+ soc_pcmcia_hw_enable(skt);
return 0;
}
debug(skt, 2, "suspending socket\n");
+ soc_pcmcia_hw_disable(skt);
if (skt->ops->socket_suspend)
skt->ops->socket_suspend(skt);
};
-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);
#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);
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);
*/
skt->ops->set_timing(skt);
- ret = skt->ops->hw_init(skt);
+ ret = soc_pcmcia_hw_init(skt);
if (ret)
goto out_err_6;
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);
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;
};
-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);